summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2017-07-31 14:43:24 +0200
committerMartin Jambor <mjambor@suse.cz>2017-07-31 14:43:24 +0200
commitb32f12dece884f1fa0f04c643a77105aff6ce8bc (patch)
treecdab5f10806561fc198f907299b0e55eb5701ef0
parent166bec868d991fdf71f9a66f994e5977fcab4aa2 (diff)
parenta168a775e93ec31ae743ad282d8e60fa1c116891 (diff)
downloadgcc-gcn.tar.gz
Merge branch 'master' into gcngcn
-rw-r--r--ChangeLog40
-rw-r--r--MAINTAINERS5
-rw-r--r--Makefile.def3
-rw-r--r--Makefile.in23
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac20
-rw-r--r--contrib/ChangeLog15
-rwxr-xr-xcontrib/filter_gcc_for_doxygen6
-rw-r--r--contrib/filter_gcc_for_doxygen_new12
-rwxr-xr-xcontrib/filter_params.pl14
-rw-r--r--contrib/gcc.doxy8
-rwxr-xr-xcontrib/gcc_update4
-rw-r--r--contrib/header-tools/ChangeLog6
-rwxr-xr-xcontrib/header-tools/graph-header-logs5
-rwxr-xr-xcontrib/mklog18
-rw-r--r--gcc/ChangeLog4686
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in196
-rw-r--r--gcc/ada/ChangeLog30
-rw-r--r--gcc/ada/checks.adb7
-rw-r--r--gcc/ada/gcc-interface/Makefile.in4
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h9
-rw-r--r--gcc/ada/gcc-interface/utils.c2
-rw-r--r--gcc/ada/system-linux-m68k.ads7
-rw-r--r--gcc/asan.c328
-rw-r--r--gcc/asan.h3
-rw-r--r--gcc/attribs.c21
-rw-r--r--gcc/auto-inc-dec.c6
-rw-r--r--gcc/auto-profile.c35
-rw-r--r--gcc/basic-block.h5
-rw-r--r--gcc/bb-reorder.c120
-rw-r--r--gcc/bitmap.c8
-rw-r--r--gcc/bitmap.h17
-rw-r--r--gcc/brig/ChangeLog12
-rw-r--r--gcc/brig/brig-c.h2
-rw-r--r--gcc/brig/brig-lang.c2
-rw-r--r--gcc/brig/brigfrontend/brig-function.cc1
-rw-r--r--gcc/brig/brigfrontend/brig-to-generic.cc1
-rw-r--r--gcc/builtin-types.def10
-rw-r--r--gcc/builtins.c30
-rw-r--r--gcc/builtins.def11
-rw-r--r--gcc/c-family/ChangeLog105
-rw-r--r--gcc/c-family/c-ada-spec.c119
-rw-r--r--gcc/c-family/c-attribs.c41
-rw-r--r--gcc/c-family/c-common.c150
-rw-r--r--gcc/c-family/c-common.h10
-rw-r--r--gcc/c-family/c-format.c1
-rw-r--r--gcc/c-family/c-indentation.c12
-rw-r--r--gcc/c-family/c-indentation.h2
-rw-r--r--gcc/c-family/c-omp.c21
-rw-r--r--gcc/c-family/c-ubsan.c6
-rw-r--r--gcc/c-family/c-warn.c105
-rw-r--r--gcc/c-family/c.opt24
-rw-r--r--gcc/c/ChangeLog55
-rw-r--r--gcc/c/c-convert.c1
-rw-r--r--gcc/c/c-decl.c14
-rw-r--r--gcc/c/c-lang.c5
-rw-r--r--gcc/c/c-parser.c66
-rw-r--r--gcc/c/c-tree.h7
-rw-r--r--gcc/c/c-typeck.c2
-rw-r--r--gcc/ccmp.c168
-rw-r--r--gcc/ccmp.h2
-rw-r--r--gcc/cfg.c119
-rw-r--r--gcc/cfg.h1
-rw-r--r--gcc/cfganal.c5
-rw-r--r--gcc/cfgbuild.c26
-rw-r--r--gcc/cfgcleanup.c65
-rw-r--r--gcc/cfgexpand.c43
-rw-r--r--gcc/cfghooks.c18
-rw-r--r--gcc/cfgloop.h13
-rw-r--r--gcc/cfgloopanal.c16
-rw-r--r--gcc/cfgloopmanip.c130
-rw-r--r--gcc/cfgloopmanip.h11
-rw-r--r--gcc/cfgrtl.c162
-rw-r--r--gcc/cfgrtl.h1
-rw-r--r--gcc/cgraph.c27
-rw-r--r--gcc/cgraphunit.c66
-rw-r--r--gcc/cilk-common.c1
-rw-r--r--gcc/combine.c23
-rw-r--r--gcc/common.opt19
-rw-r--r--gcc/common/config/arm/arm-common.c59
-rw-r--r--gcc/common/config/avr/avr-common.c1
-rw-r--r--gcc/compare-elim.c2
-rw-r--r--gcc/config.gcc73
-rw-r--r--gcc/config.in19
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c12
-rw-r--r--gcc/config/aarch64/aarch64-cores.def4
-rw-r--r--gcc/config/aarch64/aarch64-fusion-pairs.def1
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def4
-rw-r--r--gcc/config/aarch64/aarch64-protos.h18
-rw-r--r--gcc/config/aarch64/aarch64-simd.md54
-rw-r--r--gcc/config/aarch64/aarch64.c555
-rw-r--r--gcc/config/aarch64/aarch64.h34
-rw-r--r--gcc/config/aarch64/aarch64.md256
-rw-r--r--gcc/config/aarch64/arm_neon.h2
-rw-r--r--gcc/config/aarch64/constraints.md18
-rw-r--r--gcc/config/aarch64/cortex-a57-fma-steering.c17
-rw-r--r--gcc/config/aarch64/iterators.md3
-rw-r--r--gcc/config/aarch64/predicates.md13
-rw-r--r--gcc/config/aarch64/rtems.h17
-rw-r--r--gcc/config/alpha/alpha.c4
-rw-r--r--gcc/config/arc/arc-protos.h9
-rw-r--r--gcc/config/arc/arc.c317
-rw-r--r--gcc/config/arc/arc.h58
-rw-r--r--gcc/config/arc/arc.md90
-rw-r--r--gcc/config/arc/arc.opt6
-rw-r--r--gcc/config/arc/constraints.md6
-rw-r--r--gcc/config/arc/elf.h8
-rw-r--r--gcc/config/arc/linux.h8
-rw-r--r--gcc/config/arm/aarch-common-protos.h1
-rw-r--r--gcc/config/arm/aarch-common.c39
-rw-r--r--gcc/config/arm/arm-builtins.c14
-rw-r--r--gcc/config/arm/arm-c.c2
-rw-r--r--gcc/config/arm/arm-cpu-cdata.h2584
-rw-r--r--gcc/config/arm/arm-cpu-data.h566
-rw-r--r--gcc/config/arm/arm-cpu.h198
-rw-r--r--gcc/config/arm/arm-cpus.in76
-rw-r--r--gcc/config/arm/arm-isa.h11
-rw-r--r--gcc/config/arm/arm-protos.h6
-rw-r--r--gcc/config/arm/arm-tables.opt19
-rw-r--r--gcc/config/arm/arm-tune.md4
-rw-r--r--gcc/config/arm/arm.c68
-rw-r--r--gcc/config/arm/arm.h24
-rw-r--r--gcc/config/arm/arm.md2
-rw-r--r--gcc/config/arm/arm.opt14
-rw-r--r--gcc/config/arm/arm_neon.h2
-rw-r--r--gcc/config/arm/bpabi.h85
-rw-r--r--gcc/config/arm/cortex-a53.md2
-rw-r--r--gcc/config/arm/driver-arm.c5
-rw-r--r--gcc/config/arm/neon.md18
-rw-r--r--gcc/config/arm/parsecpu.awk49
-rw-r--r--gcc/config/arm/predicates.md6
-rw-r--r--gcc/config/arm/rtems.h17
-rw-r--r--gcc/config/arm/t-arm35
-rw-r--r--gcc/config/arm/vfp.md2
-rw-r--r--gcc/config/arm/vxworks.h3
-rw-r--r--gcc/config/avr/avr-arch.h1
-rw-r--r--gcc/config/avr/avr-devices.c66
-rw-r--r--gcc/config/avr/avr-log.c9
-rw-r--r--gcc/config/avr/avr-passes.def9
-rw-r--r--gcc/config/avr/avr-protos.h4
-rw-r--r--gcc/config/avr/avr.c539
-rw-r--r--gcc/config/avr/avr.h28
-rw-r--r--gcc/config/avr/avr.md41
-rw-r--r--gcc/config/avr/avr.opt4
-rw-r--r--gcc/config/avr/elf.h5
-rw-r--r--gcc/config/avr/gen-avr-mmcu-specs.c5
-rw-r--r--gcc/config/avr/specs.h1
-rw-r--r--gcc/config/bfin/bfin.c5
-rw-r--r--gcc/config/bfin/rtems.h29
-rw-r--r--gcc/config/darwin.c6
-rw-r--r--gcc/config/frv/frv.c5
-rw-r--r--gcc/config/ft32/ft32.c21
-rw-r--r--gcc/config/i386/adxintrin.h4
-rw-r--r--gcc/config/i386/avx512fintrin.h297
-rw-r--r--gcc/config/i386/avx512vlintrin.h40
-rw-r--r--gcc/config/i386/constraints.md8
-rw-r--r--gcc/config/i386/gstabs.h7
-rw-r--r--gcc/config/i386/i386-builtin-types.def2
-rw-r--r--gcc/config/i386/i386-builtin.def4
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c580
-rw-r--r--gcc/config/i386/i386.h54
-rw-r--r--gcc/config/i386/i386.md63
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/openbsd.h101
-rw-r--r--gcc/config/i386/rtemself.h29
-rw-r--r--gcc/config/i386/sse.md142
-rw-r--r--gcc/config/i386/subst.md67
-rw-r--r--gcc/config/i386/t-openbsd4
-rw-r--r--gcc/config/i386/vxworks.h31
-rw-r--r--gcc/config/i386/winnt-cxx.c25
-rw-r--r--gcc/config/ia64/ia64.c3
-rw-r--r--gcc/config/lm32/rtems.h29
-rw-r--r--gcc/config/m32c/rtems.h29
-rw-r--r--gcc/config/m68k/rtemself.h29
-rw-r--r--gcc/config/microblaze/microblaze-protos.h2
-rw-r--r--gcc/config/microblaze/microblaze.c3
-rw-r--r--gcc/config/microblaze/rtems.h29
-rw-r--r--gcc/config/mips/rtems.h29
-rw-r--r--gcc/config/mmix/mmix.c3
-rw-r--r--gcc/config/moxie/rtems.h29
-rw-r--r--gcc/config/netbsd.h16
-rw-r--r--gcc/config/nios2/rtems.h35
-rw-r--r--gcc/config/nvptx/nvptx-modes.def3
-rw-r--r--gcc/config/nvptx/nvptx-protos.h1
-rw-r--r--gcc/config/nvptx/nvptx.c206
-rw-r--r--gcc/config/nvptx/nvptx.h6
-rw-r--r--gcc/config/nvptx/nvptx.md29
-rw-r--r--gcc/config/pa/pa.c3
-rw-r--r--gcc/config/powerpcspe/powerpcspe.c25
-rw-r--r--gcc/config/powerpcspe/rtems.h9
-rw-r--r--gcc/config/riscv/riscv-builtins.c1
-rw-r--r--gcc/config/riscv/riscv-protos.h16
-rw-r--r--gcc/config/riscv/riscv.c156
-rw-r--r--gcc/config/riscv/rtems.h31
-rw-r--r--gcc/config/rl78/rl78-protos.h2
-rw-r--r--gcc/config/rl78/rl78.c4
-rw-r--r--gcc/config/rs6000/altivec.h16
-rw-r--r--gcc/config/rs6000/altivec.md130
-rw-r--r--gcc/config/rs6000/mmintrin.h1456
-rw-r--r--gcc/config/rs6000/ppc-auxv.h2
-rw-r--r--gcc/config/rs6000/predicates.md8
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def60
-rw-r--r--gcc/config/rs6000/rs6000-c.c280
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def31
-rw-r--r--gcc/config/rs6000/rs6000-p8swap.c1892
-rw-r--r--gcc/config/rs6000/rs6000-protos.h5
-rw-r--r--gcc/config/rs6000/rs6000.c2534
-rw-r--r--gcc/config/rs6000/rs6000.h11
-rw-r--r--gcc/config/rs6000/rs6000.md69
-rw-r--r--gcc/config/rs6000/rs6000.opt27
-rw-r--r--gcc/config/rs6000/rtems.h206
-rw-r--r--gcc/config/rs6000/t-rs60004
-rw-r--r--gcc/config/rs6000/t-rtems6
-rw-r--r--gcc/config/rs6000/vsx.md485
-rw-r--r--gcc/config/rs6000/x86intrin.h5
-rw-r--r--gcc/config/rtems.h40
-rw-r--r--gcc/config/s390/driver-native.c6
-rw-r--r--gcc/config/s390/predicates.md9
-rw-r--r--gcc/config/s390/s390-c.c4
-rw-r--r--gcc/config/s390/s390-opts.h2
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c160
-rw-r--r--gcc/config/s390/s390.h4
-rw-r--r--gcc/config/s390/s390.md36
-rw-r--r--gcc/config/s390/s390.opt9
-rw-r--r--gcc/config/sh/rtems.h29
-rw-r--r--gcc/config/sh/rtemself.h29
-rw-r--r--gcc/config/sh/sh-protos.h2
-rw-r--r--gcc/config/sh/sh.c66
-rw-r--r--gcc/config/sh/sh.md2
-rw-r--r--gcc/config/sparc/constraints.md12
-rw-r--r--gcc/config/sparc/driver-sparc.c1
-rw-r--r--gcc/config/sparc/m8.md242
-rw-r--r--gcc/config/sparc/niagara.md2
-rw-r--r--gcc/config/sparc/niagara2.md4
-rw-r--r--gcc/config/sparc/niagara4.md7
-rw-r--r--gcc/config/sparc/niagara7.md181
-rw-r--r--gcc/config/sparc/predicates.md27
-rw-r--r--gcc/config/sparc/rtemself.h31
-rw-r--r--gcc/config/sparc/sol2.h14
-rw-r--r--gcc/config/sparc/sparc-c.c7
-rw-r--r--gcc/config/sparc/sparc-opts.h1
-rw-r--r--gcc/config/sparc/sparc.c463
-rw-r--r--gcc/config/sparc/sparc.h23
-rw-r--r--gcc/config/sparc/sparc.md380
-rw-r--r--gcc/config/sparc/sparc.opt23
-rw-r--r--gcc/config/sparc/t-rtems36
-rw-r--r--gcc/config/sparc/ultra1_2.md8
-rw-r--r--gcc/config/sparc/ultra3.md4
-rw-r--r--gcc/config/spu/spu.c6
-rw-r--r--gcc/config/t-musl2
-rw-r--r--gcc/config/t-uclibc2
-rw-r--r--gcc/config/tilegx/tilegx.c5
-rw-r--r--gcc/config/tilepro/tilepro.c5
-rw-r--r--gcc/config/v850/rtems.h18
-rw-r--r--gcc/config/vax/builtins.md2
-rw-r--r--gcc/config/visium/visium-protos.h22
-rw-r--r--gcc/config/visium/visium.c76
-rw-r--r--gcc/config/vxworks.c36
-rw-r--r--gcc/config/vxworks.h70
-rwxr-xr-xgcc/configure94
-rw-r--r--gcc/configure.ac40
-rw-r--r--gcc/convert.c3
-rw-r--r--gcc/coretypes.h12
-rw-r--r--gcc/cp/ChangeLog480
-rw-r--r--gcc/cp/call.c152
-rw-r--r--gcc/cp/class.c478
-rw-r--r--gcc/cp/config-lang.in2
-rw-r--r--gcc/cp/constexpr.c3
-rw-r--r--gcc/cp/constraint.cc2
-rw-r--r--gcc/cp/cp-array-notation.c4
-rw-r--r--gcc/cp/cp-gimplify.c3
-rw-r--r--gcc/cp/cp-lang.c24
-rw-r--r--gcc/cp/cp-objcp-common.c7
-rw-r--r--gcc/cp/cp-tree.h137
-rw-r--r--gcc/cp/cp-ubsan.c3
-rw-r--r--gcc/cp/cxx-pretty-print.c19
-rw-r--r--gcc/cp/decl.c223
-rw-r--r--gcc/cp/decl2.c220
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/friend.c2
-rw-r--r--gcc/cp/init.c16
-rw-r--r--gcc/cp/lambda.c7
-rw-r--r--gcc/cp/lex.c100
-rw-r--r--gcc/cp/mangle.c74
-rw-r--r--gcc/cp/method.c70
-rw-r--r--gcc/cp/name-lookup.c165
-rw-r--r--gcc/cp/optimize.c6
-rw-r--r--gcc/cp/parser.c249
-rw-r--r--gcc/cp/pt.c444
-rw-r--r--gcc/cp/ptree.c1
-rw-r--r--gcc/cp/rtti.c10
-rw-r--r--gcc/cp/search.c233
-rw-r--r--gcc/cp/semantics.c60
-rw-r--r--gcc/cp/tree.c31
-rw-r--r--gcc/cp/typeck.c3
-rw-r--r--gcc/dbxout.c49
-rw-r--r--gcc/dbxout.h1
-rw-r--r--gcc/debug.c11
-rw-r--r--gcc/debug.h6
-rw-r--r--gcc/diagnostic-show-locus.c463
-rw-r--r--gcc/doc/extend.texi378
-rw-r--r--gcc/doc/generic.texi17
-rw-r--r--gcc/doc/invoke.texi261
-rw-r--r--gcc/doc/rtl.texi7
-rw-r--r--gcc/doc/sourcebuild.texi11
-rw-r--r--gcc/doc/tm.texi13
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/dojump.c127
-rw-r--r--gcc/dojump.h17
-rw-r--r--gcc/domwalk.c52
-rw-r--r--gcc/dumpfile.c7
-rw-r--r--gcc/dwarf2asm.c4
-rw-r--r--gcc/dwarf2cfi.c1
-rw-r--r--gcc/dwarf2out.c130
-rw-r--r--gcc/emit-rtl.c22
-rw-r--r--gcc/except.c78
-rw-r--r--gcc/explow.c1
-rw-r--r--gcc/expmed.c11
-rw-r--r--gcc/expmed.h6
-rw-r--r--gcc/expr.c48
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/final.c3
-rw-r--r--gcc/flag-types.h4
-rw-r--r--gcc/fold-const.c285
-rw-r--r--gcc/fold-const.h27
-rw-r--r--gcc/fortran/ChangeLog69
-rw-r--r--gcc/fortran/array.c8
-rw-r--r--gcc/fortran/check.c2
-rw-r--r--gcc/fortran/class.c1
-rw-r--r--gcc/fortran/dump-parse-tree.c3
-rw-r--r--gcc/fortran/interface.c4
-rw-r--r--gcc/fortran/ioparm.def2
-rw-r--r--gcc/fortran/openmp.c3
-rw-r--r--gcc/fortran/resolve.c4
-rw-r--r--gcc/fortran/symbol.c4
-rw-r--r--gcc/fortran/trans-array.c5
-rw-r--r--gcc/fortran/trans-decl.c5
-rw-r--r--gcc/fortran/trans-stmt.c6
-rw-r--r--gcc/fortran/trans.c14
-rw-r--r--gcc/function-tests.c4
-rw-r--r--gcc/function.c39
-rw-r--r--gcc/gcc-rich-location.c3
-rw-r--r--gcc/gcc-rich-location.h21
-rw-r--r--gcc/gcc.c29
-rw-r--r--gcc/gencheck.c3
-rw-r--r--gcc/gengenrtl.c2
-rw-r--r--gcc/genmatch.c168
-rw-r--r--gcc/genmodes.c31
-rw-r--r--gcc/genmultilib14
-rw-r--r--gcc/genrecog.c6
-rw-r--r--gcc/ggc.h41
-rw-r--r--gcc/gimple-expr.c4
-rw-r--r--gcc/gimple-fold.c7
-rw-r--r--gcc/gimple-fold.h1
-rw-r--r--gcc/gimple-match-head.c17
-rw-r--r--gcc/gimple-pretty-print.c73
-rw-r--r--gcc/gimple-ssa-isolate-paths.c4
-rw-r--r--gcc/gimple-ssa-sprintf.c6
-rw-r--r--gcc/gimple-ssa-store-merging.c10
-rw-r--r--gcc/gimple-ssa-strength-reduction.c53
-rw-r--r--gcc/gimple.c10
-rw-r--r--gcc/gimple.h45
-rw-r--r--gcc/gimplify.c14
-rw-r--r--gcc/go/ChangeLog5
-rw-r--r--gcc/go/go-backend.c8
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc194
-rw-r--r--gcc/go/gofrontend/expressions.h18
-rw-r--r--gcc/go/gofrontend/gogo.cc2
-rw-r--r--gcc/go/gofrontend/types.cc51
-rw-r--r--gcc/go/gofrontend/types.h12
-rw-r--r--gcc/godump.c1
-rw-r--r--gcc/graph.c41
-rw-r--r--gcc/haifa-sched.c14
-rw-r--r--gcc/hash-map-tests.c1
-rw-r--r--gcc/hash-set-tests.c1
-rw-r--r--gcc/hash-table.h2
-rw-r--r--gcc/hsa-brig.c2
-rw-r--r--gcc/hsa-gen.c19
-rw-r--r--gcc/ifcvt.c58
-rw-r--r--gcc/input.c52
-rw-r--r--gcc/internal-fn.c131
-rw-r--r--gcc/internal-fn.def2
-rw-r--r--gcc/ipa-comdats.c2
-rw-r--r--gcc/ipa-cp.c11
-rw-r--r--gcc/ipa-devirt.c56
-rw-r--r--gcc/ipa-fnsummary.c23
-rw-r--r--gcc/ipa-inline-analysis.c3
-rw-r--r--gcc/ipa-inline.c42
-rw-r--r--gcc/ipa-inline.h10
-rw-r--r--gcc/ipa-polymorphic-call.c19
-rw-r--r--gcc/ipa-split.c12
-rw-r--r--gcc/ipa-utils.c25
-rw-r--r--gcc/ipa-utils.h3
-rw-r--r--gcc/ipa-visibility.c53
-rw-r--r--gcc/ipa.c18
-rw-r--r--gcc/ira-color.c2
-rw-r--r--gcc/jit/ChangeLog7
-rw-r--r--gcc/jit/dummy-frontend.c2
-rw-r--r--gcc/langhooks.h2
-rw-r--r--gcc/loop-doloop.c27
-rw-r--r--gcc/loop-unroll.c20
-rw-r--r--gcc/lra-assigns.c9
-rw-r--r--gcc/lra-constraints.c7
-rw-r--r--gcc/lra-eliminations.c2
-rw-r--r--gcc/lto-opts.c4
-rw-r--r--gcc/lto-streamer-in.c8
-rw-r--r--gcc/lto-streamer-out.c10
-rw-r--r--gcc/lto-wrapper.c154
-rw-r--r--gcc/lto/ChangeLog16
-rw-r--r--gcc/lto/lto-lang.c12
-rw-r--r--gcc/lto/lto-partition.c21
-rw-r--r--gcc/lto/lto.c13
-rw-r--r--gcc/machmode.h3
-rw-r--r--gcc/match.pd216
-rw-r--r--gcc/mcf.c40
-rw-r--r--gcc/mkconfig.sh3
-rw-r--r--gcc/modulo-sched.c9
-rw-r--r--gcc/multiple_target.c65
-rw-r--r--gcc/objc/ChangeLog11
-rw-r--r--gcc/objc/objc-act.h8
-rw-r--r--gcc/objc/objc-runtime-shared-support.c52
-rw-r--r--gcc/objcp/ChangeLog4
-rw-r--r--gcc/objcp/config-lang.in20
-rw-r--r--gcc/omp-expand.c59
-rw-r--r--gcc/omp-low.c2
-rw-r--r--gcc/omp-simd-clone.c8
-rw-r--r--gcc/opt-functions.awk15
-rw-r--r--gcc/optabs.c24
-rw-r--r--gcc/optabs.h4
-rw-r--r--gcc/optc-gen.awk7
-rw-r--r--gcc/optc-save-gen.awk3
-rw-r--r--gcc/opts-common.c12
-rw-r--r--gcc/opts.c86
-rw-r--r--gcc/opts.h9
-rw-r--r--gcc/params.def5
-rw-r--r--gcc/params.h2
-rw-r--r--gcc/passes.c1
-rw-r--r--gcc/predict.c282
-rw-r--r--gcc/predict.def5
-rw-r--r--gcc/predict.h6
-rw-r--r--gcc/pretty-print.h1
-rw-r--r--gcc/print-tree.c2
-rw-r--r--gcc/profile-count.c123
-rw-r--r--gcc/profile-count.h577
-rw-r--r--gcc/profile.c14
-rw-r--r--gcc/recog.c3
-rw-r--r--gcc/reg-notes.def11
-rw-r--r--gcc/reorg.c3
-rw-r--r--gcc/rtl-tests.c1
-rw-r--r--gcc/rtl.c4
-rw-r--r--gcc/rtl.h11
-rw-r--r--gcc/rtlanal.c28
-rw-r--r--gcc/sanitizer.def12
-rw-r--r--gcc/sanopt.c143
-rw-r--r--gcc/sched-deps.c34
-rw-r--r--gcc/sched-ebb.c3
-rw-r--r--gcc/sched-rgn.c15
-rw-r--r--gcc/sdbout.c2
-rw-r--r--gcc/sel-sched-ir.c10
-rw-r--r--gcc/simplify-rtx.c11
-rw-r--r--gcc/stmt.c102
-rw-r--r--gcc/stor-layout.c3
-rw-r--r--gcc/stringpool.c23
-rw-r--r--gcc/target.def15
-rw-r--r--gcc/targhooks.c51
-rw-r--r--gcc/targhooks.h7
-rw-r--r--gcc/testsuite/ChangeLog1636
-rw-r--r--gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c118
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c82
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c19
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-12.c43
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c137
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c12
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c14
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c18
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c22
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c18
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c64
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c62
-rw-r--r--gcc/testsuite/c-c++-common/Wsign-compare-1.c33
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c22
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c27
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_instruments_all_paddings.c21
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c34
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c22
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c22
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_safe_access.c15
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c22
-rw-r--r--gcc/testsuite/c-c++-common/asan/kasan-alloca-1.c11
-rw-r--r--gcc/testsuite/c-c++-common/asan/kasan-alloca-2.c11
-rw-r--r--gcc/testsuite/c-c++-common/dump-ada-spec-7.c15
-rw-r--r--gcc/testsuite/c-c++-common/patchable_function_entry-decl.c16
-rw-r--r--gcc/testsuite/c-c++-common/patchable_function_entry-default.c16
-rw-r--r--gcc/testsuite/c-c++-common/patchable_function_entry-definition.c16
-rw-r--r--gcc/testsuite/c-c++-common/pr70264.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c3
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/pr81604.c31
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/ptr-overflow-1.c65
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/ptr-overflow-2.c113
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c4
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c2
-rw-r--r--gcc/testsuite/g++.dg/Wclass-memaccess-2.C61
-rw-r--r--gcc/testsuite/g++.dg/asan/function-argument-1.C31
-rw-r--r--gcc/testsuite/g++.dg/asan/function-argument-2.C24
-rw-r--r--gcc/testsuite/g++.dg/asan/function-argument-3.C28
-rw-r--r--gcc/testsuite/g++.dg/asan/pr81021.C33
-rw-r--r--gcc/testsuite/g++.dg/asan/pr81340.C22
-rw-r--r--gcc/testsuite/g++.dg/concepts/memfun-err.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto1.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-call4.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype9.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor29.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice17.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/missing-initializer_list-include.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept30.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing14.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn2.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-partial1.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp8.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/builtin_FUNCTION.C42
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction40.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction41.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction42.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp13.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp14.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp21.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp25.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp28.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp3.C62
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp30.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp4.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp5.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp6.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp7.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp8.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C234
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/dr393.C4
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-1.C23
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-2.C23
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/friend1.C8
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr79300.C44
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/variadic1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct6.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/mvc2.C1
-rw-r--r--gcc/testsuite/g++.dg/ext/mvc3.C1
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-3.C12
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr81261.C31
-rw-r--r--gcc/testsuite/g++.dg/lookup/decl1.C13
-rw-r--r--gcc/testsuite/g++.dg/lookup/extern-c-redecl.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/missing-std-include-2.C55
-rw-r--r--gcc/testsuite/g++.dg/lookup/missing-std-include-3.C35
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr81229.C7
-rw-r--r--gcc/testsuite/g++.dg/opt/pr79659.C5
-rw-r--r--gcc/testsuite/g++.dg/other/i386-9.C1
-rw-r--r--gcc/testsuite/g++.dg/other/pr28432.C6
-rw-r--r--gcc/testsuite/g++.dg/overload/error1.C2
-rw-r--r--gcc/testsuite/g++.dg/overload/error2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/catch2.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/crash12.C9
-rw-r--r--gcc/testsuite/g++.dg/parse/enum3.C6
-rw-r--r--gcc/testsuite/g++.dg/parse/operator6.C5
-rw-r--r--gcc/testsuite/g++.dg/parse/pr81247-a.C13
-rw-r--r--gcc/testsuite/g++.dg/parse/pr81247-b.C14
-rw-r--r--gcc/testsuite/g++.dg/parse/pr81247-c.C13
-rw-r--r--gcc/testsuite/g++.dg/parse/template-keyword1.C3
-rw-r--r--gcc/testsuite/g++.dg/plugin/decl-plugin-test.C2
-rw-r--r--gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C110
-rw-r--r--gcc/testsuite/g++.dg/pr69667.C2
-rw-r--r--gcc/testsuite/g++.dg/pr71294.C2
-rw-r--r--gcc/testsuite/g++.dg/pr81194.C60
-rw-r--r--gcc/testsuite/g++.dg/rtti/missing-typeinfo-include.C27
-rw-r--r--gcc/testsuite/g++.dg/template/crash69.C5
-rw-r--r--gcc/testsuite/g++.dg/template/duplicate1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error27.C5
-rw-r--r--gcc/testsuite/g++.dg/template/error28.C5
-rw-r--r--gcc/testsuite/g++.dg/template/lookup10.C12
-rw-r--r--gcc/testsuite/g++.dg/template/lookup11.C11
-rw-r--r--gcc/testsuite/g++.dg/template/memfriend6.C21
-rw-r--r--gcc/testsuite/g++.dg/template/partial-specialization8.C19
-rw-r--r--gcc/testsuite/g++.dg/template/template-keyword1.C15
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81249.C25
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81365.C39
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81462.C17
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr81408.C92
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr81209.C21
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr81262.C14
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr81530.C6
-rw-r--r--gcc/testsuite/g++.dg/vect/pr61171.cc23
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmultistatement-macros-1.C13
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr-3.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsign-compare-2.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsign-compare-4.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsign-compare-6.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/compare1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C20
-rw-r--r--gcc/testsuite/g++.dg/warn/pr12242.C14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/arm2.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900520_03.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/array2.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/err1.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p811.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/anon4.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash25.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/dtor4.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/redecl2.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/redecl4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/t37.C9
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr81207.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr81262.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr81290.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/stack-check-1.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr81555.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr81556.c23
-rw-r--r--gcc/testsuite/gcc.dg/Walloca-14.c1
-rw-r--r--gcc/testsuite/gcc.dg/Wmissing-braces-fixits.c25
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr81186.c18
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr81224.c11
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr81460.c8
-rw-r--r--gcc/testsuite/gcc.dg/atomic-pr81231.c12
-rw-r--r--gcc/testsuite/gcc.dg/attr-noipa.c188
-rw-r--r--gcc/testsuite/gcc.dg/builtin-unreachable-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/compare1.c2
-rw-r--r--gcc/testsuite/gcc.dg/compare2.c8
-rw-r--r--gcc/testsuite/gcc.dg/compare4.c4
-rw-r--r--gcc/testsuite/gcc.dg/compare5.c4
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/fixed-point/pr81428.c9
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges.c4
-rw-r--r--gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c1
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr68037-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c26
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c39
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr81520.c11
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-1.c36
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-2.h7
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c79
-rw-r--r--gcc/testsuite/gcc.dg/pr35430.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr44290-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr44290-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr46932.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr47443.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr48134.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr56727-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr56727-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr60087.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr70017.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr70920-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr70920-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr81030.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr81192.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr81227.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr81292-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/pr81292-2.c35
-rw-r--r--gcc/testsuite/gcc.dg/pr81345.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr81455.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr81564.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr81578.c12
-rw-r--r--gcc/testsuite/gcc.dg/predict-15.c17
-rw-r--r--gcc/testsuite/gcc.dg/predict-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-fields-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/stack-layout-dynamic-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-31.c25
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-31g.c9
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-32.c193
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-33.c42
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-33g.c45
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-34.c38
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-35.c31
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr70992-2.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr70992.c41
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr80565.c41
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr80620.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81203.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81245.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81403.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81418.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81500.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81510-2.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81510.c29
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81571.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81573.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-profiler-threads-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/addadd.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/assoc-1.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-19.c62
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/copy-sign-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c36
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/mulcmp-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/mult-abs-2.c38
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81346-1.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81346-2.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81346-3.c109
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81346-4.c79
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81369.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr81396.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c62
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-10.c44
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-11.c51
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c62
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c108
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c61
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-5.c63
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-6.c65
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-7.c63
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-8.c60
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-9.c90
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-35.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-36.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp116.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp24.c10
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/pr81162.c17
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/pr81223.c12
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/pr81505.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr80815-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr81136.c16
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr81196.c19
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr81410.c37
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-43.c9
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-45.c9
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-reduc-8.c48
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-reduc-11.c46
-rw-r--r--gcc/testsuite/gcc.target/aarch64/ccmp_2.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cmp-2.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c53
-rw-r--r--gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c49
-rw-r--r--gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c45
-rw-r--r--gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c59
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr63304_1.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr79041-2.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr81414.C9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/simd/vminmaxnm_1.c48
-rw-r--r--gcc/testsuite/gcc.target/aarch64/simd/vmla_elem_1.c67
-rw-r--r--gcc/testsuite/gcc.target/aarch64/stack-checking.c1
-rw-r--r--gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/var_shift_mask_1.c65
-rw-r--r--gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/naked-1.c18
-rw-r--r--gcc/testsuite/gcc.target/arc/naked-2.c26
-rw-r--r--gcc/testsuite/gcc.target/arc/pic-1.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/pr9000674901.c58
-rw-r--r--gcc/testsuite/gcc.target/arc/pr9001191897.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/lto/pr65837-attr_0.c3
-rw-r--r--gcc/testsuite/gcc.target/arm/lto/pr65837_0.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/stack-checking.c2
-rw-r--r--gcc/testsuite/gcc.target/avr/isr-test.h283
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/isr-01-simple.c98
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/isr-02-call.c60
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/isr-03-fixed.c146
-rw-r--r--gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-pr80846.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-pr80846.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr81532.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-pr81532.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-pr80846.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vaddsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vaddss-3.c65
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vdivsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vdivss-3.c64
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-2.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-2.c37
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmaxsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmaxss-3.c66
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vminsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vminss-3.c66
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmulsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vmulss-3.c64
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpermd-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpermq-imm-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vpermq-var-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vsubsd-3.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vsubss-3.c64
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpermd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpermq-imm-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-vpermq-var-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cmov7.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-5.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/mvc2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/mvc3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/mvc6.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/naked-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/naked-2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/naked-3.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/pr48723.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55672.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67265-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67265.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr69255-2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79793-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79793-2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr80569.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr80833-3.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81128.c65
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81214.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81225.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81294-1.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81294-2.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81300.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81313-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81313-2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81313-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81313-4.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81313-5.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81375.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81471.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81502.c34
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81563.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/testimm-10.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/testround-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/umod-3.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-insert-1.c15
-rw-r--r--gcc/testsuite/gcc.target/nvptx/decl-init.c2
-rw-r--r--gcc/testsuite/gcc.target/nvptx/slp-2-run.c23
-rw-r--r--gcc/testsuite/gcc.target/nvptx/slp-2.c25
-rw-r--r--gcc/testsuite/gcc.target/nvptx/slp-run.c23
-rw-r--r--gcc/testsuite/gcc.target/nvptx/slp.c25
-rw-r--r--gcc/testsuite/gcc.target/nvptx/v2di.c12
-rw-r--r--gcc/testsuite/gcc.target/nvptx/v2si-cvt.c39
-rw-r--r--gcc/testsuite/gcc.target/nvptx/v2si-run.c83
-rw-r--r--gcc/testsuite/gcc.target/nvptx/v2si.c12
-rw-r--r--gcc/testsuite/gcc.target/nvptx/vec.inc18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-3.c32
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-4.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-3.c31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-4.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-3.c31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-4.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-3.c36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-4.c39
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-3.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-6.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-7.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-3.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-6.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-7.c36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-12.c40
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-13.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-14.c40
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-15.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-6.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-9.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-10.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-12.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-13.c47
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-14.c54
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-15.c56
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-8.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-9.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-4.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-6.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-7.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-8.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-4.c39
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-5.c37
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-4.c33
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-5.c31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-10.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-11.c39
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-8.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-9.c38
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-8.c112
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-9.c125
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-andn-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-andn-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-bextr-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-bextr-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-bextr-4.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-bextr-5.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsi-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsi-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsr-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-blsr-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-check.h3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-bzhi32-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-bzhi64-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-check.h3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-pdep32-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-pdep64-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-pext32-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bmi2-pext64-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-1-p9-runnable.c26
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-2-p9-runnable.c72
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3-p9-runnable.c35
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3-runnable.c229
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3-vec_reve-runnable.c393
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-4-p9-runnable.c95
-rw-r--r--gcc/testsuite/gcc.target/powerpc/clone1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/clone2.c31
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dform-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dform-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dform-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-missing-lhs.c24
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-check.h35
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-packs.c91
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-packssdw-1.c60
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-packsswb-1.c60
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-packuswb-1.c50
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddb-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddd-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddsb-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddsw-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddusb-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddusw-1.c52
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-paddw-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqb-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqd-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqw-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtb-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtd-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtw-1.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pmaddwd-1.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pmulhw-1.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pmullw-1.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-pslld-1.c45
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psllw-1.c45
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psrad-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psraw-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psrld-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psrlw-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubb-2.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubd-2.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubsb-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubsw-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubusb-1.c51
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubusw-1.c52
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-psubw-2.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpckhbw-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpckhdq-1.c40
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpckhwd-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpcklbw-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpckldq-1.c40
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmx-punpcklwd-1.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-fp.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-int128-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-dimode1.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-dimode2.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-vparity.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-xxbr-1.c24
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-xxbr-2.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-1.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-10.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-round.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr63491.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr65849-1.c728
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr65849-2.c728
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr67808.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr68805.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr69461.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71656-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71656-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71680.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71698.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71720.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr72853.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr77289.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr78458.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr78543.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr78953.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr79907.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80099-1.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80099-2.c128
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80099-3.c128
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80099-4.c128
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80099-5.c128
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80103-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr81348.c24
-rw-r--r--gcc/testsuite/gcc.target/powerpc/upper-regs-df.c6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/upper-regs-sf.c6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-extract-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-init-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-init-6.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-init-7.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-set-char.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-set-int.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-set-short.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-himode.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-himode2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-himode3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-qimode.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-qimode2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-qimode3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-simode.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-simode2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-simode3.c2
-rw-r--r--gcc/testsuite/gcc.target/s390/nodatarel-1.c83
-rw-r--r--gcc/testsuite/gcc.target/s390/pr81534.c17
-rw-r--r--gcc/testsuite/gcc.target/sparc/dictunpack.c25
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpcmpdeshl.c25
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpcmpshl.c81
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpcmpurshl.c25
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpcmpushl.c43
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/do-test.S200
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c74
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp153
-rw-r--r--gcc/testsuite/gfortran.dg/array_temporaries_4.f9059
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_44.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_event_2.f0813
-rw-r--r--gcc/testsuite/gfortran.dg/dim_sum_1.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/dim_sum_2.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/dim_sum_3.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/eoshift_3.f90178
-rw-r--r--gcc/testsuite/gfortran.dg/eoshift_4.f90187
-rw-r--r--gcc/testsuite/gfortran.dg/eoshift_5.f90182
-rw-r--r--gcc/testsuite/gfortran.dg/eoshift_6.f90181
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/pr77765.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_intent_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr81175.f23
-rw-r--r--gcc/testsuite/gfortran.dg/pr81464.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/pr81529.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/realloc_on_assign_28.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr60510.f30
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr61171.f15
-rw-r--r--gcc/testsuite/gnat.dg/opt49.adb1
-rw-r--r--gcc/testsuite/gnat.dg/opt65.adb30
-rw-r--r--gcc/testsuite/gnat.dg/opt66.adb13
-rw-r--r--gcc/testsuite/gnat.dg/stack_check1.adb1
-rw-r--r--gcc/testsuite/gnat.dg/stack_check2.adb1
-rw-r--r--gcc/testsuite/gnat.dg/stack_check3.adb1
-rw-r--r--gcc/testsuite/gnat.dg/vect15.adb5
-rw-r--r--gcc/testsuite/gnat.dg/vect15.ads2
-rw-r--r--gcc/testsuite/gnat.dg/vect16.adb8
-rw-r--r--gcc/testsuite/gnat.dg/vect16.ads2
-rw-r--r--gcc/testsuite/gnat.dg/vect17.adb5
-rw-r--r--gcc/testsuite/gnat.dg/vect17.ads2
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp3
-rw-r--r--gcc/testsuite/lib/profopt.exp4
-rw-r--r--gcc/testsuite/lib/target-supports-dg.exp15
-rw-r--r--gcc/testsuite/lib/target-supports.exp165
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.c4
-rw-r--r--gcc/tracer.c9
-rw-r--r--gcc/trans-mem.c23
-rw-r--r--gcc/tree-call-cdce.c13
-rw-r--r--gcc/tree-cfg.c135
-rw-r--r--gcc/tree-cfg.h7
-rw-r--r--gcc/tree-cfgcleanup.c22
-rw-r--r--gcc/tree-chkp-opt.c3
-rw-r--r--gcc/tree-complex.c15
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-data-ref.c157
-rw-r--r--gcc/tree-data-ref.h63
-rw-r--r--gcc/tree-dump.c2
-rw-r--r--gcc/tree-eh.c29
-rw-r--r--gcc/tree-if-conv.c22
-rw-r--r--gcc/tree-inline.c46
-rw-r--r--gcc/tree-loop-distribution.c1483
-rw-r--r--gcc/tree-parloops.c52
-rw-r--r--gcc/tree-phinodes.c27
-rw-r--r--gcc/tree-predcom.c683
-rw-r--r--gcc/tree-pretty-print.c17
-rw-r--r--gcc/tree-profile.c12
-rw-r--r--gcc/tree-ssa-alias.c1
-rw-r--r--gcc/tree-ssa-dce.c2
-rw-r--r--gcc/tree-ssa-ifcombine.c14
-rw-r--r--gcc/tree-ssa-loop-ch.c2
-rw-r--r--gcc/tree-ssa-loop-im.c30
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c13
-rw-r--r--gcc/tree-ssa-loop-manip.c48
-rw-r--r--gcc/tree-ssa-loop-niter.c141
-rw-r--r--gcc/tree-ssa-loop-split.c12
-rw-r--r--gcc/tree-ssa-loop-unswitch.c46
-rw-r--r--gcc/tree-ssa-math-opts.c41
-rw-r--r--gcc/tree-ssa-operands.c45
-rw-r--r--gcc/tree-ssa-phionlycprop.c2
-rw-r--r--gcc/tree-ssa-phiopt.c6
-rw-r--r--gcc/tree-ssa-phiprop.c27
-rw-r--r--gcc/tree-ssa-pre.c39
-rw-r--r--gcc/tree-ssa-reassoc.c19
-rw-r--r--gcc/tree-ssa-sccvn.c8
-rw-r--r--gcc/tree-ssa-strlen.c638
-rw-r--r--gcc/tree-ssa-structalias.c28
-rw-r--r--gcc/tree-ssa-tail-merge.c30
-rw-r--r--gcc/tree-ssa-threadupdate.c28
-rw-r--r--gcc/tree-ssa-uninit.c25
-rw-r--r--gcc/tree-ssa.c43
-rw-r--r--gcc/tree-ssanames.c47
-rw-r--r--gcc/tree-ssanames.h3
-rw-r--r--gcc/tree-streamer-in.c4
-rw-r--r--gcc/tree-streamer-out.c4
-rw-r--r--gcc/tree-switch-conversion.c10
-rw-r--r--gcc/tree-tailcall.c5
-rw-r--r--gcc/tree-vect-data-refs.c362
-rw-r--r--gcc/tree-vect-loop-manip.c64
-rw-r--r--gcc/tree-vect-loop.c1100
-rw-r--r--gcc/tree-vect-patterns.c20
-rw-r--r--gcc/tree-vect-slp.c255
-rw-r--r--gcc/tree-vect-stmts.c208
-rw-r--r--gcc/tree-vectorizer.c89
-rw-r--r--gcc/tree-vectorizer.h64
-rw-r--r--gcc/tree-vrp.c56
-rw-r--r--gcc/tree.c199
-rw-r--r--gcc/tree.def10
-rw-r--r--gcc/tree.h146
-rw-r--r--gcc/ubsan.c327
-rw-r--r--gcc/ubsan.h1
-rw-r--r--gcc/value-prof.c78
-rw-r--r--gcc/value-prof.h4
-rw-r--r--gcc/varasm.c48
-rw-r--r--gcc/vmsdbgout.c2
-rw-r--r--gcc/wide-int-print.cc1
-rw-r--r--gcc/wide-int.cc1
-rw-r--r--gcc/xcoffout.c2
-rw-r--r--gotools/ChangeLog33
-rw-r--r--gotools/Makefile.am104
-rw-r--r--gotools/Makefile.in105
-rw-r--r--include/ChangeLog13
-rw-r--r--include/dwarf2.def12
-rw-r--r--include/dwarf2.h25
-rw-r--r--include/longlong.h36
-rw-r--r--libbacktrace/ChangeLog25
-rw-r--r--libbacktrace/Makefile.am5
-rw-r--r--libbacktrace/Makefile.in4
-rw-r--r--libbacktrace/config.h.in9
-rwxr-xr-xlibbacktrace/configure63
-rw-r--r--libbacktrace/configure.ac30
-rw-r--r--libbacktrace/elf.c2
-rw-r--r--libbacktrace/fileline.c9
-rw-r--r--libbacktrace/filetype.awk3
-rw-r--r--libbacktrace/xcoff.c1485
-rw-r--r--libcc1/ChangeLog24
-rw-r--r--libcc1/libcp1plugin.cc20
-rw-r--r--libcpp/ChangeLog18
-rw-r--r--libcpp/include/line-map.h12
-rw-r--r--libcpp/line-map.c32
-rw-r--r--libdecnumber/ChangeLog8
-rw-r--r--libdecnumber/bid/bid2dpd_dpd2bid.c273
-rw-r--r--libgcc/ChangeLog84
-rw-r--r--libgcc/config.host22
-rw-r--r--libgcc/config/aarch64/linux-unwind.h2
-rw-r--r--libgcc/config/alpha/linux-unwind.h2
-rw-r--r--libgcc/config/arm/lib1funcs.S2
-rw-r--r--libgcc/config/bfin/linux-unwind.h2
-rw-r--r--libgcc/config/i386/dragonfly-unwind.h59
-rw-r--r--libgcc/config/i386/i386-asm.h89
-rw-r--r--libgcc/config/i386/linux-unwind.h4
-rw-r--r--libgcc/config/i386/resms64.S2
-rw-r--r--libgcc/config/i386/resms64f.S2
-rw-r--r--libgcc/config/i386/resms64fx.S2
-rw-r--r--libgcc/config/i386/resms64x.S2
-rw-r--r--libgcc/config/i386/savms64.S2
-rw-r--r--libgcc/config/i386/savms64f.S2
-rw-r--r--libgcc/config/m68k/linux-unwind.h2
-rw-r--r--libgcc/config/nios2/linux-unwind.h2
-rw-r--r--libgcc/config/pa/linux-unwind.h2
-rw-r--r--libgcc/config/riscv/linux-unwind.h2
-rw-r--r--libgcc/config/rs6000/float128-ifunc.c42
-rw-r--r--libgcc/config/rs6000/ibm-ldouble.c3
-rw-r--r--libgcc/config/sh/linux-unwind.h2
-rw-r--r--libgcc/config/t-vxworks716
-rw-r--r--libgcc/config/tilepro/linux-unwind.h2
-rw-r--r--libgcc/config/xtensa/linux-unwind.h2
-rw-r--r--libgcc/configure11
-rw-r--r--libgcc/configure.ac11
-rw-r--r--libgfortran/ChangeLog161
-rw-r--r--libgfortran/generated/eoshift1_16.c23
-rw-r--r--libgfortran/generated/eoshift1_4.c23
-rw-r--r--libgfortran/generated/eoshift1_8.c23
-rw-r--r--libgfortran/generated/eoshift3_16.c24
-rw-r--r--libgfortran/generated/eoshift3_4.c24
-rw-r--r--libgfortran/generated/eoshift3_8.c24
-rw-r--r--libgfortran/generated/iall_i1.c28
-rw-r--r--libgfortran/generated/iall_i16.c28
-rw-r--r--libgfortran/generated/iall_i2.c28
-rw-r--r--libgfortran/generated/iall_i4.c28
-rw-r--r--libgfortran/generated/iall_i8.c28
-rw-r--r--libgfortran/generated/iany_i1.c28
-rw-r--r--libgfortran/generated/iany_i16.c28
-rw-r--r--libgfortran/generated/iany_i2.c28
-rw-r--r--libgfortran/generated/iany_i4.c28
-rw-r--r--libgfortran/generated/iany_i8.c28
-rw-r--r--libgfortran/generated/iparity_i1.c28
-rw-r--r--libgfortran/generated/iparity_i16.c28
-rw-r--r--libgfortran/generated/iparity_i2.c28
-rw-r--r--libgfortran/generated/iparity_i4.c28
-rw-r--r--libgfortran/generated/iparity_i8.c28
-rw-r--r--libgfortran/generated/maxloc1_16_i1.c28
-rw-r--r--libgfortran/generated/maxloc1_16_i16.c28
-rw-r--r--libgfortran/generated/maxloc1_16_i2.c28
-rw-r--r--libgfortran/generated/maxloc1_16_i4.c28
-rw-r--r--libgfortran/generated/maxloc1_16_i8.c28
-rw-r--r--libgfortran/generated/maxloc1_16_r10.c28
-rw-r--r--libgfortran/generated/maxloc1_16_r16.c28
-rw-r--r--libgfortran/generated/maxloc1_16_r4.c28
-rw-r--r--libgfortran/generated/maxloc1_16_r8.c28
-rw-r--r--libgfortran/generated/maxloc1_4_i1.c28
-rw-r--r--libgfortran/generated/maxloc1_4_i16.c28
-rw-r--r--libgfortran/generated/maxloc1_4_i2.c28
-rw-r--r--libgfortran/generated/maxloc1_4_i4.c28
-rw-r--r--libgfortran/generated/maxloc1_4_i8.c28
-rw-r--r--libgfortran/generated/maxloc1_4_r10.c28
-rw-r--r--libgfortran/generated/maxloc1_4_r16.c28
-rw-r--r--libgfortran/generated/maxloc1_4_r4.c28
-rw-r--r--libgfortran/generated/maxloc1_4_r8.c28
-rw-r--r--libgfortran/generated/maxloc1_8_i1.c28
-rw-r--r--libgfortran/generated/maxloc1_8_i16.c28
-rw-r--r--libgfortran/generated/maxloc1_8_i2.c28
-rw-r--r--libgfortran/generated/maxloc1_8_i4.c28
-rw-r--r--libgfortran/generated/maxloc1_8_i8.c28
-rw-r--r--libgfortran/generated/maxloc1_8_r10.c28
-rw-r--r--libgfortran/generated/maxloc1_8_r16.c28
-rw-r--r--libgfortran/generated/maxloc1_8_r4.c28
-rw-r--r--libgfortran/generated/maxloc1_8_r8.c28
-rw-r--r--libgfortran/generated/maxval_i1.c28
-rw-r--r--libgfortran/generated/maxval_i16.c28
-rw-r--r--libgfortran/generated/maxval_i2.c28
-rw-r--r--libgfortran/generated/maxval_i4.c28
-rw-r--r--libgfortran/generated/maxval_i8.c28
-rw-r--r--libgfortran/generated/maxval_r10.c28
-rw-r--r--libgfortran/generated/maxval_r16.c28
-rw-r--r--libgfortran/generated/maxval_r4.c28
-rw-r--r--libgfortran/generated/maxval_r8.c28
-rw-r--r--libgfortran/generated/minloc1_16_i1.c28
-rw-r--r--libgfortran/generated/minloc1_16_i16.c28
-rw-r--r--libgfortran/generated/minloc1_16_i2.c28
-rw-r--r--libgfortran/generated/minloc1_16_i4.c28
-rw-r--r--libgfortran/generated/minloc1_16_i8.c28
-rw-r--r--libgfortran/generated/minloc1_16_r10.c28
-rw-r--r--libgfortran/generated/minloc1_16_r16.c28
-rw-r--r--libgfortran/generated/minloc1_16_r4.c28
-rw-r--r--libgfortran/generated/minloc1_16_r8.c28
-rw-r--r--libgfortran/generated/minloc1_4_i1.c28
-rw-r--r--libgfortran/generated/minloc1_4_i16.c28
-rw-r--r--libgfortran/generated/minloc1_4_i2.c28
-rw-r--r--libgfortran/generated/minloc1_4_i4.c28
-rw-r--r--libgfortran/generated/minloc1_4_i8.c28
-rw-r--r--libgfortran/generated/minloc1_4_r10.c28
-rw-r--r--libgfortran/generated/minloc1_4_r16.c28
-rw-r--r--libgfortran/generated/minloc1_4_r4.c28
-rw-r--r--libgfortran/generated/minloc1_4_r8.c28
-rw-r--r--libgfortran/generated/minloc1_8_i1.c28
-rw-r--r--libgfortran/generated/minloc1_8_i16.c28
-rw-r--r--libgfortran/generated/minloc1_8_i2.c28
-rw-r--r--libgfortran/generated/minloc1_8_i4.c28
-rw-r--r--libgfortran/generated/minloc1_8_i8.c28
-rw-r--r--libgfortran/generated/minloc1_8_r10.c28
-rw-r--r--libgfortran/generated/minloc1_8_r16.c28
-rw-r--r--libgfortran/generated/minloc1_8_r4.c28
-rw-r--r--libgfortran/generated/minloc1_8_r8.c28
-rw-r--r--libgfortran/generated/minval_i1.c28
-rw-r--r--libgfortran/generated/minval_i16.c28
-rw-r--r--libgfortran/generated/minval_i2.c28
-rw-r--r--libgfortran/generated/minval_i4.c28
-rw-r--r--libgfortran/generated/minval_i8.c28
-rw-r--r--libgfortran/generated/minval_r10.c28
-rw-r--r--libgfortran/generated/minval_r16.c28
-rw-r--r--libgfortran/generated/minval_r4.c28
-rw-r--r--libgfortran/generated/minval_r8.c28
-rw-r--r--libgfortran/generated/norm2_r10.c9
-rw-r--r--libgfortran/generated/norm2_r16.c9
-rw-r--r--libgfortran/generated/norm2_r4.c9
-rw-r--r--libgfortran/generated/norm2_r8.c9
-rw-r--r--libgfortran/generated/parity_l1.c9
-rw-r--r--libgfortran/generated/parity_l16.c9
-rw-r--r--libgfortran/generated/parity_l2.c9
-rw-r--r--libgfortran/generated/parity_l4.c9
-rw-r--r--libgfortran/generated/parity_l8.c9
-rw-r--r--libgfortran/generated/product_c10.c28
-rw-r--r--libgfortran/generated/product_c16.c28
-rw-r--r--libgfortran/generated/product_c4.c28
-rw-r--r--libgfortran/generated/product_c8.c28
-rw-r--r--libgfortran/generated/product_i1.c28
-rw-r--r--libgfortran/generated/product_i16.c28
-rw-r--r--libgfortran/generated/product_i2.c28
-rw-r--r--libgfortran/generated/product_i4.c28
-rw-r--r--libgfortran/generated/product_i8.c28
-rw-r--r--libgfortran/generated/product_r10.c28
-rw-r--r--libgfortran/generated/product_r16.c28
-rw-r--r--libgfortran/generated/product_r4.c28
-rw-r--r--libgfortran/generated/product_r8.c28
-rw-r--r--libgfortran/generated/sum_c10.c28
-rw-r--r--libgfortran/generated/sum_c16.c28
-rw-r--r--libgfortran/generated/sum_c4.c28
-rw-r--r--libgfortran/generated/sum_c8.c28
-rw-r--r--libgfortran/generated/sum_i1.c28
-rw-r--r--libgfortran/generated/sum_i16.c28
-rw-r--r--libgfortran/generated/sum_i2.c28
-rw-r--r--libgfortran/generated/sum_i4.c28
-rw-r--r--libgfortran/generated/sum_i8.c28
-rw-r--r--libgfortran/generated/sum_r10.c28
-rw-r--r--libgfortran/generated/sum_r16.c28
-rw-r--r--libgfortran/generated/sum_r4.c28
-rw-r--r--libgfortran/generated/sum_r8.c28
-rw-r--r--libgfortran/intrinsics/eoshift0.c144
-rw-r--r--libgfortran/intrinsics/eoshift2.c23
-rw-r--r--libgfortran/io/unit.c6
-rw-r--r--libgfortran/io/unix.c3
-rw-r--r--libgfortran/m4/eoshift1.m423
-rw-r--r--libgfortran/m4/eoshift3.m424
-rw-r--r--libgfortran/m4/ifunction.m426
-rw-r--r--libgo/Makefile.am11
-rw-r--r--libgo/Makefile.in52
-rwxr-xr-xlibgo/configure2
-rw-r--r--libgo/go/cmd/go/build.go44
-rw-r--r--libgo/go/runtime/malloc.go7
-rw-r--r--libgo/go/runtime/mem_gccgo.go5
-rw-r--r--libgo/go/runtime/stubs.go4
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/callback.go4
-rw-r--r--libgo/go/syscall/libcall_linux.go4
-rw-r--r--libgo/go/syscall/syscall_linux_alpha.go32
-rw-r--r--libgo/go/syscall/syscall_linux_s390.go22
-rw-r--r--libgo/go/syscall/syscall_linux_s390x.go37
-rwxr-xr-xlibgo/merge.sh22
-rw-r--r--libgo/misc/cgo/errors/err1.go18
-rw-r--r--libgo/misc/cgo/errors/err2.go13
-rw-r--r--libgo/misc/cgo/errors/err3.go18
-rw-r--r--libgo/misc/cgo/errors/issue11097a.go15
-rw-r--r--libgo/misc/cgo/errors/issue11097b.go15
-rw-r--r--libgo/misc/cgo/errors/issue13129.go14
-rw-r--r--libgo/misc/cgo/errors/issue13423.go12
-rw-r--r--libgo/misc/cgo/errors/issue13635.go24
-rw-r--r--libgo/misc/cgo/errors/issue13830.go26
-rw-r--r--libgo/misc/cgo/errors/issue14669.go23
-rw-r--r--libgo/misc/cgo/errors/issue16116.go12
-rw-r--r--libgo/misc/cgo/errors/issue16591.go17
-rw-r--r--libgo/misc/cgo/errors/issue7757.go14
-rw-r--r--libgo/misc/cgo/errors/issue8442.go17
-rw-r--r--libgo/misc/cgo/errors/malloc.go34
-rw-r--r--libgo/misc/cgo/errors/ptr.go576
-rw-r--r--libgo/misc/cgo/errors/test.bash73
-rw-r--r--libgo/misc/cgo/fortran/answer.f909
-rw-r--r--libgo/misc/cgo/fortran/fortran.go12
-rw-r--r--libgo/misc/cgo/fortran/fortran_test.go13
-rw-r--r--libgo/misc/cgo/fortran/helloworld/helloworld.f903
-rw-r--r--libgo/misc/cgo/fortran/test.bash39
-rw-r--r--libgo/misc/cgo/gmp/fib.go45
-rw-r--r--libgo/misc/cgo/gmp/gmp.go380
-rw-r--r--libgo/misc/cgo/gmp/pi.go73
-rw-r--r--libgo/misc/cgo/life/c-life.c56
-rw-r--r--libgo/misc/cgo/life/life.go41
-rw-r--r--libgo/misc/cgo/life/life.h7
-rw-r--r--libgo/misc/cgo/life/main.go48
-rw-r--r--libgo/misc/cgo/life/main.out16
-rw-r--r--libgo/misc/cgo/nocgo/nocgo.go22
-rw-r--r--libgo/misc/cgo/nocgo/nocgo_test.go14
-rw-r--r--libgo/misc/cgo/stdio/chain.go48
-rw-r--r--libgo/misc/cgo/stdio/chain.out55
-rw-r--r--libgo/misc/cgo/stdio/fib.go52
-rw-r--r--libgo/misc/cgo/stdio/fib.out91
-rw-r--r--libgo/misc/cgo/stdio/file.go44
-rw-r--r--libgo/misc/cgo/stdio/hello.go15
-rw-r--r--libgo/misc/cgo/stdio/hello.out1
-rw-r--r--libgo/misc/cgo/stdio/run.out150
-rw-r--r--libgo/misc/cgo/stdio/stdio.go22
-rw-r--r--libgo/misc/cgo/test/align.go76
-rw-r--r--libgo/misc/cgo/test/api.go30
-rw-r--r--libgo/misc/cgo/test/backdoor.go11
-rw-r--r--libgo/misc/cgo/test/basic.go167
-rw-r--r--libgo/misc/cgo/test/buildid_linux.go77
-rw-r--r--libgo/misc/cgo/test/callback.go1782
-rw-r--r--libgo/misc/cgo/test/callback_c.c90
-rw-r--r--libgo/misc/cgo/test/callback_c_gc.c25
-rw-r--r--libgo/misc/cgo/test/callback_c_gccgo.c21
-rw-r--r--libgo/misc/cgo/test/cflags.go32
-rw-r--r--libgo/misc/cgo/test/cgo_linux_test.go12
-rw-r--r--libgo/misc/cgo/test/cgo_stubs_android_test.go13
-rw-r--r--libgo/misc/cgo/test/cgo_test.go80
-rw-r--r--libgo/misc/cgo/test/cgo_thread_lock.go53
-rw-r--r--libgo/misc/cgo/test/cgo_unix_test.go13
-rw-r--r--libgo/misc/cgo/test/checkconst.go33
-rw-r--r--libgo/misc/cgo/test/complex.go24
-rw-r--r--libgo/misc/cgo/test/cthread.go44
-rw-r--r--libgo/misc/cgo/test/cthread_unix.c34
-rw-r--r--libgo/misc/cgo/test/cthread_windows.c37
-rw-r--r--libgo/misc/cgo/test/duplicate_symbol.go21
-rw-r--r--libgo/misc/cgo/test/env.go41
-rw-r--r--libgo/misc/cgo/test/exports.go18
-rw-r--r--libgo/misc/cgo/test/fpvar.go50
-rw-r--r--libgo/misc/cgo/test/gcc68255.go17
-rw-r--r--libgo/misc/cgo/test/gcc68255/a.go17
-rw-r--r--libgo/misc/cgo/test/gcc68255/c.c8
-rw-r--r--libgo/misc/cgo/test/gcc68255/c.h5
-rw-r--r--libgo/misc/cgo/test/helpers.go35
-rw-r--r--libgo/misc/cgo/test/issue10303.go76
-rw-r--r--libgo/misc/cgo/test/issue11925.go37
-rw-r--r--libgo/misc/cgo/test/issue12030.go35
-rw-r--r--libgo/misc/cgo/test/issue1222.go29
-rw-r--r--libgo/misc/cgo/test/issue1328.go30
-rw-r--r--libgo/misc/cgo/test/issue13402.go10
-rw-r--r--libgo/misc/cgo/test/issue13930.go13
-rw-r--r--libgo/misc/cgo/test/issue14838.go37
-rw-r--r--libgo/misc/cgo/test/issue1560.go50
-rw-r--r--libgo/misc/cgo/test/issue1635.go38
-rw-r--r--libgo/misc/cgo/test/issue17065.go29
-rw-r--r--libgo/misc/cgo/test/issue17537.go58
-rw-r--r--libgo/misc/cgo/test/issue18126.go26
-rw-r--r--libgo/misc/cgo/test/issue18146.go128
-rw-r--r--libgo/misc/cgo/test/issue2462.go102
-rw-r--r--libgo/misc/cgo/test/issue3250.go95
-rw-r--r--libgo/misc/cgo/test/issue3250w.go11
-rw-r--r--libgo/misc/cgo/test/issue3261.go49
-rw-r--r--libgo/misc/cgo/test/issue3729.go47
-rw-r--r--libgo/misc/cgo/test/issue3729w.go16
-rw-r--r--libgo/misc/cgo/test/issue3741.go22
-rw-r--r--libgo/misc/cgo/test/issue3775.go39
-rw-r--r--libgo/misc/cgo/test/issue3945.go22
-rw-r--r--libgo/misc/cgo/test/issue4029.c10
-rw-r--r--libgo/misc/cgo/test/issue4029.go68
-rw-r--r--libgo/misc/cgo/test/issue4029w.go12
-rw-r--r--libgo/misc/cgo/test/issue4054a.go23
-rw-r--r--libgo/misc/cgo/test/issue4054b.go23
-rw-r--r--libgo/misc/cgo/test/issue4273.c10
-rw-r--r--libgo/misc/cgo/test/issue4273b.c11
-rw-r--r--libgo/misc/cgo/test/issue4339.c18
-rw-r--r--libgo/misc/cgo/test/issue4339.go16
-rw-r--r--libgo/misc/cgo/test/issue4339.h9
-rw-r--r--libgo/misc/cgo/test/issue4417.go42
-rw-r--r--libgo/misc/cgo/test/issue4857.go15
-rw-r--r--libgo/misc/cgo/test/issue5227.go38
-rw-r--r--libgo/misc/cgo/test/issue5242.go31
-rw-r--r--libgo/misc/cgo/test/issue5337.go31
-rw-r--r--libgo/misc/cgo/test/issue5337w.go11
-rw-r--r--libgo/misc/cgo/test/issue5548.go27
-rw-r--r--libgo/misc/cgo/test/issue5548_c.c24
-rw-r--r--libgo/misc/cgo/test/issue5603.go32
-rw-r--r--libgo/misc/cgo/test/issue5740.go15
-rw-r--r--libgo/misc/cgo/test/issue5740a.c9
-rw-r--r--libgo/misc/cgo/test/issue5740b.c9
-rw-r--r--libgo/misc/cgo/test/issue5986.go33
-rw-r--r--libgo/misc/cgo/test/issue6128.go20
-rw-r--r--libgo/misc/cgo/test/issue6390.go23
-rw-r--r--libgo/misc/cgo/test/issue6472.go22
-rw-r--r--libgo/misc/cgo/test/issue6506.go36
-rw-r--r--libgo/misc/cgo/test/issue6612.go93
-rw-r--r--libgo/misc/cgo/test/issue6833.go27
-rw-r--r--libgo/misc/cgo/test/issue6833_c.c10
-rw-r--r--libgo/misc/cgo/test/issue6997_linux.c28
-rw-r--r--libgo/misc/cgo/test/issue6997_linux.go42
-rw-r--r--libgo/misc/cgo/test/issue7234_test.go21
-rw-r--r--libgo/misc/cgo/test/issue7560.go44
-rw-r--r--libgo/misc/cgo/test/issue7665.go25
-rw-r--r--libgo/misc/cgo/test/issue7786.go51
-rw-r--r--libgo/misc/cgo/test/issue7978.go138
-rw-r--r--libgo/misc/cgo/test/issue8092.go36
-rw-r--r--libgo/misc/cgo/test/issue8148.go31
-rw-r--r--libgo/misc/cgo/test/issue8331.h7
-rw-r--r--libgo/misc/cgo/test/issue8331a.go15
-rw-r--r--libgo/misc/cgo/test/issue8331b.go13
-rw-r--r--libgo/misc/cgo/test/issue8428.go55
-rw-r--r--libgo/misc/cgo/test/issue8441.go27
-rw-r--r--libgo/misc/cgo/test/issue8517.go13
-rw-r--r--libgo/misc/cgo/test/issue8517_windows.c24
-rw-r--r--libgo/misc/cgo/test/issue8517_windows.go45
-rw-r--r--libgo/misc/cgo/test/issue8694.go40
-rw-r--r--libgo/misc/cgo/test/issue8756.go17
-rw-r--r--libgo/misc/cgo/test/issue8756/issue8756.go11
-rw-r--r--libgo/misc/cgo/test/issue8811.c8
-rw-r--r--libgo/misc/cgo/test/issue8811.go22
-rw-r--r--libgo/misc/cgo/test/issue8828.go16
-rw-r--r--libgo/misc/cgo/test/issue8828/issue8828.c7
-rw-r--r--libgo/misc/cgo/test/issue8828/trivial.go8
-rw-r--r--libgo/misc/cgo/test/issue8945.go16
-rw-r--r--libgo/misc/cgo/test/issue9026.go9
-rw-r--r--libgo/misc/cgo/test/issue9026/issue9026.go36
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_386.s27
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_amd64x.s27
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_arm.s39
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_arm64.s39
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_mips64x.s33
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_mipsx.s31
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_ppc64x.s32
-rw-r--r--libgo/misc/cgo/test/issue9400/asm_s390x.s26
-rw-r--r--libgo/misc/cgo/test/issue9400/gccgo.go24
-rw-r--r--libgo/misc/cgo/test/issue9400/stubs.go9
-rw-r--r--libgo/misc/cgo/test/issue9400_linux.go58
-rw-r--r--libgo/misc/cgo/test/issue9510.go24
-rw-r--r--libgo/misc/cgo/test/issue9510a/a.go15
-rw-r--r--libgo/misc/cgo/test/issue9510b/b.go15
-rw-r--r--libgo/misc/cgo/test/issue9557.go36
-rw-r--r--libgo/misc/cgo/test/setgid_linux.go49
-rw-r--r--libgo/misc/cgo/test/sigaltstack.go73
-rw-r--r--libgo/misc/cgo/test/sigprocmask.c38
-rw-r--r--libgo/misc/cgo/test/sigprocmask.go40
-rw-r--r--libgo/misc/cgo/testasan/main.go49
-rw-r--r--libgo/misc/cgo/testcarchive/carchive_test.go587
-rw-r--r--libgo/misc/cgo/testcarchive/main.c48
-rw-r--r--libgo/misc/cgo/testcarchive/main2.c199
-rw-r--r--libgo/misc/cgo/testcarchive/main3.c155
-rw-r--r--libgo/misc/cgo/testcarchive/main4.c197
-rw-r--r--libgo/misc/cgo/testcarchive/main5.c78
-rw-r--r--libgo/misc/cgo/testcarchive/main_unix.c59
-rw-r--r--libgo/misc/cgo/testcarchive/main_windows.c17
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo/libgo.go53
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go50
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go44
-rw-r--r--libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go52
-rw-r--r--libgo/misc/cgo/testcarchive/src/p/p.go10
-rw-r--r--libgo/misc/cgo/testcshared/main0.c36
-rw-r--r--libgo/misc/cgo/testcshared/main1.c69
-rw-r--r--libgo/misc/cgo/testcshared/main2.c56
-rw-r--r--libgo/misc/cgo/testcshared/main3.c29
-rw-r--r--libgo/misc/cgo/testcshared/main4.c215
-rw-r--r--libgo/misc/cgo/testcshared/main5.c199
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo/libgo.go46
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo2/dup2.go13
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo2/dup3.go13
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo2/libgo2.go52
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo4/libgo4.go45
-rw-r--r--libgo/misc/cgo/testcshared/src/libgo5/libgo5.go44
-rw-r--r--libgo/misc/cgo/testcshared/src/p/p.go10
-rw-r--r--libgo/misc/cgo/testcshared/test.bash193
-rw-r--r--libgo/misc/cgo/testgodefs/anonunion.go26
-rw-r--r--libgo/misc/cgo/testgodefs/issue8478.go20
-rw-r--r--libgo/misc/cgo/testgodefs/main.go15
-rw-r--r--libgo/misc/cgo/testgodefs/test.bash22
-rw-r--r--libgo/misc/cgo/testplugin/altpath/src/common/common.go11
-rw-r--r--libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go17
-rw-r--r--libgo/misc/cgo/testplugin/src/common/common.go11
-rw-r--r--libgo/misc/cgo/testplugin/src/host/host.go148
-rw-r--r--libgo/misc/cgo/testplugin/src/iface/main.go46
-rw-r--r--libgo/misc/cgo/testplugin/src/iface_a/a.go17
-rw-r--r--libgo/misc/cgo/testplugin/src/iface_b/b.go17
-rw-r--r--libgo/misc/cgo/testplugin/src/iface_i/i.go17
-rw-r--r--libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go13
-rw-r--r--libgo/misc/cgo/testplugin/src/issue18676/main.go31
-rw-r--r--libgo/misc/cgo/testplugin/src/issue18676/plugin.go11
-rw-r--r--libgo/misc/cgo/testplugin/src/plugin1/plugin1.go38
-rw-r--r--libgo/misc/cgo/testplugin/src/plugin2/plugin2.go27
-rw-r--r--libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go23
-rw-r--r--libgo/misc/cgo/testplugin/test.bash46
-rw-r--r--libgo/misc/cgo/testplugin/unnamed1.go12
-rw-r--r--libgo/misc/cgo/testplugin/unnamed2.go12
-rw-r--r--libgo/misc/cgo/testsanitizers/msan.go35
-rw-r--r--libgo/misc/cgo/testsanitizers/msan2.go35
-rw-r--r--libgo/misc/cgo/testsanitizers/msan3.go33
-rw-r--r--libgo/misc/cgo/testsanitizers/msan4.go50
-rw-r--r--libgo/misc/cgo/testsanitizers/msan5.go57
-rw-r--r--libgo/misc/cgo/testsanitizers/msan_fail.go36
-rw-r--r--libgo/misc/cgo/testsanitizers/msan_shared.go12
-rw-r--r--libgo/misc/cgo/testsanitizers/test.bash204
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan.go44
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan2.go55
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan3.go40
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan4.go34
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan5.go51
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan6.go49
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan7.go40
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan8.go60
-rw-r--r--libgo/misc/cgo/testsanitizers/tsan9.go67
-rw-r--r--libgo/misc/cgo/testshared/shared_test.go828
-rw-r--r--libgo/misc/cgo/testshared/src/dep2/dep2.go15
-rw-r--r--libgo/misc/cgo/testshared/src/dep3/dep3.go22
-rw-r--r--libgo/misc/cgo/testshared/src/depBase/asm.s10
-rw-r--r--libgo/misc/cgo/testshared/src/depBase/dep.go33
-rw-r--r--libgo/misc/cgo/testshared/src/depBase/gccgo.go5
-rw-r--r--libgo/misc/cgo/testshared/src/depBase/stubs.go5
-rw-r--r--libgo/misc/cgo/testshared/src/exe/exe.go44
-rw-r--r--libgo/misc/cgo/testshared/src/exe2/exe2.go8
-rw-r--r--libgo/misc/cgo/testshared/src/exe3/exe3.go7
-rw-r--r--libgo/misc/cgo/testshared/src/execgo/exe.go8
-rw-r--r--libgo/misc/cgo/testshared/src/explicit/explicit.go9
-rw-r--r--libgo/misc/cgo/testshared/src/iface/main.go17
-rw-r--r--libgo/misc/cgo/testshared/src/iface_a/a.go17
-rw-r--r--libgo/misc/cgo/testshared/src/iface_b/b.go17
-rw-r--r--libgo/misc/cgo/testshared/src/iface_i/i.go17
-rw-r--r--libgo/misc/cgo/testshared/src/implicit/implicit.go5
-rw-r--r--libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go10
-rw-r--r--libgo/misc/cgo/testshared/src/trivial/trivial.go4
-rw-r--r--libgo/misc/cgo/testsigfwd/main.go113
-rw-r--r--libgo/misc/cgo/testso/cgoso.c14
-rw-r--r--libgo/misc/cgo/testso/cgoso.go31
-rw-r--r--libgo/misc/cgo/testso/cgoso_c.c30
-rw-r--r--libgo/misc/cgo/testso/cgoso_unix.go20
-rw-r--r--libgo/misc/cgo/testso/main.go13
-rw-r--r--libgo/misc/cgo/testsovar/cgoso.go43
-rw-r--r--libgo/misc/cgo/testsovar/cgoso_c.c7
-rw-r--r--libgo/misc/cgo/testsovar/cgoso_c.h17
-rw-r--r--libgo/misc/cgo/testsovar/main.go13
-rw-r--r--libgo/misc/cgo/testtls/tls.go30
-rw-r--r--libgo/misc/cgo/testtls/tls_test.go13
-rw-r--r--libgo/misc/cgo/testtls/tls_unix.c19
-rwxr-xr-xlibgo/mksysinfo.sh13
-rw-r--r--libgo/runtime/go-caller.c14
-rw-r--r--libgo/runtime/go-libmain.c3
-rw-r--r--libgo/runtime/go-main.c3
-rw-r--r--libgo/runtime/go-signal.c10
-rw-r--r--libgo/runtime/proc.c1
-rw-r--r--libgo/runtime/runtime.h2
-rw-r--r--libgo/runtime/runtime_c.c6
-rw-r--r--libgo/runtime/thread-linux.c20
-rw-r--r--libgo/runtime/thread-sema.c20
-rw-r--r--libgo/sysinfo.c9
-rw-r--r--libgomp/ChangeLog31
-rw-r--r--libgomp/env.c44
-rw-r--r--libgomp/plugin/plugin-hsa.c27
-rw-r--r--libgomp/plugin/plugin-nvptx.c12
-rw-r--r--libgomp/secure_getenv.h61
-rw-r--r--libgomp/testsuite/libgomp.c++/pr45784.C5
-rw-r--r--libgomp/testsuite/libgomp.c/pr45784.c41
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/gomp-debug-env.c13
-rw-r--r--libgomp/testsuite/libgomp.oacc-c/vec.c48
-rw-r--r--libiberty/ChangeLog4
-rw-r--r--libiberty/dwarfnames.c11
-rw-r--r--libquadmath/ChangeLog54
-rw-r--r--libquadmath/math/acosq.c2
-rw-r--r--libquadmath/math/asinhq.c1
-rw-r--r--libquadmath/math/asinq.c6
-rw-r--r--libquadmath/math/atanhq.c6
-rw-r--r--libquadmath/math/atanq.c5
-rw-r--r--libquadmath/math/ceilq.c33
-rw-r--r--libquadmath/math/coshq.c4
-rw-r--r--libquadmath/math/erfq.c33
-rw-r--r--libquadmath/math/expm1q.c33
-rw-r--r--libquadmath/math/expq.c14
-rw-r--r--libquadmath/math/finiteq.c2
-rw-r--r--libquadmath/math/floorq.c35
-rw-r--r--libquadmath/math/fmaq.c55
-rw-r--r--libquadmath/math/frexpq.c2
-rw-r--r--libquadmath/math/hypotq.c15
-rw-r--r--libquadmath/math/j0q.c87
-rw-r--r--libquadmath/math/j1q.c103
-rw-r--r--libquadmath/math/llrintq.c43
-rw-r--r--libquadmath/math/llroundq.c29
-rw-r--r--libquadmath/math/log10q.c5
-rw-r--r--libquadmath/math/log1pq.c14
-rw-r--r--libquadmath/math/log2q.c5
-rw-r--r--libquadmath/math/logq.c7
-rw-r--r--libquadmath/math/lrintq.c84
-rw-r--r--libquadmath/math/lroundq.c58
-rw-r--r--libquadmath/math/nearbyintq.c4
-rw-r--r--libquadmath/math/nextafterq.c11
-rw-r--r--libquadmath/math/powq.c32
-rw-r--r--libquadmath/math/rem_pio2q.c330
-rw-r--r--libquadmath/math/remquoq.c11
-rw-r--r--libquadmath/math/rintq.c2
-rw-r--r--libquadmath/math/roundq.c40
-rw-r--r--libquadmath/math/scalblnq.c2
-rw-r--r--libquadmath/math/scalbnq.c2
-rw-r--r--libquadmath/math/sincos_table.c4
-rw-r--r--libquadmath/math/sincosq.c5
-rw-r--r--libquadmath/math/sincosq_kernel.c17
-rw-r--r--libquadmath/math/sinhq.c7
-rw-r--r--libquadmath/math/sinq_kernel.c5
-rw-r--r--libquadmath/math/tanhq.c5
-rw-r--r--libquadmath/math/tanq.c13
-rw-r--r--libquadmath/math/truncq.c4
-rw-r--r--libquadmath/quadmath-imp.h41
-rw-r--r--libsanitizer/ChangeLog15
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.cc3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.h4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc2
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cc2
-rw-r--r--libsanitizer/ubsan/ubsan_checks.inc1
-rw-r--r--libsanitizer/ubsan/ubsan_handlers.cc31
-rw-r--r--libsanitizer/ubsan/ubsan_handlers.h7
-rw-r--r--libstdc++-v3/ChangeLog356
-rw-r--r--libstdc++-v3/config/allocator/malloc_allocator_base.h4
-rw-r--r--libstdc++-v3/config/allocator/new_allocator_base.h4
-rw-r--r--libstdc++-v3/config/cpu/aarch64/opt/bits/opt_random.h47
-rw-r--r--libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h180
-rw-r--r--libstdc++-v3/doc/html/faq.html144
-rw-r--r--libstdc++-v3/doc/html/manual/bugs.html282
-rw-r--r--libstdc++-v3/doc/html/manual/test.html4
-rw-r--r--libstdc++-v3/doc/xml/faq.xml146
-rw-r--r--libstdc++-v3/doc/xml/manual/intro.xml282
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml18
-rw-r--r--libstdc++-v3/include/bits/algorithmfwd.h3
-rw-r--r--libstdc++-v3/include/bits/basic_ios.h4
-rw-r--r--libstdc++-v3/include/bits/basic_string.h11
-rw-r--r--libstdc++-v3/include/bits/c++config78
-rw-r--r--libstdc++-v3/include/bits/deque.tcc2
-rw-r--r--libstdc++-v3/include/bits/forward_list.h2
-rw-r--r--libstdc++-v3/include/bits/forward_list.tcc2
-rw-r--r--libstdc++-v3/include/bits/fstream.tcc110
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h6
-rw-r--r--libstdc++-v3/include/bits/ios_base.h4
-rw-r--r--libstdc++-v3/include/bits/istream.tcc50
-rw-r--r--libstdc++-v3/include/bits/list.tcc2
-rw-r--r--libstdc++-v3/include/bits/locale_facets.h4
-rw-r--r--libstdc++-v3/include/bits/locale_facets_nonio.h2
-rw-r--r--libstdc++-v3/include/bits/move.h9
-rw-r--r--libstdc++-v3/include/bits/quoted_string.h8
-rw-r--r--libstdc++-v3/include/bits/random.h9
-rw-r--r--libstdc++-v3/include/bits/random.tcc7
-rw-r--r--libstdc++-v3/include/bits/regex.h142
-rw-r--r--libstdc++-v3/include/bits/regex.tcc9
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.h7
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.tcc6
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.h5
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.tcc6
-rw-r--r--libstdc++-v3/include/bits/regex_constants.h9
-rw-r--r--libstdc++-v3/include/bits/regex_error.h7
-rw-r--r--libstdc++-v3/include/bits/regex_executor.h6
-rw-r--r--libstdc++-v3/include/bits/regex_executor.tcc6
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.h6
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.tcc6
-rw-r--r--libstdc++-v3/include/bits/specfun.h2
-rw-r--r--libstdc++-v3/include/bits/sstream.tcc21
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h8
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h3
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h4
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h2
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h13
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_funcs.h4
-rw-r--r--libstdc++-v3/include/bits/stl_list.h163
-rw-r--r--libstdc++-v3/include/bits/stl_map.h4
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h4
-rw-r--r--libstdc++-v3/include/bits/stl_multiset.h4
-rw-r--r--libstdc++-v3/include/bits/stl_relops.h7
-rw-r--r--libstdc++-v3/include/bits/stl_set.h4
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h149
-rw-r--r--libstdc++-v3/include/bits/uniform_int_dist.h5
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h4
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h4
-rw-r--r--libstdc++-v3/include/bits/uses_allocator.h5
-rw-r--r--libstdc++-v3/include/bits/vector.tcc66
-rw-r--r--libstdc++-v3/include/c_global/cmath30
-rw-r--r--libstdc++-v3/include/c_std/cmath13
-rw-r--r--libstdc++-v3/include/decimal/decimal8
-rw-r--r--libstdc++-v3/include/decimal/decimal.h7
-rw-r--r--libstdc++-v3/include/experimental/algorithm8
-rw-r--r--libstdc++-v3/include/experimental/any7
-rw-r--r--libstdc++-v3/include/experimental/array6
-rw-r--r--libstdc++-v3/include/experimental/bits/erase_if.h6
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_dir.h7
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_fwd.h10
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_ops.h7
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_path.h6
-rw-r--r--libstdc++-v3/include/experimental/bits/lfts_config.h23
-rw-r--r--libstdc++-v3/include/experimental/bits/shared_ptr.h8
-rw-r--r--libstdc++-v3/include/experimental/bits/string_view.tcc8
-rw-r--r--libstdc++-v3/include/experimental/chrono5
-rw-r--r--libstdc++-v3/include/experimental/deque19
-rw-r--r--libstdc++-v3/include/experimental/filesystem8
-rw-r--r--libstdc++-v3/include/experimental/forward_list20
-rw-r--r--libstdc++-v3/include/experimental/functional12
-rw-r--r--libstdc++-v3/include/experimental/iterator8
-rw-r--r--libstdc++-v3/include/experimental/list12
-rw-r--r--libstdc++-v3/include/experimental/map25
-rw-r--r--libstdc++-v3/include/experimental/memory8
-rw-r--r--libstdc++-v3/include/experimental/memory_resource18
-rw-r--r--libstdc++-v3/include/experimental/numeric8
-rw-r--r--libstdc++-v3/include/experimental/optional11
-rw-r--r--libstdc++-v3/include/experimental/propagate_const7
-rw-r--r--libstdc++-v3/include/experimental/random8
-rw-r--r--libstdc++-v3/include/experimental/ratio8
-rw-r--r--libstdc++-v3/include/experimental/regex5
-rw-r--r--libstdc++-v3/include/experimental/set26
-rw-r--r--libstdc++-v3/include/experimental/source_location8
-rw-r--r--libstdc++-v3/include/experimental/string39
-rw-r--r--libstdc++-v3/include/experimental/string_view21
-rw-r--r--libstdc++-v3/include/experimental/system_error8
-rw-r--r--libstdc++-v3/include/experimental/tuple8
-rw-r--r--libstdc++-v3/include/experimental/type_traits11
-rw-r--r--libstdc++-v3/include/experimental/unordered_map28
-rw-r--r--libstdc++-v3/include/experimental/unordered_set28
-rw-r--r--libstdc++-v3/include/experimental/utility8
-rw-r--r--libstdc++-v3/include/experimental/vector20
-rw-r--r--libstdc++-v3/include/ext/bitmap_allocator.h8
-rw-r--r--libstdc++-v3/include/ext/codecvt_specializations.h4
-rw-r--r--libstdc++-v3/include/ext/random7
-rw-r--r--libstdc++-v3/include/ext/rope22
-rw-r--r--libstdc++-v3/include/ext/ropeimpl.h6
-rw-r--r--libstdc++-v3/include/ext/typelist.h21
-rw-r--r--libstdc++-v3/include/std/chrono25
-rw-r--r--libstdc++-v3/include/std/complex6
-rw-r--r--libstdc++-v3/include/std/functional6
-rw-r--r--libstdc++-v3/include/std/istream12
-rw-r--r--libstdc++-v3/include/std/mutex6
-rw-r--r--libstdc++-v3/include/std/numeric10
-rw-r--r--libstdc++-v3/include/std/sstream30
-rw-r--r--libstdc++-v3/include/std/streambuf7
-rw-r--r--libstdc++-v3/include/std/string_view11
-rw-r--r--libstdc++-v3/include/std/thread7
-rw-r--r--libstdc++-v3/include/std/variant340
-rw-r--r--libstdc++-v3/include/tr1/array6
-rw-r--r--libstdc++-v3/include/tr1/bessel_function.tcc8
-rw-r--r--libstdc++-v3/include/tr1/beta_function.tcc8
-rw-r--r--libstdc++-v3/include/tr1/cmath47
-rw-r--r--libstdc++-v3/include/tr1/complex6
-rw-r--r--libstdc++-v3/include/tr1/ell_integral.tcc8
-rw-r--r--libstdc++-v3/include/tr1/exp_integral.tcc8
-rw-r--r--libstdc++-v3/include/tr1/functional15
-rw-r--r--libstdc++-v3/include/tr1/functional_hash.h6
-rw-r--r--libstdc++-v3/include/tr1/gamma.tcc8
-rw-r--r--libstdc++-v3/include/tr1/hashtable.h6
-rw-r--r--libstdc++-v3/include/tr1/hashtable_policy.h7
-rw-r--r--libstdc++-v3/include/tr1/hypergeometric.tcc8
-rw-r--r--libstdc++-v3/include/tr1/legendre_function.tcc8
-rw-r--r--libstdc++-v3/include/tr1/modified_bessel_func.tcc8
-rw-r--r--libstdc++-v3/include/tr1/poly_hermite.tcc8
-rw-r--r--libstdc++-v3/include/tr1/poly_laguerre.tcc8
-rw-r--r--libstdc++-v3/include/tr1/random.h13
-rw-r--r--libstdc++-v3/include/tr1/random.tcc9
-rw-r--r--libstdc++-v3/include/tr1/regex9
-rw-r--r--libstdc++-v3/include/tr1/riemann_zeta.tcc8
-rw-r--r--libstdc++-v3/include/tr1/shared_ptr.h6
-rw-r--r--libstdc++-v3/include/tr1/special_function_util.h8
-rw-r--r--libstdc++-v3/include/tr1/tuple6
-rw-r--r--libstdc++-v3/include/tr1/type_traits6
-rw-r--r--libstdc++-v3/include/tr1/unordered_map.h6
-rw-r--r--libstdc++-v3/include/tr1/unordered_set.h6
-rw-r--r--libstdc++-v3/include/tr1/utility6
-rw-r--r--libstdc++-v3/include/tr2/bool_set6
-rw-r--r--libstdc++-v3/include/tr2/bool_set.tcc6
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset6
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset.tcc6
-rw-r--r--libstdc++-v3/include/tr2/ratio6
-rw-r--r--libstdc++-v3/include/tr2/type_traits6
-rw-r--r--libstdc++-v3/libsupc++/new2
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py12
-rw-r--r--libstdc++-v3/src/c++11/chrono.cc8
-rw-r--r--libstdc++-v3/src/c++11/compatibility-c++0x.cc7
-rw-r--r--libstdc++-v3/src/c++11/compatibility-chrono.cc8
-rw-r--r--libstdc++-v3/src/c++11/cxx11-shim_facets.cc6
-rw-r--r--libstdc++-v3/src/c++11/hashtable_c++0x.cc6
-rw-r--r--libstdc++-v3/src/c++11/placeholders.cc6
-rw-r--r--libstdc++-v3/src/c++11/thread.cc7
-rw-r--r--libstdc++-v3/src/c++98/bitmap_allocator.cc6
-rw-r--r--libstdc++-v3/src/c++98/hashtable_tr1.cc4
-rw-r--r--libstdc++-v3/src/c++98/list.cc8
-rw-r--r--libstdc++-v3/src/shared/hashtable-aux.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/literals/range.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/forward/c_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/forward/f_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/compile.cc103
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/deduction.cc39
-rw-r--r--libstdc++-v3/testsuite/22_locale/locale/cons/5.cc55
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc71
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/sample/81221.cc22
-rw-r--r--libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc8
-rw-r--r--libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc8
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc46
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc39
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc41
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/81381.cc42
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_stringstream/assign/81338.cc40
-rw-r--r--libstdc++-v3/testsuite/27_io/types/1.cc8
-rw-r--r--libstdc++-v3/testsuite/27_io/types/4.cc29
-rw-r--r--libstdc++-v3/testsuite/30_threads/scoped_lock/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc25
-rw-r--r--libstdc++-v3/testsuite/30_threads/scoped_lock/requirements/typedefs.cc6
-rw-r--r--libstdc++-v3/testsuite/abi/pr42230.cc2
-rw-r--r--libstdc++-v3/testsuite/performance/23_containers/insert/81476.cc86
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc15
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.h2
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_hooks.cc8
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_iterators.h12
-rw-r--r--lto-plugin/ChangeLog7
-rw-r--r--lto-plugin/lto-plugin.c13
1929 files changed, 68098 insertions, 20895 deletions
diff --git a/ChangeLog b/ChangeLog
index 86fe51acbf1..204733e823d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2017-07-28 Tony Reix <tony.reix@atos.net>
+
+ * configure.ac (target-libffi): Don't disable for AIX.
+ (go): Don't add to unsupported_languages on AIX.
+ (target-libgo): Don't disable for AIX.
+ * configure: Regenerate.
+
+2017-07-19 Yury Gribov <tetra2005@gmail.com>
+
+ * MAINTAINERS: Add myself.
+
+2017-07-18 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * MAINTAINERS: Update my email address.
+
+2017-07-04 Richard Earnshaw <rearnsha@arm.com>
+
+ * contrib/gcc_update (files_and_dependencies): Remove stamp rules for
+ arm-specific auto-generated header files.
+
+2017-07-03 Nathan Sidwell <nathan@acm.org>
+
+ * configure.ac: Set srcdir when sourcing config-lang.in fragments.
+ * configure: Rebuilt.
+
+2017-07-03 Bernd Schmidt <bschmidt@redhat.com>
+
+ * MAINTAINERS: Readd myself for c6x.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR bootstrap/81217
+ * Makefile.def: Remove superfluous bootstrap_target from
+ bootstrap_stage.
+ * Makefile.in: Re-generate the file.
+
+2017-06-26 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * MAINTAINERS: Add myself to Write After Approval
+
2017-06-21 Andrew Jenner <andrew@codesourcery.com>
* MAINTAINERS: Add myself as maintainer for PowerPC SPE port.
diff --git a/MAINTAINERS b/MAINTAINERS
index c76c1818d08..1b9c5bdcbbe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -49,6 +49,7 @@ arm port Richard Earnshaw <richard.earnshaw@arm.com>
arm port Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
avr port Denis Chertykov <chertykov@gmail.com>
bfin port Jie Zhang <jzhang918@gmail.com>
+c6x port Bernd Schmidt <bernds_cb1@t-online.de>
cris port Hans-Peter Nilsson <hp@axis.com>
epiphany port Joern Rennecke <gnu@amylaar.uk>
fr30 port Nick Clifton <nickc@redhat.com>
@@ -398,6 +399,7 @@ Torbjorn Granlund <tege@swox.com>
Anthony Green <green@redhat.com>
Doug Gregor <doug.gregor@gmail.com>
Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+Yury Gribov <tetra2005@gmail.com>
Jon Grimm <jgrimm2@us.ibm.com>
Laurent Guerby <laurent@guerby.net>
Xuepeng Guo <terry.guo@arm.com>
@@ -523,6 +525,7 @@ Braden Obrzut <admin@maniacsvault.net>
Carlos O'Donell <carlos@redhat.com>
Peter O'Gorman <pogma@thewrittenword.com>
Andrea Ornstein <andrea.ornstein@st.com>
+Maxim Ostapenko <m.ostapenko@samsung.com>
Patrick Palka <ppalka@gcc.gnu.org>
Devang Patel <dpatel@apple.com>
Andris Pavenis <andris.pavenis@iki.fi>
@@ -555,7 +558,7 @@ Hariharan Sandanagobalane <hariharan.gcc@gmail.com>
Iain Sandoe <iain@codesourcery.com>
Duncan Sands <baldrick@gcc.gnu.org>
Sujoy Saraswati <sujoy.saraswati@hpe.com>
-Trevor Saunders <tsaunders@mozilla.com>
+Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
Roger Sayle <roger@eyesopen.com>
Will Schmidt <will_schmidt@vnet.ibm.com>
diff --git a/Makefile.def b/Makefile.def
index 08d0dc08a46..bd7b080d905 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -623,8 +623,7 @@ bootstrap_stage = {
bootstrap_stage = {
id=profile ; prev=1 ; };
bootstrap_stage = {
- id=train; prev=profile ;
- bootstrap_target=profiledbootstrap ; };
+ id=train; prev=profile ; } ;
bootstrap_stage = {
id=feedback ; prev=train;
bootstrap_target=profiledbootstrap ; };
diff --git a/Makefile.in b/Makefile.in
index 2e2e504e106..78db0982ba2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -56151,29 +56151,6 @@ do-clean: clean-stagetrain
-.PHONY: profiledbootstrap profiledbootstrap-lean
-profiledbootstrap:
- echo stagetrain > stage_final
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(MAKE) $(RECURSE_FLAGS_TO_PASS) stagetrain-bubble
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- TFLAGS="$(STAGEtrain_TFLAGS)"; \
- $(MAKE) $(TARGET_FLAGS_TO_PASS) all-host all-target
-
-profiledbootstrap-lean:
- echo stagetrain > stage_final
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(MAKE) $(RECURSE_FLAGS_TO_PASS) LEAN=: stagetrain-bubble
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- TFLAGS="$(STAGEtrain_TFLAGS)"; \
- $(MAKE) $(TARGET_FLAGS_TO_PASS) all-host all-target
-
# Rules to wipe a stage and all the following ones, also used for cleanstrap
distclean-stageprofile:: distclean-stagetrain
diff --git a/configure b/configure
index 084986f475e..8e5c7ab7969 100755
--- a/configure
+++ b/configure
@@ -3463,11 +3463,8 @@ case "${target}" in
noconfigdirs="$noconfigdirs target-libffi"
;;
powerpc-*-aix*)
- # copied from rs6000-*-* entry
- noconfigdirs="$noconfigdirs target-libffi"
;;
rs6000-*-aix*)
- noconfigdirs="$noconfigdirs target-libffi"
;;
ft32-*-*)
noconfigdirs="$noconfigdirs target-libffi"
@@ -3480,7 +3477,7 @@ esac
# Disable the go frontend on systems where it is known to not work. Please keep
# this in sync with contrib/config-list.mk.
case "${target}" in
-*-*-darwin* | *-*-cygwin* | *-*-mingw* | *-*-aix*)
+*-*-darwin* | *-*-cygwin* | *-*-mingw*)
unsupported_languages="$unsupported_languages go"
;;
esac
@@ -3496,9 +3493,6 @@ if test x$enable_libgo = x; then
*-*-cygwin* | *-*-mingw*)
noconfigdirs="$noconfigdirs target-libgo"
;;
- *-*-aix*)
- noconfigdirs="$noconfigdirs target-libgo"
- ;;
esac
fi
@@ -6166,7 +6160,12 @@ if test -d ${srcdir}/gcc; then
language=
lang_requires=
lang_requires_boot_languages=
- . ${lang_frag}
+ # set srcdir during sourcing lang_frag to the gcc dir.
+ # Sadly overriding srcdir on the . line doesn't work in plain sh as it
+ # polutes this shell
+ saved_srcdir=${srcdir}
+ srcdir=${srcdir}/gcc . ${lang_frag}
+ srcdir=${saved_srcdir}
for other in ${lang_requires} ${lang_requires_boot_languages}; do
case ,${enable_languages}, in
*,$other,*) ;;
@@ -6241,7 +6240,10 @@ if test -d ${srcdir}/gcc; then
subdir_requires=
boot_language=no
build_by_default=yes
- . ${lang_frag}
+ # set srcdir during sourcing. See above about save & restore
+ saved_srcdir=${srcdir}
+ srcdir=${srcdir}/gcc . ${lang_frag}
+ srcdir=${saved_srcdir}
if test x${language} = x; then
echo "${lang_frag} doesn't set \$language." 1>&2
exit 1
diff --git a/configure.ac b/configure.ac
index 0cf052b2c75..173443fc247 100644
--- a/configure.ac
+++ b/configure.ac
@@ -791,11 +791,8 @@ case "${target}" in
noconfigdirs="$noconfigdirs target-libffi"
;;
powerpc-*-aix*)
- # copied from rs6000-*-* entry
- noconfigdirs="$noconfigdirs target-libffi"
;;
rs6000-*-aix*)
- noconfigdirs="$noconfigdirs target-libffi"
;;
ft32-*-*)
noconfigdirs="$noconfigdirs target-libffi"
@@ -808,7 +805,7 @@ esac
# Disable the go frontend on systems where it is known to not work. Please keep
# this in sync with contrib/config-list.mk.
case "${target}" in
-*-*-darwin* | *-*-cygwin* | *-*-mingw* | *-*-aix*)
+*-*-darwin* | *-*-cygwin* | *-*-mingw*)
unsupported_languages="$unsupported_languages go"
;;
esac
@@ -824,9 +821,6 @@ if test x$enable_libgo = x; then
*-*-cygwin* | *-*-mingw*)
noconfigdirs="$noconfigdirs target-libgo"
;;
- *-*-aix*)
- noconfigdirs="$noconfigdirs target-libgo"
- ;;
esac
fi
@@ -1839,7 +1833,12 @@ if test -d ${srcdir}/gcc; then
language=
lang_requires=
lang_requires_boot_languages=
- . ${lang_frag}
+ # set srcdir during sourcing lang_frag to the gcc dir.
+ # Sadly overriding srcdir on the . line doesn't work in plain sh as it
+ # polutes this shell
+ saved_srcdir=${srcdir}
+ srcdir=${srcdir}/gcc . ${lang_frag}
+ srcdir=${saved_srcdir}
for other in ${lang_requires} ${lang_requires_boot_languages}; do
case ,${enable_languages}, in
*,$other,*) ;;
@@ -1914,7 +1913,10 @@ if test -d ${srcdir}/gcc; then
subdir_requires=
boot_language=no
build_by_default=yes
- . ${lang_frag}
+ # set srcdir during sourcing. See above about save & restore
+ saved_srcdir=${srcdir}
+ srcdir=${srcdir}/gcc . ${lang_frag}
+ srcdir=${saved_srcdir}
if test x${language} = x; then
echo "${lang_frag} doesn't set \$language." 1>&2
exit 1
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 51adaaa178f..35bd9e2f232 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,18 @@
+2017-07-17 Yury Gribov <tetra2005@gmail.com>
+
+ * mklog: Fix extraction of changed file name.
+
+2017-07-17 Georg-Johann Lay <avr@gjlay.de>
+
+ * gcc_update (files_and_dependencies)
+ [gcc/config/avr/avr-tables.opt]: Remove dead entry.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ * gcc.doxy: Add default location for filters and output folder.
+ * filter_gcc_for_doxygen_new: Rename to filter_gcc_for_doxygen.
+ * filter_params.pl: Remove.
+
2017-06-21 Thomas Preud'homme <thomas.preudhomme@arm.com>
* dg-cmp-results.sh: Restore filtering on target variant.
diff --git a/contrib/filter_gcc_for_doxygen b/contrib/filter_gcc_for_doxygen
index 3787eebbf0e..d1109a50c88 100755
--- a/contrib/filter_gcc_for_doxygen
+++ b/contrib/filter_gcc_for_doxygen
@@ -1,12 +1,12 @@
#!/bin/sh
# This filters GCC source before Doxygen can get confused by it;
-# this script is listed in the doxyfile. The output is not very
+# this script is listed in the doxyfile. The output is not very
# pretty, but at least we get output that Doxygen can understand.
#
-# $1 is a source file of some kind. The source we wish doxygen to
+# $1 is a source file of some kind. The source we wish doxygen to
# process is put on stdout.
dir=`dirname $0`
-perl $dir/filter_params.pl < $1 | perl $dir/filter_knr2ansi.pl
+python $dir/filter_params.py $1
exit 0
diff --git a/contrib/filter_gcc_for_doxygen_new b/contrib/filter_gcc_for_doxygen_new
deleted file mode 100644
index d1109a50c88..00000000000
--- a/contrib/filter_gcc_for_doxygen_new
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-# This filters GCC source before Doxygen can get confused by it;
-# this script is listed in the doxyfile. The output is not very
-# pretty, but at least we get output that Doxygen can understand.
-#
-# $1 is a source file of some kind. The source we wish doxygen to
-# process is put on stdout.
-
-dir=`dirname $0`
-python $dir/filter_params.py $1
-exit 0
diff --git a/contrib/filter_params.pl b/contrib/filter_params.pl
deleted file mode 100755
index 22dae6cc561..00000000000
--- a/contrib/filter_params.pl
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/perl
-
-# Filters out some of the #defines used throughout the GCC sources:
-# - GTY(()) marks declarations for gengtype.c
-# - PARAMS(()) is used for K&R compatibility. See ansidecl.h.
-
-while (<>) {
- s/^\/\* /\/\*\* \@verbatim /;
- s/\*\// \@endverbatim \*\//;
- s/GTY[ \t]*\(\(.*\)\)//g;
- s/[ \t]ATTRIBUTE_UNUSED//g;
- s/PARAMS[ \t]*\(\((.*?)\)\)/\($1\)/sg;
- print;
-}
diff --git a/contrib/gcc.doxy b/contrib/gcc.doxy
index 7a284e754aa..a8eeb03c9a0 100644
--- a/contrib/gcc.doxy
+++ b/contrib/gcc.doxy
@@ -11,16 +11,12 @@
# Values that contain spaces should be placed between quotes (" ")
-#-----------------------------------------------------------------------------
-# NOTE: YOU MUST EDIT THE FOLLOWING HARDWIRED PATHS BEFORE USING THIS FILE.
-#-----------------------------------------------------------------------------
-
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY = @OUTPUT_DIRECTORY@
+OUTPUT_DIRECTORY = gcc-doxygen
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -30,7 +26,7 @@ OUTPUT_DIRECTORY = @OUTPUT_DIRECTORY@
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
-INPUT_FILTER = @INPUT_FILTER@
+INPUT_FILTER = contrib/filter_gcc_for_doxygen
#-----------------------------------------------------------------------------
diff --git a/contrib/gcc_update b/contrib/gcc_update
index fe643af68dc..8c111959fba 100755
--- a/contrib/gcc_update
+++ b/contrib/gcc_update
@@ -82,10 +82,6 @@ gcc/fixinc/fixincl.x: gcc/fixinc/fixincl.tpl gcc/fixinc/inclhack.def
gcc/config/aarch64/aarch64-tune.md: gcc/config/aarch64/aarch64-cores.def gcc/config/aarch64/gentune.sh
gcc/config/arm/arm-tune.md: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecpu.awk
gcc/config/arm/arm-tables.opt: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecpu.awk
-gcc/config/arm/arm-cpu.h: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecpu.awk
-gcc/config/arm/arm-cpu-data.h: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecpu.awk
-gcc/config/arm/arm-cpu-cdata.h: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecpu.awk
-gcc/config/avr/avr-tables.opt: gcc/config/avr/avr-mcus.def gcc/config/avr/genopt.sh
gcc/config/avr/t-multilib: gcc/config/avr/avr-mcus.def gcc/config/avr/genmultilib.awk
gcc/config/c6x/c6x-tables.opt: gcc/config/c6x/c6x-isas.def gcc/config/c6x/genopt.sh
gcc/config/c6x/c6x-sched.md: gcc/config/c6x/c6x-sched.md.in gcc/config/c6x/gensched.sh
diff --git a/contrib/header-tools/ChangeLog b/contrib/header-tools/ChangeLog
index bf89e6c2da9..8977a000cd9 100644
--- a/contrib/header-tools/ChangeLog
+++ b/contrib/header-tools/ChangeLog
@@ -1,3 +1,9 @@
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * graph-header-logs (ignore): Update coretypes.h header list.
+
2016-06-21 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
* README: Remove references to avr-rtems.
diff --git a/contrib/header-tools/graph-header-logs b/contrib/header-tools/graph-header-logs
index d4febd7f571..e537aaeac0c 100755
--- a/contrib/header-tools/graph-header-logs
+++ b/contrib/header-tools/graph-header-logs
@@ -25,9 +25,12 @@ depstring = ("In file included from", " from")
# indentation indicates nesting levels of included files
ignore = [ "coretypes_h",
- "machmode_h",
+ "insn_modes_h",
"signop_h",
"wide_int_h",
+ "wide_int_print_h",
+ "insn_modes_inline_h",
+ "machmode_h",
"double_int_h",
"real_h",
"fixed_value_h",
diff --git a/contrib/mklog b/contrib/mklog
index 61126280f1f..ff20cf1ba0f 100755
--- a/contrib/mklog
+++ b/contrib/mklog
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+# Copyright (C) 2012-2017 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -195,8 +195,20 @@ foreach (@diff_lines) {
} elsif($right eq '/dev/null') {
$filename = $left;
} else {
- print STDERR "Error: failed to parse diff for $left and $right\n";
- exit 1;
+ my @ldirs = split /[\/\\]/, $left;
+ my @rdirs = split /[\/\\]/, $right;
+
+ $filename = '';
+ while ((my $l = pop @ldirs) && (my $r = pop @rdirs)) {
+ last if ($l ne $r);
+ $filename = "$l/$filename";
+ }
+ $filename =~ s/\/$//;
+
+ if (!$filename) {
+ print STDERR "Error: failed to parse diff for $left and $right\n";
+ exit 1;
+ }
}
$left = $right = undef;
($clname, $relname) = get_clname ($filename);
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eb945484a55..27e4af12cbc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,4616 @@
+2017-07-31 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config.gcc: Add z14.
+ * config/s390/driver-native.c (s390_host_detect_local_cpu): Add
+ CPU model numbers for z13s and z14.
+ * config/s390/s390-c.c (s390_resolve_overloaded_builtin): Replace
+ arch12 with z14.
+ * config/s390/s390-opts.h (enum processor_type): Rename
+ PROCESSOR_ARCH12 to PROCESSOR_3906_Z14.
+ * config/s390/s390.c (processor_table): Add field for CPU name to
+ be passed to Binutils.
+ (s390_asm_output_machine_for_arch): Use the new field in
+ processor_table for Binutils.
+ (s390_expand_builtin): Replace arch12 with z14.
+ (s390_issue_rate): Rename PROCESSOR_ARCH12 to PROCESSOR_3906_Z14.
+ (s390_get_sched_attrmask): Likewise.
+ (s390_get_unit_mask): Likewise.
+ * config/s390/s390.opt: Add z14 to processor_type enum.
+
+2017-07-31 Martin Jambor <mjambor@suse.cz>
+
+ PR hsa/81477
+ * ipa-fnsummary.c (ipa_fn_summary_generate): Set versionable
+ regardless of optimization level.
+
+2017-07-31 Jan Hubicka <hubicka@ucw.cz>
+ Martin Liska <mliska@suse.cz>
+
+ * predict.def: Remove old comment and adjust probability.
+ * gimplify.c (should_warn_for_implicit_fallthrough): Ignore
+ PREDICT statements.
+
+2017-07-31 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/25967
+ * config/i386/i386.c (ix86_function_naked): New function.
+ (ix86_can_use_return_insn_p): Return false for naked functions.
+ (ix86_expand_prologue): Skip prologue for naked functions.
+ (ix86_expand_epilogue): Skip epilogue for naked functions
+ and emit trap instruction.
+ (ix86_warn_func_return): New function.
+ (ix86_attribute_table): Add "naked" attribute specification.
+ (TARGET_WARN_FUNC_RETURN): Define.
+ * doc/extend.texi (x86 Function Attributes) <naked>: Document it.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ * gimple-pretty-print.c (dump_gimple_label): Never dump BB info.
+ (dump_gimple_bb_header): Always dump BB info.
+ (pp_cfg_jump): Do not append info about BB when dumping a jump.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81530
+ * convert.c (convert_to_integer_1): Guard condition with flag_sanitize_p
+ also with current_function_decl non-null equality.
+
+2017-07-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81604
+ * ubsan.c (ubsan_type_descriptor): For UBSAN_PRINT_ARRAY don't
+ change type to the element type, instead add eltype variable and
+ use it where we are interested in the element type.
+
+ PR tree-optimization/81603
+ * ipa-polymorphic-call.c
+ (ipa_polymorphic_call_context::ipa_polymorphic_call_context): Perform
+ offset arithmetic in offset_int, bail out if the resulting bit offset
+ doesn't fit into shwi.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ * gimplify.c (mostly_copy_tree_r): Remove Java specific hunk.
+ (gimplify_save_expr): Fix comment.
+
+2017-07-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/79793
+ * config/i386/i386.c (ix86_function_arg): Update arguments for
+ exception handler.
+ (ix86_compute_frame_layout): Set the initial stack offset to
+ INCOMING_FRAME_SP_OFFSET. Update red-zone offset with
+ INCOMING_FRAME_SP_OFFSET.
+ (ix86_expand_epilogue): Don't pop the 'ERROR_CODE' off the
+ stack before exception handler returns.
+ * config/i386/i386.h (INCOMING_FRAME_SP_OFFSET): Add the
+ the 'ERROR_CODE' for exception handler.
+
+2017-07-30 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (ASM_PRINTF_EXTENSIONS): New macro.
+ (ASM_OUTPUT_REG_PUSH): Rewrite with new operand modifiers.
+ (ASM_OUTPUT_REG_POP): Ditto.
+ * config/i386/i386.c (ix86_asm_output_function_label): Use fputs
+ instead of asm_fprintf to output pure string.
+
+2017-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ * debug.h (struct gcc_debug_hooks): Add IMPLICIT argument
+ to imported_module_or_decl hook.
+ (debug_nothing_tree_tree_tree_bool): Remove.
+ (debug_nothing_tree_tree_tree_bool_bool): New declaration.
+ * debug.c (do_nothing_debug_hooks): Use
+ debug_nothing_tree_tree_tree_bool_bool instead of
+ debug_nothing_tree_tree_tree_bool.
+ * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
+ * dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Likewise.
+ * sdbout.c (sdb_debug_hooks): Likewise.
+ * dwarf2out.c (dwarf2_lineno_debug_hooks): Likewise.
+ (gen_namespace_die): Add DW_AT_export_symbols attribute if
+ langhook wants it.
+ (dwarf2out_imported_module_or_decl): Add IMPLICIT argument,
+ if true, -gdwarf-5 and decl will have DW_AT_export_symbols
+ attribute, don't add anything.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * fold-const.c (fold_build1_stat_loc): Remove _stat from name.
+ (fold_build2_stat_loc): Likewise.
+ (fold_build3_stat_loc): Likewise.
+ * fold-const.h (fold_build1, fold_build2, fold_build3): Adjust.
+ (fold_build1_loc): Remove macro.
+ (fold_build2_loc): Likewise.
+ (fold_build3_loc): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * gimple.c (gimple_build_debug_bind_stat): Remove _stat from name.
+ (gimple_build_debug_bind_source_stat): Likewise.
+ * gimple.h (gimple_build_debug_bind): Remove macro.
+ (gimple_build_debug_bind_source): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * bitmap.c (bitmap_alloc): Adjust.
+ (bitmap_gc_alloc): Likewise.
+ * bitmap.h (bitmap_initialize_stat): Remove _stat from name.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * bitmap.c (bitmap_obstack_alloc_stat): Rename to bitmap_alloc.
+ (bitmap_gc_alloc_stat): Rename to bitmap_gc_alloc.
+ * bitmap.h (bitmap_obstack_alloc_stat): Adjust prototype.
+ (bitmap_gc_alloc_stat): Likewise.
+ (BITMAP_ALLOC, BITMAP_GGC_ALLOC): Adjust.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * rtl.c (shallow_copy_rtx_stat): Remove _stat from name.
+ * rtl.h (shallow_copy_rtx): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * emit-rtl.c (gen_raw_REG): Adjust.
+ * gengenrtl.c (gendef): Likewise.
+ * rtl.c (rtx_alloc_stat): Remove _stat from name.
+ * rtl.h (rtx_alloc): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (build_tree_list_vec_stat): Remove _stat from name.
+ (build_tree_list_stat): Likewise.
+ * tree.h (build_tree_list): Remove macro.
+ (build_tree_list_vec): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (make_vector_stat): Remove _stat from name.
+ (build_vector_stat): Likewise.
+ * tree.h (make_vector_stat): Remove macro.
+ (build_vector_stat): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.h (build_var_debug_value): Remove prototype.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (tree_cons_stat): Remove _stat from name.
+ * tree.h (tree_cons): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (build_vl_exp_stat): Remove _stat from name.
+ * tree.h (build_vl_exp): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (build_decl_stat): Remove _stat from name.
+ * tree.h (build_decl): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * gimple.c (gimple_build_with_ops_stat): Adjust.
+ (gimple_alloc_stat): Remove _stat from name.
+ * gimple.h (gimple_alloc): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (make_tree_vec_stat): Remove _stat from name.
+ (grow_tree_vec_stat): Likewise.
+ * tree.h (make_tree_vec_stat): Adjust prototype.
+ (grow_tree_vec_stat): Likewise.
+ (make_tree_vec): Remove macro.
+ (grow_tree_vec): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * fold-const.c (fold_build1_stat_loc): Adjust.
+ (fold_build2_stat_loc): Likewise.
+ (fold_build3_stat_loc): Likewise.
+ * tree.c (build0_stat): Remove _stat from name.
+ (build1_stat): Likewise.
+ (build2_stat): Likewise.
+ (build3_stat): Likewise.
+ (build4_stat): Likewise.
+ (build5_stat): Likewise.
+ * tree.h (build1_loc): Remove macro, and rename _stat function
+ to this.
+ (build2_loc): Likewise.
+ (build3_loc): Likewise.
+ (build4_loc): Likewise.
+ (build5_loc): Likewise.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (make_int_cst_stat): Remove _stat from name.
+ * tree.h (make_int_cst_stat): Adjust prototype.
+ (make_int_cst): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (make_tre_binfo_stat): Remove _stat from name.
+ * tree.h (make_tree_binfo_stat): Adjust prototype.
+ (make_tree_binfo): Remove.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (copy_node_stat): Rename to copy_node.
+ (build_distinct_type_copy): Adjust.
+ * tree.h (copy_node_stat): Adjust prototype.
+ (copy_node): Remove macro.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * tree.c (make_node_stat): rename to make_node.
+ (build_tree_list_stat): Adjust.
+ (build0_stat): Likewise.
+ (build2_stat): Likewise.
+ (build3_stat): Likewise.
+ (build4_stat): Likewise.
+ (build5_stat): Likewise.
+ (build_decl_stat): Likewise.
+ * tree.h (make_node_stat): Adjust prototype.
+ (make_node): remove macro.
+
+2017-07-28 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/ppc-auxv.h (PPC_FEATURE2_DARN): New define.
+ (PPC_FEATURE2_SCV): Likewise.
+ * config/rs6000/rs6000.c (cpu_supports_info): Use them.
+
+2017-07-28 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64.c
+ (aarch64_internal_mov_immediate): Add new special pattern.
+ * config/aarch64/aarch64.md (*movdi_aarch64):
+ Add reg/32bit const mov case.
+
+2017-07-28 Tamar Christina <tamar.christina@arm.com>
+ Richard Sandiford <richard.sandiford@linaro.org>
+
+ * config/aarch64/aarch64.md (mov<mode>): Generalize.
+ (*movhf_aarch64, *movsf_aarch64, *movdf_aarch64):
+ Add integer and movi cases.
+ (movi-split-hf-df-sf split, fp16): New.
+ (enabled): Added TARGET_FP_F16INST.
+ * config/aarch64/iterators.md (GPF_HF): New.
+ * config/aarch64/predicates.md (aarch64_reg_or_fp_float): New.
+
+2017-07-28 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64.c
+ (aarch64_simd_container_mode): Add prototype.
+ (aarch64_expand_mov_immediate): Add HI support.
+ (aarch64_reinterpret_float_as_int, aarch64_float_const_rtx_p: New.
+ (aarch64_can_const_movi_rtx_p): New.
+ (aarch64_preferred_reload_class):
+ Remove restrictions of using FP registers for certain SIMD operations.
+ (aarch64_rtx_costs): Added new cost for CONST_DOUBLE moves.
+ (aarch64_valid_floating_const): Add integer move validation.
+ (aarch64_simd_imm_scalar_p): Remove.
+ (aarch64_output_scalar_simd_mov_immediate): Generalize function.
+ (aarch64_legitimate_constant_p): Expand list of supported cases.
+ * config/aarch64/aarch64-protos.h
+ (aarch64_float_const_rtx_p, aarch64_can_const_movi_rtx_p): New.
+ (aarch64_reinterpret_float_as_int): New.
+ (aarch64_simd_imm_scalar_p): Remove.
+ * config/aarch64/constraints.md (Uvi): New.
+ (Dd): Split into Ds and new Dd.
+ * config/aarch64/aarch64.md (*movsi_aarch64):
+ Add SIMD mov case.
+ (*movdi_aarch64): Add SIMD mov case.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c: (struct chain): Handle store-store chain in which
+ stores for elimination only store loop invariant values.
+ (execute_pred_commoning_chain): Ditto.
+ (prepare_initializers_chain_store_elim): Ditto.
+ (prepare_finalizers): Ditto.
+ (is_inv_store_elimination_chain): New function.
+ (initialize_root_vars_store_elim_1): New function.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c: Revise general description of the pass.
+ (enum chain_type): New enum type for store elimination.
+ (struct chain): New field supporting store elimination.
+ (struct component): Ditto.
+ (dump_chain): Dump store-stores chain.
+ (release_chain): Release resources.
+ (split_data_refs_to_components): Compute and create component
+ contains only stores for elimination.
+ (get_chain_last_ref_at): New function.
+ (make_invariant_chain): Initialization.
+ (make_rooted_chain): Specify chain type in parameter and record it.
+ (add_looparound_copies): Skip for store-stores chain.
+ (determine_roots_comp): Compute type of chain and pass it to
+ make_rooted_chain.
+ (initialize_root_vars_store_elim_2): New function.
+ (finalize_eliminated_stores): New function.
+ (remove_stmt): Handle store for elimination.
+ (execute_pred_commoning_chain): Execute predictive commoning on
+ store-store chains.
+ (determine_unroll_factor): Skip unroll for store-stores chain.
+ (prepare_initializers_chain_store_elim): New function.
+ (prepare_initializers_chain): Hanlde store-store chain.
+ (prepare_finalizers_chain, prepare_finalizers): New function.
+ (tree_predictive_commoning_loop): Return integer value indicating
+ if loop is unrolled or lcssa form is corrupted.
+ (tree_predictive_commoning): Rewrite for lcssa form if necessary.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c (initialize_root): Delete.
+ (execute_pred_commoning_chain): Initialize root vars and replace
+ reference of non-combined chain directly, rather than call above
+ function.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c (ref_at_iteration): Add parameter NITERS. Compute
+ memory reference to DR at (NITERS + ITERS)-th iteration of loop.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c (struct chain): New field init_seq.
+ (release_chain): Release init_seq.
+ (prepare_initializers_chain): Record intialization stmts in above
+ field.
+ (insert_init_seqs): New function.
+ (tree_predictive_commoning_loop): Call insert_init_seqs.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-predcom.c (determine_roots_comp): Skip trivial components.
+
+2017-07-28 Richard Biener <rguenther@suse.de>
+
+ * match.pd: Remove superfluous :c.
+ * genmatch.c (simplify::id): Add member.
+ (lower_commutative, lower_opt_convert, lower_cond, lower_for):
+ Copy id.
+ (current_id): New global.
+ (dt_node::parent): Move from ...
+ (dt_operand::parent): ... here. Add for_id member.
+ (is_a_helper <dt_operand *>::test): DT_TRUE is also a dt_operand.
+ (decision_tree::find_node): Relax order requirement when
+ merging DT_TRUE nodes to ones inbetween the current simplify
+ and the one we try to merge with. Add diagnostic whenever
+ we need to enforce pattern order by not merging.
+ (decision_tree::insert): Set current_id.
+ (decision_tree::print_node): Dump parent node and for_id.
+ (parser::last_id): Add member.
+ (parser::push_simplify): Assign unique id.
+ (parser::parser): Initialize last_id.
+
+2017-07-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81340
+ * sanopt.c (sanitize_rewrite_addressable_params): Set VALUE_EXPR after
+ gimple_build_debug_bind.
+
+2017-07-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81502
+ * match.pd: Add pattern combining BIT_INSERT_EXPR with
+ BIT_FIELD_REF.
+ * tree-cfg.c (verify_expr): Verify types of BIT_FIELD_REF
+ size/pos operands.
+ (verify_gimple_assign_ternary): Likewise for BIT_INSERT_EXPR pos.
+ * gimple-fold.c (maybe_canonicalize_mem_ref_addr): Use bitsizetype
+ for BIT_FIELD_REF args.
+ * fold-const.c (make_bit_field_ref): Likewise.
+ * tree-vect-stmts.c (vectorizable_simd_clone_call): Likewise.
+
+2017-07-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/80998
+ * sanopt.c (pass_sanopt::execute): Handle IFN_UBSAN_PTR.
+ * tree-ssa-alias.c (call_may_clobber_ref_p_1): Likewise.
+ * flag-types.h (enum sanitize_code): Add SANITIZER_POINTER_OVERFLOW.
+ Or it into SANITIZER_UNDEFINED.
+ * ubsan.c: Include gimple-fold.h and varasm.h.
+ (ubsan_expand_ptr_ifn): New function.
+ (instrument_pointer_overflow): New function.
+ (maybe_instrument_pointer_overflow): New function.
+ (instrument_object_size): Formatting fix.
+ (pass_ubsan::execute): Call instrument_pointer_overflow
+ and maybe_instrument_pointer_overflow.
+ * internal-fn.c (expand_UBSAN_PTR): New function.
+ * ubsan.h (ubsan_expand_ptr_ifn): Declare.
+ * sanitizer.def (__ubsan_handle_pointer_overflow,
+ __ubsan_handle_pointer_overflow_abort): New builtins.
+ * tree-ssa-tail-merge.c (merge_stmts_p): Handle IFN_UBSAN_PTR.
+ * internal-fn.def (UBSAN_PTR): New internal function.
+ * opts.c (sanitizer_opts): Add pointer-overflow.
+ * lto-streamer-in.c (input_function): Handle IFN_UBSAN_PTR.
+ * fold-const.c (build_range_check): Compute pointer range check in
+ integral type if pointer arithmetics would be needed. Formatting
+ fixes.
+
+2017-07-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81460
+ * sanopt.c (sanitize_rewrite_addressable_params): Do not rewrite
+ parameters that are of a variable-length.
+
+2017-07-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config.gcc (powerpc-*-rtems*): Remove rs6000/eabi.h. Add
+ rs6000/biarch64.h.
+ * config/rs6000/rtems.h (ASM_DECLARE_FUNCTION_SIZE): New macro.
+ (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P): Likewise.
+ (CRT_CALL_STATIC_FUNCTION): Likewise.
+ (ASM_DEFAULT_SPEC): New define.
+ (ASM_SPEC32): Likewise.
+ (ASM_SPEC64): Likewise.
+ (ASM_SPEC_COMMON): Likewise.
+ (ASM_SPEC): Likewise.
+ (INVALID_64BIT): Likewise.
+ (LINK_OS_DEFAULT_SPEC): Likewise.
+ (LINK_OS_SPEC32): Likewise.
+ (LINK_OS_SPEC64): Likewise.
+ (POWERPC_LINUX): Likewise.
+ (PTRDIFF_TYPE): Likewise.
+ (RESTORE_FP_PREFIX): Likewise.
+ (RESTORE_FP_SUFFIX): Likewise.
+ (SAVE_FP_PREFIX): Likewise.
+ (SAVE_FP_SUFFIX): Likewise.
+ (SIZE_TYPE): Likewise.
+ (SUBSUBTARGET_OVERRIDE_OPTIONS): Likewise.
+ (TARGET_64BIT): Likewise.
+ (TARGET_64BIT): Likewise.
+ (TARGET_AIX): Likewise.
+ (WCHAR_TYPE_SIZE): Likewise.
+ (WCHAR_TYPE): Undefine.
+ (TARGET_OS_CPP_BUILTINS): Add 64-bit PowerPC defines.
+ (CPP_OS_DEFAULT_SPEC): Use previous CPP_OS_RTEMS_SPEC.
+ (CPP_OS_RTEMS_SPEC): Delete.
+ (SUBSUBTARGET_EXTRA_SPECS): Remove cpp_os_rtems. Add
+ asm_spec_common, asm_spec32, asm_spec64, link_os_spec32, and
+ link_os_spec64.
+ * config/rs6000/t-rtems: Add mcpu=e6500/m64 multilibs.
+
+2017-07-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81578
+ * tree-parloops.c (build_new_reduction): Bail out if
+ reduction_code isn't one of the standard OpenMP reductions.
+ Move the details printing after that decision.
+
+2017-07-27 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/predicates.md (volatile_mem_operand): Remove code
+ related to reload_in_progress.
+ (splat_input_operand): Likewise.
+ * config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_rtx):
+ Delete prototype.
+ * config/rs6000/rs6000.c (machine_function): Remove sdmode_stack_slot
+ field.
+ (TARGET_EXPAND_TO_RTL_HOOK): Delete.
+ (TARGET_INSTANTIATE_DECLS): Likewise.
+ (legitimate_indexed_address_p): Delete reload_in_progress code.
+ (rs6000_debug_legitimate_address_p): Likewise.
+ (rs6000_eliminate_indexed_memrefs): Likewise.
+ (rs6000_emit_le_vsx_store): Likewise.
+ (rs6000_emit_move_si_sf_subreg): Likewise.
+ (rs6000_emit_move): Likewise.
+ (register_to_reg_type): Likewise.
+ (rs6000_pre_atomic_barrier): Likewise.
+ (rs6000_machopic_legitimize_pic_address): Likewise.
+ (rs6000_allocate_stack_temp): Likewise.
+ (rs6000_address_for_fpconvert): Likewise.
+ (rs6000_address_for_altivec): Likewise.
+ (rs6000_secondary_memory_needed_rtx): Delete function.
+ (rs6000_check_sdmode): Likewise.
+ (rs6000_alloc_sdmode_stack_slot): Likewise.
+ (rs6000_instantiate_decls): Likewise.
+ * config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_RTX): Delete.
+ * config/rs6000/rs6000.md (splitter for *movsi_got_internal):
+ Delete reload_in_progress.
+ (*vec_reload_and_plus_<mptrsize>): Likewise.
+ * config/rs6000/vsx.md (vsx_mul_v2di): Likewise.
+ (vsx_div_v2di): Likewise.
+ (vsx_udiv_v2di): Likewise.
+
+2017-07-27 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/rs6000.opt (mlra): Replace with stub.
+ * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Delete OPTION_MASK_LRA.
+ * config/rs6000/rs6000.c (TARGET_LRA_P): Delete.
+ (rs6000_debug_reg_global): Delete print of LRA status.
+ (rs6000_option_override_internal): Delete dead LRA related code.
+ (rs6000_lra_p): Delete function.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Delete -mlra.
+
+2017-07-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config.gcc (riscv*-*-elf*): Add (riscv*-*-rtems*).
+ * config/riscv/rtems.h: New file.
+
+2017-07-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Sudakshina Das <sudi.das@arm.com>
+
+ * config/aarch64/aarch64.md
+ (define_split for and<mode>3nr_compare): Move
+ non aarch64_logical_operand to a register.
+ (define_split for and_<SHIFT:optab><mode>3nr_compare0): Move non
+ register immediate operand to a register.
+ * config/aarch64/predicates.md (aarch64_mov_imm_operand): New.
+
+2017-07-27 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR middle-end/81564
+ * tree-cfg.c (group_case_labels_stmt): Handle already deleted blocks.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81573
+ PR tree-optimization/81494
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Handle
+ multi defuse cycle case.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81571
+ * tree-vect-slp.c (vect_build_slp_tree): Properly verify reduction
+ PHIs.
+
+2017-07-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.c (sparc_option_override): Set MASK_FSMULD flag
+ earlier and only if MASK_FPU is set. Adjust formatting.
+
+2017-07-27 Martin Liska <mliska@suse.cz>
+
+ * opt-functions.awk: Add validation of value of Init.
+ * optc-gen.awk: Pass new argument.
+
+2017-07-27 Martin Liska <mliska@suse.cz>
+
+ * auto-profile.c (autofdo_source_profile::update_inlined_ind_target):
+ Fix wrong condition.
+
+2017-07-27 Martin Liska <mliska@suse.cz>
+
+ * auto-profile.c (afdo_annotate_cfg): Assign zero counts to
+ BBs and edges seen by autoFDO.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81502
+ * tree-ssa.c (non_rewritable_lvalue_p): Handle BIT_INSERT_EXPR
+ with incompatible but same sized type.
+ (execute_update_addresses_taken): Likewise.
+
+2017-07-27 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * tree-ssa-loop-ch.c (pass_ch::process_loop_p): Guard on
+ flag_tree_loop_vectorize rather than flag_tree_vectorize.
+
+2017-07-27 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/81534
+ * config/s390/s390.md ("*atomic_compare_and_swap<mode>_1")
+ ("*atomic_compare_and_swapdi_2", "*atomic_compare_and_swapsi_3"):
+ Change s_operand to memory_operand.
+
+2017-07-27 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * config/rs6000/rs6000-protos.h (rs6000_emit_le_vsx_permute): Declare.
+ * config/rs6000/rs6000.c (rs6000_gen_le_vsx_permute): Replace with...
+ (rs6000_emit_le_vsx_permute): ...this. Take the destination as input.
+ Emit instructions rather than returning an expression. Handle TFmode
+ and KFmode by casting to TImode.
+ (rs6000_emit_le_vsx_load): Update to use rs6000_emit_le_vsx_permute.
+ (rs6000_emit_le_vsx_store): Likewise.
+ * config/rs6000/vsx.md (VSX_TI): New iterator.
+ (*vsx_le_permute_<mode>): Use it instead of VSX_LE_128.
+ (*vsx_le_undo_permute_<mode>): Likewise.
+ (*vsx_le_perm_load_<mode>): Use rs6000_emit_le_vsx_permute to
+ emit the split sequence.
+ (*vsx_le_perm_store_<mode>): Likewise.
+
+2017-07-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81555
+ PR tree-optimization/81556
+ * tree-ssa-reassoc.c (rewrite_expr_tree): Add NEXT_CHANGED argument,
+ if true, force CHANGED for the recursive invocation.
+ (reassociate_bb): Remember original length of ops array, pass
+ len != orig_len as NEXT_CHANGED in rewrite_expr_tree call.
+
+ * attribs.c (decl_attributes): Imply noinline, noclone and no_icf
+ attributes for noipa attribute. For naked attribute use
+ lookup_attribute first before lookup_attribute_spec.
+ * final.c (rest_of_handle_final): Disable IPA RA for functions with
+ noipa attribute.
+ * ipa-visibility.c (non_local_p): Fix comment typos. Return true
+ for functions with noipa attribute.
+ (cgraph_externally_visible_p): Return true for functions with noipa
+ attribute.
+ * cgraph.c (cgraph_node::get_availability): Return AVAIL_INTERPOSABLE
+ for functions with noipa attribute.
+ * doc/extend.texi: Document noipa function attribute.
+ * tree-ssa-structalias.c (refered_from_nonlocal_fn): Set *nonlocal_p
+ also for functions with noipa attribute.
+ (ipa_pta_execute): Set nonlocal_p also for nodes with noipa attribute.
+
+2017-07-26 Andrew Pinski <apinski@cavium.com>
+
+ * config/aarch64/aarch64.c (thunderx_vector_cost): Decrease cost of
+ vec_unalign_load_cost and vec_unalign_store_cost.
+
+2017-07-26 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER): Delete
+ -mvsx-small-integer option.
+ (ISA_3_0_MASKS_IEEE): Likewise.
+ (OTHER_VSX_VECTOR_MASKS): Likewise.
+ (POWERPC_MASKS): Likewise.
+ * config/rs6000/rs6000.opt (-mvsx-small-integer): Likewise.
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Simplify
+ code, only testing for DImode being allowed in non-VSX floating
+ point registers.
+ (rs6000_init_hard_regno_mode_ok): Change TARGET_VSX_SMALL_INTEGER
+ to TARGET_P8_VECTOR test. Remove redundant VSX test inside of
+ another VSX test.
+ (rs6000_option_override_internal): Delete -mvsx-small-integer.
+ (rs6000_expand_vector_set): Change TARGET_VSX_SMALL_INTEGER to
+ TARGET_P8_VECTOR test.
+ (rs6000_secondary_reload_simple_move): Likewise.
+ (rs6000_preferred_reload_class): Delete TARGET_VSX_SMALL_INTEGER,
+ since TARGET_P9_VECTOR was already tested.
+ (rs6000_opt_masks): Remove -mvsx-small-integer.
+ * config/rs6000/vsx.md (vsx_extract_<mode>): Delete
+ TARGET_VSX_SMALL_INTEGER, since a test for TARGET_P9_VECTOR was
+ used.
+ (vsx_extract_<mode>_p9): Delete TARGET_VSX_SMALL_INTEGER, since a
+ test for TARGET_VEXTRACTUB was used, and that uses
+ TARGET_P9_VECTOR.
+ (p9 extract splitter): Likewise.
+ (vsx_extract_<mode>_di_p9): Likewise.
+ (vsx_extract_<mode>_store_p9): Likewise.
+ (vsx_extract_si): Delete TARGET_VSX_SMALL_INTEGER, since a test
+ for TARGET_P9_VECTOR was used. Delete code that is now dead with
+ the elimination of TARGET_VSX_SMALL_INTEGER.
+ (vsx_extract_<mode>_p8): Likewise.
+ (vsx_ext_<VSX_EXTRACT_I:VS_scalar>_fl_<FL_CONV:mode>): Likewise.
+ (vsx_ext_<VSX_EXTRACT_I:VS_scalar>_ufl_<FL_CONV:mode>): Likewise.
+ (vsx_set_<mode>_p9): Likewise.
+ (vsx_set_v4sf_p9): Likewise.
+ (vsx_set_v4sf_p9_zero): Likewise.
+ (vsx_insert_extract_v4sf_p9): Likewise.
+ (vsx_insert_extract_v4sf_p9_2): Likewise.
+ * config/rs6000/rs6000.md (sign extend splitter): Change
+ TARGET_VSX_SMALL_INTEGER to TARGET_P8_VECTOR test.
+ (floatsi<mode>2_lfiwax_mem): Likewise.
+ (floatunssi<mode>2_lfiwzx_mem): Likewise.
+ (float<QHI:mode><FP_ISA3:mode>2): Delete TARGET_VSX_SMALL_INTEGER,
+ since a test for TARGET_P9_VECTOR was used.
+ (float<QHI:mode><FP_ISA3:mode>2_internal): Likewise.
+ (floatuns<QHI:mode><FP_ISA3:mode>2): Likewise.
+ (floatuns<QHI:mode><FP_ISA3:mode>2_internal): Likewise.
+ (fix_trunc<mode>si2): Change TARGET_VSX_SMALL_INTEGER to
+ TARGET_P8_VECTOR test.
+ (fix_trunc<mode>si2_stfiwx): Likewise.
+ (fix_trunc<mode>si2_internal): Likewise.
+ (fix_trunc<SFDF:mode><QHI:mode>2): Delete
+ TARGET_VSX_SMALL_INTEGER, since a test for TARGET_P9_VECTOR was
+ used.
+ (fix_trunc<SFDF:mode><QHI:mode>2_internal): Likewise.
+ (fixuns_trunc<mode>si2): Change TARGET_VSX_SMALL_INTEGER to
+ TARGET_P8_VECTOR test.
+ (fixuns_trunc<mode>si2_stfiwx): Likewise.
+ (fixuns_trunc<SFDF:mode><QHI:mode>2): Delete
+ TARGET_VSX_SMALL_INTEGER, since a test for TARGET_P9_VECTOR was
+ used.
+ (fixuns_trunc<SFDF:mode><QHI:mode>2_internal): Likewise.
+ (fctiw<u>z_<mode>_smallint): Delete TARGET_VSX_SMALL_INTEGER,
+ since a test for TARGET_P9_VECTOR was used.
+ (splitter for loading small constants): Likewise.
+
+2017-07-26 Andrew Pinski <apinski@cavium.com>
+
+ * config/aarch64/aarch64.c (thunderx_vector_cost): Fix
+ vec_fp_stmt_cost.
+
+2017-07-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/81563
+ * config/i386/i386.c (sp_valid_at): Properly check CFA offset.
+ (fp_valid_at): Likewise.
+
+2017-07-26 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (cortexa57_addrcost_table): Remove.
+ (qdf24xx_addrcost_table): Likewise.
+ (cortexa57_tunings): Update to use generic_branch_cost.
+ (cortexa72_tunings): Likewise.
+ (cortexa73_tunings): Likewise.
+ (qdf24xx_tunings): Likewise.
+
+2017-07-26 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (cortexa57_branch_cost): Remove.
+ (thunderx2t99_branch_cost): Likewise.
+ (cortexa35_tunings): Update to use generic_branch_cost.
+ (cortexa53_tunings): Likewise.
+ (cortexa57_tunings): Likewise.
+ (cortexa72_tunings): Likewise.
+ (cortexa73_tunings): Likewise.
+ (thunderx2t99_tunings): Likewise.
+
+2017-07-26 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/sparc/sparc.c (dump_target_flag_bits): Dump MASK_FSMULD.
+ (sparc_option_override): Honour MASK_FSMULD.
+ * config/sparc/sparc.h (MASK_FEATURES): Add MASK_FSMULD.
+ * config/sparc/sparc.md (muldf3_extend): Use TARGET_FSMULD.
+ * config/sparc/sparc.opt (mfsmuld): New option.
+ * doc/invoke.texi (mfsmuld): Document option.
+
+2017-07-26 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/70992
+ * tree.c (build2_stat): Don't set TREE_CONSTANT on divisions by zero.
+
+2017-07-26 Richard Biener <rguenther@suse.de>
+
+ * gimple-match-head.c (do_valueize): Return OP if valueize
+ returns NULL_TREE.
+ (get_def): New helper to get at the def stmt of a SSA name
+ if valueize allows.
+ * genmatch.c (dt_node::gen_kids_1): Use get_def instead of
+ do_valueize to get at the def stmt.
+ (dt_operand::gen_gimple_expr): Simplify do_valueize calls.
+
+2017-07-26 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/46932
+ * auto-inc-dec.c (parse_add_or_inc): Block autoinc on sfp.
+
+2017-07-26 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81186
+ * function.c (expand_function_start): Make expansion of
+ nonlocal_goto_save_area after parm_birth_insn.
+
+2017-07-26 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/sparc/sparc.c (sparc_option_override): Remove MASK_FPU
+ from all CPU target flags enable members.
+
+2017-07-26 Richard Biener <rguenther@suse.de>
+
+ * genmatch.c (dt_simplify::gen): Make iterator vars const.
+ (decision_tree::gen): Make 'type' const.
+ (write_predicate): Likewise.
+
+2017-07-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok):
+ Eliminate TARGET_UPPER_REGS_{DF,DI,SF} usage.
+ (rs6000_option_override_internal): Likewise.
+ (rs6000_expand_vector_set): Likewise.
+ * config/rs6000/rs6000.h (TARGET_UPPER_REGS_DF): Delete.
+ (TARGET_UPPER_REGS_SF): Likewise.
+ (TARGET_UPPER_REGS_DI): Likewise.
+ (TARGET_VEXTRACTUB): Eliminate TARGET_UPPER_REGS_{DF,DI,SF}.
+ (TARGET_DIRECT_MOVE_64BIT): Likewise.
+ * config/rs6000/rs6000.md (ALTIVEC_DFORM): Likewise.
+ (float<QHI:mode><FP_ISA3:mode>2_internal): Likewise.
+ (Splitters for DI constants in Altivec registers): Likewise.
+ * config/rs6000/vsx.md (vsx_set_<mode>_p9): Likewise.
+ (vsx_set_v4sf_p9): Likewise.
+ (vsx_set_v4sf_p9_zero): Likewise.
+ (vsx_insert_extract_v4sf_p9): Likewise.
+ (vsx_insert_extract_v4sf_p9_2): Likewise.
+
+2017-07-25 Carl Love <cel@us.ibm.com>
+
+ * doc/extend.texi: Update the built-in documentation file for the
+ existing built-in functions
+ vector signed char vec_cnttz (vector signed char);
+ vector unsigned char vec_cnttz (vector unsigned char);
+ vector signed short vec_cnttz (vector signed short);
+ vector unsigned short vec_cnttz (vector unsigned short);
+ vector signed int vec_cnttz (vector signed int);
+ vector unsigned int vec_cnttz (vector unsigned int);
+ vector signed long long vec_cnttz (vector signed long long);
+ vector unsigned long long vec_cnttz (vector unsigned long long);
+
+2017-07-25 Andrew Pinski <apinski@cavium.com>
+
+ * tree-ssa-uninit.c (warn_uninitialized_vars): Don't warn about memory
+ accesses where the use is for the first operand of a BIT_INSERT.
+
+2017-07-25 Jim Wilson <jim.wilson@linaro.org>
+
+ PR bootstrap/81521
+ * config/i386/winnt-cxx.c (i386_pe_adjust_class_at_definition): Look
+ for FUNCTION_DECLs in TYPE_FIELDS rather than TYPE_METHODS.
+
+2017-07-25 Jim Wilson <jim.wilson@linaro.org>
+
+ * config/i386/gstabs.h: Delete.
+ * config/i386/openbsd.h, config/i386/t-openbsd: Likewise.
+
+2017-07-25 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_decompose_address): Do not check for
+ register RTX when looking at index_reg or base_reg.
+ * config/i386/i386.h (INCOMING_RETURN_ADDR_RTX): Use stack_pointer_rtx.
+
+2017-07-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimple.c (gimple_assign_set_rhs_with_ops): Do not ask gsi_replace
+ to update EH info here.
+
+2017-07-25 Alexander Monakov <amonakov@ispras.ru>
+
+ * match.pd ((X * CST1) * CST2): Simplify to X * (CST1 * CST2).
+
+2017-07-25 Alexander Monakov <amonakov@ispras.ru>
+
+ * match.pd ((X * CST) * Y): Reassociate to (X * Y) * CST.
+
+2017-07-25 Torsten Duwe <duwe@suse.de>
+
+ * common.opt: Introduce -fpatchable-function-entry
+ command line option, and its variables function_entry_patch_area_size
+ and function_entry_patch_area_start.
+ * opts.c (common_handle_option): Add -fpatchable_function_entry_ case,
+ including a two-value parser.
+ * target.def (print_patchable_function_entry): New target hook.
+ * targhooks.h (default_print_patchable_function_entry): New function.
+ * targhooks.c (default_print_patchable_function_entry): Likewise.
+ * toplev.c (process_options): Switch off IPA-RA if
+ patchable function entries are being generated.
+ * varasm.c (assemble_start_function): Look at the
+ patchable-function-entry command line switch and current
+ function attributes and maybe generate NOP instructions by
+ calling the print_patchable_function_entry hook.
+ * doc/extend.texi: Document patchable_function_entry attribute.
+ * doc/invoke.texi: Document -fpatchable_function_entry
+ command line option.
+ * doc/tm.texi.in (TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY):
+ New target hook.
+ * doc/tm.texi: Re-generate.
+
+2017-07-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/81532
+ * config/i386/constraints.md (Yd, Ye): Use ALL_SSE_REGS for
+ TARGET_AVX512DQ rather than TARGET_AVX512BW.
+
+2017-07-25 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/parsecpu.awk (all_cores): Remove duplicates.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81455
+ * tree-ssa-loop-unswitch.c (find_loop_guard): Make sure to
+ not walk in cycles when looking for guards.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81529
+ * tree-vect-stmts.c (process_use): Disregard live induction PHIs
+ when optimizing backedge uses.
+
+2017-07-25 David Edelsohn <dje.gcc@gmail.com>
+
+ * dwarf2asm.c (dw2_asm_output_nstring): Encode double quote
+ character for AIX.
+ * dwarf2out.c (output_macinfo): Copy debug_line_section_label
+ to dl_section_ref. On AIX, append an expression to subtract
+ the size of the section length to dl_section_ref.
+
+2017-07-25 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * configure.ac: If any of the config.* scripts fail, exit 1.
+ * configure: Regenerate.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81546
+ * tree-ssa-operands.c (verify_imm_links): Remove cap on number
+ of immediate uses, be more verbose on errors.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81510
+ * tree-vect-loop.c (vect_is_simple_reduction): When the
+ reduction stmt is not inside the loop bail out.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81303
+ * tree-vect-loop-manip.c (vect_loop_versioning): Build
+ profitability check against LOOP_VINFO_NITERSM1.
+
+2017-07-25 Alexander Monakov <amonakov@ispras.ru>
+
+ * domwalk.c (cmp_bb_postorder): Simplify.
+ (sort_bbs_postorder): New function. Use it...
+ (dom_walker::walk): ...here to optimize common cases.
+
+2017-07-25 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81520
+ * ipa-visibility.c (function_and_variable_visibility): Make the
+ redirection just on target that supports aliasing.
+ Fix GNU coding style.
+
+2017-07-25 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ PR libgcc/61152
+ * config/aarch64/rtems.h: Add GCC Runtime Library Exception.
+ Format changes.
+ * config/arm/rtems.h: Likewise.
+ * config/bfin/rtems.h: Likewise.
+ * config/i386/rtemself.h: Likewise.
+ * config/lm32/rtems.h: Likewise.
+ * config/m32c/rtems.h: Likewise.
+ * config/m68k/rtemself.h: Likewise.
+ * config/microblaze/rtems.h: Likewise.
+ * config/mips/rtems.h: Likewise.
+ * config/moxie/rtems.h: Likewise.
+ * config/nios2/rtems.h: Likewise.
+ * config/powerpcspe/rtems.h: Likewise.
+ * config/rs6000/rtems.h: Likewise.
+ * config/rtems.h: Likewise.
+ * config/sh/rtems.h: Likewise.
+ * config/sh/rtemself.h: Likewise.
+ * config/sparc/rtemself.h: Likewise.
+
+2017-07-25 Georg-Johann Lay <avr@gjlay.de>
+
+ PR 81487
+ * hsa-brig.c (brig_init): Use xasprintf instead of asprintf.
+ * gimple-pretty-print.c (dump_profile, dump_probability): Same.
+ * tree-ssa-structalias.c (alias_get_name): Same.
+
+2017-07-25 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81414
+ * config/aarch64/cortex-a57-fma-steering.c (analyze): Skip fmul/fmac
+ instructions if no du chain is found.
+
+2017-07-25 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr-log.c (avr_log_vadump) ['T']: Print NULL-TREE.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81505
+ * fold-const.c (fold_negate_const): TREE_OVERFLOW should be
+ sticky.
+
+2017-07-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Delete
+ upper-regs options.
+ (ISA_2_7_MASKS_SERVER): Likewise.
+ (ISA_3_0_MASKS_IEEE): Likewise.
+ (OTHER_P8_VECTOR_MASKS): Likewise.
+ (OTHER_VSX_VECTOR_MASKS): Likewise.
+ (POWERPC_MASKS): Likewise.
+ (power7 cpu): Use ISA_2_6_MASKS_SERVER instead of using a
+ duplicate list of options.
+ * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Remove
+ explicit -mupper-regs options.
+ * config/rs6000/rs6000.opt (-mvsx-scalar-memory): Delete
+ -mupper-regs* options. Delete -mvsx-scalar-memory, which was an
+ alias for -mupper-regs-df.
+ * config/rs6000/rs6000.c (rs6000_setup_reg_addr_masks): Likewise.
+ (rs6000_init_hard_regno_mode_ok): Likewise.
+ (rs6000_option_override_internal): Likewise.
+ (rs6000_opt_masks): Likewise.
+ * config/rs6000/rs6000.h (TARGET_UPPER_REGS_DF): Define upper regs
+ options in terms of whether -mvsx or -mpower8-vector was used.
+ (TARGET_UPPER_REGS_DI): Likewise.
+ (TARGET_UPPER_REGS_SF): Likewise.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Delete the
+ -mupper-regs-* options.
+
+2017-07-24 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * passes.c (emergency_dump_function): Print some empty lines and a
+ header before the RTL dump.
+
+2017-07-24 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * cfgrtl.c (rtl_dump_bb): Don't call NEXT_INSN on NULL.
+
+2017-07-24 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/79041
+ * config/aarch64/aarch64.c (aarch64_classify_symbol):
+ Avoid SYMBOL_SMALL_ABSOLUTE for literals with pc-relative literals.
+
+2017-07-24 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for built-in functions
+ vector float vec_extract_fp32_from_shorth (vector unsigned short);
+ vector float vec_extract_fp32_from_shortl (vector unsigned short);
+ * config/rs6000/altivec.h (vec_extract_fp_from_shorth,
+ vec_extract_fp_from_shortl): Add defines for the two builtins.
+ * config/rs6000/rs6000-builtin.def (VEXTRACT_FP_FROM_SHORTH,
+ VEXTRACT_FP_FROM_SHORTL): Add BU_P9V_OVERLOAD_1 and BU_P9V_VSX_1
+ new builtins.
+ * config/rs6000/vsx.md vsx_xvcvhpsp): Add define_insn.
+ (vextract_fp_from_shorth, vextract_fp_from_shortl): Add define_expands.
+ * doc/extend.texi: Update the built-in documentation file for the
+ new built-in function.
+
+2017-07-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/81521
+ * tree.def: Remove TYPE_METHODS documentation, adjust TYPE_FIELDS
+ documentation.
+ * doc/generic.texi: Likewise.
+ * config/i386/winnt-cxx.c (i386_pe_adjust_class_at_definition): Look
+ for FUNCTION_DECLs in TYPE_FIELDS rather than TYPE_METHODS.
+
+2017-07-24 Jackson Woodruff <jackson.woodruff@arm.com>
+
+ * config/aarch64/aarch64-simd.md (aarch64_mla_elt_merge<mode>): New.
+ (aarch64_mls_elt_merge<mode>): Likewise.
+
+2017-07-23 Krister Walfridsson <krister.walfridsson@gmail.com>
+
+ * config.gcc (*-*-netbsd*): Remove check for NetBSD versions not
+ having __cxa_atexit.
+
+2017-07-23 Michael Collison <michael.collison@arm.com>
+
+ * config/arm/arm.c (arm_option_override): Deprecate
+ use of -mstructure-size-boundary.
+ * config/arm/arm.opt: Deprecate -mstructure-size-boundary.
+ * doc/invoke.texi: Deprecate -mstructure-size-boundary.
+
+2017-07-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR target/80695
+ * config/rs6000/rs6000.c (rs6000_builtin_vectorization_cost):
+ Reduce cost estimate for direct moves.
+
+2017-07-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/80569
+ * config/i386/i386.c (ix86_option_override_internal): Disable
+ BMI, BMI2 and TBM instructions for -m16.
+
+2017-07-21 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
+ ALTIVEC_BUILTIN_VMULESW, ALTIVEC_BUILTIN_VMULEUW,
+ ALTIVEC_BUILTIN_VMULOSW, ALTIVEC_BUILTIN_VMULOUW entries.
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin,
+ builtin_function_type): Add ALTIVEC_BUILTIN_* case statements.
+ * config/rs6000/altivec.md (MVULEUW, VMULESW, VMULOUW,
+ VMULOSW): New enum "unspec" values.
+ (altivec_vmuleuw, altivec_vmulesw, altivec_vmulouw,
+ altivec_vmulosw): New patterns.
+ * config/rs6000/rs6000-builtin.def (VMLEUW, VMULESW, VMULOUW,
+ VMULOSW): Add definitions.
+
+2017-07-21 Jim Wilson <jim.wilson@linaro.org>
+
+ * config/aarch64/aarch64-cores.def (falkor): Add AARCH64_FL_RDMA.
+ (qdf24xx): Likewise.
+ * config/aarch64/aarch64-options-extensions.def (rdma); New.
+ * config/aarch64/aarch64.h (AARCH64_FL_RDMA): New.
+ (AARCH64_FL_V8_1): Renumber.
+ (AARCH64_FL_FOR_ARCH8_1): Add AARCH64_FL_RDMA.
+ (AARCH64_ISA_RDMA): Use AARCH64_FL_RDMA.
+ * config/aarch64/arm_neon.h: Use +rdma instead of arch=armv8.1-a.
+ * doc/invoke.texi (AArch64 Options): Mention +rmda in -march docs. Add
+ rdma to feature modifiers list.
+
+2017-07-21 Yury Gribov <tetra2005@gmail.com>
+
+ PR middle-end/56727
+ * ipa-visibility (function_and_variable_visibility): Convert
+ recursive PLT call to direct call if appropriate.
+
+2017-07-21 Andrew Pinski <apinski@cavium.com>
+
+ * tree-ssa-sccvn.c (vn_nary_op_eq): Check BIT_INSERT_EXPR's
+ operand 1 to see if the types precision matches.
+ * fold-const.c (operand_equal_p): Likewise.
+
+2017-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81303
+ * tree-vect-data-refs.c (vect_get_peeling_costs_all_drs): Pass
+ in datarefs vector. Allow NULL dr0 for no peeling cost estimate.
+ (vect_peeling_hash_get_lowest_cost): Adjust.
+ (vect_enhance_data_refs_alignment): Likewise. Use
+ vect_get_peeling_costs_all_drs to compute the penalty for no
+ peeling to match up costs.
+
+2017-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81500
+ * tree-vect-loop.c (vect_is_simple_reduction): Properly fail if
+ we didn't identify a reduction path.
+
+2017-07-21 Tom de Vries <tom@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+
+ PR gcov-profile/81442
+ * config/nvptx/nvptx.c (nvptx_goacc_reduction_init): Add missing edge
+ probabilities.
+
+2017-07-21 Tom de Vries <tom@codesourcery.com>
+
+ PR lto/81430
+ * config/nvptx/nvptx.c (nvptx_override_options_after_change): New
+ function.
+ (TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE): Define to
+ nvptx_override_options_after_change.
+
+2017-07-21 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf2out.c (output_file_names): Avoid double testing for
+ dwarf_version >= 5.
+
+2017-07-21 Georg-Johann Lay <avr@gjlay.de>
+
+ * doc/invoke.texi (AVR Built-in Functions): Re-layout section.
+
+2016-07-21 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfgcleanup.c (flow_find_cross_jump): Do not crossjump across
+ hot/cold regions.
+ (try_crossjump_to_edge): Do not punt on partitioned functions.
+
+2016-07-21 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (find_rarely_executed_basic_blocks_and_crossing_edges):
+ Put all BBs reachable only via paths crossing cold region to cold
+ region.
+ * cfgrtl.c (find_bbs_reachable_by_hot_paths): New function.
+
+2016-07-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81303
+ * tree-vect-loop.c (vect_estimate_min_profitable_iters): Take
+ into account prologue and epilogue iterations when raising
+ min_profitable_iters to sth at least covering one vector iteration.
+
+2017-07-21 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm.c (arm_test_cpu_arch_dat):
+ Check for overlap.
+
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ Remove TYPE_METHODS.
+ * tree.h (TYPE_METHODS): Delete.
+ * dwarf2out.c (gen_member_die): Member fns are on TYPE_FIELDS.
+ * dbxout.c (dbxout_type_fields): Ignore FUNCTION_DECLs.
+ (dbxout_type_methods): Scan TYPE_FIELDS.
+ (dbxout_type): Don't check TYPE_METHODS here.
+ * function.c (use_register_for_decl): Always ignore register for
+ class types when not optimizing.
+ * ipa-devirt.c (odr_types_equivalent_p): Delete TYPE_METHODS scan.
+ * tree.c (free_lang_data_in_type): Stitch out member functions and
+ templates from TYPE_FIELDS.
+ (build_distinct_type_copy, verify_type_variant,
+ verify_type): Member fns are on TYPE_FIELDS.
+ * tree-dump.c (dequeue_and_dump): No TYPE_METHODS.
+ * tree-pretty-print.c (dump_generic_node): Likewise.
+
+2017-07-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/80846
+ * config/i386/i386.c (ix86_expand_vector_init_general): Handle
+ V2TImode and V4TImode.
+ (ix86_expand_vector_extract): Likewise.
+ * config/i386/sse.md (VMOVE): Enable V4TImode even for just
+ TARGET_AVX512F, instead of only for TARGET_AVX512BW.
+ (ssescalarmode): Handle V4TImode and V2TImode.
+ (VEC_EXTRACT_MODE): Add V4TImode and V2TImode.
+ (*vec_extractv2ti, *vec_extractv4ti): New insns.
+ (VEXTRACTI128_MODE): New mode iterator.
+ (splitter for *vec_extractv?ti first element): New.
+ (VEC_INIT_MODE): New mode iterator.
+ (vec_init<mode>): Consolidate 3 expanders into one using
+ VEC_INIT_MODE mode iterator.
+
+2017-07-20 Alexander Monakov <amonakov@ispras.ru>
+
+ * lra-assigns.c (pseudo_compare_func): Fix comparison step based on
+ non_spilled_static_chain_regno_p.
+
+2017-07-20 Alexander Monakov <amonakov@ispras.ru>
+
+ * gimple-ssa-store-merging.c (sort_by_bitpos): Return 0 on equal bitpos.
+
+2017-07-20 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (connect_traces): Allow copying of blocks within
+ single partition.
+
+2017-07-20 Richard Biener <rguenther@suse.de>
+
+ * gimple.h (gimple_phi_result): Add gphi * overload.
+ (gimple_phi_result_ptr): Likewise.
+ (gimple_phi_arg): Likewise. Adjust index assert to only
+ allow actual argument accesses rather than all slots available
+ by capacity.
+ (gimple_phi_arg_def): Add gphi * overload.
+ * tree-phinodes.c (make_phi_node): Initialize only actual
+ arguments.
+ (resize_phi_node): Clear memory not covered by old node,
+ do not initialize excess argument slots.
+ (reserve_phi_args_for_new_edge): Initialize new argument slot
+ completely.
+
+2017-07-20 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/81388
+ Revert r238585:
+ 2016-07-21 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): Clean up
+ by removing computation of may_be_zero.
+
+2017-07-18 Jan Hubicka <hubicka@ucw.cz>
+ Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/81030
+ * cfgbuild.c (find_many_sub_basic_blocks): Update REG_BR_PROB note
+ when gimple level profile disagrees with what RTL expander did.
+
+2017-07-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61171
+ * tree-vectorizer.h (slp_instance): Add reduc_phis member.
+ (vect_analyze_stmt): Add slp instance parameter.
+ (vectorizable_reduction): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_operations): Adjust.
+ (vect_is_simple_reduction): Deal with chains not detected
+ as SLP reduction chain, specifically not properly associated
+ chains containing a mix of plus/minus.
+ (get_reduction_op): Remove.
+ (get_initial_defs_for_reduction): Simplify, pass in whether
+ this is a reduction chain, pass in the SLP node for the PHIs.
+ (vect_create_epilog_for_reduction): Get the SLP instance as
+ arg and adjust.
+ (vectorizable_reduction): Get the SLP instance as arg.
+ During analysis remember the SLP node with the PHIs in the
+ instance. Simplify getting at the vectorized reduction PHIs.
+ * tree-vect-slp.c (vect_slp_analyze_node_operations): Pass
+ through SLP instance.
+ (vect_slp_analyze_operations): Likewise.
+ * tree-vect-stms.c (vect_analyze_stmt): Likewise.
+ (vect_transform_stmt): Likewise.
+
+2017-07-20 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/81489
+ * gimple-ssa-isolate-paths.c (find_implicit_erroneous_behavior): Move
+ read of phi arg location to before loop that modifies phi.
+
+2017-07-20 Naveen H.S <Naveen.Hurugalawadi@cavium.com>
+
+ * match.pd (((m1 >/</>=/<= m2) * d -> (m1 >/</>=/<= m2) ? d : 0):
+ New pattern.
+
+2017-07-19 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81331
+ * except.c (execute): Fix ordering issue.
+
+2018-07-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/81423
+ * combine.c (make_compound_operation_int): Don't try to optimize
+ the AND of a SUBREG of an LSHIFTRT if that SUBREG is paradoxical.
+
+2017-07-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/81423
+ * simplify-rtx.c (simplify_truncation): Handle truncating an IOR
+ with a constant that is -1 in the truncated to mode.
+
+2017-07-19 Jan Hubicka <hubicka@ucw.cz>
+
+ * predict.c (propagate_unlikely_bbs_forward): Break out from ...
+ (determine_unlikely_bbs): ... here.
+ * predict.h (propagate_unlikely_bbs_forward): Declare.
+ * cfgexpand.c (pass_expand::execute): Use it.
+ * bb-reorder.c (sanitize_hot_paths): Do not consider known to be
+ unlikely edges.
+ (find_rarely_executed_basic_blocks_and_crossing_edges): Use
+ propagate_unlikely_bbs_forward.
+
+2017-07-19 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81331
+ * except.c (maybe_add_nop_after_section_switch): New function.
+ (execute): Use it.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * gimple.h (gimple_phi_set_arg): Make assert more strict.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * gimple.h (gimple_phi_arg): Make assert more strict.
+
+2017-07-19 Steven Munroe <munroesj@gcc.gnu.org>
+
+ * config.gcc (powerpc*-*-*): Add mmintrin.h.
+ * config/rs6000/mmintrin.h: New file.
+ * config/rs6000/x86intrin.h [__ALTIVEC__]: Include mmintrin.h.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81346
+ * match.pd: Optimize (X - 1U) <= INT_MAX-1U into (int) X > 0.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * config/nvptx/nvptx.md (VECIM): Add V2DI.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * config/nvptx/nvptx-modes.def: Add V2DImode.
+ * config/nvptx/nvptx-protos.h (nvptx_data_alignment): Declare.
+ * config/nvptx/nvptx.c (nvptx_ptx_type_from_mode): Handle V2DImode.
+ (nvptx_output_mov_insn): Handle lack of mov.b128.
+ (nvptx_print_operand): Handle 'H' and 'L' codes.
+ (nvptx_vector_mode_supported): Allow V2DImode.
+ (nvptx_preferred_simd_mode): New function.
+ (nvptx_data_alignment): New function.
+ (TARGET_VECTORIZE_PREFERRED_SIMD_MODE): Redefine to
+ nvptx_preferred_simd_mode.
+ * config/nvptx/nvptx.h (STACK_BOUNDARY, BIGGEST_ALIGNMENT): Change from
+ 64 to 128 bits.
+ (DATA_ALIGNMENT): Define. Set to nvptx_data_alignment.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * config/nvptx/nvptx-modes.def: New file. Add V2SImode.
+ * config/nvptx/nvptx.c (nvptx_ptx_type_from_mode): Handle V2SImode.
+ (nvptx_vector_mode_supported): New function. Allow V2SImode.
+ (TARGET_VECTOR_MODE_SUPPORTED_P): Redefine to nvptx_vector_mode_supported.
+ * config/nvptx/nvptx.md (VECIM): New mode iterator. Add V2SI.
+ (mov<VECIM>_insn): New define_insn.
+ (define_expand "mov<VECIM>): New define_expand.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * config/nvptx/nvptx.c (nvptx_print_operand): Handle v2 vector mode.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81346
+ * fold-const.h (fold_div_compare, range_check_type): Declare.
+ * fold-const.c (range_check_type): New function.
+ (build_range_check): Use range_check_type.
+ (fold_div_compare): No longer static, rewritten into
+ a match.pd helper function.
+ (fold_comparison): Don't call fold_div_compare here.
+ * match.pd (X / C1 op C2): New optimization using fold_div_compare
+ as helper function.
+
+2017-07-19 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (TYPE_MINVAL, TYPE_MAXVAL): Rename to ...
+ (TYPE_MIN_VALUE_RAW, TYPE_MAX_VALUE_RAW): ... these.
+ * tree.c (find_decls_types_r, verify_type): Use
+ TYPE_{MIN,MAX}_VALUE_RAW.
+ * lto-streamer-out.c (DFS::DFS_write_tree_body): Likewise.
+ (hash_tree): Likewise.
+ * tree-streamer-in.c (lto_input_ts_type_non_common_tree_pointers):
+ Likewise.
+ * tree-streamer-out.c (write_ts_type_non_common_tree_pointers):
+ Likewise.
+
+2017-07-18 Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/81464
+ * omp-expand.c (expand_omp_for_static_chunk): Handle
+ equal-argument loop exit phi.
+
+2017-07-18 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81471
+ * config/i386/i386.md (rorx_immediate_operand): New mode attribute.
+ (*bmi2_rorx<mode>3_1): Use rorx_immediate_operand as
+ operand 2 predicate.
+ (*bmi2_rorxsi3_1_zext): Use const_0_to_31_operand as
+ operand 2 predicate.
+ (ror,rol -> rorx splitters): Use const_int_operand as
+ operand 2 predicate.
+
+2017-06-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81410
+ * tree-vect-stmts.c (vectorizable_load): Properly adjust for
+ the gap in the ! slp_perm SLP case after each group.
+
+2017-07-18 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81463
+ * cfgloopmanip.c (scale_loop_profile): Watch out for zero frequency
+ again.
+
+2017-07-18 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81462
+ * predict.c (set_even_probabilities): Cleanup; do not affect
+ probabilities that are already known.
+ (combine_predictions_for_bb): Call even when count is set.
+
+2017-07-18 Nathan Sidwell <nathan@acm.org>
+
+ * tree-parloops.c (try_transform_to_exit_first_loop_alt): Use
+ TYPE_MAX_VALUE.
+
+2017-07-18 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81408
+ * tree-ssa-loop-niter.c (number_of_iterations_exit): Dump missed
+ optimization for loop niter analysis.
+
+2017-07-18 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/81473
+ * config/avr/avr.c (avr_optimize_casesi): Don't use
+ INT8_MIN, INT8_MAX, UINT8_MAX, INT16_MIN, INT16_MAX, UINT16_MAX.
+
+2017-07-18 Robin Dapp <rdapp@linux.vnet.ibm.com>
+
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Remove
+ body_cost_vec from _vect_peel_extended_info.
+ (vect_peeling_hash_get_lowest_cost): Do not set body_cost_vec.
+ (vect_peeling_hash_choose_best_peeling): Remove body_cost_vec and
+ npeel.
+
+2017-07-18 Bin Cheng <bin.cheng@arm.com>
+
+ * config/arm/arm.c (emit_unlikely_jump): Remove unused var.
+
+2017-07-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80620
+ PR tree-optimization/81403
+ * tree-ssa-pre.c (phi_translate_1): Clear range and points-to
+ info when re-using a VN table entry.
+
+2017-07-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81418
+ * tree-vect-loop.c (vectorizable_reduction): Properly compute
+ vectype_in. Verify that with lane-reducing reduction operations
+ we have a single def-use cycle.
+
+2017-07-17 Carl Love <cel@us.ibm.com>
+
+ Revert commit r249424 2017-06-20 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
+ ALTIVEC_BUILTIN_VMULESW, ALTIVEC_BUILTIN_VMULEUW,
+ ALTIVEC_BUILTIN_VMULOSW, ALTIVEC_BUILTIN_VMULOUW entries.
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin,
+ builtin_function_type): Add ALTIVEC_BUILTIN_* case statements.
+ * config/rs6000/altivec.md (MVULEUW, VMULESW, VMULOUW,
+ VMULOSW): New enum "unspec" values.
+ (vec_widen_umult_even_v4si, vec_widen_smult_even_v4si,
+ vec_widen_umult_odd_v4si, vec_widen_smult_odd_v4si,
+ altivec_vmuleuw, altivec_vmulesw, altivec_vmulouw,
+ altivec_vmulosw): New patterns.
+ * config/rs6000/rs6000-builtin.def (VMLEUW, VMULESW, VMULOUW,
+ VMULOSW): Add definitions.
+2017-07-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/alpha.c: Include predict.h.
+
+2017-07-17 Yury Gribov <tetra2005@gmail.com>
+
+ * tree-vrp.c (compare_assert_loc): Fix comparison function
+ to return predictable results.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (adddi3): Remove support for mexpand-adddi
+ option.
+ (subdi3): Likewise.
+ * config/arc/arc.opt (mexpand-adddi): Deprecate it.
+ * doc/invoke.texi (mexpand-adddi): Update text.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (clzsi2): Expand to an arc_clzsi2 instruction
+ that also clobbers the CC register. The old expand code is moved
+ to ...
+ (*arc_clzsi2): ... here.
+ (ctzsi2): Expand to an arc_ctzsi2 instruction that also clobbers
+ the CC register. The old expand code is moved to ...
+ (arc_ctzsi2): ... here.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.opt (mindexed-loads): Use initial value
+ TARGET_INDEXED_LOADS_DEFAULT.
+ (mauto-modify-reg): Use initial value
+ TARGET_AUTO_MODIFY_REG_DEFAULT.
+ * config/arc/elf.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
+ (TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
+ * config/arc/linux.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
+ (TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
+
+2017-07-17 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81302
+ * opts.c (finish_options): Do not allow -fgnu-tm
+ w/ -fsanitize={kernel-,}address. Say sorry.
+
+2017-07-17 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81369
+ * tree-loop-distribution.c (classify_partition): Only assert on
+ numer of iterations.
+ (merge_dep_scc_partitions): Delete prameter. Update function call.
+ (distribute_loop): Remove code handling loop with unknown niters.
+ (pass_loop_distribution::execute): Skip loop with unknown niters.
+
+2017-07-17 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81369
+ * tree-loop-distribution.c (merge_dep_scc_partitions): Sink call to
+ function sort_partitions_by_post_order.
+
+2017-07-17 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/81374
+ * tree-loop-distribution.c (pass_loop_distribution::execute): Record
+ the max index of basic blocks, rather than number of basic blocks.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc-protos.h (arc_legitimate_pc_offset_p): Remove
+ proto.
+ (arc_legitimate_pic_operand_p): Likewise.
+ * config/arc/arc.c (arc_legitimate_pic_operand_p): Remove
+ function.
+ (arc_needs_pcl_p): Likewise.
+ (arc_legitimate_pc_offset_p): Likewise.
+ (arc_legitimate_pic_addr_p): Remove LABEL_REF case, as this
+ function is also used in constrains.md.
+ (arc_legitimate_constant_p): Use arc_legitimate_pic_addr_p to
+ validate pic constants. Handle CONST_INT, CONST_DOUBLE, MINUS and
+ PLUS. Only return true/false in known cases, otherwise assert.
+ (arc_legitimate_address_p): Remove arc_legitimate_pic_addr_p as it
+ is already called in arc_legitimate_constant_p.
+ * config/arc/arc.h (CONSTANT_ADDRESS_P): Consider also LABEL for
+ pic addresses.
+ (LEGITIMATE_PIC_OPERAND_P): Use
+ arc_raw_symbolic_reference_mentioned_p function.
+ * config/arc/constraints.md (Cpc): Use arc_legitimate_pic_addr_p
+ function.
+ (Cal): Likewise.
+ (C32): Likewise.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+ Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
+ (arc_return_address_register): New function.
+ * config/arc/arc.c (arc_handle_fndecl_attribute): New function.
+ (arc_handle_fndecl_attribute): Add naked attribute.
+ (TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
+ (TARGET_WARN_FUNC_RETURN): Likewise.
+ (arc_allocate_stack_slots_for_args): New function.
+ (arc_warn_func_return): Likewise.
+ (machine_function): Change type fn_type.
+ (arc_compute_function_type): Consider new naked function type,
+ change function return type.
+ (arc_must_save_register): Adapt to handle new
+ arc_compute_function_type's return type.
+ (arc_expand_prologue): Likewise.
+ (arc_expand_epilogue): Likewise.
+ (arc_return_address_regs): Delete.
+ (arc_return_address_register): New function.
+ (arc_epilogue_uses): Use above function.
+ * config/arc/arc.h (arc_return_address_regs): Delete prototype.
+ (arc_function_type): Change encoding, add naked type.
+ (ARC_INTERRUPT_P): Change to handle the new encoding.
+ (ARC_FAST_INTERRUPT_P): Likewise.
+ (ARC_NORMAL_P): Define.
+ (ARC_NAKED_P): Likewise.
+ (arc_compute_function_type): Delete prototype.
+ * config/arc/arc.md (in_ret_delay_slot): Use
+ arc_return_address_register function.
+ (simple_return): Likewise.
+ (p_return_i): Likewise.
+
+2017-07-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81428
+ * match.pd (X / X -> one): Don't optimize _Fract divisions, as 1
+ can't be built for those types.
+
+2017-07-17 Georg-Johann Lay <avr@gjlay.de>
+
+ Remove stuff dead since r239246.
+
+ * config/avr/avr-arch.h (avr_inform_devices): Remove dead proto.
+ * config/avr/avr-devices.c (mcu_name, comparator, avr_mcus_str)
+ (avr_inform_devices): Remove dead stuff.
+
+2017-07-17 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm_neon.h: Fix softp typo.
+
+2017-07-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81365
+ * tree-ssa-phiprop.c (propagate_with_phi): When considering hoisting
+ aggregate moves onto bb predecessor edges, make sure there are no
+ loads that could alias the lhs in between the start of bb and the
+ loads from *phi.
+
+2017-07-17 Georg-Johann Lay <avr@gjlay.de>
+
+ PR 80929
+ * config/avr/avr.c (avr_mul_highpart_cost): New static function.
+ (avr_rtx_costs_1) [TRUNCATE]: Use it to compute mul_highpart cost.
+ [LSHIFTRT, outer_code = TRUNCATE]: Same.
+
+2017-07-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81396
+ * tree-ssa-math-opts.c (struct symbolic_number): Add n_ops field.
+ (init_symbolic_number): Initialize it to 1.
+ (perform_symbolic_merge): Add n_ops from both operands into the new
+ n_ops.
+ (find_bswap_or_nop): Don't consider n->n == cmpnop computations
+ without base_addr as useless if they need more than one operation.
+ (bswap_replace): Handle !bswap case for NULL base_addr.
+
+2017-07-17 Tom de Vries <tom@codesourcery.com>
+
+ PR target/81069
+ * config/nvptx/nvptx.c (nvptx_single): Insert diverging branch as late
+ as possible.
+
+2017-07-17 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/sparc/rtemself.h (TARGET_OS_CPP_BUILTINS): Add
+ conditional builtin define __FIX_LEON3FT_B2BST.
+
+2017-07-17 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/t-rtems: Add mfix-gr712rc multilibs. Replace
+ MULTILIB_EXCEPTIONS with MULTILIB_REQUIRED. Match -mfix-gr712rc
+ with -mfix-ut700.
+
+2017-07-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/81424
+ * optabs.c (prepare_cmp_insn): Use copy_to_reg instead of force_reg
+ to remove potential trapping from operands if -fnon-call-exceptions.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Use
+ profile_proability for scalling.
+ * scale_profile_for_vect_loop.c (scale_profile_for_vect_loop): Likewise.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.c (cgraph_edge::redirect_call_stmt_to_caller): Cleanup.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfgloopmanip.c (scale_loop_profile): Avoid use of REG_BR_PROB_BASE
+ fixpoint arithmetics.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-loop-unswitch.c (hoist_guard): Avoid use of REG_BR_PROB_BASE
+ fixpoint arithmetics.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * asan.c (create_cond_insert_point): Avoid use of REG_BR_PROB_BASE
+ fixpoint arithmetics.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.h (profile_probability::from_reg_br_prob_note,
+ profile_probability::to_reg_br_prob_note): New functions.
+ * doc/rtl.texi (REG_BR_PROB_NOTE): Update documentation.
+ * reg-notes.h (REG_BR_PROB, REG_BR_PRED): Update docs.
+ * predict.c (probability_reliable_p): Update.
+ (edge_probability_reliable_p): Update.
+ (br_prob_note_reliable_p): Update.
+ (invert_br_probabilities): Update.
+ (add_reg_br_prob_note): New function.
+ (combine_predictions_for_insn): Update.
+ * asan.c (asan_clear_shadow): Update.
+ * cfgbuild.c (compute_outgoing_frequencies): Update.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Update.
+ (update_br_prob_note): Update.
+ (rtl_verify_edges): Update.
+ (purge_dead_edges): Update.
+ (fixup_reorder_chain): Update.
+ * emit-rtl.c (try_split): Update.
+ * ifcvt.c (cond_exec_process_insns): Update.
+ (cond_exec_process_if_block): Update.
+ (dead_or_predicable): Update.
+ * internal-fn.c (expand_addsub_overflow): Update.
+ (expand_neg_overflow): Update.
+ (expand_mul_overflow): Update.
+ * loop-doloop.c (doloop_modify): Update.
+ * loop-unroll.c (compare_and_jump_seq): Update.
+ * optabs.c (emit_cmp_and_jump_insn_1): Update.
+ * predict.h: Update.
+ * reorg.c (mostly_true_jump): Update.
+ * rtl.h: Update.
+ * config/aarch64/aarch64.c (aarch64_emit_unlikely_jump): Update.
+ * config/alpha/alpha.c (emit_unlikely_jump): Update.
+ * config/arc/arc.c: (emit_unlikely_jump): Update.
+ * config/arm/arm.c: (emit_unlikely_jump): Update.
+ * config/bfin/bfin.c (cbranch_predicted_taken_p): Update.
+ * config/frv/frv.c (frv_print_operand_jump_hint): Update.
+ * config/i386/i386.c (ix86_expand_split_stack_prologue): Update.
+ (ix86_print_operand): Update.
+ (ix86_split_fp_branch): Update.
+ (predict_jump): Update.
+ * config/ia64/ia64.c (ia64_print_operand): Update.
+ * config/mmix/mmix.c (mmix_print_operand): Update.
+ * config/powerpcspe/powerpcspe.c (output_cbranch): Update.
+ (rs6000_expand_split_stack_prologue): Update.
+ * config/rs6000/rs6000.c: Update.
+ * config/s390/s390.c (s390_expand_vec_strlen): Update.
+ (s390_expand_vec_movstr): Update.
+ (s390_expand_cs_tdsi): Update.
+ (s390_expand_split_stack_prologue): Update.
+ * config/sh/sh.c (sh_print_operand): Update.
+ (expand_cbranchsi4): Update.
+ (expand_cbranchdi4): Update.
+ * config/sparc/sparc.c (output_v9branch): Update.
+ * config/spu/spu.c (get_branch_target): Update.
+ (ea_load_store_inline): Update.
+ * config/tilegx/tilegx.c (cbranch_predicted_p): Update.
+ * config/tilepro/tilepro.c: Update.
+
+2017-07-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimplify.c (mostly_copy_tree_r): Revert latest change.
+ (gimplify_save_expr): Likewise.
+
+2017-07-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-visibility.c (function_and_variable_visibility): Fix pasto.
+
+2017-07-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-fnsummary.c (pass_data_ipa_fn_summary): Use
+ TV_IPA_FNSUMMARY.
+ * timevar.def (TV_IPA_FNSUMMARY): Define.
+
+2017-07-16 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.md (divdf3_fix): Add NOP to prevent back
+ to back store errata sensitive sequence from being generated.
+ (sqrtdf2_fix): Likewise.
+
+2017-07-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-threadupdate.c (compute_path_counts,
+ update_joiner_offpath_counts): Use profile_probability.
+
+2017-07-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ Revert:
+ 2017-07-14 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-c.c (arm_cpu_builtins): Define
+ __ARM_FEATURE_NUMERIC_MAXMIN solely based on TARGET_VFP5.
+
+2017-07-14 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
+ array entries to represent __ieee128 versions of the
+ scalar_test_data_class, scalar_test_neg, scalar_extract_exp,
+ scalar_extract_sig, and scalar_insert_exp built-in functions.
+ (altivec_resolve_overloaded_builtin): Add special case handling
+ for the __builtin_scalar_insert_exp function, as represented by
+ the P9V_BUILTIN_VEC_VSIEDP constant.
+ * config/rs6000/rs6000-builtin.def (VSEEQP): Add scalar extract
+ exponent support for __ieee128 argument.
+ (VSESQP): Add scalar extract signature support for __ieee128
+ argument.
+ (VSTDCNQP): Add scalar test negative support for __ieee128
+ argument.
+ (VSIEQP): Add scalar insert exponent support for __int128 argument
+ with __ieee128 result.
+ (VSIEQPF): Add scalar insert exponent support for __ieee128
+ argument with __ieee128 result.
+ (VSTDCQP): Add scalar test data class support for __ieee128
+ argument.
+ (VSTDCNQP): Add overload support for scalar test negative with
+ __ieee128 argument.
+ (VSTDCQP): Add overload support for scalar test data class
+ __ieee128 argument.
+ * config/rs6000/vsx.md (UNSPEC_VSX_SXSIG) Replace
+ UNSPEC_VSX_SXSIGDP.
+ (UNSPEC_VSX_SIEXPQP): New constant.
+ (xsxexpqp): New insn for VSX scalar extract exponent quad
+ precision.
+ (xsxsigqp): New insn for VSX scalar extract significand quad
+ precision.
+ (xsiexpqpf): New insn for VSX scalar insert exponent quad
+ precision with floating point argument.
+ (xststdcqp): New expand for VSX scalar test data class quad
+ precision.
+ (xststdcnegqp): New expand for VSX scalar test negative quad
+ precision.
+ (xststdcqp): New insn to match expansions for VSX scalar test data
+ class quad precision and VSX scalar test negative quad precision.
+ * config/rs6000/rs6000.c (rs6000_expand_binop_builtin): Add
+ special case operand checking to enforce that second operand of
+ VSX scalar test data class with quad precision argument is a 7-bit
+ unsigned literal.
+ * doc/extend.texi (PowerPC AltiVec Built-in Functions): Add
+ prototypes and descriptions of __ieee128 versions of
+ scalar_extract_exp, scalar_extract_sig, scalar_insert_exp,
+ scalar_test_data_class, and scalar_test_neg built-in functions.
+
+2016-07-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/81162
+ * gimple-ssa-strength-reduction.c (replace_mult_candidate): Don't
+ replace a negate with an add.
+
+2017-07-14 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * doc/invoke.texi (arm/-mcpu): Document +crypto.
+
+2017-07-14 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-c.c (arm_cpu_builtins): Define
+ __ARM_FEATURE_NUMERIC_MAXMIN solely based on TARGET_VFP5.
+
+2017-07-14 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-cpus.in (cortex-r52): Add new entry.
+ (armv8-r): Set ARM Cortex-R52 as default CPU.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Regenerate.
+ * config/arm/driver-arm.c (arm_cpu_table): Add entry for ARM
+ Cortex-R52.
+ * doc/invoke.texi: Mention -mtune=cortex-r52 and availability of fp.dp
+ extension for -mcpu=cortex-r52.
+
+2017-07-14 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-isa.h (isa_bit_FP_ARMv8): Delete enumerator.
+ (ISA_FP_ARMv8): Define as ISA_FPv5 and ISA_FP_D32.
+ * config/arm/arm-cpus.in (armv8-r): Define fp.sp as enabling FPv5.
+ (fp-armv8): Define it as FP_ARMv8 only.
+ config/arm/arm.h (TARGET_FPU_ARMV8): Delete.
+ (TARGET_VFP_FP16INST): Define using TARGET_VFP5 rather than
+ TARGET_FPU_ARMV8.
+ config/arm/arm.c (arm_rtx_costs_internal): Replace checks against
+ TARGET_FPU_ARMV8 by checks against TARGET_VFP5.
+ * config/arm/arm-builtins.c (arm_builtin_vectorized_function): Define
+ first ARM_CHECK_BUILTIN_MODE definition using TARGET_VFP5 rather
+ than TARGET_FPU_ARMV8.
+ * config/arm/arm-c.c (arm_cpu_builtins): Likewise for
+ __ARM_FEATURE_NUMERIC_MAXMIN macro definition.
+ * config/arm/arm.md (cmov<mode>): Condition on TARGET_VFP5 rather than
+ TARGET_FPU_ARMV8.
+ * config/arm/neon.md (neon_vrint): Likewise.
+ (neon_vcvt): Likewise.
+ (neon_<fmaxmin_op><mode>): Likewise.
+ (<fmaxmin><mode>3): Likewise.
+ * config/arm/vfp.md (l<vrint_pattern><su_optab><mode>si2): Likewise.
+ * config/arm/predicates.md (arm_cond_move_operator): Check against
+ TARGET_VFP5 rather than TARGET_FPU_ARMV8 and fix spacing.
+
+2017-07-14 Jackson Woodruff <jackson.woodruff@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_print_operand): Move comments
+ to top of function.
+
+2017-07-14 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gimple-ssa-store-merging.c (clear_bit_region): Replace reference to
+ loop in comment with memset.
+
+2017-07-14 Martin Liska <mliska@suse.cz>
+
+ * cfgexpand.c (expand_gimple_basic_block): Remove dead comment.
+ * dwarf2out.c (is_java): Remove the function.
+ (output_pubname): Remove usage of the function.
+ (lower_bound_default): Remove usage of DW_LANG_Java.
+ (gen_compile_unit_die): Likewise.
+ * gcc.c: Remove compiler defaults for .java and .zip files.
+ * gimple-expr.c (remove_suffix): Change as there's no longer
+ extension than 4-letter one.
+ * gimplify.c (mostly_copy_tree_r): Remove Java-special part.
+ (gimplify_save_expr): Likewise.
+ * ipa-utils.h (polymorphic_type_binfo_p): Remove the comment
+ as it's possible even for other languages than Java.
+ * langhooks.h (struct lang_hooks): Remove Java from a comment.
+ * lto-opts.c (lto_write_options): Remove reference to Java.
+ * opts.c (strip_off_ending): Update file extension handling.
+ * tree-cfg.c (verify_gimple_call): Remove comment with Java.
+ * tree-eh.c (lower_resx): Likewise.
+ * tree.c (free_lang_data_in_type): Remove dead code.
+ (find_decls_types_r): Likewise.
+ (build_common_builtin_nodes): Remove Java from a comment.
+ (verify_type): Remove dead code.
+ * varasm.c (assemble_external): Remove Java from a comment.
+
+2017-07-14 Martin Liska <mliska@suse.cz>
+
+ * opts.c (finish_options): Add quotes.
+ (common_handle_option): Likewise.
+
+2017-07-14 Martin Liska <mliska@suse.cz>
+
+ * dbxout.c (get_lang_number): Do not handle GNU Pascal.
+ * dbxout.h (extern void dbxout_stab_value_internal_label_diff):
+ Remove N_SO_PASCAL.
+ * dwarf2out.c (lower_bound_default): Do not handle
+ DW_LANG_Pascal83.
+ (gen_compile_unit_die): Likewise.
+ * gcc.c: Remove default extension binding for GNU Pascal.
+ * stmt.c: Remove Pascal language from a comment.
+ * xcoffout.c: Likewise.
+
+2017-07-13 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/81405
+ * diagnostic-show-locus.c (fixit_cmp): New function.
+ (layout::layout): Sort m_fixit_hints.
+ (column_range::column_range): Assert that the values are valid.
+ (struct char_span): New struct.
+ (correction::overwrite): New method.
+ (struct source_line): New struct.
+ (line_corrections::add_hint): Add assertions. Reimplement memcpy
+ calls in terms of classes source_line and char_span, and
+ correction::overwrite.
+ (selftest::test_overlapped_fixit_printing_2): New function.
+ (selftest::diagnostic_show_locus_c_tests): Call it.
+
+2017-07-13 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Return
+ early if there is no lhs.
+
+2017-07-13 Martin Liska <mliska@suse.cz>
+
+ * dwarf2out.c (gen_pointer_type_die): Remove dead code.
+ (gen_reference_type_die): Likewise.
+ * stor-layout.c: Remove Pascal-related comment.
+
+2017-07-13 Martin Liska <mliska@suse.cz>
+
+ * opts.c (finish_options): Add quotes to error messages.
+ (parse_sanitizer_options): Likewise.
+
+2017-07-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * doc/invoke.texi (armv8-r): Document +fp.sp ARMv8-R extension.
+
+2017-07-13 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/vxworks.h (TARGET_ENDIAN_DEFAULT): Define.
+
+2017-07-13 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * asan.c (asan_emit_allocas_unpoison): Use ptr_mode for arguments
+ during expansion.
+ * builtins.c (expand_asan_emit_allocas_unpoison): Likewise.
+
+2017-07-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/81193
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): If GLIBC
+ provides the hardware capability bits, define the macro
+ __BUILTIN_CPU_SUPPORTS__.
+ * config/rs6000/rs6000.c (cpu_expand_builtin): Generate a warning
+ if GLIBC does not provide the hardware capability bits. Add a
+ gcc_unreachable call if the built-in cpu function is neither
+ __builtin_cpu_is nor __builtin_cpu_supports.
+ (rs6000_get_function_versions_dispatcher): Change the warning
+ that an old GLIBC is used which does not export the capability
+ bits to be an error.
+ * doc/extend.texi (target_clones attribute): Document the
+ restriction that GLIBC 2.23 or newer is needed on the PowerPC.
+ (PowerPC built-in functions): Document that GLIBC 2.23 or newer is
+ needed by __builtin_cpu_is and __builtin_cpu_supports. Document
+ the macros defined by GCC if the newer GLIBC is available.
+
+2017-07-12 Jeff Law <law@redhat.com>
+
+ * config/riscv/riscv.c: Remove unnecessary includes. Reorder
+ remaining includes slightly.
+ * config/riscv/riscv-builtins.c: Include profile-count.h.
+
+2017-07-12 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/79883
+ * config/avr/avr.c (avr_set_current_function): In diagnostic
+ messages: Quote keywords and (parts of) identifiers.
+ [WITH_AVRLIBC]: Warn for functions named "ISR", "SIGNAL" or
+ "INTERUPT".
+
+2017-07-12 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for built-in functions
+ vector bool char vec_revb (vector bool char);
+ vector bool short vec_revb (vector short char);
+ vector bool int vec_revb (vector bool int);
+ vector bool long long vec_revb (vector bool long long);
+ * doc/extend.texi: Update the built-in documentation file for the
+ new built-in functions.
+
+2017-07-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/s390.md: Remove movcc splitter.
+
+2017-07-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/s390.c (s390_rtx_costs): Return proper costs for
+ load/store on condition.
+
+2017-07-12 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/81407
+ * config/avr/avr.c (avr_encode_section_info)
+ [progmem && !TREE_READONLY]: Error if progmem object needs
+ constructing.
+
+2017-07-11 Michael Collison <michael.collison@arm.com>
+
+ * config/aarch64/aarch64-simd.md (aarch64_sub<mode>_compare0):
+ New pattern.
+
+2017-07-11 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for builtins
+ vector unsigned int vec_parity_lsbb (vector signed int);
+ vector unsigned int vec_parity_lsbb (vector unsigned int);
+ vector unsigned __int128 vec_parity_lsbb (vector signed __int128);
+ vector unsigned __int128 vec_parity_lsbb (vector unsigned __int128);
+ vector unsigned long long vec_parity_lsbb (vector signed long long);
+ vector unsigned long long vec_parity_lsbb (vector unsigned long long);
+ * config/rs6000/rs6000-builtin.def (VPARITY_LSBB): Add BU_P9V_OVERLOAD1.
+ * config/rs6000/altivec.h (vec_parity_lsbb): Add define.
+ * doc/extend.texi: Update the built-in documentation file for the
+ new built-in functions.
+
+2017-07-11 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-show-locus.c: Include "gcc-rich-location.h".
+ (layout::m_primary_loc): New field.
+ (layout::layout): Initialize new field. Move location filtering
+ logic from here to...
+ (layout::maybe_add_location_range): ...this new method. Add
+ support for filtering to just the lines already specified by other
+ locations.
+ (layout::will_show_line_p): New method.
+ (gcc_rich_location::add_location_if_nearby): New method.
+ (selftest::test_add_location_if_nearby): New test function.
+ (selftest::diagnostic_show_locus_c_tests): Call it.
+ * gcc-rich-location.h (gcc_rich_location::add_location_if_nearby):
+ New method.
+
+2017-07-11 Tom de Vries <tom@codesourcery.com>
+
+ * config/nvptx/nvptx.c (WORKAROUND_PTXJIT_BUG): New macro.
+ (bb_first_real_insn): New function.
+ (nvptx_single): Add extra initialization of broadcasted condition
+ variables.
+
+2017-07-11 Nathan Sidwell <nathan@acm.org>
+
+ * dwarf2out.c (gen_member_die): Remove useless check for anon ctors.
+
+2017-07-11 Georg-Johann Lay <avr@gjlay.de>
+
+ * doc/extend.texi (AVR Function Attributes): Remove weblink to
+ Binutils doc as TEXI will mess them up.
+ * doc/invoke.texi (AVR Options): Same here.
+
+2017-07-11 Daniel Cederman <cederman@gaisler.com>
+
+ * config/sparc/sparc.opt (mfix-ut700): New option.
+ (mfix-gr712rc): Likewise.
+ (sparc_fix_b2bst): New variable.
+ * doc/invoke.texi (SPARC options): Document them.
+ (ARM options): Fix warnings.
+ * config/sparc/sparc.c (sparc_do_work_around_errata): Insert NOP
+ instructions to prevent sequences that can trigger the store-store
+ errata for certain LEON3FT processors.
+ (pass_work_around_errata::gate): Also test sparc_fix_b2bst.
+ (sparc_option_override): Set sparc_fix_b2bst appropriately.
+ * config/sparc/sparc.md (fix_b2bst): New attribute.
+ (in_branch_delay): Prevent stores in delay slot if fix_b2bst.
+
+2017-07-10 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81375
+ * config/i386/i386.md (divsf3): Add TARGET_SSE to TARGET_SSE_MATH.
+ (rcpps): Ditto.
+ (*rsqrtsf2_sse): Ditto.
+ (rsqrtsf2): Ditto.
+ (div<mode>3): Macroize insn from divdf3 and divsf3
+ using MODEF mode iterator.
+
+2017-07-10 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/80397
+ * gimple-ssa-sprintf.c (format_integer): Use INTEGRAL_TYPE_P()
+ instead of testing for equality to INTEGER_TYPE.
+
+2017-07-10 Vineet Gupta <vgupta@synopsys.com>
+
+ * config.gcc: Remove uclibc from arc target spec.
+
+2017-07-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.h (ADDITIONAL_REGISTER_NAMES): Define.
+
+2017-07-07 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/80838
+ * lto-wrapper.c (remove_option): New function.
+ (merge_and_complain): Merge PIC/PIE options more realistically.
+
+2017-07-10 Georg-Johann Lay <avr@gjlay.de>
+
+ Better ISR prologues by supporting GASes __gcc_isr pseudo insn.
+
+ PR target/20296
+ PR target/81268
+ * configure.ac [target=avr]: Add GAS check for -mgcc-isr.
+ (HAVE_AS_AVR_MGCCISR_OPTION): If so, AC_DEFINE it.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+ * doc/extend.texi (AVR Function Attributes) <no_gccisr>: Document it.
+ * doc/invoke.texi (AVR Options) <-mgas-isr-prologues>: Document it.
+ * config/avr/avr.opt (-mgas-isr-prologues): New option and...
+ (TARGET_GASISR_PROLOGUES): ...target mask.
+ * common/config/avr/avr-common.c
+ (avr_option_optimization_table) [OPT_LEVELS_1_PLUS_NOT_DEBUG]:
+ Set -mgas-isr-prologues.
+ * config/avr/avr-passes.def (avr_pass_pre_proep): Add
+ INSERT_PASS_BEFORE for it.
+ * config/avr/avr-protos.h (make_avr_pass_pre_proep): New proto.
+ * config/avr/avr.c (avr_option_override)
+ [!HAVE_AS_AVR_MGCCISR_OPTION]: Unset TARGET_GASISR_PROLOGUES.
+ (avr_no_gccisr_function_p, avr_hregs_split_reg): New static functions.
+ (avr_attribute_table) <no_gccisr>: Add new function attribute.
+ (avr_set_current_function) <is_no_gccisr>: Init machine field.
+ (avr_pass_data_pre_proep, avr_pass_pre_proep): New pass data
+ and rtl_opt_pass.
+ (make_avr_pass_pre_proep): New function.
+ (emit_push_sfr) <treg>: Add argument to function and use it
+ instead of TMP_REG.
+ (avr_expand_prologue) [machine->gasisr.maybe]: Emit gasisr insn
+ and set machine->gasisr.yes.
+ (avr_expand_epilogue) [machine->gasisr.yes]: Similar.
+ (avr_asm_function_end_prologue) [machine->gasisr.yes]: Add
+ __gcc_isr.n_pushed to .L__stack_usage.
+ (TARGET_ASM_FINAL_POSTSCAN_INSN): Define to...
+ (avr_asm_final_postscan_insn): ...this new static function.
+ * config/avr/avr.h (machine_function)
+ <is_no_gccisr, use_L__stack_usage>: New fields.
+ <gasisr, gasisr.yes, gasisr.maybe, gasisr.regno>: New fields.
+ * config/avr/avr.md (UNSPECV_GASISR): Add unspecv enum.
+ (GASISR_Prologue, GASISR_Epilogue, GASISR_Done): New define_constants.
+ (gasisr, *gasisr): New expander and insn.
+ * config/avr/gen-avr-mmcu-specs.c (print_mcu)
+ [HAVE_AS_AVR_MGCCISR_OPTION]: Print asm_gccisr spec.
+ * config/avr/specs.h (ASM_SPEC) <asm_gccisr>: Add sub spec.
+
+2017-07-10 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/parsecpu.awk (gen_comm_data): Do not escape single quotes
+ in quoted strings.
+
+2017-07-10 Georg-Johann Lay <avr@gjlay.de>
+
+ Move jump-tables out of .text again.
+
+ PR target/81075
+ * config/avr/avr.c (ASM_OUTPUT_ADDR_VEC_ELT): Remove function.
+ (ASM_OUTPUT_ADDR_VEC): New function.
+ (avr_adjust_insn_length) [JUMP_TABLE_DATA_P]: Return 0.
+ (avr_final_prescan_insn) [avr_log.insn_addresses]: Dump
+ INSN_ADDRESSes as asm comment.
+ * config/avr/avr.h (JUMP_TABLES_IN_TEXT_SECTION): Adjust comment.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Remove define.
+ (ASM_OUTPUT_ADDR_VEC): Define to avr_output_addr_vec.
+ * config/avr/avr.md (*tablejump): Adjust comment.
+ * config/avr/elf.h (ASM_OUTPUT_BEFORE_CASE_LABEL): Remove.
+ * config/avr/avr-log.c (avr_log_set_avr_log) <insn_addresses>:
+ New detail.
+ * config/avr/avr-protos.h (avr_output_addr_vec_elt): Remove proto.
+ (avr_output_addr_vec): New proto.
+ (avr_log_t) <insn_addresses>: New field.
+
+2017-07-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/81313
+ * config/i386/i386.c (ix86_function_arg_advance): Set
+ outgoing_args_on_stack to true if there are outgoing arguments
+ on stack.
+ (ix86_function_arg): Likewise.
+ (ix86_get_drap_rtx): Use DRAP only if there are outgoing
+ arguments on stack and ACCUMULATE_OUTGOING_ARGS is false.
+ * config/i386/i386.h (machine_function): Add
+ outgoing_args_on_stack.
+
+2017-07-09 Krister Walfridsson <krister.walfridsson@gmail.com>
+
+ * config.gcc (*-*-netbsd*): Remove check for NetBSD versions not
+ supporting pthreds.
+ * config/netbsd.h (NETBSD_LIBGCC_SPEC): Always enable pthreads.
+
+2017-07-08 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * Makefile.in (HOOKS_H, RTL_BASE_H, FUNCTION_H, EXPR_H, REGS_H)
+ (REAL_H): Remove $(MACHMODE_H).
+ (FIXED_VALUE_H, TREE_CORE_H, CFGLOOP_H): Remove $(MACHMODE_H) and
+ double-int.h.
+ (CORETYPES_H): Add signop.h, wide-int.h, wide-int-print.h,
+ $(MACHMODE_H) and double-int.h.
+ (build/min-insn-modes.o): Depend on $(CORETYPES_H) rather than
+ $(MACHMODE_H).
+ (gengtype-state.o, gengtype.o, build/gengtype.o): Don't depend on
+ double-int.h.
+
+2017-07-07 Andrew Pinski <apinski@cavium.com>
+
+ * config/aarch64/aarch64.c (aarch_macro_fusion_pair_p): Check
+ prev_set and curr_set for AARCH64_FUSE_ALU_BRANCH.
+
+2017-07-07 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_get_function_versions_dispatcher):
+ Add warning if GCC was not configured to link against a GLIBC that
+ exports the hardware capability bits.
+ (make_resolver_func): Make resolver function private and not a
+ COMDAT function. Create the name with clone_function_name instead
+ of make_unique_name.
+
+ PR target/81348
+ * config/rs6000/rs6000.md (HI sign_extend splitter): Use the
+ correct operand in doing the split.
+
+2017-07-07 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c: Add support for built-in function
+ vector unsigned short vec_pack_to_short_fp32 (vector float,
+ vector float).
+ * config/rs6000/rs6000-builtin.def (CONVERT_4F32_8I16): Add
+ BU_P9V_AV_2 and BU_P9V_OVERLOAD_2 definitions.
+ * config/rs6000/altivec.h (vec_pack_to_short_fp32): Add define.
+ * config/rs6000/altivec.md(UNSPEC_CONVERT_4F32_8I16): Add UNSPEC.
+ (convert_4f32_8i16): Add define_expand.
+ * doc/extend.texi: Update the built-in documentation file for the
+ new built-in function.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/m8.md: New file.
+ * config/sparc/sparc.md: Include m8.md.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/sparc.opt: New option -mvis4b.
+ * config/sparc/sparc.c (dump_target_flag_bits): Handle MASK_VIS4B.
+ (sparc_option_override): Handle VIS4B.
+ (enum sparc_builtins): Define
+ SPARC_BUILTIN_DICTUNPACK{8,16,32},
+ SPARC_BUILTIN_FPCMP{LE,GT,EQ,NE}{8,16,32}SHL,
+ SPARC_BUILTIN_FPCMPU{LE,GT}{8,16,32}SHL,
+ SPARC_BUILTIN_FPCMPDE{8,16,32}SHL and
+ SPARC_BUILTIN_FPCMPUR{8,16,32}SHL.
+ (check_constant_argument): New function.
+ (sparc_vis_init_builtins): Define builtins
+ __builtin_vis_dictunpack{8,16,32},
+ __builtin_vis_fpcmp{le,gt,eq,ne}{8,16,32}shl,
+ __builtin_vis_fpcmpu{le,gt}{8,16,32}shl,
+ __builtin_vis_fpcmpde{8,16,32}shl and
+ __builtin_vis_fpcmpur{8,16,32}shl.
+ (sparc_expand_builtin): Check that the constant operands to
+ __builtin_vis_fpcmp*shl and _builtin_vis_dictunpack* are indeed
+ constant and in range.
+ * config/sparc/sparc-c.c (sparc_target_macros): Handle
+ TARGET_VIS4B.
+ * config/sparc/sparc.h (SPARC_IMM2_P): Define.
+ (SPARC_IMM5_P): Likewise.
+ * config/sparc/sparc.md (cpu_feature): Add new feagure "vis4b".
+ (enabled): Handle vis4b.
+ (UNSPEC_DICTUNPACK): New unspec.
+ (UNSPEC_FPCMPSHL): Likewise.
+ (UNSPEC_FPUCMPSHL): Likewise.
+ (UNSPEC_FPCMPDESHL): Likewise.
+ (UNSPEC_FPCMPURSHL): Likewise.
+ (cpu_feature): New CPU feature `vis4b'.
+ (dictunpack{8,16,32}): New insns.
+ (FPCSMODE): New mode iterator.
+ (fpcscond): New code iterator.
+ (fpcsucond): Likewise.
+ (fpcmp{le,gt,eq,ne}{8,16,32}{si,di}shl): New insns.
+ (fpcmpu{le,gt}{8,16,32}{si,di}shl): Likewise.
+ (fpcmpde{8,16,32}{si,di}shl): Likewise.
+ (fpcmpur{8,16,32}{si,di}shl): Likewise.
+ * config/sparc/constraints.md: Define constraints `q' for unsigned
+ 2-bit integer constants and `t' for unsigned 5-bit integer
+ constants.
+ * config/sparc/predicates.md (imm5_operand_dictunpack8): New
+ predicate.
+ (imm5_operand_dictunpack16): Likewise.
+ (imm5_operand_dictunpack32): Likewise.
+ (imm2_operand): Likewise.
+ * doc/invoke.texi (SPARC Options): Document -mvis4b.
+ * doc/extend.texi (SPARC VIS Built-in Functions): Document the
+ ditunpack* and fpcmp*shl builtins.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config.gcc: Handle m8 in --with-{cpu,tune} options.
+ * config.in: Add HAVE_AS_SPARC6 define.
+ * config/sparc/driver-sparc.c (cpu_names): Add entry for the SPARC
+ M8.
+ * config/sparc/sol2.h (CPP_CPU64_DEFAULT_SPEC): Define for
+ TARGET_CPU_m8.
+ (ASM_CPU32_DEFAUILT_SPEC): Likewise.
+ (CPP_CPU_SPEC): Handle m8.
+ (ASM_CPU_SPEC): Likewise.
+ * config/sparc/sparc-opts.h (enum processor_type): Add
+ PROCESSOR_M8.
+ * config/sparc/sparc.c (m8_costs): New struct.
+ (sparc_option_override): Handle TARGET_CPU_m8.
+ (sparc32_initialize_trampoline): Likewise.
+ (sparc64_initialize_trampoline): Likewise.
+ (sparc_issue_rate): Likewise.
+ (sparc_register_move_cost): Likewise.
+ * config/sparc/sparc.h (TARGET_CPU_m8): Define.
+ (CPP_CPU64_DEFAULT_SPEC): Define for M8.
+ (ASM_CPU64_DEFAULT_SPEC): Likewise.
+ (CPP_CPU_SPEC): Handle M8.
+ (ASM_CPU_SPEC): Likewise.
+ (AS_M8_FLAG): Define.
+ * config/sparc/sparc.md: Add m8 to the cpu attribute.
+ * config/sparc/sparc.opt: New option -mcpu=m8 for sparc targets.
+ * configure.ac (HAVE_AS_SPARC6): Check for assembler support for
+ M8 instructions.
+ * configure: Regenerate.
+ * doc/invoke.texi (SPARC Options): Document -mcpu=m8 and
+ -mtune=m8.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/niagara7.md: Rework the DFA scheduler to use insn
+ subtypes.
+ * config/sparc/sparc.md: Remove the `v3pipe' insn attribute.
+ ("*movdi_insn_sp32"): Do not set v3pipe.
+ ("*movsi_insn"): Likewise.
+ ("*movdi_insn_sp64"): Likewise.
+ ("*movsf_insn"): Likewise.
+ ("*movdf_insn_sp32"): Likewise.
+ ("*movdf_insn_sp64"): Likewise.
+ ("*zero_extendsidi2_insn_sp64"): Likewise.
+ ("*sign_extendsidi2_insn"): Likewise.
+ ("*mov<VM32:mode>_insn"): Likewise.
+ ("*mov<VM64:mode>_insn_sp64"): Likewise.
+ ("*mov<VM64:mode>_insn_sp32"): Likewise.
+ ("<plusminus_insn><VADDSUB:mode>3"): Likewise.
+ ("<vlop:code><VL:mode>3"): Likewise.
+ ("*not_<vlop:code><VL:mode>3"): Likewise.
+ ("*nand<VL:mode>_vis"): Likewise.
+ ("*<vlnotop:code>_not1<VL:mode>_vis"): Likewise.
+ ("*<vlnotop:code>_not2<VL:mode>_vis"): Likewise.
+ ("one_cmpl<VL:mode>2"): Likewise.
+ ("faligndata<VM64:mode>_vis"): Likewise.
+ ("alignaddrsi_vis"): Likewise.
+ ("alignaddrdi_vis"): Likweise.
+ ("alignaddrlsi_vis"): Likewise.
+ ("alignaddrldi_vis"): Likewise.
+ ("fcmp<gcond:code><GCM:gcm_name><P:mode>_vis"): Likewise.
+ ("bmaskdi_vis"): Likewise.
+ ("bmasksi_vis"): Likewise.
+ ("bshuffle<VM64:mode>_vis"): Likewise.
+ ("cmask8<P:mode>_vis"): Likewise.
+ ("cmask16<P:mode>_vis"): Likewise.
+ ("cmask32<P:mode>_vis"): Likewise.
+ ("pdistn<P:mode>_vis"): Likewise.
+ ("<vis3_addsub_ss_patname><VASS:mode>3"): Likewise.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/sparc.md ("subtype"): New insn attribute.
+ ("*wrgsr_sp64"): Set insn subtype.
+ ("*rdgsr_sp64"): Likewise.
+ ("alignaddrsi_vis"): Likewise.
+ ("alignaddrdi_vis"): Likewise.
+ ("alignaddrlsi_vis"): Likewise.
+ ("alignaddrldi_vis"): Likewise.
+ ("<plusminus_insn><VADDSUB:mode>3"): Likewise.
+ ("fexpand_vis"): Likewise.
+ ("fpmerge_vis"): Likewise.
+ ("faligndata<VM64:mode>_vis"): Likewise.
+ ("bshuffle<VM64:mode>_vis"): Likewise.
+ ("cmask8<P:mode>_vis"): Likewise.
+ ("cmask16<P:mode>_vis"): Likewise.
+ ("cmask32<P:mode>_vis"): Likewise.
+ ("fchksm16_vis"): Likewise.
+ ("v<vis3_shift_patname><GCM:mode>3"): Likewise.
+ ("fmean16_vis"): Likewise.
+ ("fp<plusminus_insn>64_vis"): Likewise.
+ ("<plusminus_insn>v8qi3"): Likewise.
+ ("<vis3_addsub_ss_patname><VASS:mode>3"): Likewise.
+ ("<vis4_minmax_patname><VMMAX:mode>3"): Likewise.
+ ("<vis4_uminmax_patname><VMMAX:mode>3"): Likewise.
+ ("<vis3_addsub_ss_patname>v8qi3"): Likewise.
+ ("<vis4_addsub_us_patname><VAUS:mode>3"): Likewise.
+ ("*movqi_insn"): Likewise.
+ ("*movhi_insn"): Likewise.
+ ("*movsi_insn"): Likewise.
+ ("movsi_pic_gotdata_op"): Likewise.
+ ("*movdi_insn_sp32"): Likewise.
+ ("*movdi_insn_sp64"): Likewise.
+ ("movdi_pic_gotdata_op"): Likewise.
+ ("*movsf_insn"): Likewise.
+ ("*movdf_insn_sp32"): Likewise.
+ ("*movdf_insn_sp64"): Likewise.
+ ("*zero_extendhisi2_insn"): Likewise.
+ ("*zero_extendqihi2_insn"): Likewise.
+ ("*zero_extendqisi2_insn"): Likewise.
+ ("*zero_extendqidi2_insn"): Likewise.
+ ("*zero_extendhidi2_insn"): Likewise.
+ ("*zero_extendsidi2_insn_sp64"): Likewise.
+ ("ldfsr"): Likewise.
+ ("prefetch_64"): Likewise.
+ ("prefetch_32"): Likewise.
+ ("tie_ld32"): Likewise.
+ ("tie_ld64"): Likewise.
+ ("*tldo_ldub_sp32"): Likewise.
+ ("*tldo_ldub1_sp32"): Likewise.
+ ("*tldo_ldub2_sp32"): Likewise.
+ ("*tldo_ldub_sp64"): Likewise.
+ ("*tldo_ldub1_sp64"): Likewise.
+ ("*tldo_ldub2_sp64"): Likewise.
+ ("*tldo_ldub3_sp64"): Likewise.
+ ("*tldo_lduh_sp32"): Likewise.
+ ("*tldo_lduh1_sp32"): Likewise.
+ ("*tldo_lduh_sp64"): Likewise.
+ ("*tldo_lduh1_sp64"): Likewise.
+ ("*tldo_lduh2_sp64"): Likewise.
+ ("*tldo_lduw_sp32"): Likewise.
+ ("*tldo_lduw_sp64"): Likewise.
+ ("*tldo_lduw1_sp64"): Likewise.
+ ("*tldo_ldx_sp64"): Likewise.
+ ("*mov<VM32:mode>_insn"): Likewise.
+ ("*mov<VM64:mode>_insn_sp64"): Likewise.
+ ("*mov<VM64:mode>_insn_sp32"): Likewise.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/sparc.md ("type"): New insn type viscmp.
+ ("fcmp<gcond:code><GCM:gcm_name><P:mode>_vis"): Set insn type to
+ viscmp.
+ ("fpcmp<gcond:code>8<P:mode>_vis"): Likewise.
+ ("fucmp<gcond:code>8<P:mode>_vis"): Likewise.
+ ("fpcmpu<gcond:code><GCM:gcm_name><P:mode>_vis"): Likewise.
+ * config/sparc/niagara7.md ("n7_vis_logical_v3pipe"): Handle
+ viscmp.
+ ("n7_vis_logical_11cycle"): Likewise.
+ * config/sparc/niagara4.md ("n4_vis_logical"): Likewise.
+ * config/sparc/niagara2.md ("niag3_vis": Likewise.
+ * config/sparc/niagara.md ("niag_vis"): Likewise.
+ * config/sparc/ultra3.md ("us3_fga"): Likewise.
+ * config/sparc/ultra1_2.md ("us1_fga_double"): Likewise.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/sparc/sparc.md: New instruction type `bmask'.
+ (bmaskdi_vis): Use the `bmask' type.
+ (bmasksi_vis): Likewise.
+ * config/sparc/ultra3.md (us3_array): Likewise.
+ * config/sparc/niagara7.md (n7_array): Likewise.
+ * config/sparc/niagara4.md (n4_array): Likewise.
+ * config/sparc/niagara2.md (niag2_vis): Likewise.
+ (niag3_vis): Likewise.
+ * config/sparc/niagara.md (niag_vis): Likewise.
+
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-comdats.c: Remove optimize check from gate.
+ * ipa-fnsummary.c (ipa_fn_summary_generate): do not generate summary
+ for functions not optimized.
+ (ipa_fn_summary_read): Skip optimize check.
+ (ipa_fn_summary_write): Likewise.
+ * ipa-inline-analysis.c (do_estimate_growth_1): Check that caller
+ is optimized.
+ * ipa-inline.c (can_inline_edge_p): Not optimized functions are
+ uninlinable.
+ (can_inline_edge_p): Check flag_pcc_struct_return for match.
+ (check_callers): Give up on caller which is not optimized.
+ (inline_small_functions): Likewise.
+ (ipa_inline): Do not give up when not optimizing.
+ * ipa-visbility.c (function_and_variable_visibility): Do not optimize
+ away unoptimizes cdtors.
+ (whole_program_function_and_variable_visibility): Do
+ ipa_discover_readonly_nonaddressable_vars in LTO mode.
+ * ipa.c (process_references): Do not check optimize.
+ (symbol_table::remove_unreachable_nodes): Update optimize check.
+ (set_writeonly_bit): Update optimize check.
+ (pass_ipa_cdtor_merge::gate): Do not check optimize.
+ (pass_ipa_single_use::gate): Remove.
+
+2017-07-06 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (union_defs, union_uses, insn_is_load_p,
+ insn_is_store_p, insn_is_swap_p, const_load_sequence_p, v2df_reduction_p,
+ rtx_is_swappable_p, insn_is_swappable_p, chain_contains_only_swaps,
+ mark_swaps_for_removal, swap_const_vector_halves, adjust_subreg_index,
+ permute_load, permute_store, adjust_extract, adjust_splat,
+ adjust_xxpermdi, adjust_concat, adjust_vperm, handle_special_swappables,
+ replace_swap_with_copy, dump_swap_insn_table,
+ alignment_with_canonical_addr, alignment_mask, find_alignment_op,
+ recombine_lvx_pattern, recombine_stvx_pattern,
+ recombine_lvx_stvx_patterns, rs6000_analyze_swaps,
+ make_pass_analyze_swaps): Move all code related to p8 swap optimizations
+ to file rs6000-p8swap.c.
+ * config/rs6000/rs6000-p8swap.c: New file.
+ * config/rs6000/t-rs6000: Add rule to build rs6000-p8swap.o.
+ * config.gcc: Add rs6000-p8swap.o to extra_objs for powerpc*-*-*
+ and rs6000*-*-* targets.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (selftest): Remove dependency on s-selftest-c++.
+
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-wrapper.c (merge_and_complain): Do not merge
+ fexceptions, fnon_call_exceptions, ftrapv, ffp_contract_, fmath_errno,
+ fsigned_zeros, ftrapping_math, fwrapv.
+ (append_compiler_options): Do not track these options.
+ (append_linker_options): Likewie
+
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraphunit.c (cgraph_node::finalize_function): When
+ !flag_toplevel_reorde set no_reorder flag.
+ (varpool_node::finalize_decl): Likewise.
+ (symbol_table::compile): Drop no toplevel reorder path.
+
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (better_edge_p): Do not build traces across abnormal/eh
+ edges; zero probability is not better than uninitialized.
+
+2017-07-06 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * asan.h (asan_sanitize_allocas_p): Declare.
+ * asan.c (asan_sanitize_allocas_p): New function.
+ (handle_builtin_stack_restore): Bail out if !asan_sanitize_allocas_p.
+ (handle_builtin_alloca): Likewise.
+ * cfgexpand.c (expand_used_vars): Do not add allocas unpoisoning stuff
+ if !asan_sanitize_allocas_p.
+ * params.def (asan-instrument-allocas): Add new option.
+ * params.h (ASAN_PROTECT_ALLOCAS): Define.
+ * opts.c (common_handle_option): Disable allocas sanitization for
+ KASan by default.
+
+2017-07-06 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * asan.c: Include gimple-fold.h.
+ (get_last_alloca_addr): New function.
+ (handle_builtin_stackrestore): Likewise.
+ (handle_builtin_alloca): Likewise.
+ (asan_emit_allocas_unpoison): Likewise.
+ (get_mem_refs_of_builtin_call): Add new parameter, remove const
+ quallifier from first paramerer. Handle BUILT_IN_ALLOCA,
+ BUILT_IN_ALLOCA_WITH_ALIGN and BUILT_IN_STACK_RESTORE builtins.
+ (instrument_builtin_call): Pass gimple iterator to
+ get_mem_refs_of_builtin_call.
+ (last_alloca_addr): New global.
+ * asan.h (asan_emit_allocas_unpoison): Declare.
+ * builtins.c (expand_asan_emit_allocas_unpoison): New function.
+ (expand_builtin): Handle BUILT_IN_ASAN_ALLOCAS_UNPOISON.
+ * cfgexpand.c (expand_used_vars): Call asan_emit_allocas_unpoison
+ if function calls alloca.
+ * gimple-fold.c (replace_call_with_value): Remove static keyword.
+ * gimple-fold.h (replace_call_with_value): Declare.
+ * internal-fn.c: Include asan.h.
+ * sanitizer.def (BUILT_IN_ASAN_ALLOCA_POISON,
+ BUILT_IN_ASAN_ALLOCAS_UNPOISON): New builtins.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (SELFTEST_FLAGS): Drop "-x c", moving it to...
+ (C_SELFTEST_FLAGS): New.
+ (CPP_SELFTEST_FLAGS): New.
+ (SELFTEST_DEPS): New, from deps of s-selftest.
+ (C_SELFTEST_DEPS): New, from deps of s-selftest.
+ (CPP_SELFTEST_DEPS): New.
+ (selftest): Add dependency on s-selftest-c++.
+ (s-selftest): Rename to...
+ (s-selftest-c): ...this, moving deps to SELFTEST_DEPS
+ and C_SELFTEST_DEPS, and using C_SELFTEST_FLAGS rather
+ than SELFTEST_FLAGS.
+ (selftest-gdb): Rename to...
+ (selftest-c-gdb): ...this, using C_SELFTEST_DEPS and
+ C_SELFTEST_FLAGS.
+ (selftest-gdb): Reintroduce as an alias for selftest-c-gdb.
+ (selftest-valgrind): Rename to...
+ (selftest-c-valgrind): ...this, using C_SELFTEST_DEPS and
+ C_SELFTEST_FLAGS.
+ (selftest-valgrind): Reintroduce as an alias for
+ selftest-c-valgrind.
+ (s-selftest-c++): New.
+ (selftest-c++-gdb): New.
+ (selftest-c++-valgrind): New.
+
+2017-07-06 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.c (process_command): When deciding if undefined variables
+ should be ignored when processing specs, accept "gcc -v" as well.
+
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.c (afdo_set_bb_count, afdo_propagate_edge,
+ afdo_annotate_cfg): Set counts/probabilities as determined by afdo.
+
+2017-07-06 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-cpus.in (armv8-r): Add new entry.
+ * config/arm/arm-isa.h (ISA_ARMv8r): Define macro.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm.h (enum base_architecture): Add BASE_ARCH_8R
+ enumerator.
+ * doc/invoke.texi: Mention -march=armv8-r and its extensions.
+
+2017-07-06 Carl Love <cel@us.ibm.com>
+
+ * ChangeLog: Clean up from mid air collision
+
+2017-07-06 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for built-in functions
+ vector signed int vec_subc (vector signed int, vector signed int);
+ vector signed __int128 vec_subc (vector signed __int128,
+ vector signed __int128);
+ vector unsigned __int128 vec_subc (vector unsigned __int128,
+ vector unsigned __int128);
+ vector signed int vec_sube (vector signed int, vector signed int,
+ vector signed int);
+ vector unsigned int vec_sube (vector unsigned int,
+ vector unsigned int,
+ vector unsigned int);
+ vector signed __int128 vec_sube (vector signed __int128,
+ vector signed __int128,
+ vector signed__int128);
+ vector unsigned __int128 vec_sube (vector unsigned __int128,
+ vector unsigned __int128,
+ vector unsigned __int128);
+ vector signed int vec_subec (vector signed int, vector signed int,
+ vector signed int);
+ vector unsigned int vec_subec (vector unsigned int,
+ vector unsigned int,
+ vector unsigned int);
+ vector signed __int128 vec_subec (vector signed __int128,
+ vector signed __int128,
+ vector signed__int128);
+ vector unsigned __int128 vec_subec (vector unsigned __int128,
+ vector unsigned __int128,
+ vector unsigned __int128);
+ * config/rs6000/rs6000.c (ALTIVEC_BUILTIN_VEC_SUBE,
+ ALTIVEC_BUILTIN_VEC_SUBEC): Add ef_builtins.
+ * config/rs6000/rs6000-builtin.def (SUBE, SUBEC): Add
+ BU_ALTIVEC_OVERLOAD_X definitions.
+ * config/rs6000/altivec.h (vec_sube, vec_subec): Add builtin defines.
+ * doc/extend.texi: Update the built-in documentation file for the new
+ built-in functions.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/79300
+ * diagnostic-show-locus.c (layout::layout): Use start and finish
+ spelling location for the start and finish of each range.
+ * genmatch.c (linemap_client_expand_location_to_spelling_point):
+ Add unused aspect param.
+ * input.c (expand_location_1): Add "aspect" param, and use it
+ to access the correct part of the location.
+ (expand_location): Pass LOCATION_ASPECT_CARET to new param of
+ expand_location_1.
+ (expand_location_to_spelling_point): Likewise.
+ (linemap_client_expand_location_to_spelling_point): Add "aspect"
+ param, and pass it to expand_location_1.
+
+2017-07-06 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * config/i386/avx512fintrin.h (_mm_mask_getexp_round_ss,
+ _mm_maskz_getexp_round_ss, _mm_mask_getexp_round_sd,
+ _mm_maskz_getexp_round_sd, _mm_mask_getmant_round_sd,
+ _mm_maskz_getmant_round_sd, _mm_mask_getmant_round_ss,
+ _mm_maskz_getmant_round_ss, _mm_mask_getexp_ss, _mm_maskz_getexp_ss,
+ _mm_mask_getexp_sd, _mm_maskz_getexp_sd, _mm_mask_getmant_sd,
+ _mm_maskz_getmant_sd, _mm_mask_getmant_ss,
+ _mm_maskz_getmant_ss): New intrinsics.
+ (__builtin_ia32_getexpss128_mask): Changed to ...
+ __builtin_ia32_getexpss128_round ... this.
+ (__builtin_ia32_getexpsd128_mask): Changed to ...
+ __builtin_ia32_getexpsd128_round ... this.
+ * config/i386/i386-builtin-types.def
+ ((V2DF, V2DF, V2DF, INT, V2DF, UQI, INT),
+ (V4SF, V4SF, V4SF, INT, V4SF, UQI, INT)): New function type aliases.
+ * config/i386/i386-builtin.def (__builtin_ia32_getexpsd_mask_round,
+ __builtin_ia32_getexpss_mask_round, __builtin_ia32_getmantsd_mask_round,
+ __builtin_ia32_getmantss_mask_round): New builtins.
+ * config/i386/i386.c (V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT,
+ V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT): Handle new types.
+ (CODE_FOR_avx512f_vgetmantv2df_mask_round,
+ CODE_FOR_avx512f_vgetmantv4sf_mask_round): New cases.
+ * config/i386/sse.md
+ (avx512f_sgetexp<mode><round_saeonly_name>): Changed to ...
+ avx512f_sgetexp<mode><mask_scalar_name>
+ <round_saeonly_scalar_name> ... this.
+ (vgetexp<ssescalarmodesuffix>\t{<round_saeonly_op3>%2, %1, %0|
+ %0, %1, %2<round_saeonly_op3>}): Changed to ...
+ vgetexp<ssescalarmodesuffix>
+ \t{<round_saeonly_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|
+ %0<mask_scalar_operand3>, %1, %2<round_saeonly_scalar_mask_op3>} ... this.
+ (avx512f_vgetmant<mode><round_saeonly_name>): Changed to ...
+ avx512f_vgetmant<mode><mask_scalar_name>
+ <round_saeonly_scalar_name> ... this.
+ (vgetmant<ssescalarmodesuffix>\t{%3, <round_saeonly_op4>%2, %1, %0|
+ %0, %1, %2<round_saeonly_op4>, %3}): Changed to ...
+ vgetmant<ssescalarmodesuffix>
+ \t{%3, <round_saeonly_scalar_mask_op4>%2, %1, %0<mask_scalar_operand4>|
+ %0<mask_scalar_operand4>, %1, %2
+ <round_saeonly_scalar_mask_op4>, %3} ... this.
+ * config/i386/subst.md (mask_scalar_operand4,
+ round_saeonly_scalar_mask_operand4, round_saeonly_scalar_mask_op4,
+ round_saeonly_scalar_nimm_predicate): New subst attributes.
+
+2017-07-06 Julia Koval <julia.koval@intel.com>
+
+ * config/i386/i386.c (ix86_erase_embedded_rounding):
+ Remove code for old rounding pattern.
+
+2017-07-06 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/t-arm (GTM_H): Add arm-cpu.h.
+
+2017-07-06 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * doc/sourcebuild.texi (Test Directives, Variants of
+ dg-require-support): Add documentation for dg-require-stack-check.
+
+2017-07-05 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * config/i386/subst.md (mask_scalar, round_scalar,
+ round_saeonly_scalar): New meta-templates.
+ (mask_scalar_name, mask_scalar_operand3, round_scalar_name,
+ round_scalar_mask_operand3, round_scalar_mask_op3,
+ round_scalar_constraint, round_scalar_prefix, round_saeonly_scalar_name,
+ round_saeonly_scalar_mask_operand3, round_saeonly_scalar_mask_op3,
+ round_saeonly_scalar_constraint,
+ round_saeonly_scalar_prefix): New subst attribute.
+ * config/i386/sse.md
+ (<sse>_vm<plusminus_insn><mode>3<mask_name><round_name>): Renamed to ...
+ <sse>_vm<plusminus_insn><mode>3<mask_scalar_name>
+ <round_scalar_name> ... this.
+ (<sse>_vm<multdiv_mnemonic><mode>3<mask_name><round_name>): Renamed to ...
+ <sse>_vm<multdiv_mnemonic><mode>3<mask_scalar_name>
+ <round_scalar_name> ... this.
+ (<sse>_vm<code><mode>3<mask_name><round_saeonly_name>): Renamed to ...
+ <sse>_vm<code><mode>3<mask_scalar_name>
+ <round_saeonly_scalar_name> ... this.
+ (v<plusminus_mnemonic><ssescalarmodesuffix>
+ \t{<round_mask_op3>%2, %1, %0<mask_operand3>|
+ %0<mask_operand3>, %1, %<iptr>2<round_mask_op3>}): Changed to ...
+ v<plusminus_mnemonic><ssescalarmodesuffix>
+ \t{<round_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|
+ %0<mask_scalar_operand3>, %1, %<iptr>2<round_scalar_mask_op3>} ... this.
+ (v<multdiv_mnemonic><ssescalarmodesuffix>
+ \t{<round_mask_op3>%2, %1, %0<mask_operand3>|
+ %0<mask_operand3>, %1, %<iptr>2<round_mask_op3>}): Changed to ...
+ v<multdiv_mnemonic><ssescalarmodesuffix>
+ \t{<round_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|
+ %0<mask_scalar_operand3>, %1, %<iptr>2<round_scalar_mask_op3>} ... this.
+ (v<maxmin_float><ssescalarmodesuffix>
+ \t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|
+ %0<mask_operand3>, %1, %<iptr>2<round_saeonly_mask_op3>}): Changed to ...
+ v<maxmin_float><ssescalarmodesuffix>
+ \t{<round_saeonly_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|
+ %0<mask_scalar_operand3>, %1, %<iptr>2
+ <round_saeonly_scalar_mask_op3>} ... this.
+
+2017-07-05 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/arm.c (arm_fixed_condition_code_regs): New function.
+ (TARGET_FIXED_CONDITION_CODE_REGS): Redefine.
+
+2017-07-05 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * combine.c (simplify_if_then_else): Remove "enum" before
+ "machine_mode".
+ * compare-elim.c (can_eliminate_compare): Likewise.
+ * config/aarch64/aarch64-builtins.c (aarch64_simd_builtin_std_type):
+ Likewise.
+ (aarch64_lookup_simd_builtin_type): Likewise.
+ (aarch64_simd_builtin_type): Likewise.
+ (aarch64_init_simd_builtin_types): Likewise.
+ (aarch64_simd_expand_args): Likewise.
+ * config/aarch64/aarch64-protos.h (aarch64_simd_attr_length_rglist):
+ Likewise.
+ (aarch64_reverse_mask): Likewise.
+ (aarch64_simd_emit_reg_reg_move): Likewise.
+ (aarch64_gen_adjusted_ldpstp): Likewise.
+ (aarch64_ccmp_mode_to_code): Likewise.
+ (aarch64_operands_ok_for_ldpstp): Likewise.
+ (aarch64_operands_adjust_ok_for_ldpstp): Likewise.
+ * config/aarch64/aarch64.c (aarch64_ira_change_pseudo_allocno_class):
+ Likewise.
+ (aarch64_min_divisions_for_recip_mul): Likewise.
+ (aarch64_reassociation_width): Likewise.
+ (aarch64_get_condition_code_1): Likewise.
+ (aarch64_simd_emit_reg_reg_move): Likewise.
+ (aarch64_simd_attr_length_rglist): Likewise.
+ (aarch64_reverse_mask): Likewise.
+ (aarch64_operands_ok_for_ldpstp): Likewise.
+ (aarch64_operands_adjust_ok_for_ldpstp): Likewise.
+ (aarch64_gen_adjusted_ldpstp): Likewise.
+ * config/aarch64/cortex-a57-fma-steering.c (fma_node::rename):
+ Likewise.
+ * config/arc/arc.c (legitimate_offset_address_p): Likewise.
+ * config/arm/arm-builtins.c (arm_simd_builtin_std_type): Likewise.
+ (arm_lookup_simd_builtin_type): Likewise.
+ (arm_simd_builtin_type): Likewise.
+ (arm_init_simd_builtin_types): Likewise.
+ (arm_expand_builtin_args): Likewise.
+ * config/arm/arm-protos.h (arm_expand_builtin): Likewise.
+ * config/ft32/ft32.c (ft32_libcall_value): Likewise.
+ (ft32_setup_incoming_varargs): Likewise.
+ (ft32_function_arg): Likewise.
+ (ft32_function_arg_advance): Likewise.
+ (ft32_pass_by_reference): Likewise.
+ (ft32_arg_partial_bytes): Likewise.
+ (ft32_valid_pointer_mode): Likewise.
+ (ft32_addr_space_pointer_mode): Likewise.
+ (ft32_addr_space_legitimate_address_p): Likewise.
+ * config/i386/i386-protos.h (ix86_operands_ok_for_move_multiple):
+ Likewise.
+ * config/i386/i386.c (ix86_setup_incoming_vararg_bounds): Likewise.
+ (ix86_emit_outlined_ms2sysv_restore): Likewise.
+ (iamcu_alignment): Likewise.
+ (canonicalize_vector_int_perm): Likewise.
+ (ix86_noce_conversion_profitable_p): Likewise.
+ (ix86_mpx_bound_mode): Likewise.
+ (ix86_operands_ok_for_move_multiple): Likewise.
+ * config/microblaze/microblaze-protos.h
+ (microblaze_expand_conditional_branch_reg): Likewise.
+ * config/microblaze/microblaze.c
+ (microblaze_expand_conditional_branch_reg): Likewise.
+ * config/powerpcspe/powerpcspe.c (rs6000_init_hard_regno_mode_ok):
+ Likewise.
+ (rs6000_reassociation_width): Likewise.
+ (rs6000_invalid_binary_op): Likewise.
+ (fusion_p9_p): Likewise.
+ (emit_fusion_p9_load): Likewise.
+ (emit_fusion_p9_store): Likewise.
+ * config/riscv/riscv-protos.h (riscv_regno_mode_ok_for_base_p):
+ Likewise.
+ (riscv_hard_regno_mode_ok_p): Likewise.
+ (riscv_address_insns): Likewise.
+ (riscv_split_symbol): Likewise.
+ (riscv_legitimize_move): Likewise.
+ (riscv_function_value): Likewise.
+ (riscv_hard_regno_nregs): Likewise.
+ (riscv_expand_builtin): Likewise.
+ * config/riscv/riscv.c (riscv_build_integer_1): Likewise.
+ (riscv_build_integer): Likewise.
+ (riscv_split_integer): Likewise.
+ (riscv_legitimate_constant_p): Likewise.
+ (riscv_cannot_force_const_mem): Likewise.
+ (riscv_regno_mode_ok_for_base_p): Likewise.
+ (riscv_valid_base_register_p): Likewise.
+ (riscv_valid_offset_p): Likewise.
+ (riscv_valid_lo_sum_p): Likewise.
+ (riscv_classify_address): Likewise.
+ (riscv_legitimate_address_p): Likewise.
+ (riscv_address_insns): Likewise.
+ (riscv_load_store_insns): Likewise.
+ (riscv_force_binary): Likewise.
+ (riscv_split_symbol): Likewise.
+ (riscv_force_address): Likewise.
+ (riscv_legitimize_address): Likewise.
+ (riscv_move_integer): Likewise.
+ (riscv_legitimize_const_move): Likewise.
+ (riscv_legitimize_move): Likewise.
+ (riscv_address_cost): Likewise.
+ (riscv_subword): Likewise.
+ (riscv_output_move): Likewise.
+ (riscv_canonicalize_int_order_test): Likewise.
+ (riscv_emit_int_order_test): Likewise.
+ (riscv_function_arg_boundary): Likewise.
+ (riscv_pass_mode_in_fpr_p): Likewise.
+ (riscv_pass_fpr_single): Likewise.
+ (riscv_pass_fpr_pair): Likewise.
+ (riscv_get_arg_info): Likewise.
+ (riscv_function_arg): Likewise.
+ (riscv_function_arg_advance): Likewise.
+ (riscv_arg_partial_bytes): Likewise.
+ (riscv_function_value): Likewise.
+ (riscv_pass_by_reference): Likewise.
+ (riscv_setup_incoming_varargs): Likewise.
+ (riscv_print_operand): Likewise.
+ (riscv_elf_select_rtx_section): Likewise.
+ (riscv_save_restore_reg): Likewise.
+ (riscv_for_each_saved_reg): Likewise.
+ (riscv_register_move_cost): Likewise.
+ (riscv_hard_regno_mode_ok_p): Likewise.
+ (riscv_hard_regno_nregs): Likewise.
+ (riscv_class_max_nregs): Likewise.
+ (riscv_memory_move_cost): Likewise.
+ * config/rl78/rl78-protos.h (rl78_split_movsi): Likewise.
+ * config/rl78/rl78.c (rl78_split_movsi): Likewise.
+ (rl78_addr_space_address_mode): Likewise.
+ * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin):
+ Likewise.
+ * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Likewise.
+ (rs6000_reassociation_width): Likewise.
+ (rs6000_invalid_binary_op): Likewise.
+ (fusion_p9_p): Likewise.
+ (emit_fusion_p9_load): Likewise.
+ (emit_fusion_p9_store): Likewise.
+ * config/visium/visium-protos.h (prepare_move_operands): Likewise.
+ (ok_for_simple_move_operands): Likewise.
+ (ok_for_simple_move_strict_operands): Likewise.
+ (ok_for_simple_arith_logic_operands): Likewise.
+ (visium_legitimize_reload_address): Likewise.
+ (visium_select_cc_mode): Likewise.
+ (output_cbranch): Likewise.
+ (visium_split_double_move): Likewise.
+ (visium_expand_copysign): Likewise.
+ (visium_expand_int_cstore): Likewise.
+ (visium_expand_fp_cstore): Likewise.
+ * config/visium/visium.c (visium_pass_by_reference): Likewise.
+ (visium_function_arg): Likewise.
+ (visium_function_arg_advance): Likewise.
+ (visium_libcall_value): Likewise.
+ (visium_setup_incoming_varargs): Likewise.
+ (visium_legitimate_constant_p): Likewise.
+ (visium_legitimate_address_p): Likewise.
+ (visium_legitimize_address): Likewise.
+ (visium_secondary_reload): Likewise.
+ (visium_register_move_cost): Likewise.
+ (visium_memory_move_cost): Likewise.
+ (prepare_move_operands): Likewise.
+ (ok_for_simple_move_operands): Likewise.
+ (ok_for_simple_move_strict_operands): Likewise.
+ (ok_for_simple_arith_logic_operands): Likewise.
+ (visium_function_value_1): Likewise.
+ (rtx_ok_for_offset_p): Likewise.
+ (visium_legitimize_reload_address): Likewise.
+ (visium_split_double_move): Likewise.
+ (visium_expand_copysign): Likewise.
+ (visium_expand_int_cstore): Likewise.
+ (visium_expand_fp_cstore): Likewise.
+ (visium_split_cstore): Likewise.
+ (visium_select_cc_mode): Likewise.
+ (visium_split_cbranch): Likewise.
+ (output_cbranch): Likewise.
+ (visium_print_operand_address): Likewise.
+ * expmed.c (flip_storage_order): Likewise.
+ * expmed.h (emit_cstore): Likewise.
+ (flip_storage_order): Likewise.
+ * genrecog.c (validate_pattern): Likewise.
+ * hsa-gen.c (gen_hsa_addr): Likewise.
+ * internal-fn.c (expand_arith_overflow): Likewise.
+ * ira-color.c (allocno_copy_cost_saving): Likewise.
+ * lra-assigns.c (find_hard_regno_for_1): Likewise.
+ * lra-constraints.c (prohibited_class_reg_set_mode_p): Likewise.
+ (process_invariant_for_inheritance): Likewise.
+ * lra-eliminations.c (move_plus_up): Likewise.
+ * omp-low.c (lower_oacc_reductions): Likewise.
+ * simplify-rtx.c (simplify_subreg): Likewise.
+ * target.def (TARGET_SETUP_INCOMING_VARARG_BOUNDS): Likewise.
+ (TARGET_CHKP_BOUND_MODE): Likewise..
+ * targhooks.c (default_chkp_bound_mode): Likewise.
+ (default_setup_incoming_vararg_bounds): Likewise.
+ * targhooks.h (default_chkp_bound_mode): Likewise.
+ (default_setup_incoming_vararg_bounds): Likewise.
+ * tree-ssa-math-opts.c (divmod_candidate_p): Likewise.
+ * tree-vect-loop.c (calc_vec_perm_mask_for_shift): Likewise.
+ (have_whole_vector_shift): Likewise.
+ * tree-vect-stmts.c (vectorizable_load): Likewise.
+ * doc/tm.texi: Regenerate.
+
+2017-07-05 Georg-Johann Lay <avr@gjlay.de>
+
+ Graceful degrade if Binutils PR21472 is not available.
+
+ PR target/81072
+ * configure.ac [target=avr]: WARN instead of ERROR if avrxmega3
+ .rodata in flash test fails.
+ (HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH): Define it if test passes.
+ * confgure: Regenerate.
+ * config.in: Regenerate.
+ * config/avr/avr.c (avr_asm_named_section)
+ [HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH]: Only trigger
+ __do_copy_data for stuff in .rodata if flash_pm_offset = 0.
+ (avr_asm_init_sections): Same.
+
+2017-07-05 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/neon.md (fma<VCVTF:mode>4): Remove %?.
+ (fma<VH:mode>4_intrinsic): Likewise.
+ (*fmsub<VCVTF:mode>4): Likewise.
+ (*fmsub<VH:mode>4_intrinsic): Likewise.
+
+2017-07-05 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/81305
+ * config/avr/avr.c (avr_out_movhi_mr_r_xmega) [CONSTANT_ADDRESS_P]:
+ Don't depend on "optimize > 0".
+ (out_movhi_r_mr, out_movqi_mr_r): Same.
+ (out_movhi_mr_r, out_movqi_r_mr): Same.
+ (avr_address_cost) [CONSTANT_ADDRESS_P]: Don't depend cost for
+ io_address_operand on "optimize > 0".
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c: Add general explanantion on the pass.
+ (generate_loops_for_partition): Mark distributed loop.
+ (pg_add_dependence_edges): New parameter. Handle alias data
+ dependence specially and record it in the parameter if asked.
+ (struct pg_vdata, pg_edata, pg_edge_callback_data): New structs.
+ (init_partition_graph_vertices, add_partition_graph_edge): New.
+ (pg_skip_alias_edge, free_partition_graph_edata_cb): New.
+ (free_partition_graph_vdata, build_partition_graph): New.
+ (sort_partitions_by_post_order, merge_dep_scc_partitions): New.
+ (pg_collect_alias_ddrs, break_alias_scc_partitions): New.
+ (data_ref_segment_size, latch_dominated_by_data_ref): New.
+ (compute_alias_check_pairs, version_loop_by_alias_check): New.
+ (version_for_distribution_p, finalize_partitions): New.
+ (distribute_loop): Handle alias data dependence specially. Factor
+ out loop fusion code as functions and call these functions.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (classify_partition): New parameter and
+ better handle reduction statement.
+ (rdg_build_partitions): Revise comment.
+ (distribute_loop): Compute statements in all partitions and pass it
+ to classify_partition.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (enum partition_type): New.
+ (struct partition): New field type.
+ (partition_merge_into): Add parameter. Update partition type.
+ (data_dep_in_cycle_p, update_type_for_merge): New functions.
+ (build_rdg_partition_for_vertex): Compute partition type.
+ (rdg_build_partitions): Dump partition type.
+ (distribute_loop): Update calls to partition_merge_into.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (struct ddr_hasher): New.
+ (ddr_hasher::hash, ::equal, get_data_dependence): New function.
+ (ddrs_table): New.
+ (classify_partition): Call get_data_dependence.
+ (pg_add_dependence_edges): Ditto.
+ (distribute_loop): Release data dependence hash table.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (ref_base_address): Delete.
+ (similar_memory_accesses): Rename ...
+ (share_memory_accesses): ... to this. Check if partitions access
+ the same memory reference.
+ (distribute_loop): Call share_memory_accesses.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (struct partition): New field recording
+ its data reference.
+ (partition_alloc, partition_free): Init and release data refs.
+ (partition_merge_into): Merge data refs.
+ (build_rdg_partition_for_vertex): Collect data refs for partition.
+ (pg_add_dependence_edges): Change parameters from vector to bitmap.
+ Update uses.
+ (distribute_loop): Remve data refs from vertice data of partition
+ graph.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (params.h): Include header file.
+ (MAX_DATAREFS_NUM, DR_INDEX): New macro.
+ (datarefs_vec): New global var.
+ (create_rdg_vertices): Use datarefs_vec directly.
+ (free_rdg): Don't free data references.
+ (build_rdg): Update use. Don't free data references.
+ (distribute_loop): Compute global variable for data references.
+ Bail out if there are too many data references.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (loop_nest): New global var.
+ (build_rdg): Use loop directly, rather than loop nest.
+ (pg_add_dependence_edges): Remove loop nest parameter. Use global
+ variable directly.
+ (distribute_loop): Compute global variable loop nest. Update use.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (enum fuse_type, fuse_message): New.
+ (partition_merge_into): New parameter. Dump reason for fusion.
+ (distribute_loop): Update use of partition_merge_into.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (bb_top_order_index): New.
+ (bb_top_order_index_size, bb_top_order_cmp): New.
+ (stmts_from_loop): Use topological order.
+ (pass_loop_distribution::execute): Compute and release topological
+ order for basic blocks.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-loop-distribution.c (pass_loop_distribution::execute): Skip
+ if no loops.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * cfgloop.h (struct loop): Add comment. New field orig_loop_num.
+ * cfgloopmanip.c (lv_adjust_loop_entry_edge): Comment change.
+ * internal-fn.c (expand_LOOP_DIST_ALIAS): New function.
+ * internal-fn.def (LOOP_DIST_ALIAS): New.
+ * tree-vectorizer.c (fold_loop_vectorized_call): Rename to ...
+ (fold_loop_internal_call): ... this.
+ (vect_loop_dist_alias_call): New function.
+ (set_uid_loop_bbs): Call fold_loop_internal_call.
+ (vectorize_loops): Fold IFN_LOOP_VECTORIZED and IFN_LOOP_DIST_ALIAS
+ internal calls.
+
+2017-07-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81300
+ * config/i386/i386.md (setcc + movzbl/and to xor + setcc peepholes):
+ Require dead FLAGS_REG at the beginning of a peephole.
+
+2017-07-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81294
+ * config/i386/adxintrin.h (_subborrow_u32): Swap _X and _Y
+ arguments in the call to __builtin_ia32_sbb_u32.
+ (_subborrow_u64): Swap _X and _Y arguments in the call to
+ __builtin_ia32_sbb_u64.
+
+2017-07-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/81278
+ * tree-vrp.c (compare_assert_loc): Turn into a function template
+ with stable template parameter. Only test if a->e is NULL,
+ !a->e == !b->e has been verified already. Use e == NULL or
+ e != NULL instead of e or ! e tests. If stable is true, don't use
+ iterative_hash_expr, on the other side allow a or b or both NULL
+ and sort the NULLs last.
+ (process_assert_insertions): Sort using compare_assert_loc<false>
+ instead of compare_assert_loc, later sort using
+ compare_assert_loc<true> before calling process_assert_insertions_for
+ in a loop. Use break instead of continue once seen NULL pointer.
+
+2017-07-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/driver-arm.c (arm_cpu_table): Add entry for ARM
+ Cortex-R7 and Cortex-R8 processors.
+
+2017-07-04 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-utils.c (ipa_merge_profiles): Fix merging when dst is
+ uninitialized while src is not.
+
+2017-07-04 Richard Earnshaw <rearnsha@arm.com>
+
+ * common/config/arm/arm-common.c: Adjust include path for
+ arm-cpu-cdata.h
+ * config/arm/t-arm (TM_H): Adjust path for arm-cpu.h.
+ (arm-cpu.h): Create in build directory. Adjust dependency rules.
+ (arm-cpu-data.h): Likewise.
+ (arm-cpu-cdata.h): Likewise.
+ * config/arm/arm-cpu.h: Delete.
+ * config/arm/arm-cpu-cdata.h: Delete.
+ * config/arm/arm-cpu-data.h: Delete.
+
+2017-07-04 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/arm-cpus.in (cortex-a55): New.
+ (cortex-a75): Likewise.
+ (cortex-a75.cortex-a55): Likewise.
+ * config/arm/driver-arm.c (arm_cpu_table): Add cortex-a55 and
+ cortex-a75.
+ * doc/invoke.texi (-mcpu): Document cortex-a55 and cortex-a75.
+ * config/arm/arm-cpu-cdata.h: Regenerate.
+ * config/arm/arm-cpu-data.h: Regenerate.
+ * config/arm/arm-cpu.h: Regenerate.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Regenerate.
+
+2017-07-04 Jan Hubicka <hubicka@ucw.cz>
+
+ * haifa-sched.c (sched_create_recovery_edges): Update profile.
+
+2017-07-04 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (better_edge_p): Fix handling of uninitialized
+ probability.
+
+2017-07-04 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/81292
+ * tree-ssa-strlen.c (handle_builtin_strlen): When setting
+ full_string_p, also call adjust_related_strinfos if the adjustment
+ is simple, otherwise invalidate related strinfos.
+
+2017-07-04 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81040
+ * sanopt.c (sanitize_rewrite_addressable_params): Mark the
+ newly created variable as DECL_IGNORED_P.
+
+2017-07-04 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81293
+ * ipa-inline.c (inline_small_functions):
+ Use xstrdup_for_dump.
+
+2017-07-04 Tom de Vries <tom@codesourcery.com>
+
+ * graph.c (draw_cfg_edges): Save and restore EDGE_DFS_BACK.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR target/81033
+ * config/darwin.c (darwin_function_switched_text_sections):
+ Fix spaces.
+
+2017-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-vect-loop-manip.c (vect_do_peeling): Fix scaling up.
+
+2017-07-03 Richard Earnshaw <rearnsha@arm.com>
+
+ * doc/invoke.texi (ARM Options): Add -mbe8 and -mbe32 to option summary.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vect-loop.c (vect_analyze_loop_2): Treat min_scalar_loop_bound,
+ min_profitable_iters, and th as inclusive lower bounds.
+ Fix LOOP_VINFO_PEELING_FOR_GAPS condition.
+ (vect_estimate_min_profitable_iters): Return inclusive lower bounds
+ for min_profitable_iters and min_profitable_estimate.
+ (vect_transform_loop): Treat th as an inclusive lower bound.
+ * tree-vect-loop-manip.c (vect_loop_versioning): Likewise.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR target/81033
+ * config/darwin.c (darwin_function_switched_text_sections):
+ Replace DECL_NAME with DECL_ASSEMBLER_NAME, split assemble_name_raw
+ in two pieces, and suppress the use of buf.
+
+2017-07-03 Nathan Sidwell <nathan@acm.org>
+
+ * hash-table.h (hash_table_mod1): Fix indentation.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81290
+ * predict.c (force_edge_cold): Be more careful about propagation
+ backward.
+ * profile-count.h (profile_probability::guessed,
+ profile_probability::fdo, profile_count::guessed, profile_count::fdo):
+ New.
+ * tree-ssa-threadupdate.c (recompute_probabilities): Result is guessed.
+
+2017-07-03 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * doc/invoke.texi (rcpc architecture extension): Document it.
+
+2017-07-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/60510
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Pass in
+ the scalar reduction PHI and use it.
+ (vectorizable_reduction): Properly guard the single_defuse_cycle
+ path for non-SLP reduction chains where we cannot use it.
+ Rework reduc_def/index and vector type deduction. Rework
+ vector operand gathering during reduction op code-gen.
+ * tree-vect-slp.c (vect_analyze_slp): For failed SLP reduction
+ chains dissolve the chain and leave it to non-SLP reduction
+ handling.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.h (dr_alignment): Declare.
+ * tree-data-ref.c (dr_alignment): New function.
+ * tree-vectorizer.h (dataref_aux): Remove base_element_aligned.
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Don't
+ set it.
+ * tree-vect-stmts.c (vectorizable_store): Use dr_alignment.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.h (innermost_loop_behavior): Add base_alignment
+ and base_misalignment fields.
+ (DR_BASE_ALIGNMENT, DR_BASE_MISALIGNMENT): New macros.
+ * tree-data-ref.c: Include builtins.h.
+ (dr_analyze_innermost): Set up the new innmost_loop_behavior fields.
+ * tree-vectorizer.h (STMT_VINFO_DR_BASE_ALIGNMENT): New macro.
+ (STMT_VINFO_DR_BASE_MISALIGNMENT): Likewise.
+ * tree-vect-data-refs.c: Include tree-cfg.h.
+ (vect_compute_data_ref_alignment): Use the new innermost_loop_behavior
+ fields instead of calculating an alignment here.
+ (vect_analyze_data_refs): Use dr_analyze_innermost. Dump the new
+ innermost_loop_behavior fields.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.h (innermost_loop_behavior): Add a step_alignment
+ field.
+ (DR_STEP_ALIGNMENT): New macro.
+ * tree-vectorizer.h (STMT_VINFO_DR_STEP_ALIGNMENT): Likewise.
+ * tree-data-ref.c (dr_analyze_innermost): Initalize step_alignment.
+ (create_data_ref): Print it.
+ * tree-vect-stmts.c (vectorizable_load): Use the step alignment
+ to tell whether the step preserves vector (mis)alignment.
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Likewise.
+ Move the check for an integer step and generalise to all INTEGER_CST.
+ (vect_analyze_data_refs): Set DR_STEP_ALIGNMENT when setting DR_STEP.
+ Print the outer step alignment.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.h (innermost_loop_behavior): Replace aligned_to
+ with offset_alignment.
+ (DR_ALIGNED_TO): Delete.
+ (DR_OFFSET_ALIGNMENT): New macro.
+ * tree-vectorizer.h (STMT_VINFO_DR_ALIGNED_TO): Delete.
+ (STMT_VINFO_DR_OFFSET_ALIGNMENT): New macro.
+ * tree-data-ref.c (dr_analyze_innermost): Update after above changes.
+ (create_data_ref): Likewise.
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Likewise.
+ (vect_analyze_data_refs): Likewise.
+ * tree-if-conv.c (if_convertible_loop_p_1): Use memset before
+ creating dummy innermost behavior.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.h (dr_analyze_innermost): Replace the dr argument
+ with a "innermost_loop_behavior *" and refeence tree.
+ * tree-data-ref.c (dr_analyze_innermost): Likewise.
+ (create_data_ref): Update call accordingly.
+ * tree-predcom.c (find_looparound_phi): Likewise.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vectorizer.h (_stmt_vec_info): Replace individual dr_*
+ fields with dr_wrt_vec_loop.
+ (STMT_VINFO_DR_BASE_ADDRESS, STMT_VINFO_DR_INIT, STMT_VINFO_DR_OFFSET)
+ (STMT_VINFO_DR_STEP, STMT_VINFO_DR_ALIGNED_TO): Update accordingly.
+ (STMT_VINFO_DR_WRT_VEC_LOOP): New macro.
+ (vect_dr_behavior): New function.
+ (vect_create_addr_base_for_vector_ref): Remove loop parameter.
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Use
+ vect_dr_behavior. Use a step_preserves_misalignment_p boolean to
+ track whether the step preserves the misalignment.
+ (vect_create_addr_base_for_vector_ref): Remove loop parameter.
+ Use vect_dr_behavior.
+ (vect_setup_realignment): Update call accordingly.
+ (vect_create_data_ref_ptr): Likewise. Use vect_dr_behavior.
+ * tree-vect-loop-manip.c (vect_gen_prolog_loop_niters): Update
+ call to vect_create_addr_base_for_vector_ref.
+ (vect_create_cond_for_align_checks): Likewise.
+ * tree-vect-patterns.c (vect_recog_bool_pattern): Copy
+ STMT_VINFO_DR_WRT_VEC_LOOP as a block.
+ (vect_recog_mask_conversion_pattern): Likewise.
+ * tree-vect-stmts.c (compare_step_with_zero): Use vect_dr_behavior.
+ (new_stmt_vec_info): Remove redundant zeroing.
+
+2017-07-03 Richard Earnshaw <rearnsha@arm.com>
+
+ * common/config/arm/arm-common.c (arm_be8_option): New function.
+ * config/arm/arm-isa.h (isa_feature): Add new feature bit isa_bit_be8.
+ (ISA_ARMv6): Add isa_bit_be8.
+ * config/arm/arm.h (arm_be8_option): Add prototype.
+ (BE8_SPEC_FUNCTION): New define.
+ (EXTRA_SPEC_FUNCTIONS): Add BE8_SPEC_FUNCTION.
+ * config/arm/arm.opt (mbig-endian): Mark as Negative of mlittle-endian.
+ (mlittle-endian): Similarly.
+ (mbe8, mbe32): New options.
+ * config/arm/bpabi.h (BE8_LINK_SPEC): Call arm_be8_option.
+ * doc/invoke.texi (ARM Options): Document -mbe8 and -mbe32.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-cfg.c (gimple_find_sub_bbs): Fix profile updating.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-cfgcleanup.c (want_merge_blocks_p): New function.
+ (cleanup_tree_cfg_bb): Use it.
+ * profile-count.h (profile_count::of_for_merging, profile_count::merge):
+ New functions.
+ * tree-cfg.c (gimple_merge_blocks): Use profile_count::merge.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ PR bootstrap/81285
+ * loop-doloop.c (add_test): Update profile.
+
+2017-07-03 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81040
+ * sanopt.c (rewrite_usage_of_param): New function.
+ (sanitize_rewrite_addressable_params): Likewise.
+ (pass_sanopt::execute): Call rewrite_usage_of_param.
+
+2017-07-03 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Revert
+ back to using VIEW_CONVERT_EXPR.
+
+2017-07-03 Martin Liska <mliska@suse.cz>
+
+ PR other/78366
+ * doc/extend.texi: Document when a resolver function is
+ generated for target_clones.
+
+2017-07-03 Martin Liska <mliska@suse.cz>
+
+ * asan.c (asan_emit_stack_protection): Unpoison just red zones
+ and shadow memory of auto variables which are subject of
+ use-after-scope sanitization.
+ (asan_expand_mark_ifn): Add do set only when is_poison.
+
+2016-07-03 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vect_analyze_loop_operations): Also analyze
+ reduction PHIs.
+ (vect_force_simple_reduction): Record reduction def -> phi mapping.
+ (vectorizable_reduction): Perform reduction PHI creation when
+ visiting a reduction PHI and adjust and simplify code generation
+ phase of the reduction op. Cache dts, use fold_binary, not fold_build2.
+ (vect_transform_loop): Visit reduction PHIs.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Record reduction
+ defs into the SLP tree.
+ (vect_build_slp_tree): Reduction defs terminate the recursion.
+ * tree-vect-stmts.c (vect_get_vec_def_for_operand_1): Allow lookup
+ of reduction defs.
+ (vect_get_vec_defs_for_stmt_copy): Export.
+ (vect_get_vec_defs): Likewise.
+ * tree-vectorizer.h (struct _stmt_vec_info): Amend reduc_def
+ purpose.
+ (vect_get_vec_defs_for_stmt_copy): Declare.
+ (vect_get_vec_defs): Likewise.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-data-ref.c (dr_analyze_innermost): Replace the "nest"
+ parameter with a "loop" parameter and use it instead of the
+ loop containing DR_STMT. Don't check simple_iv when doing
+ BB analysis. Describe the two analysis modes in the comment.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/69468
+ * tree-ssa-tail-merge.c (ignore_edge_flags): New constant.
+ (find_same_succ_bb): Handle ignore_edge_flags.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/81192
+ * tree-ssa-tail-merge.c (same_succ_hash): Use bb->loop_father->num in
+ hash.
+ (same_succ::equal): Don't find bbs to be equal if bb->loop_father
+ differs.
+ (find_same_succ_bb): Remove obsolete test on bb->loop_father->latch.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/81192
+ * tree-ssa-tail-merge.c (same_succ_flush_bb): Handle
+ BB_SAME_SUCC (bb) == NULL.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfgrtl.c (rtl_verify_edges): Enable checking of profile_probability
+ consistency.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * dumpfile.c: Include profile-count.h
+ * tree-cfg.c (gimple_duplicate_sese_tail): Drop UNUSED attributes;
+ update profile.
+ (insert_cond_bb): Update profile.
+ * tree-cfg.h (insert_cond_bb): Update prototype.
+ * tree-chkp-opt.c (chkp_optimize_string_function_calls): Update.
+ * tree-dump.c: Do not include tree-cfg.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (fix_up_crossing_landing_pad): Update profile.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * expect.c (dw2_build_landing_pads): Update profile of the landing pad
+ bb.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-complex.c (expand_complex_div_wide): update profile.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * Makefile.in (MACHMODE_H): Remove insn-modes.h
+ (CORETYPES_H): New define.
+ (MOSTLYCLEANFILES): Add insn-modes-inline.h.
+ (insn-modes-inline.h, s-modes-inline-h): New rules.
+ (generated_files): Add insn-modes-inline.h.
+ (RTL_BASE_H, TREE_CORE_H): Use CORETYPES_H instead of coretypes.h.
+ (build/gensupport.o, build/ggc-none.o, build/print-rtl.o): Likewise.
+ (build/read-md.o, build/read-rtl.o, build/rtl.o): Likewise.
+ (build/vec.o, build/hash-table.o, build/inchash.o): Likewise.
+ (build/gencondmd.o, build/genattr.o, build/genattr-common.o): Likewise.
+ (build/genattrtab.o, build/genautomata.o, build/gencheck.o): Likewise.
+ (build/gencodes.o, build/genconditions.o): Likewise.
+ (build/genconfig.o, build/genconstants.o, build/genemit.o): Likewise.
+ (build/genenums.o, build/genextract.o, build/genflags.o): Likewise.
+ (build/gentarget-def.o, build/genmddeps.o, build/genopinit.o)
+ (build/genoutput.o, build/genpeep.o, build/genpreds.o): Likewise.
+ (build/genrecog.o, build/genmddump.o, build/genmatch.o): Likewise.
+ (build/gencfn-macros.o, build/gcov-iov.o): Likewise.
+ * coretypes.h: Include everything up to real.h for generators.
+ Include insn-modes.h first. Include wide-int-print.h after
+ wide-int.h. Include insn-modes-inline.h and then machmode.h.
+ * machmode.h: Don't include insn-modes.h here.
+ * function-tests.c: Remove includes of signop.h, machmode.h,
+ double-int.h and wide-int.h.
+ * rtl.h: Likewise.
+ * gcc-rich-location.c: Remove includes of machmode.h, double-int.h
+ and wide-int.h.
+ * optc-save-gen.awk: Likewise.
+ * gencheck.c (BITS_PER_UNIT): Delete dummy definition.
+ * godump.c: Remove include of wide-int-print.h.
+ * pretty-print.h: Likewise.
+ * wide-int-print.cc: Likewise.
+ * wide-int.cc: Likewise.
+ * hash-map-tests.c: Remove include of signop.h.
+ * hash-set-tests.c: Likewise.
+ * rtl-tests.c: Likewise.
+ * mkconfig.sh: Remove include of machmode.h.
+ * genmodes.c (emit_insn_modes_h): Split emission of inline functions
+ into...
+ (emit_insn_modes_inline_h): ...this new function. Emit the code
+ into an insn-modes-inline.h header file, adding appropriate
+ include guards and end comments.
+ (emit_insn_modes_c_header): Remove include of machmode.h.
+ (emit_min_insn_modes_c_header): Include coretypes.h rather than
+ machmode.h.
+ (main): Handle -i flag and call emit_insn_modes_inline_h when
+ it is passed.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-ssa-strlen.c (strinfo): Rename the length field to
+ nonzero_chars. Add a full_string_p field.
+ (compare_nonzero_chars, zero_length_string_p): New functions.
+ (get_addr_stridx): Add an offset_out parameter.
+ Use compare_nonzero_chars.
+ (get_stridx): Update accordingly. Use compare_nonzero_chars.
+ (new_strinfo): Update after above changes to strinfo.
+ (set_endptr_and_length): Set full_string_p.
+ (get_string_length): Update after above changes to strinfo.
+ (unshare_strinfo): Update call to new_strinfo.
+ (maybe_invalidate): Likewise.
+ (get_stridx_plus_constant): Change off to unsigned HOST_WIDE_INT.
+ Use compare_nonzero_chars and zero_string_p. Treat nonzero_chars
+ as a uhwi instead of an shwi. Update after above changes to
+ strinfo and new_strinfo.
+ (zero_length_string): Assert that chainsi contains full strings.
+ Use zero_length_string_p. Update call to new_strinfo.
+ (adjust_related_strinfos): Update after above changes to strinfo.
+ Copy full_string_p from origsi.
+ (adjust_last_stmt): Use zero_length_string_p.
+ (handle_builtin_strlen): Update after above changes to strinfo and
+ new_strinfo. Install the lhs as the string length if the previous
+ entry didn't describe a full string.
+ (handle_builtin_strchr): Update after above changes to strinfo
+ and new_strinfo.
+ (handle_builtin_strcpy): Likewise.
+ (handle_builtin_strcat): Likewise.
+ (handle_builtin_malloc): Likewise.
+ (handle_pointer_plus): Likewise.
+ (handle_builtin_memcpy): Likewise. Track nonzero characters
+ that aren't necessarily followed by a nul terminator.
+ (handle_char_store): Likewise.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/80769
+ * tree-ssa-strlen.c (strinfo): Document that "stmt" is also used
+ for malloc and calloc. Document the new invariant that all related
+ strinfos have delayed lengths or none do.
+ (verify_related_strinfos): Move earlier in file.
+ (set_endptr_and_length): New function, split out from...
+ (get_string_length): ...here. Also set the lengths of related
+ strinfos.
+ (zero_length_string): Assert that chainsi has known (rather than
+ delayed) lengths.
+ (adjust_related_strinfos): Likewise.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/81136
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel): Only
+ assert that two references with the same misalignment have the same
+ compile-time misalignment if those compile-time misalignments
+ are known.
+
+2017-07-01 Andi Kleen <ak@linux.intel.com>
+
+ * print-tree.c (print_node): Print all attributes.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfg.c (scale_bbs_frequencies): New function.
+ * cfg.h (scale_bbs_frequencies): Declare it.
+ * cfgloopanal.c (single_likely_exit): Cleanup.
+ * cfgloopmanip.c (scale_loop_frequencies): Take profile_probability
+ as parameter.
+ (scale_loop_profile): Likewise.
+ (loop_version): Likewise.
+ (create_empty_loop_on_edge): Update.
+ * cfgloopmanip.h (scale_loop_frequencies, scale_loop_profile,
+ scale_loop_frequencies, scale_loop_profile, loopify,
+ loop_version): Update prototypes.
+ * modulo-sched.c (sms_schedule): Update.
+ * predict.c (unlikely_executed_edge_p): Also check probability.
+ (probably_never_executed_edge_p): Fix typo.
+ * tree-if-conv.c (version_loop_for_if_conversion): Update.
+ * tree-parloops.c (gen_parallel_loop): Update.
+ * tree-ssa-loop-ivcanon.c (try_peel_loop): Update.
+ * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update.
+ * tree-ssa-loop-split.c (split_loop): Update.
+ * tree-ssa-loop-unswitch.c (tree_unswitch_loop): Update.
+ * tree-vect-loop-manip.c (vect_do_peeling): Update.
+ (vect_loop_versioning): Update.
+ * tree-vect-loop.c (scale_profile_for_vect_loop): Update.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * trans-mem.c (split_bb_make_tm_edge): Update profile.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-if-conv.c (combine_blocks): Use make_single_succ_edge
+ to keep profile consistent.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfgrtl.c (rtl_flow_call_edges_add): Update profile.
+ * tree-cfg.c (gimple_flow_call_edges_add): Likewise.
+ * profile-count.h (max_safe_multiplier): Make unsigned.
+ (profile_count::guessed_zero): New.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * bb-reorder.c (fix_up_crossing_landing_pad,
+ fix_crossing_conditional_branches): Use make_single_succ_edge
+ to keep profile consistent.
+
+2017-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-vect-loop.c (optimize_mask_stores): Use make_single_succ_edge
+ to update profile.
+
+2017-07-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81262
+ * bb-reorder.c (fix_up_fall_thru_edges): Move variable declarations to
+ the right scopes, make sure cond_jump isn't preserved between multiple
+ iterations. Search for fallthru edge whenever there are 3+ edges and
+ use find_fallthru_edge for it.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ Patch by Alexander Monakov <amonakov@ispras.ru>
+ * sel-sched-ir.c (compute_succs_info): Handle uninitialized
+ probabilities consistently.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ * pa.c (pa_expand_compare_and_swap_loop): Update call of
+ emit_cmp_and_jump_insns.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/81261
+ * tree-inline.c (expand_call_inline): Combine profile statuses.
+
+2017-06-30 Andrew Pinski <apinski@cavium.com>
+
+ * tree-if-conv.c (predicate_scalar_phi): Update new_stmt if
+ fold_stmt returned true.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * ggc.h (empty_string): Delete.
+ * cfgexpand.c (expand_asm_stmt): Use plain "".
+ * optabs.c (expand_asm_memory_barrier): Likewise.
+ * stringpool.c (empty_string): Delete.
+ (digit_vector, digit_string): Delete.
+ (ggc_alloc_string): Use plain "", don't optimize single digit
+ strings. Use ggc_alloc_atomic.
+
+2017-06-30 Richard Earnshaw <rearnsha@arm.com>
+
+ * rtlanal.c (insn_rtx_cost): If a parallel contains exactly one
+ comparison set and one other set, use the cost of the non-comparison
+ set.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * ggc.h: Replace all 'static inline' with plain 'inline'. Fix
+ some formatting.
+
+2017-06-30 Peter Bergner <bergner@vnet.ibm.com>
+
+ * tree-cfg.c (group_case_labels_stmt): Merge scanning and compressing
+ loops. Remove now unneeded calls to gimple_switch_set_label() that
+ just set removed labels to NULL_TREE.
+
+2017-06-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssanames.c (set_range_info_raw): Abstract from ...
+ (set_range_info): ...here. Only call set_range_info_raw if domain
+ is useful.
+ (set_nonzero_bits): Call set_range_info_raw.
+ * tree-ssanames.h (set_range_info_raw): New.
+
+2017-06-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/81225
+ * config/i386/sse.md (vec_extract_lo_<mode><mask_name>): For V8FI,
+ V16FI and VI8F_256 iterators, use <store_mask_predicate> instead
+ of nonimmediate_operand and <store_mask_constraint> instead of m
+ for the input operand. For V8FI iterator, always split if input
+ is a MEM. For V16FI and V8SF_256 iterators, don't test if both
+ operands are MEM if <mask_applied>. For VI4F_256 iterator, use
+ <store_mask_predicate> instead of register_operand and
+ <store_mask_constraint> instead of v for the input operand. Make
+ sure both operands aren't MEMs for if not <mask_applied>.
+
+2017-06-30 Sylvestre Ledru <sylvestre@debian.org>
+
+ * lto-wrapper.c (copy_file) Close both file descriptors before
+ exiting normally.
+
+2017-06-30 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81214
+ * multiple_target.c (create_dispatcher_calls): Make ifunc
+ also for function that don't have calls or are not referenced.
+
+2017-06-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_slp_analyze_node_operations): Only
+ analyze the first scalar stmt. Move vector type computation
+ for the BB case here from ...
+ * tree-vect-stmts.c (vect_analyze_stmt): ... here. Guard
+ live operation processing in the SLP case properly.
+
+2017-06-30 Richard Biener <rguenther@suse.de>
+
+ * graph.c (draw_cfg_node_succ_edges): Fix broken dot syntax.
+
+2017-06-30 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81021
+ * tree-eh.c (lower_resx): Call BUILT_IN_ASAN_HANDLE_NO_RETURN
+ before BUILT_IN_UNWIND_RESUME when ASAN is used.
+
+2017-06-30 Yvan Roux <yvan.roux@linaro.org>
+
+ * doc/invoke.texi (AArch64): Add missing options and remove redundant
+ ones.
+
+2017-06-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81249
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Convert
+ condition reduction result to original scalar type.
+
+2017-06-30 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * profile-count.h (enum profile_quality): Fix typos and whitespace
+ issues.
+
+2017-06-30 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/s390.c (s390_expand_setmem): Adjust to the new data
+ type for branch probabilities.
+
+2017-06-29 Julian Brown <julian@codesourcery.com>
+ Naveen H.S <Naveen.Hurugalawadi@cavium.com>
+
+ * config/aarch64/aarch64-fusion-pairs.def: Add ALU_BRANCH entry.
+ * config/aarch64/aarch64.c (AARCH64_FUSE_ALU_BRANCH): New fusion type.
+ (thunderx2t99_tunings): Set AARCH64_FUSE_ALU_BRANCH flag.
+ (aarch_macro_fusion_pair_p): Add support for AARCH64_FUSE_ALU_BRANCH.
+
+2017-06-29 Naveen H.S <Naveen.Hurugalawadi@cavium.com>
+
+ * config/aarch64/aarch64.c (aarch_macro_fusion_pair_p): Push the
+ check for CC usage into AARCH64_FUSE_CMP_BRANCH.
+ * config/i386/i386.c (ix86_macro_fusion_pair_p): Push the check for
+ CC usage from generic code to here.
+ * sched-deps.c (sched_macro_fuse_insns): Move the condition for
+ CC usage into the target macros.
+
+2017-06-29 Maya Rashish <coypu@sdf.org>
+
+ * config/netbsd.h (NETBSD_LIB_SPEC): Add -lc when creating shared
+ objects.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ * arm/arm-builtins.c: Include profile-count.h
+ * except.c (sjlj_emit_function_enter): Use
+ profile_probability::unlikely.
+
+2017-06-29 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (toc_relative_expr_p): Make tocrel_base
+ and tocrel_offset be pointer args rather than implicitly using
+ static versions.
+ (legitimate_constant_pool_address_p, rs6000_emit_move,
+ const_load_sequence_p, adjust_vperm): Add local tocrel_base and
+ tocrel_offset and use in toc_relative_expr_p call.
+ (print_operand, print_operand_address): Use static tocrel_base_oac
+ and tocrel_offset_oac.
+ (rs6000_output_addr_const_extra): Use static tocrel_base_oac and
+ tocrel_offset_oac.
+
+2017-06-29 Maya Rashish <coypu@sdf.org>
+
+ * config/vax/builtins.md (ffssi2_internal): Correct constraint.
+
+2017-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.c (expand_expr) <normal_inner_ref>: When testing for unaligned
+ objects, take into account only the alignment of 'op0' and 'mode1' if
+ 'op0' is a MEM.
+
+2017-06-29 Steve Ellcey <sellcey@cavium.com>
+
+ * ccmp.c (ccmp_tree_comparison_p): New function.
+ (ccmp_candidate_p): Update to use above function.
+ (get_compare_parts): New function.
+ (expand_ccmp_next): Update to use new functions.
+ (expand_ccmp_expr_1): Take tree arg instead of gimple, update to use
+ new functions.
+ (expand_ccmp_expr): Pass tree instead of gimple to expand_ccmp_expr_1,
+ take mode as argument.
+ * ccmp.h (expand_ccmp_expr): Add mode as argument.
+ * expr.c (expand_expr_real_1): Pass mode as argument.
+
+2017-06-29 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * combine.c (combine_instructions): Print insns to dump_file, together
+ with their costs.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ * asan.c (asan_emit_stack_protection): Update.
+ (create_cond_insert_point): Update.
+ * auto-profile.c (afdo_propagate_circuit): Update.
+ * basic-block.h (struct edge_def): Turn probability to
+ profile_probability.
+ (EDGE_FREQUENCY): Update.
+ * bb-reorder.c (find_traces_1_round): Update.
+ (better_edge_p): Update.
+ (sanitize_hot_paths): Update.
+ * cfg.c (unchecked_make_edge): Initialize probability to uninitialized.
+ (make_single_succ_edge): Update.
+ (check_bb_profile): Update.
+ (dump_edge_info): Update.
+ (update_bb_profile_for_threading): Update.
+ * cfganal.c (connect_infinite_loops_to_exit): Initialize new edge
+ probabilitycount to 0.
+ * cfgbuild.c (compute_outgoing_frequencies): Update.
+ * cfgcleanup.c (try_forward_edges): Update.
+ (outgoing_edges_match): Update.
+ (try_crossjump_to_edge): Update.
+ * cfgexpand.c (expand_gimple_cond): Update make_single_succ_edge.
+ (expand_gimple_tailcall): Update.
+ (construct_init_block): Use make_single_succ_edge.
+ (construct_exit_block): Use make_single_succ_edge.
+ * cfghooks.c (verify_flow_info): Update.
+ (redirect_edge_succ_nodup): Update.
+ (split_edge): Update.
+ (account_profile_record): Update.
+ * cfgloopanal.c (single_likely_exit): Update.
+ * cfgloopmanip.c (scale_loop_profile): Update.
+ (set_zero_probability): Remove.
+ (duplicate_loop_to_header_edge): Update.
+ * cfgloopmanip.h (loop_version): Update prototype.
+ * cfgrtl.c (try_redirect_by_replacing_jump): Update.
+ (force_nonfallthru_and_redirect): Update.
+ (update_br_prob_note): Update.
+ (rtl_verify_edges): Update.
+ (purge_dead_edges): Update.
+ (rtl_lv_add_condition_to_bb): Update.
+ * cgraph.c: (cgraph_edge::redirect_call_stmt_to_calle): Update.
+ * cgraphunit.c (init_lowered_empty_function): Update.
+ (cgraph_node::expand_thunk): Update.
+ * cilk-common.c: Include profile-count.h
+ * dojump.c (inv): Remove.
+ (jumpifnot): Update.
+ (jumpifnot_1): Update.
+ (do_jump_1): Update.
+ (do_jump): Update.
+ (do_jump_by_parts_greater_rtx): Update.
+ (do_compare_rtx_and_jump): Update.
+ * dojump.h (jumpifnot, jumpifnot_1, jumpif_1, jumpif, do_jump,
+ do_jump_1. do_compare_rtx_and_jump): Update prototype.
+ * dwarf2cfi.c: Include profile-count.h
+ * except.c (dw2_build_landing_pads): Use make_single_succ_edge.
+ (sjlj_emit_dispatch_table): Likewise.
+ * explow.c: Include profile-count.h
+ * expmed.c (emit_store_flag_force): Update.
+ (do_cmp_and_jump): Update.
+ * expr.c (compare_by_pieces_d::generate): Update.
+ (compare_by_pieces_d::finish_mode): Update.
+ (emit_block_move_via_loop): Update.
+ (store_expr_with_bounds): Update.
+ (store_constructor): Update.
+ (expand_expr_real_2): Update.
+ (expand_expr_real_1): Update.
+ * expr.h (try_casesi, try_tablejump): Update prototypes.
+ * gimple-pretty-print.c (dump_probability): Update.
+ (dump_profile): New.
+ (dump_gimple_label): Update.
+ (dump_gimple_bb_header): Update.
+ * graph.c (draw_cfg_node_succ_edges): Update.
+ * hsa-gen.c (convert_switch_statements): Update.
+ * ifcvt.c (cheap_bb_rtx_cost_p): Update.
+ (find_if_case_1): Update.
+ (find_if_case_2): Update.
+ * internal-fn.c (expand_arith_overflow_result_store): Update.
+ (expand_addsub_overflow): Update.
+ (expand_neg_overflow): Update.
+ (expand_mul_overflow): Update.
+ (expand_vector_ubsan_overflow): Update.
+ * ipa-cp.c (good_cloning_opportunity_p): Update.
+ * ipa-split.c (split_function): Use make_single_succ_edge.
+ * ipa-utils.c (ipa_merge_profiles): Update.
+ * loop-doloop.c (add_test): Update.
+ (doloop_modify): Update.
+ * loop-unroll.c (compare_and_jump_seq): Update.
+ (unroll_loop_runtime_iterations): Update.
+ * lra-constraints.c (lra_inheritance): Update.
+ * lto-streamer-in.c (input_cfg): Update.
+ * lto-streamer-out.c (output_cfg): Update.
+ * mcf.c (adjust_cfg_counts): Update.
+ * modulo-sched.c (sms_schedule): Update.
+ * omp-expand.c (expand_omp_for_init_counts): Update.
+ (extract_omp_for_update_vars): Update.
+ (expand_omp_ordered_sink): Update.
+ (expand_omp_for_ordered_loops): Update.
+ (expand_omp_for_generic): Update.
+ (expand_omp_for_static_nochunk): Update.
+ (expand_omp_for_static_chunk): Update.
+ (expand_cilk_for): Update.
+ (expand_omp_simd): Update.
+ (expand_omp_taskloop_for_outer): Update.
+ (expand_omp_taskloop_for_inner): Update.
+ * omp-simd-clone.c (simd_clone_adjust): Update.
+ * optabs.c (expand_doubleword_shift): Update.
+ (expand_abs): Update.
+ (emit_cmp_and_jump_insn_1): Update.
+ (expand_compare_and_swap_loop): Update.
+ * optabs.h (emit_cmp_and_jump_insns): Update prototype.
+ * predict.c (predictable_edge_p): Update.
+ (edge_probability_reliable_p): Update.
+ (set_even_probabilities): Update.
+ (combine_predictions_for_insn): Update.
+ (combine_predictions_for_bb): Update.
+ (propagate_freq): Update.
+ (estimate_bb_frequencies): Update.
+ (force_edge_cold): Update.
+ * profile-count.c (profile_count::dump): Add missing space into dump.
+ (profile_count::debug): Add newline.
+ (profile_count::differs_from_p): Explicitly convert to unsigned.
+ (profile_count::stream_in): Update.
+ (profile_probability::dump): New member function.
+ (profile_probability::debug): New member function.
+ (profile_probability::differs_from_p): New member function.
+ (profile_probability::differs_lot_from_p): New member function.
+ (profile_probability::stream_in): New member function.
+ (profile_probability::stream_out): New member function.
+ * profile-count.h (profile_count_quality): Rename to ...
+ (profile_quality): ... this one.
+ (profile_probability): New.
+ (profile_count): Update.
+ * profile.c (compute_branch_probabilities): Update.
+ * recog.c (peep2_attempt): Update.
+ * sched-ebb.c (schedule_ebbs): Update.
+ * sched-rgn.c (find_single_block_region): Update.
+ (compute_dom_prob_ps): Update.
+ (schedule_region): Update.
+ * sel-sched-ir.c (compute_succs_info): Update.
+ * stmt.c (struct case_node): Update.
+ (do_jump_if_equal): Update.
+ (get_outgoing_edge_probs): Update.
+ (conditional_probability): Update.
+ (emit_case_dispatch_table): Update.
+ (expand_case): Update.
+ (expand_sjlj_dispatch_table): Update.
+ (emit_case_nodes): Update.
+ * targhooks.c: Update.
+ * tracer.c (better_p): Update.
+ (find_best_successor): Update.
+ * trans-mem.c (expand_transaction): Update.
+ * tree-call-cdce.c: Update.
+ * tree-cfg.c (gimple_split_edge): Upate.
+ (move_sese_region_to_fn): Upate.
+ * tree-cfgcleanup.c (cleanup_control_expr_graph): Upate.
+ * tree-eh.c (lower_resx): Upate.
+ (cleanup_empty_eh_move_lp): Upate.
+ * tree-if-conv.c (version_loop_for_if_conversion): Update.
+ * tree-inline.c (copy_edges_for_bb): Update.
+ (copy_cfg_body): Update.
+ * tree-parloops.c (gen_parallel_loop): Update.
+ * tree-profile.c (gimple_gen_ic_func_profiler): Update.
+ (gimple_gen_time_profiler): Update.
+ * tree-ssa-dce.c (remove_dead_stmt): Update.
+ * tree-ssa-ifcombine.c (update_profile_after_ifcombine): Update.
+ * tree-ssa-loop-im.c (execute_sm_if_changed): Update.
+ * tree-ssa-loop-ivcanon.c (remove_exits_and_undefined_stmts): Update.
+ (unloop_loops): Update.
+ (try_peel_loop): Update.
+ * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update.
+ * tree-ssa-loop-split.c (connect_loops): Update.
+ (split_loop): Update.
+ * tree-ssa-loop-unswitch.c (tree_unswitch_loop): Update.
+ (hoist_guard): Update.
+ * tree-ssa-phionlycprop.c (propagate_rhs_into_lhs): Update.
+ * tree-ssa-phiopt.c (replace_phi_edge_with_variable): Update.
+ (value_replacement): Update.
+ * tree-ssa-reassoc.c (branch_fixup): Update.
+ * tree-ssa-tail-merge.c (replace_block_by): Update.
+ * tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges): Update.
+ (create_edge_and_update_destination_phis): Update.
+ (compute_path_counts): Update.
+ (recompute_probabilities): Update.
+ (update_joiner_offpath_counts): Update.
+ (freqs_to_counts_path): Update.
+ (duplicate_thread_path): Update.
+ * tree-switch-conversion.c (hoist_edge_and_branch_if_true): Update.
+ (struct switch_conv_info): Update.
+ (gen_inbound_check): Update.
+ * tree-vect-loop-manip.c (slpeel_add_loop_guard): Update.
+ (vect_do_peeling): Update.
+ (vect_loop_versioning): Update.
+ * tree-vect-loop.c (scale_profile_for_vect_loop): Update.
+ (optimize_mask_stores): Update.
+ * ubsan.c (ubsan_expand_null_ifn): Update.
+ * value-prof.c (gimple_divmod_fixed_value): Update.
+ (gimple_divmod_fixed_value_transform): Update.
+ (gimple_mod_pow2): Update.
+ (gimple_mod_pow2_value_transform): Update.
+ (gimple_mod_subtract): Update.
+ (gimple_mod_subtract_transform): Update.
+ (gimple_ic): Update.
+ (gimple_stringop_fixed_value): Update.
+ (gimple_stringops_transform): Update.
+ * value-prof.h: Update.
+
+2017-06-29 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for built-in functions
+ vector signed int vec_signed (vector float);
+ vector signed long long vec_signed (vector double);
+ vector signed int vec_signed2 (vector double, vector double);
+ vector signed int vec_signede (vector double);
+ vector signed int vec_signedo (vector double);
+ * config/rs6000/rs6000.c (rs6000_generate_vsigned2_code): Add
+ instruction generator.
+ * config/rs6000/vsx.md (UNSPEC_VSX_XVCVSPSXWS, UNSPEC_VSX_XVCVSPSXDS,
+ UNSPEC_VSX_VSIGNED2): Add UNSPECS.
+ (vsx_xvcvspsxws, vsx_xvcvdpuxds_scale, vsx_xvcvspuxws, vsigned2_v2df):
+ Add define_insn.
+ (vsignedo_v2df, vsignede_v2df, vunsigned2_v2df, vunsignedo_v2df,
+ vunsignede_v2df): Add define_expands.
+ * config/rs6000/rs6000-builtin.def (VEC_SIGNED, VEC_UNSIGNED,
+ VEC_SIGNED2, VEC_UNSIGNED2, VEC_SIGNEDE, VEC_UNSIGNEDE, VEC_SIGNEDO,
+ VEC_UNSIGNEDO): Add definitions.
+ * config/vsx.md (UNSPEC_VSX_XVCVSPSXWS, UNSPEC_VSX_XVCVSPSXDS,
+ UNSPEC_VSX_VSIGNED2): Add UNSPECs.
+ (vsx_xvcvspsxws, vsx_xvcvspuxws): Add define_insn.
+ (vsigned2_v2df, vsigendo_v2df, vsignede_v2df,
+ vunsigned2_v2df, vunsignedo_v2df, vunsignede_v2df): Add define_expands.
+ * config/rs6000/altivec.h (vec_signed, vec_signed2,
+ vec_signede and vec_signedo, vec_unsigned, vec_unsigned2,
+ vec_unsignede, vec_unsignedo): Add builtin defines.
+ * config/rs6000-protos.h (rs6000_generate_vsigned2_code): Add extern
+ declaration.
+ * doc/extend.texi: Update the built-in documentation file for the
+ new built-in functions.
+
+2017-06-29 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vect_analyze_scalar_cycles_1): Do not add
+ reduction chains to LOOP_VINFO_REDUCTIONS.
+ * tree-vect-slp.c (vect_analyze_slp): Continue looking for
+ SLP reductions after processing reduction chains.
+
+2017-06-29 Nathan Sidwell <nathan@acm.org>
+
+ * builtins.c (fold_builtin_FUNCTION): Use
+ lang_hooks.decl_printable_name.
+
+2017-06-29 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR middle-end/81194
+ * cfgexpand.c (expand_gimple_stmt_1): Handle switch statements
+ with only one label.
+ * stmt.c (expand_case): Assert NCASES is greater than one.
+
+2017-06-29 Richard Biener <rguenther@suse.de>
+
+ * tree-cfg.c (group_case_labels_stmt): Return whether we changed
+ anything.
+ (group_case_labels): Likewise.
+ (find_taken_edge): Push sanity checking on val to workers...
+ (find_taken_edge_cond_expr): ... here
+ (find_taken_edge_switch_expr): ... and here, handle cases
+ with just a default label.
+ * tree-cfg.h (group_case_labels_stmt): Adjust prototype.
+ (group_case_labels): Likewise.
+ * tree-cfgcleanup.c (execute_cleanup_cfg_post_optimizing): When
+ group_case_labels does anything cleanup the CFG again.
+
+2017-06-29 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/81196
+ * tree-ssa-loop-niter.c (number_of_iterations_cond): Handle loop
+ exit condition comparing two IVs.
+
+2017-06-29 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/parsecpu.awk (gen_comm_data): Add initializer for
+ profile to the dummy entry at the end of the list of architectures.
+ * config/arm/arm-cpu-cdata.h: Regenerated.
+
+2017-06-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Michael Collison <michael.collison@arm.com>
+
+ PR target/70119
+ * config/aarch64/aarch64.md (*aarch64_<optab>_reg_<mode>3_mask1):
+ New pattern.
+ (*aarch64_reg_<mode>3_neg_mask2): New pattern.
+ (*aarch64_reg_<mode>3_minus_mask): New pattern.
+ (*aarch64_<optab>_reg_di3_mask2): New pattern.
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Account for cost
+ of shift when the shift amount is masked with constant equal to
+ the size of the mode.
+ * config/aarch64/predicates.md (subreg_lowpart_operator): New
+ predicate.
+
+2017-06-29 Martin Liska <mliska@suse.cz>
+
+ * config/i386/i386.opt: Change range from [1,5] to [0,5].
+
+2017-06-29 Yury Gribov <tetra2005@gmail.com>
+
+ PR bootstrap/80565
+ * ipa-cp.c (allocate_and_init_ipcp_value): Add initialization
+ code.
+ * ipa-inline.h
+ (edge_growth_cache_entry::edge_growth_cache_entry): New
+ function.
+ (reset_edge_growth_cache): Update to use constructor.
+
+2017-06-28 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_EXPAND_ALIGNMENT): New.
+ (DATA_ALIGNMENT): Update to use AARCH64_EXPAND_ALIGNMENT.
+ (LOCAL_ALIGNMENT): Update to use AARCH64_EXPAND_ALIGNMENT.
+
+2017-06-28 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * config/i386/avx512vlintrin.h (_mm256_permutexvar_epi64)
+ (_mm256_permutexvar_epi32, _mm256_permutex_epi64): New intrinsics.
+
+2017-06-28 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config.gcc (*-linux-musl*): Add t-musl tmake_file.
+ (*-linux-uclibc*): Add t-uclibc tmake_file.
+ * config/t-musl: New.
+ * config/t-uclibc: New.
+
+2017-06-28 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/parsecpu.awk (profile): Parse new keyword in an arch
+ context.
+ (gen_comm_data): Emit architectural setting of arch_prof.
+ * config/arm/arm-cpus.in (armv6-m, armv6s-m, armv7-a, armv7ve): Set the
+ profile.
+ (armv7-r, armv7-m, armv7e-m, armv8-a, armv8.1-a, armv8.2-a): Likewise.
+ (armv8-m.base, armv8-m.main): Likewise.
+ * arm-protos.h (arm_build_target): Add profile field.
+ (arch_option): Likewise.
+ * config/arm/arm.c (arm_configure_build_target): Copy the profile to
+ the active target.
+ * config/arm/arm.h (TARGET_ARM_ARCH_PROFILE): Use
+ arm_active_target.profile.
+
+2017-06-28 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81227
+ * fold-const.c (negate_expr_p): Use TYPE_UNSIGNED, not
+ TYPE_OVERFLOW_WRAPS.
+ * match.pd (negate_expr_p): Likewise.
+ * tree-ssa-reassoc.c (optimize_range_tests_diff): Use
+ fold_build2, not fold_binary.
+
+2017-06-28 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64 (aarch64_expand_mov_immediate):
+ Convert memory address to Pmode.
+ (aarch64_print_operand): Assert MEM operands are always Pmode.
+
+2017-06-28 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/79665
+ * config/arm/aarch-common.c (arm_no_early_alu_shift_dep):
+ Remove redundant if.
+ (aarch_forward_to_shift_is_not_shifted_reg): Remove.
+ * config/arm/aarch-common-protos.h
+ (aarch_forward_to_shift_is_not_shifted_re): Remove.
+ * config/arm/cortex-a53.md: Use arm_no_early_alu_shift_dep in bypass.
+
+2017-06-28 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR ipa/81238
+ * multiple_target.c (create_dispatcher_calls): Set the default
+ clone to be static, not public.
+
+2017-06-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-loop.c (vectorizable_reduction): Move special
+ cond reduction IV var creation ...
+ (vect_create_epilog_for_reduction): ... here. Remove induction_index
+ parameter. Use STMT_VINFO_VECTYPE.
+ * tree-vect-slp.c (vect_get_constant_vectors): Properly reset
+ constant_p.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81128
+ * ipa-visibility.c (non_local_p): Handle visibility.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR driver/79659
+ * common.opt: Add IntegerRange to various options.
+ * opt-functions.awk (integer_range_info): New function.
+ * optc-gen.awk: Add integer_range_info to cl_options struct.
+ * opts-common.c (decode_cmdline_option): Handle
+ CL_ERR_INT_RANGE_ARG.
+ (cmdline_handle_error): Likewise.
+ * opts.c (print_filtered_help): Show valid interval in
+ when --help is provided.
+ * opts.h (struct cl_option): Add range_min and range_max fields.
+ * config/i386/i386.opt: Add IntegerRange for -mbranch-cost.
+
+2017-06-28 Marc Glisse <marc.glisse@inria.fr>
+
+ * match.pd ((X & ~Y) | (~X & Y)): Generalize to + and ^.
+ (x * C EQ/NE y * C): New transformation.
+
+2017-06-28 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * genmultilib (combination_space): Accept '+' in option names.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81224
+ * asan.c (instrument_derefs): Bail out inner references
+ that are hard register variables.
+
+2017-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/81175
+ * config/i386/i386.c (ix86_init_mmx_sse_builtins): Use def_builtin
+ rather than def_builtin_pure for __builtin_ia32_gatherpf*.
+
+2017-06-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vect_get_vec_defs): Remove.
+ (vect_get_slp_defs): Adjust.
+ * tree-vect-loop.c (get_initial_defs_for_reduction): Split
+ out from ...
+ * tree-vect-slp.c (vect_get_constant_vectors): ... here and
+ simplify.
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Use
+ get_initial_defs_for_reduction instead of vect_get_vec_defs.
+ (vectorizable_reduction): Adjust.
+ * tree-vect-slp.c (vect_get_constant_vectors): Remove reduction
+ handling.
+ (vect_get_slp_defs): Likewise.
+ * tree-vect-stmts.c (vect_get_vec_defs): Make static and adjust.
+ (vectorizable_bswap): Adjust.
+ (vectorizable_call): Likewise.
+ (vectorizable_conversion): Likewise.
+ (vectorizable_assignment): Likewise.
+ (vectorizable_shift): Likewise.
+ (vectorizable_operation): Likewise.
+ (vectorizable_store): Likewise.
+ (vectorizable_condition): Likewise.
+ (vectorizable_comparison): Likewise.
+
+2017-06-28 Michael Collison <michael.collison@arm.com>
+
+ PR target/68535
+ * config/arm/arm.c (gen_ldm_seq): Remove last unnecessary
+ set of base_reg
+ (arm_gen_movmemqi): Removed unused variable 'i'.
+ Convert 'for' loop into 'while' loop.
+ (arm_expand_prologue): Remove last unnecessary set of insn.
+ (thumb_pop): Remove unused variable 'pushed_words'.
+ (thumb_exit): Remove last unnecessary set of regs_to_pop.
+
+2017-06-28 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/predicates.md: Use s390_rel_address_ok_p.
+ * config/s390/s390-protos.h: Add prototype of
+ s390_rel_address_ok_p.
+ * config/s390/s390.c (s390_got_symbol): New function.
+ (s390_rel_address_ok_p): New function.
+ (legitimize_pic_address): Use s390_rel_address_ok_p.
+ (s390_load_got): Use s390_got_symbol.
+ (s390_option_override): Issue error if
+ -mno-pic-data-is-text-relative is used without -fpic/-fPIC.
+ * config/s390/s390.h (TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE):
+ New macro.
+ * config/s390/s390.opt: New option mpic-data-is-text-relative.
+
+2017-06-27 Andrew Pinski <apinski@cavium.com>
+
+ * match.pd (X >/>=/</<= 0 ? 1.0 : -1.0): New patterns.
+ (X * copysign (1.0, X)): New pattern.
+ (X * copysign (1.0, -X)): New pattern.
+ (copysign (-1.0, CST)): New pattern.
+
+2017-06-27 Joseph Myers <joseph@codesourcery.com>
+
+ * genmultilib (combination_space): Remove variable.
+ Validate reuse rules against regular expression for any sequence
+ of multilib options in any order.
+
+2017-06-27 Michael Collison <michael.collison@arm.com>
+
+ * config/aarch64/aarch64-simd.md (aarch64_combine<mode>): Directly
+ call aarch64_split_simd_combine.
+ * (aarch64_combine_internal<mode>): Delete pattern.
+ * config/aarch64/aarch64.c (aarch64_split_simd_combine):
+ Allow register and subreg operands.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+
+ * config/i386/vxworks.h (ASM_SPEC): Remove definition. No target
+ specific need, just fallback on defaults.
+ (ASM_OUTPUT_ALIGNED_BSS): Add #undef before #define.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * config/i386/vxworks.h (DBX_REGISTER_NUMBER): Pick distinct
+ map for 64bits.
+ (TARGET_OS_CPP_BUILTINS): builtin_define CPU to X86_64 for 64bit
+ targets. Pick a default if no particular attempt applied.
+ (STACK_CHECK_PROTECT): Double for 64bit targets, which have
+ larger contexts.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+
+ * config.gcc (i*86-wrs-vxworks7): Handle new acceptable triplet.
+ (x86_64-wrs-vxworks7): Likewise.
+
+2017-06-27 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/81223
+ * ubsan.c (instrument_null): Check get_base_address's result for null.
+
+2017-06-27 Marc Glisse <marc.glisse@inria.fr>
+
+ * match.pd ((A+-B)+(C-A), (A+B)-(A-C)): New transformations.
+
+2017-06-27 Marc Glisse <marc.glisse@inria.fr>
+
+ * builtin-types.def (BT_FENV_T_PTR, BT_CONST_FENV_T_PTR,
+ BT_FEXCEPT_T_PTR, BT_CONST_FEXCEPT_T_PTR): New primitive types.
+ (BT_FN_INT_FENV_T_PTR, BT_FN_INT_CONST_FENV_T_PTR,
+ BT_FN_INT_FEXCEPT_T_PTR_INT, BT_FN_INT_CONST_FEXCEPT_T_PTR_INT):
+ New function types.
+ * builtins.def (BUILT_IN_FECLEAREXCEPT, BUILT_IN_FEGETENV,
+ BUILT_IN_FEGETEXCEPTFLAG, BUILT_IN_FEGETROUND,
+ BUILT_IN_FEHOLDEXCEPT, BUILT_IN_FERAISEEXCEPT,
+ BUILT_IN_FESETENV, BUILT_IN_FESETEXCEPTFLAG,
+ BUILT_IN_FESETROUND, BUILT_IN_FETESTEXCEPT,
+ BUILT_IN_FEUPDATEENV): New builtins.
+ * tree-core.h (TI_FENV_T_PTR_TYPE, TI_CONST_FENV_T_PTR_TYPE,
+ TI_FEXCEPT_T_PTR_TYPE, TI_CONST_FEXCEPT_T_PTR_TYPE): New entries.
+ * tree.h (fenv_t_ptr_type_node, const_fenv_t_ptr_type_node,
+ fexcept_t_ptr_type_node, const_fexcept_t_ptr_type_node): New
+ macros.
+ (builtin_structptr_types): Adjust size.
+ * tree.c (builtin_structptr_types): Add four entries.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (VXWORKS_LIB_SPEC): Incorporate ...
+ (TLS_SYM): New local macro, forcing reference to __tls__ on
+ link command lines for VxWorks 7 RTPs, triggering initialization
+ of tlsLib.
+ (VXWORKS_HAVE_TLS): New macro. State whether the target VxWorks
+ OS features TLS support, true for RTPs on VxWorks 7.
+ * config/vxworks.c (vxworks_override_options): Setup emutls
+ accordingly.
+
+2017-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ * predict.c (test_prediction_value_range): Use -1U instead of -1
+ to avoid narrowing conversion warning.
+ * dumpfile.c (dump_options): Wrap all value into dump_flags_t cast
+ to avoid narrowing conversion warning.
+ * opt-functions.awk (var_ref): Return (unsigned short) -1 instead of
+ -1.
+ * optc-gen.awk (END): Expect (unsigned short) -1 instead of -1.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+
+ * config/vxworks.h (VXWORKS_LIBS_RTP): Alternative definition for
+ 64bit configurations.
+ (PTR_DIFF_TYPE): Alternative definition for TARGET_LP64.
+ (SIZE_TYPE): Likewise.
+ * config/vxworks.c (vxworks_emutls_var_fields): Use
+ long_unsigned_type_node instead of unsigned_type_node as the offset
+ field type, which is "pointer" mode in emutls.c.
+
+2017-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81209
+ * ubsan.c (ubsan_encode_value): Initialize DECL_CONTEXT on var.
+
+ PR middle-end/81207
+ * gimple-fold.c (replace_call_with_call_and_fold): Handle
+ gimple_vuse copying separately from gimple_vdef copying.
+
+2017-06-27 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * value-prof.c (free_hist): Remove call to memset and the enclosing if
+ condition.
+
+2017-06-26 Jerome Lambourg <lambourg@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * config.gcc (*-*-vxworks*): Add TARGET_VXWORKS7=1 to tm_defines
+ for all vxworks7 targets.
+ * config/vxworks.h (TARGET_VXWORKS7): If not defined, define to 0.
+ (VXWORKS_ADDITIONAL_CPP_SPEC): Alternative definition for VXWORKS7.
+ (VXWORKS_LIBS_RTP, VXWORKS_LIBS_RTP_DIR): New macros, allowing
+ variations for VX6/VX7 and 32/64bits later on in ...
+ (VXWORKS_LIB_SPEC): Leverage new macros.
+ (VXWORKS_OS_CPP_BUILTINS): Define _VSB_CONFIG_FILE for VXWORKS7,
+ as well as _ALLOW_KEYWORD_MACROS when "inline" is not a keyword.
+
+2017-06-26 Jerome Lambourg <lambourg@adacore.com>
+
+ * config/vxworks.h (VXWORKS_OS_CPP_BUILTINS): builtin_define
+ _VX_TOOL_FAMILY and _VX_TOOL to gnu.
+
+2017-06-26 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/rs6000-c.c: Add support for built-in functions
+ vector bool char vec_reve (vector bool char);
+ vector signed char vec_reve (vector signed char);
+ vector unsigned char vec_reve (vector unsigned char);
+ vector bool int vec_reve (vector bool int);
+ vector signed int vec_reve (vector signed int);
+ vector unsigned int vec_reve (vector unsigned int);
+ vector bool long long vec_reve (vector bool long long);
+ vector signed long long vec_reve (vector signed long long);
+ vector unsigned long long vec_reve (vector unsigned long long);
+ vector bool short vec_reve (vector bool short);
+ vector signed short vec_reve (vector signed short);
+ vector double vec_reve (vector double);
+ vector float vec_reve (vector float);
+ * config/rs6000/rs6000-builtin.def (VREVE_V2DI, VREVE_V4SI,
+ VREVE_V8HI, VREVE_V16QI, VREVE_V2DF, VREVE_V4SF, VREVE): New builtin.
+ * config/rs6000/altivec.md (UNSPEC_VREVEV): New UNSPEC.
+ (altivec_vreve): New pattern.
+ * config/rs6000/altivec.h (vec_reve): New define.
+ * doc/extend.texi (vec_rev): Update the built-in documentation file
+ for the new built-in functions.
+
+2016-06-26 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/71815
+ * gimple-ssa-strength-reduction.c (uses_consumed_by_stmt): New
+ function.
+ (find_basis_for_candidate): Call uses_consumed_by_stmt rather than
+ has_single_use.
+ (slsr_process_phi): Likewise.
+ (replace_uncond_cands_and_profitable_phis): Don't replace a
+ multiply candidate with a stride of 1 (copy or cast).
+ (phi_incr_cost): Call uses_consumed_by_stmt rather than
+ has_single_use.
+ (lowest_cost_path): Likewise.
+ (total_savings): Likewise.
+
+2017-06-26 Richard Biener <rguenther@suse.de>
+
+ PR target/81175
+ * config/i386/i386.c (ix86_init_mmx_sse_builtins):
+ Use def_builtin_pure for all gather builtins.
+
+2017-06-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81203
+ * tree-tailcall.c (find_tail_calls): Do not move stmts into
+ non-dominating BBs.
+
+2017-06-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/80116
+ * doc/invoke.texi: Document -Wmultistatement-macros.
+
+2017-06-26 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * doc/sourcebuild.texi (ARM-specific attributes): Document new
+ arm_neon_ok_no_float_abi effective target.
+
2017-06-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/80928
@@ -285,7 +4898,7 @@
attribute type list for neon_multiply.
* config/arm/types.md (crypto_pmull): Add.
* config/arm/xgene1.md (xgene1_neon_pmull): Add crypto_pmull to
- attribute type list.
+ attribute type list.
2017-06-20 Andreas Tobler <andreast@gcc.gnu.org>
@@ -541,9 +5154,9 @@
2017-06-16 Richard Earnshaw <rearnsha@arm.com>
* config/arm/t-linux-eabi (MULTILIB_EXCEPTIONS): Set to empty.
- (MULTILIB_RESUE): Likewise.
- (MULTILIB_MATCHES): Likewise.
- (MULTLIB_REQUIRED): Likewise.
+ (MULTILIB_RESUE): Likewise.
+ (MULTILIB_MATCHES): Likewise.
+ (MULTLIB_REQUIRED): Likewise.
2017-06-16 Richard Earnshaw <rearnsha@arm.com>
@@ -916,28 +5529,28 @@
2017-06-16 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
- * config/aarch64/aarch64.c (qdf24xx_prefetch_tune): Update
- prefetch settings, and enable prefetching by default at -O3.
+ * config/aarch64/aarch64.c (qdf24xx_prefetch_tune): Update
+ prefetch settings, and enable prefetching by default at -O3.
2017-06-16 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
- * config/aarch64/aarch64.c (aarch64_override_options_internal):
- Set flag_prefetch_loop_arrays according to tuning data.
+ * config/aarch64/aarch64.c (aarch64_override_options_internal):
+ Set flag_prefetch_loop_arrays according to tuning data.
2017-06-16 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
- * config/aarch64/aarch64-protos.h (struct cpu_prefetch_tune):
- New tune structure.
- (struct tune_params): Use cpu_prefetch_tune instead of cache_line_size.
- [Unrelated to main purpose of the patch] Place the pointer field last
- to enable type checking errors when tune structure are wrongly merged.
- * config/aarch64/aarch64.c (generic_prefetch_tune,)
- (exynosm1_prefetch_tune, qdf24xx_prefetch_tune,)
- (thunderx2t99_prefetch_tune): New tune constants.
- (tune_params *_tunings): Update all tunings (no functional change).
- (aarch64_override_options_internal): Set PARAM_SIMULTANEOUS_PREFETCHES,
- PARAM_L1_CACHE_SIZE, PARAM_L1_CACHE_LINE_SIZE, and PARAM_L2_CACHE_SIZE
- from tunings structures.
+ * config/aarch64/aarch64-protos.h (struct cpu_prefetch_tune):
+ New tune structure.
+ (struct tune_params): Use cpu_prefetch_tune instead of cache_line_size.
+ [Unrelated to main purpose of the patch] Place the pointer field last
+ to enable type checking errors when tune structure are wrongly merged.
+ * config/aarch64/aarch64.c (generic_prefetch_tune,)
+ (exynosm1_prefetch_tune, qdf24xx_prefetch_tune,)
+ (thunderx2t99_prefetch_tune): New tune constants.
+ (tune_params *_tunings): Update all tunings (no functional change).
+ (aarch64_override_options_internal): Set PARAM_SIMULTANEOUS_PREFETCHES,
+ PARAM_L1_CACHE_SIZE, PARAM_L1_CACHE_LINE_SIZE, and PARAM_L2_CACHE_SIZE
+ from tunings structures.
2017-06-16 Jakub Jelinek <jakub@redhat.com>
@@ -1069,7 +5682,7 @@
PR target/71663
* config/aarch64/aarch64.c (aarch64_expand_vector_init):
- Improve vector initialization code gen for only variable case.
+ Improve vector initialization code gen for only variable case.
2017-06-14 Eric Botcazou <ebotcazou@adacore.com>
@@ -1913,7 +6526,7 @@
PR sanitizer/80932
* fold-const.c (extract_muldiv_1) <case MINUS_EXPR>: Add
- TYPE_OVERFLOW_WRAPS check.
+ TYPE_OVERFLOW_WRAPS check.
2017-06-07 Bin Cheng <bin.cheng@arm.com>
@@ -1956,12 +6569,13 @@
2017-06-07 Tamar Christina <tamar.christina@arm.com>
- * config/aarch64/aarch64.c (aarch64_rtx_costs): Make sdiv more expensive than udiv.
- Remove floating point cases from mod.
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Make sdiv more
+ expensive than udiv. Remove floating point cases from mod.
2017-06-07 Tamar Christina <tamar.christina@arm.com>
- * config/arm/aarch-cost-tables.h (cortexa53_extra_cost): Increase idiv cost.
+ * config/arm/aarch-cost-tables.h (cortexa53_extra_cost):
+ Increase idiv cost.
2017-06-07 Tamar Christina <tamar.christina@arm.com>
@@ -5671,7 +10285,7 @@
2017-05-04 Prakhar Bahuguna <prakhar.bahuguna@arm.com>
- * gcc/config/arm/arm-builtins.c (arm_init_builtins): Rename
+ * config/arm/arm-builtins.c (arm_init_builtins): Rename
__builtin_arm_ldfscr to __builtin_arm_get_fpscr, and rename
__builtin_arm_stfscr to __builtin_arm_set_fpscr.
@@ -11632,7 +16246,7 @@
2017-02-06 Palmer Dabbelt <palmer@dabbelt.com>
* config/riscv/riscv.c: New file.
- * gcc/common/config/riscv/riscv-common.c: Likewise.
+ * common/config/riscv/riscv-common.c: Likewise.
* config.gcc: Likewise.
* config/riscv/constraints.md: Likewise.
* config/riscv/elf.h: Likewise.
@@ -12895,7 +17509,7 @@
* config/i386/avx512bwintrin.h: Add k-mask test, kortest intrinsics.
* config/i386/avx512dqintrin.h: Ditto.
* config/i386/avx512fintrin.h: Ditto.
- * gcc/config/i386/i386.c: Handle new builtins.
+ * config/i386/i386.c: Handle new builtins.
* config/i386/i386-builtin.def: Add new builtins.
* config/i386/sse.md (ktest<mode>, kortest<mode>): New.
(UNSPEC_KORTEST, UNSPEC_KTEST): New.
@@ -13076,7 +17690,7 @@
* config/i386/avx512dqintrin.h: Ditto.
* config/i386/avx512fintrin.h: Ditto.
* config/i386/i386-builtin-types.def: Add new types.
- * gcc/config/i386/i386.c: Handle new types.
+ * config/i386/i386.c: Handle new types.
* config/i386/i386-builtin.def (__builtin_ia32_kshiftliqi)
(__builtin_ia32_kshiftlihi, __builtin_ia32_kshiftlisi)
(__builtin_ia32_kshiftlidi, __builtin_ia32_kshiftriqi)
@@ -13099,14 +17713,14 @@
(with_madd4): Add validation.
(all_defaults): Add madd4.
* config/mips/mips.opt (mmadd4): New option.
- * gcc/config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
+ * config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
mmadd4.
(TARGET_CPU_CPP_BUILTINS): Add builtin_define for
__mips_no_madd4.
(ISA_HAS_UNFUSED_MADD4): Gate with mips_madd4.
(ISA_HAS_FUSED_MADD4): Likewise.
- * gcc/doc/invoke.texi (-mmadd4): Document the new option.
- * gcc/doc/install.texi (--with-madd4): Document the new option.
+ * doc/invoke.texi (-mmadd4): Document the new option.
+ * doc/install.texi (--with-madd4): Document the new option.
2017-01-19 Jiong Wang <jiong.wang@arm.com>
@@ -13244,12 +17858,12 @@
(with_lxc1_sxc1): Add validation.
(all_defaults): Add lxc1-sxc1.
* config/mips/mips.opt (mlxc1-sxc1): New option.
- * gcc/config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
+ * config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for
mlxc1-sxc1.
(TARGET_CPU_CPP_BUILTINS): Add builtin_define for
__mips_no_lxc1_sxc1.
(ISA_HAS_LXC1_SXC1): Gate with mips_lxc1_sxc1.
- * gcc/doc/invoke.texi (-mlxc1-sxc1): Document the new option.
+ * doc/invoke.texi (-mlxc1-sxc1): Document the new option.
* doc/install.texi (--with-lxc1-sxc1): Document the new option.
2017-01-19 Richard Biener <rguenther@suse.de>
@@ -14666,8 +19280,8 @@
'arm_const_bounds'.
* config/arm/types.md (coproc): New.
* config/arm/unspecs.md (VUNSPEC_CDP, VUNSPEC_CDP2): New.
- * gcc/doc/extend.texi (ACLE): Add a mention of Coprocessor intrinsics.
- * gcc/doc/sourcebuild.texi (arm_coproc1_ok, arm_coproc2_ok,
+ * doc/extend.texi (ACLE): Add a mention of Coprocessor intrinsics.
+ * doc/sourcebuild.texi (arm_coproc1_ok, arm_coproc2_ok,
arm_coproc3_ok, arm_coproc4_ok): Document new effective targets.
2017-01-06 Andre Vieira <andre.simoesdiasvieira@arm.com>
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 57a754a6e0d..cbcfeb98518 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20170626
+20170731
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 67d69c1c0d2..efca9169671 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -900,17 +900,19 @@ COMMON_TARGET_DEF = common/common-target.def target-hooks-macros.h
TARGET_H = $(TM_H) target.h $(TARGET_DEF) insn-modes.h insn-codes.h
C_TARGET_H = c-family/c-target.h $(C_TARGET_DEF)
COMMON_TARGET_H = common/common-target.h $(INPUT_H) $(COMMON_TARGET_DEF)
-MACHMODE_H = machmode.h mode-classes.def insn-modes.h
-HOOKS_H = hooks.h $(MACHMODE_H)
+MACHMODE_H = machmode.h mode-classes.def
+HOOKS_H = hooks.h
HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
TARGET_DEF_H = target-def.h target-hooks-def.h $(HOOKS_H) targhooks.h
C_TARGET_DEF_H = c-family/c-target-def.h c-family/c-target-hooks-def.h \
$(TREE_H) $(C_COMMON_H) $(HOOKS_H) common/common-targhooks.h
-RTL_BASE_H = coretypes.h rtl.h rtl.def $(MACHMODE_H) reg-notes.def \
+CORETYPES_H = coretypes.h insn-modes.h signop.h wide-int.h wide-int-print.h \
+ insn-modes-inline.h $(MACHMODE_H) double-int.h
+RTL_BASE_H = $(CORETYPES_H) rtl.h rtl.def reg-notes.def \
insn-notes.def $(INPUT_H) $(REAL_H) statistics.h $(VEC_H) \
$(FIXED_VALUE_H) alias.h $(HASHTAB_H)
-FIXED_VALUE_H = fixed-value.h $(MACHMODE_H) double-int.h
+FIXED_VALUE_H = fixed-value.h
RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
PARAMS_H = params.h params-enum.h params.def
@@ -919,11 +921,11 @@ BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
hsa-builtins.def
INTERNAL_FN_DEF = internal-fn.def
INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
-TREE_CORE_H = tree-core.h coretypes.h all-tree.def tree.def \
- c-family/c-common.def $(lang_tree_files) $(MACHMODE_H) \
+TREE_CORE_H = tree-core.h $(CORETYPES_H) all-tree.def tree.def \
+ c-family/c-common.def $(lang_tree_files) \
$(BUILTINS_DEF) $(INPUT_H) statistics.h \
$(VEC_H) treestruct.def $(HASHTAB_H) \
- double-int.h alias.h $(SYMTAB_H) $(FLAGS_H) \
+ alias.h $(SYMTAB_H) $(FLAGS_H) \
$(REAL_H) $(FIXED_VALUE_H)
TREE_H = tree.h $(TREE_CORE_H) tree-check.h
REGSET_H = regset.h $(BITMAP_H) hard-reg-set.h
@@ -938,12 +940,12 @@ EMIT_RTL_H = emit-rtl.h
FLAGS_H = flags.h flag-types.h $(OPTIONS_H)
OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
FUNCTION_H = function.h $(HASHTAB_H) $(TM_H) hard-reg-set.h \
- $(VEC_H) $(INPUT_H) $(MACHMODE_H)
-EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
+ $(VEC_H) $(INPUT_H)
+EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) \
+ $(EMIT_RTL_H)
OPTABS_H = optabs.h insn-codes.h insn-opinit.h
-REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
-CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \
- $(BITMAP_H) sbitmap.h
+REGS_H = regs.h hard-reg-set.h
+CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(BITMAP_H) sbitmap.h
IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
@@ -984,7 +986,7 @@ DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
$(C_COMMON_H) $(TREE_H)
TREE_INLINE_H = tree-inline.h
-REAL_H = real.h $(MACHMODE_H)
+REAL_H = real.h
LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
$(CGRAPH_H) $(VEC_H) $(HASH_TABLE_H) $(TREE_H) $(GIMPLE_H) \
$(GCOV_IO_H) $(DIAGNOSTIC_H) alloc-pool.h
@@ -1632,7 +1634,7 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
insn-latencytab.c insn-opinit.c insn-opinit.h insn-preds.c insn-constants.h \
tm-preds.h tm-constrs.h checksum-options gimple-match.c generic-match.c \
- tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
+ tree-check.h min-insn-modes.c insn-modes.c insn-modes.h insn-modes-inline.h \
genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
case-cfn-macros.h cfn-operators.pd \
xgcc$(exeext) cpp$(exeext) $(FULL_DRIVER_NAME) \
@@ -1903,30 +1905,64 @@ rest.cross: specs
# "nul.s" on Windows. Because on Windows "nul" is a reserved file name.
# Specify the path to gcc/testsuite/selftests within the srcdir
# as an argument to -fself-test.
-SELFTEST_FLAGS = -nostdinc -x c /dev/null -S -o /dev/null \
+SELFTEST_FLAGS = -nostdinc /dev/null -S -o /dev/null \
-fself-test=$(srcdir)/testsuite/selftests
-# Run the selftests during the build once we have a driver and a cc1,
+C_SELFTEST_FLAGS = -xc $(SELFTEST_FLAGS)
+CPP_SELFTEST_FLAGS = -xc++ $(SELFTEST_FLAGS)
+
+SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
+
+C_SELFTEST_DEPS = cc1$(exeext) $(SELFTEST_DEPS)
+CPP_SELFTEST_DEPS = cc1plus$(exeext) $(SELFTEST_DEPS)
+
+# Run the selftests during the build once we have a driver and the frontend,
# so that self-test failures are caught as early as possible.
-# Use "s-selftest" to ensure that we only run the selftests if the
-# driver, cc1, or selftest data change.
+# Use "s-selftest-FE" to ensure that we only run the selftests if the
+# driver, frontend, or selftest data change.
.PHONY: selftest
-selftest: s-selftest
-s-selftest: $(GCC_PASSES) cc1$(exeext) stmp-int-hdrs \
- $(srcdir)/testsuite/selftests
- $(GCC_FOR_TARGET) $(SELFTEST_FLAGS)
+
+# By default, only run the selftests within the C frontend
+selftest: s-selftest-c
+
+# C selftests
+s-selftest-c: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS)
$(STAMP) $@
-# Convenience method for running selftests under gdb:
-.PHONY: selftest-gdb
-selftest-gdb: $(GCC_PASSES) cc1$(exeext) stmp-int-hdrs
- $(GCC_FOR_TARGET) $(SELFTEST_FLAGS) \
+# Convenience methods for running C selftests under gdb:
+.PHONY: selftest-c-gdb
+selftest-c-gdb: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS) \
-wrapper gdb,--args
-# Convenience method for running selftests under valgrind:
+.PHONY: selftest-gdb
+selftest-gdb: selftest-c-gdb
+
+# Convenience methods for running C selftests under valgrind:
+.PHONY: selftest-c-valgrind
+selftest-c-valgrind: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS) \
+ -wrapper valgrind,--leak-check=full
+
.PHONY: selftest-valgrind
-selftest-valgrind: $(GCC_PASSES) cc1$(exeext) stmp-int-hdrs
- $(GCC_FOR_TARGET) $(SELFTEST_FLAGS) \
+selftest-valgrind: selftest-c-valgrind
+
+# C++ selftests
+s-selftest-c++: $(CPP_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(CPP_SELFTEST_FLAGS)
+ $(STAMP) $@
+
+# Convenience method for running C++ selftests under gdb:
+.PHONY: selftest-c++-gdb
+selftest-c++-gdb: $(CPP_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(CPP_SELFTEST_FLAGS) \
+ -wrapper gdb,--args
+
+# Convenience method for running C++ selftests under valgrind:
+.PHONY: selftest-c++-valgrind
+selftest-c++-valgrind: $(CPP_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(CPP_SELFTEST_FLAGS) \
-wrapper valgrind,--leak-check=full
# Recompile all the language-independent object files.
@@ -2318,6 +2354,7 @@ s-genrtl-h: build/gengenrtl$(build_exeext)
insn-modes.c: s-modes; @true
insn-modes.h: s-modes-h; @true
+insn-modes-inline.h: s-modes-inline-h; @true
min-insn-modes.c: s-modes-m; @true
s-modes: build/genmodes$(build_exeext)
@@ -2330,6 +2367,12 @@ s-modes-h: build/genmodes$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-modes.h insn-modes.h
$(STAMP) s-modes-h
+s-modes-inline-h: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -i > tmp-modes-inline.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes-inline.h \
+ insn-modes-inline.h
+ $(STAMP) s-modes-inline-h
+
s-modes-m: build/genmodes$(build_exeext)
$(RUN_GEN) build/genmodes$(build_exeext) -m > tmp-min-modes.c
$(SHELL) $(srcdir)/../move-if-change tmp-min-modes.c min-insn-modes.c
@@ -2566,7 +2609,8 @@ s-gtype: build/gengtype$(build_exeext) $(filter-out [%], $(GTFILES)) \
generated_files = config.h tm.h $(TM_P_H) $(TM_H) multilib.h \
$(simple_generated_h) specs.h \
- tree-check.h genrtl.h insn-modes.h tm-preds.h tm-constrs.h \
+ tree-check.h genrtl.h insn-modes.h insn-modes-inline.h \
+ tm-preds.h tm-constrs.h \
$(ALL_GTFILES_H) gtype-desc.c gtype-desc.h gcov-iov.h \
options.h target-hooks-def.h insn-opinit.h \
common/common-target-hooks-def.h pass-instances.def \
@@ -2593,30 +2637,30 @@ build/version.o: version.c version.h \
# Header dependencies for the programs that generate source code.
# These are library modules...
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)
-build/ggc-none.o : ggc-none.c $(BCONFIG_H) $(SYSTEM_H) coretypes.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)
+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) \
- $(MACHMODE_H)
-build/print-rtl.o: print-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(CORETYPES_H)
+build/print-rtl.o: print-rtl.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
$(GTM_H) $(RTL_BASE_H)
-build/read-md.o: read-md.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+build/read-md.o: read-md.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
$(HASHTAB_H) errors.h $(READ_MD_H)
-build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
$(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) $(READ_MD_H) \
$(GENSUPPORT_H)
-build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_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)
-build/hash-table.o : hash-table.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASH_TABLE_H) $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H)
-build/inchash.o : inchash.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASHTAB_H) inchash.h
+build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(VEC_H) \
+ $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_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/inchash.o : inchash.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(HASHTAB_H) inchash.h
build/gencondmd.o : build/gencondmd.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) insn-constants.h \
+ $(CORETYPES_H) $(GTM_H) insn-constants.h \
$(filter-out insn-flags.h, $(RTL_H) $(TM_P_H) $(FUNCTION_H) $(REGS_H) \
$(RECOG_H) output.h $(FLAGS_H) $(RESOURCE_H) toplev.h $(DIAGNOSTIC_CORE_H) reload.h \
$(EXCEPT_H) tm-constrs.h)
@@ -2628,39 +2672,39 @@ build/gencondmd.o : \
# ...these are the programs themselves.
build/genattr.o : genattr.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/genattr-common.o : genattr-common.c $(RTL_BASE_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/genattrtab.o : genattrtab.c $(RTL_BASE_H) $(OBSTACK_H) \
- $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(GGC_H) \
+ $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(GGC_H) \
$(READ_MD_H) $(GENSUPPORT_H) $(FNMATCH_H)
build/genautomata.o : genautomata.c $(RTL_BASE_H) $(OBSTACK_H) \
- $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(VEC_H) \
+ $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(VEC_H) \
$(HASHTAB_H) $(GENSUPPORT_H) $(FNMATCH_H)
build/gencheck.o : gencheck.c all-tree.def $(BCONFIG_H) $(GTM_H) \
- $(SYSTEM_H) coretypes.h tree.def c-family/c-common.def \
+ $(SYSTEM_H) $(CORETYPES_H) tree.def c-family/c-common.def \
$(lang_tree_files) gimple.def
build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H)
build/gencodes.o : gencodes.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H)
build/genconditions.o : genconditions.c $(RTL_BASE_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(HASHTAB_H) $(READ_MD_H) \
- $(GENSUPPORT_H)
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(HASHTAB_H) \
+ $(READ_MD_H) $(GENSUPPORT_H)
build/genconfig.o : genconfig.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H)
build/genconstants.o : genconstants.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h errors.h $(READ_MD_H)
+ $(CORETYPES_H) errors.h $(READ_MD_H)
build/genemit.o : genemit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) internal-fn.def
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) internal-fn.def
build/genenums.o : genenums.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h errors.h $(READ_MD_H)
+ $(CORETYPES_H) errors.h $(READ_MD_H)
build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/gentarget-def.o : gentarget-def.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
- $(HASH_TABLE_H) target-insns.def
+ $(CORETYPES_H) $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) \
+ $(GENSUPPORT_H) $(HASH_TABLE_H) target-insns.def
build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
# The gengtype generator program is special: Two versions are built.
@@ -2684,42 +2728,44 @@ CFLAGS-gengtype-parse.o += -DHOST_GENERATOR_FILE
build/gengtype-parse.o: $(BCONFIG_H)
gengtype-state.o build/gengtype-state.o: gengtype-state.c $(SYSTEM_H) \
- gengtype.h errors.h double-int.h version.h $(HASHTAB_H) $(OBSTACK_H) \
+ gengtype.h errors.h version.h $(HASHTAB_H) $(OBSTACK_H) \
$(XREGEX_H)
CFLAGS-gengtype-state.o += -DHOST_GENERATOR_FILE
build/gengtype-state.o: $(BCONFIG_H)
gengtype.o build/gengtype.o : gengtype.c $(SYSTEM_H) gengtype.h \
- rtl.def insn-notes.def errors.h double-int.h version.h \
+ rtl.def insn-notes.def errors.h version.h \
$(HASHTAB_H) $(OBSTACK_H) $(XREGEX_H)
CFLAGS-gengtype.o += -DHOST_GENERATOR_FILE
build/gengtype.o: $(BCONFIG_H)
CFLAGS-errors.o += -DHOST_GENERATOR_FILE
-build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
errors.h $(READ_MD_H)
build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h \
$(HASHTAB_H) machmode.def $(extra_modes_file)
build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def
build/genoutput.o : genoutput.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h $(DIAGNOSTIC_CORE_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h \
+ $(DIAGNOSTIC_CORE_H)
build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H)
build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
$(HASH_TABLE_H) inchash.h
build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF) \
$(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
build/genmatch.o : genmatch.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \
+ $(CORETYPES_H) errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \
tree.def builtins.def internal-fn.def
build/gencfn-macros.o : gencfn-macros.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h errors.h $(HASH_TABLE_H) hash-set.h builtins.def internal-fn.def
+ $(CORETYPES_H) errors.h $(HASH_TABLE_H) hash-set.h builtins.def \
+ internal-fn.def
# Compile the programs that generate insn-* from the machine description.
# They are compiled with $(COMPILER_FOR_BUILD), and associated libraries,
@@ -2817,8 +2863,8 @@ CFLAGS-cppdefault.o += $(PREPROCESSOR_DEFINES)
# having an empty command (nothing following the semicolon).
# gcov-iov.c is run on the build machine to generate gcov-iov.h from version.c
-build/gcov-iov.o: gcov-iov.c $(BCONFIG_H) coretypes.h $(GTM_H) \
- $(SYSTEM_H) coretypes.h $(TM_H)
+build/gcov-iov.o: gcov-iov.c $(BCONFIG_H) $(CORETYPES_H) $(GTM_H) \
+ $(SYSTEM_H) $(CORETYPES_H) $(TM_H)
build/gcov-iov$(build_exeext): build/gcov-iov.o
+$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) \
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index dc8f27994d5..dda51d423b6 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,7 +1,33 @@
+2017-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-interface/utils.c (gnat_write_global_declarations): Pass false
+ as new argument to the imported_module_or_decl debug hook.
+
+2017-07-25 Javier Miranda <miranda@adacore.com>
+
+ * checks.adb (Apply_Divide_Checks): Ensure that operands are not
+ evaluated twice.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-interface/ada-tree.h (TYPE_OBJECT_RECORD_TYPE,
+ TYPE_GCC_MIN_VALUE): Use TYPE_MIN_VALUE_RAW instead of TYPE_MINVAL.
+ (TYPE_GCC_MAX_VALUE): Use TYPE_MAX_VALUE_RAW instead of TYPE_MAXVAL.
+
+2017-07-18 Mike Frysinger <vapier@chromium.org>
+
+ * gcc-interface/Makefile.in (../../gnatmake$(exeext)): Delete $(P).
+ (../../gnatlink$(exeext)): Likewise.
+
+2017-07-15 John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+
+ PR ada/81446
+ * system-linux-m68k.ads: Add pragma No_Elaboration_Code_All.
+ (Backend_Overflow_Checks): Set to True.
+
2017-06-23 Jakub Jelinek <jakub@redhat.com>
- * gcc-interface/trans.c (gnat_to_gnu): Initialize sync to false to
- avoid UB.
+ * gcc-interface/trans.c (gnat_to_gnu): Initialize sync to false.
2017-06-21 Pierre-Marie de Rodat <derodat@adacore.com>
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 6162a0e38c0..a6670fa7697 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -1818,6 +1818,13 @@ package body Checks is
and then
((not LOK) or else (Llo = LLB))
then
+ -- Ensure that expressions are not evaluated twice (once
+ -- for their runtime checks and once for their regular
+ -- computation).
+
+ Force_Evaluation (Left, Mode => Strict);
+ Force_Evaluation (Right, Mode => Strict);
+
Insert_Action (N,
Make_Raise_Constraint_Error (Loc,
Condition =>
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 1c172037d92..b485c18ec21 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -2643,10 +2643,10 @@ gnatlink-re: ../stamp-tools gnatmake-re
# stamp target in the parent directory whenever gnat1 is rebuilt
# Likewise for the tools
-../../gnatmake$(exeext): $(P) b_gnatm.o $(GNATMAKE_OBJS)
+../../gnatmake$(exeext): b_gnatm.o $(GNATMAKE_OBJS)
+$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) $(TOOLS_LIBS) $(TOOLS1_LIBS)
-../../gnatlink$(exeext): $(P) b_gnatl.o $(GNATLINK_OBJS)
+../../gnatlink$(exeext): b_gnatl.o $(GNATLINK_OBJS)
+$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) $(TOOLS_LIBS) $(TOOLS1_LIBS)
../stamp-gnatlib-$(RTSDIR):
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 511a0bd8173..2470c83c901 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -209,21 +209,24 @@ do { \
this is a conflict on the minval field, but there doesn't seem to be
simple fix, so we'll live with this kludge for now. */
#define TYPE_OBJECT_RECORD_TYPE(NODE) \
- (TYPE_MINVAL (TREE_CHECK2 ((NODE), UNCONSTRAINED_ARRAY_TYPE, ENUMERAL_TYPE)))
+ (TYPE_MIN_VALUE_RAW (TREE_CHECK2 ((NODE), UNCONSTRAINED_ARRAY_TYPE, \
+ ENUMERAL_TYPE)))
/* For numerical types, this is the GCC lower bound of the type. The GCC
type system is based on the invariant that an object X of a given type
cannot hold at run time a value smaller than its lower bound; otherwise
the behavior is undefined. The optimizer takes advantage of this and
considers that the assertion X >= LB is always true. */
-#define TYPE_GCC_MIN_VALUE(NODE) (TYPE_MINVAL (NUMERICAL_TYPE_CHECK (NODE)))
+#define TYPE_GCC_MIN_VALUE(NODE) \
+ (TYPE_MIN_VALUE_RAW (NUMERICAL_TYPE_CHECK (NODE)))
/* For numerical types, this is the GCC upper bound of the type. The GCC
type system is based on the invariant that an object X of a given type
cannot hold at run time a value larger than its upper bound; otherwise
the behavior is undefined. The optimizer takes advantage of this and
considers that the assertion X <= UB is always true. */
-#define TYPE_GCC_MAX_VALUE(NODE) (TYPE_MAXVAL (NUMERICAL_TYPE_CHECK (NODE)))
+#define TYPE_GCC_MAX_VALUE(NODE) \
+ (TYPE_MAX_VALUE_RAW (NUMERICAL_TYPE_CHECK (NODE)))
/* For a FUNCTION_TYPE, if the subprogram has parameters passed by copy in/
copy out, this is the list of nodes used to specify the return values of
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 9e656579dda..475261b3682 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -5553,7 +5553,7 @@ gnat_write_global_declarations (void)
FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter)
if (TREE_CODE (iter) == IMPORTED_DECL && !DECL_IGNORED_P (iter))
debug_hooks->imported_module_or_decl (iter, DECL_NAME (iter),
- DECL_CONTEXT (iter), 0);
+ DECL_CONTEXT (iter), false, false);
}
/* ************************************************************************
diff --git a/gcc/ada/system-linux-m68k.ads b/gcc/ada/system-linux-m68k.ads
index 9aa6143f262..71d4f5762fb 100644
--- a/gcc/ada/system-linux-m68k.ads
+++ b/gcc/ada/system-linux-m68k.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- (GNU/Linux/m68k Version) --
-- --
--- Copyright (C) 2014-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 2014-2017, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -40,6 +40,9 @@ package System is
-- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada
-- 2005, this is Pure in any case (AI-362).
+ pragma No_Elaboration_Code_All;
+ -- Allow the use of that restriction in units that WITH this unit
+
type Name is (SYSTEM_NAME_GNAT);
System_Name : constant Name := SYSTEM_NAME_GNAT;
@@ -126,7 +129,7 @@ private
-- of the individual switch values.
Backend_Divide_Checks : constant Boolean := False;
- Backend_Overflow_Checks : constant Boolean := False;
+ Backend_Overflow_Checks : constant Boolean := True;
Command_Line_Args : constant Boolean := True;
Configurable_Run_Time : constant Boolean := False;
Denorm : constant Boolean := True;
diff --git a/gcc/asan.c b/gcc/asan.c
index e730530930b..5f9275f6425 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "cfgloop.h"
#include "gimple-builder.h"
+#include "gimple-fold.h"
#include "ubsan.h"
#include "params.h"
#include "builtins.h"
@@ -245,6 +246,7 @@ along with GCC; see the file COPYING3. If not see
static unsigned HOST_WIDE_INT asan_shadow_offset_value;
static bool asan_shadow_offset_computed;
static vec<char *> sanitized_sections;
+static tree last_alloca_addr;
/* Set of variable declarations that are going to be guarded by
use-after-scope sanitizer. */
@@ -308,6 +310,12 @@ asan_sanitize_stack_p (void)
return (sanitize_flags_p (SANITIZE_ADDRESS) && ASAN_STACK);
}
+bool
+asan_sanitize_allocas_p (void)
+{
+ return (asan_sanitize_stack_p () && ASAN_PROTECT_ALLOCAS);
+}
+
/* Checks whether section SEC should be sanitized. */
static bool
@@ -529,11 +537,186 @@ get_mem_ref_of_assignment (const gassign *assignment,
return true;
}
+/* Return address of last allocated dynamic alloca. */
+
+static tree
+get_last_alloca_addr ()
+{
+ if (last_alloca_addr)
+ return last_alloca_addr;
+
+ last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr");
+ gassign *g = gimple_build_assign (last_alloca_addr, null_pointer_node);
+ edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ gsi_insert_on_edge_immediate (e, g);
+ return last_alloca_addr;
+}
+
+/* Insert __asan_allocas_unpoison (top, bottom) call after
+ __builtin_stack_restore (new_sp) call.
+ The pseudocode of this routine should look like this:
+ __builtin_stack_restore (new_sp);
+ top = last_alloca_addr;
+ bot = new_sp;
+ __asan_allocas_unpoison (top, bot);
+ last_alloca_addr = new_sp;
+ In general, we can't use new_sp as bot parameter because on some
+ architectures SP has non zero offset from dynamic stack area. Moreover, on
+ some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each
+ particular function only after all callees were expanded to rtl.
+ The most noticeable example is PowerPC{,64}, see
+ http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK.
+ To overcome the issue we use following trick: pass new_sp as a second
+ parameter to __asan_allocas_unpoison and rewrite it during expansion with
+ virtual_dynamic_stack_rtx later in expand_asan_emit_allocas_unpoison
+ function.
+*/
+
+static void
+handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
+{
+ if (!iter || !asan_sanitize_allocas_p ())
+ return;
+
+ tree last_alloca = get_last_alloca_addr ();
+ tree restored_stack = gimple_call_arg (call, 0);
+ tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
+ gimple *g = gimple_build_call (fn, 2, last_alloca, restored_stack);
+ gsi_insert_after (iter, g, GSI_NEW_STMT);
+ g = gimple_build_assign (last_alloca, restored_stack);
+ gsi_insert_after (iter, g, GSI_NEW_STMT);
+}
+
+/* Deploy and poison redzones around __builtin_alloca call. To do this, we
+ should replace this call with another one with changed parameters and
+ replace all its uses with new address, so
+ addr = __builtin_alloca (old_size, align);
+ is replaced by
+ left_redzone_size = max (align, ASAN_RED_ZONE_SIZE);
+ Following two statements are optimized out if we know that
+ old_size & (ASAN_RED_ZONE_SIZE - 1) == 0, i.e. alloca doesn't need partial
+ redzone.
+ misalign = old_size & (ASAN_RED_ZONE_SIZE - 1);
+ partial_redzone_size = ASAN_RED_ZONE_SIZE - misalign;
+ right_redzone_size = ASAN_RED_ZONE_SIZE;
+ additional_size = left_redzone_size + partial_redzone_size +
+ right_redzone_size;
+ new_size = old_size + additional_size;
+ new_alloca = __builtin_alloca (new_size, max (align, 32))
+ __asan_alloca_poison (new_alloca, old_size)
+ addr = new_alloca + max (align, ASAN_RED_ZONE_SIZE);
+ last_alloca_addr = new_alloca;
+ ADDITIONAL_SIZE is added to make new memory allocation contain not only
+ requested memory, but also left, partial and right redzones as well as some
+ additional space, required by alignment. */
+
+static void
+handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
+{
+ if (!iter || !asan_sanitize_allocas_p ())
+ return;
+
+ gassign *g;
+ gcall *gg;
+ const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
+
+ tree last_alloca = get_last_alloca_addr ();
+ tree callee = gimple_call_fndecl (call);
+ tree old_size = gimple_call_arg (call, 0);
+ tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
+ : ptr_type_node;
+ tree partial_size = NULL_TREE;
+ bool alloca_with_align
+ = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA_WITH_ALIGN;
+ unsigned int align
+ = alloca_with_align ? tree_to_uhwi (gimple_call_arg (call, 1)) : 0;
+
+ /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
+ bytes of allocated space. Otherwise, align alloca to ASAN_RED_ZONE_SIZE
+ manually. */
+ align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
+
+ tree alloca_rz_mask = build_int_cst (size_type_node, redzone_mask);
+ tree redzone_size = build_int_cst (size_type_node, ASAN_RED_ZONE_SIZE);
+
+ /* Extract lower bits from old_size. */
+ wide_int size_nonzero_bits = get_nonzero_bits (old_size);
+ wide_int rz_mask
+ = wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits));
+ wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask);
+
+ /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial
+ redzone. Otherwise, compute its size here. */
+ if (wi::ne_p (old_size_lower_bits, 0))
+ {
+ /* misalign = size & (ASAN_RED_ZONE_SIZE - 1)
+ partial_size = ASAN_RED_ZONE_SIZE - misalign. */
+ g = gimple_build_assign (make_ssa_name (size_type_node, NULL),
+ BIT_AND_EXPR, old_size, alloca_rz_mask);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ tree misalign = gimple_assign_lhs (g);
+ g = gimple_build_assign (make_ssa_name (size_type_node, NULL), MINUS_EXPR,
+ redzone_size, misalign);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ partial_size = gimple_assign_lhs (g);
+ }
+
+ /* additional_size = align + ASAN_RED_ZONE_SIZE. */
+ tree additional_size = build_int_cst (size_type_node, align / BITS_PER_UNIT
+ + ASAN_RED_ZONE_SIZE);
+ /* If alloca has partial redzone, include it to additional_size too. */
+ if (partial_size)
+ {
+ /* additional_size += partial_size. */
+ g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR,
+ partial_size, additional_size);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ additional_size = gimple_assign_lhs (g);
+ }
+
+ /* new_size = old_size + additional_size. */
+ g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR, old_size,
+ additional_size);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ tree new_size = gimple_assign_lhs (g);
+
+ /* Build new __builtin_alloca call:
+ new_alloca_with_rz = __builtin_alloca (new_size, align). */
+ tree fn = builtin_decl_implicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ gg = gimple_build_call (fn, 2, new_size,
+ build_int_cst (size_type_node, align));
+ tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
+ gimple_call_set_lhs (gg, new_alloca_with_rz);
+ gsi_insert_before (iter, gg, GSI_SAME_STMT);
+
+ /* new_alloca = new_alloca_with_rz + align. */
+ g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
+ new_alloca_with_rz,
+ build_int_cst (size_type_node,
+ align / BITS_PER_UNIT));
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ tree new_alloca = gimple_assign_lhs (g);
+
+ /* Poison newly created alloca redzones:
+ __asan_alloca_poison (new_alloca, old_size). */
+ fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
+ gg = gimple_build_call (fn, 2, new_alloca, old_size);
+ gsi_insert_before (iter, gg, GSI_SAME_STMT);
+
+ /* Save new_alloca_with_rz value into last_alloca to use it during
+ allocas unpoisoning. */
+ g = gimple_build_assign (last_alloca, new_alloca_with_rz);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+
+ /* Finally, replace old alloca ptr with NEW_ALLOCA. */
+ replace_call_with_value (iter, new_alloca);
+}
+
/* Return the memory references contained in a gimple statement
representing a builtin call that has to do with memory access. */
static bool
-get_mem_refs_of_builtin_call (const gcall *call,
+get_mem_refs_of_builtin_call (gcall *call,
asan_mem_ref *src0,
tree *src0_len,
bool *src0_is_store,
@@ -544,7 +727,8 @@ get_mem_refs_of_builtin_call (const gcall *call,
tree *dst_len,
bool *dst_is_store,
bool *dest_is_deref,
- bool *intercepted_p)
+ bool *intercepted_p,
+ gimple_stmt_iterator *iter = NULL)
{
gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
@@ -603,6 +787,14 @@ get_mem_refs_of_builtin_call (const gcall *call,
len = gimple_call_lhs (call);
break;
+ case BUILT_IN_STACK_RESTORE:
+ handle_builtin_stack_restore (call, iter);
+ break;
+
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ case BUILT_IN_ALLOCA:
+ handle_builtin_alloca (call, iter);
+ break;
/* And now the __atomic* and __sync builtins.
These are handled differently from the classical memory memory
access builtins above. */
@@ -1016,7 +1208,9 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
jump = get_last_insn ();
gcc_assert (JUMP_P (jump));
- add_int_reg_note (jump, REG_BR_PROB, REG_BR_PROB_BASE * 80 / 100);
+ add_reg_br_prob_note (jump,
+ profile_probability::guessed_always ()
+ .apply_scale (80, 100));
}
void
@@ -1062,7 +1256,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
HOST_WIDE_INT base_offset = offsets[length - 1];
HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
- HOST_WIDE_INT last_offset;
+ HOST_WIDE_INT last_offset, last_size;
int l;
unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
tree str_cst, decl, id;
@@ -1145,9 +1339,9 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
emit_move_insn (orig_base, base);
ret = expand_normal (asan_detect_stack_use_after_return);
lab = gen_label_rtx ();
- int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
- VOIDmode, 0, lab, very_likely);
+ VOIDmode, 0, lab,
+ profile_probability::very_likely ());
snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
use_after_return_class);
ret = init_one_libfunc (buf);
@@ -1158,9 +1352,9 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
/* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
and NULL otherwise. Check RET value is NULL here and jump over the
BASE reassignment in this case. Otherwise, reassign BASE to RET. */
- int very_unlikely = REG_BR_PROB_BASE / 2000 - 1;
emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
- VOIDmode, 0, lab, very_unlikely);
+ VOIDmode, 0, lab,
+ profile_probability:: very_unlikely ());
ret = convert_memory_address (Pmode, ret);
emit_move_insn (base, ret);
emit_label (lab);
@@ -1255,9 +1449,9 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
{
rtx_code_label *lab2 = gen_label_rtx ();
char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
- int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
- VOIDmode, 0, lab2, very_likely);
+ VOIDmode, 0, lab2,
+ profile_probability::very_likely ());
shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
set_mem_alias_set (shadow_mem, asan_shadow_set);
mem = gen_rtx_MEM (ptr_mode, base);
@@ -1297,58 +1491,55 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
if (STRICT_ALIGNMENT)
set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
- /* Unpoison shadow memory of a stack at the very end of a function.
- As we're poisoning stack variables at the end of their scope,
- shadow memory must be properly unpoisoned here. The easiest approach
- would be to collect all variables that should not be unpoisoned and
- we unpoison shadow memory of the whole stack except ranges
- occupied by these variables. */
+ prev_offset = base_offset;
last_offset = base_offset;
- HOST_WIDE_INT current_offset = last_offset;
- if (length)
+ last_size = 0;
+ for (l = length; l; l -= 2)
{
- HOST_WIDE_INT var_end_offset = 0;
- HOST_WIDE_INT stack_start = offsets[length - 1];
- gcc_assert (last_offset == stack_start);
-
- for (int l = length - 2; l > 0; l -= 2)
+ offset = base_offset + ((offsets[l - 1] - base_offset)
+ & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
+ if (last_offset + last_size != offset)
{
- HOST_WIDE_INT var_offset = offsets[l];
- current_offset = var_offset;
- var_end_offset = offsets[l - 1];
- HOST_WIDE_INT rounded_size = ROUND_UP (var_end_offset - var_offset,
- BITS_PER_UNIT);
+ shadow_mem = adjust_address (shadow_mem, VOIDmode,
+ (last_offset - prev_offset)
+ >> ASAN_SHADOW_SHIFT);
+ prev_offset = last_offset;
+ asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+ last_offset = offset;
+ last_size = 0;
+ }
+ last_size += base_offset + ((offsets[l - 2] - base_offset)
+ & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
+ - offset;
- /* Should we unpoison the variable? */
+ /* Unpoison shadow memory that corresponds to a variable that is
+ is subject of use-after-return sanitization. */
+ if (l > 2)
+ {
+ decl = decls[l / 2 - 2];
if (asan_handled_variables != NULL
&& asan_handled_variables->contains (decl))
{
+ HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
if (dump_file && (dump_flags & TDF_DETAILS))
{
const char *n = (DECL_NAME (decl)
? IDENTIFIER_POINTER (DECL_NAME (decl))
: "<unknown>");
fprintf (dump_file, "Unpoisoning shadow stack for variable: "
- "%s (%" PRId64 "B)\n", n,
- var_end_offset - var_offset);
+ "%s (%" PRId64 " B)\n", n, size);
}
- unsigned HOST_WIDE_INT s
- = shadow_mem_size (current_offset - last_offset);
- asan_clear_shadow (shadow_mem, s);
- HOST_WIDE_INT shift
- = shadow_mem_size (current_offset - last_offset + rounded_size);
- shadow_mem = adjust_address (shadow_mem, VOIDmode, shift);
- last_offset = var_offset + rounded_size;
- current_offset = last_offset;
+ last_size += size & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
}
-
}
-
- /* Handle last redzone. */
- current_offset = offsets[0];
- asan_clear_shadow (shadow_mem,
- shadow_mem_size (current_offset - last_offset));
+ }
+ if (last_size)
+ {
+ shadow_mem = adjust_address (shadow_mem, VOIDmode,
+ (last_offset - prev_offset)
+ >> ASAN_SHADOW_SHIFT);
+ asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
}
/* Clean-up set with instrumented stack variables. */
@@ -1366,6 +1557,29 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
return insns;
}
+/* Emit __asan_allocas_unpoison (top, bot) call. The BASE parameter corresponds
+ to BOT argument, for TOP virtual_stack_dynamic_rtx is used. NEW_SEQUENCE
+ indicates whether we're emitting new instructions sequence or not. */
+
+rtx_insn *
+asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
+{
+ if (before)
+ push_to_sequence (before);
+ else
+ start_sequence ();
+ rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
+ top = convert_memory_address (ptr_mode, top);
+ bot = convert_memory_address (ptr_mode, bot);
+ ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, top,
+ ptr_mode, bot, ptr_mode);
+
+ do_pending_stack_adjust ();
+ rtx_insn *insns = get_insns ();
+ end_sequence ();
+ return insns;
+}
+
/* Return true if DECL, a global var, might be overridden and needs
therefore a local alias. */
@@ -1584,11 +1798,11 @@ create_cond_insert_point (gimple_stmt_iterator *iter,
/* Set up the newly created 'then block'. */
e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
- int fallthrough_probability
+ profile_probability fallthrough_probability
= then_more_likely_p
- ? PROB_VERY_UNLIKELY
- : PROB_ALWAYS - PROB_VERY_UNLIKELY;
- e->probability = PROB_ALWAYS - fallthrough_probability;
+ ? profile_probability::very_unlikely ()
+ : profile_probability::very_likely ();
+ e->probability = fallthrough_probability.invert ();
if (create_then_fallthru_edge)
make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
@@ -1875,6 +2089,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
|| bitsize != size_in_bytes * BITS_PER_UNIT)
return;
+ if (VAR_P (inner) && DECL_HARD_REGISTER (inner))
+ return;
+
if (VAR_P (inner)
&& offset == NULL_TREE
&& bitpos >= 0
@@ -2000,7 +2217,7 @@ instrument_builtin_call (gimple_stmt_iterator *iter)
&src0, &src0_len, &src0_is_store,
&src1, &src1_len, &src1_is_store,
&dest, &dest_len, &dest_is_store,
- &dest_is_deref, &intercepted_p))
+ &dest_is_deref, &intercepted_p, iter))
{
if (dest_is_deref)
{
@@ -2797,9 +3014,13 @@ asan_expand_mark_ifn (gimple_stmt_iterator *iter)
decl = TREE_OPERAND (decl, 0);
gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
- if (asan_handled_variables == NULL)
- asan_handled_variables = new hash_set<tree> (16);
- asan_handled_variables->add (decl);
+
+ if (is_poison)
+ {
+ if (asan_handled_variables == NULL)
+ asan_handled_variables = new hash_set<tree> (16);
+ asan_handled_variables->add (decl);
+ }
tree len = gimple_call_arg (g, 2);
gcc_assert (tree_fits_shwi_p (len));
@@ -3186,6 +3407,7 @@ asan_instrument (void)
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
transform_statements ();
+ last_alloca_addr = NULL_TREE;
return 0;
}
diff --git a/gcc/asan.h b/gcc/asan.h
index 95bb89e197c..c82d4d901e5 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -25,6 +25,7 @@ extern void asan_function_start (void);
extern void asan_finish_file (void);
extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int,
HOST_WIDE_INT *, tree *, int);
+extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *);
extern bool asan_protect_global (tree);
extern void initialize_sanitizer_builtins (void);
extern tree asan_dynamic_init_call (bool);
@@ -107,6 +108,8 @@ extern void set_sanitized_sections (const char *);
extern bool asan_sanitize_stack_p (void);
+extern bool asan_sanitize_allocas_p (void);
+
/* Return TRUE if builtin with given FCODE will be intercepted by
libasan. */
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 5eb19e82795..05fa8ef8692 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -404,8 +404,8 @@ decl_attributes (tree *node, tree attributes, int flags)
those targets that support it. */
if (TREE_CODE (*node) == FUNCTION_DECL
&& attributes
- && lookup_attribute_spec (get_identifier ("naked"))
- && lookup_attribute ("naked", attributes) != NULL)
+ && lookup_attribute ("naked", attributes) != NULL
+ && lookup_attribute_spec (get_identifier ("naked")))
{
if (lookup_attribute ("noinline", attributes) == NULL)
attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
@@ -414,6 +414,23 @@ decl_attributes (tree *node, tree attributes, int flags)
attributes = tree_cons (get_identifier ("noclone"), NULL, attributes);
}
+ /* A "noipa" function attribute implies "noinline", "noclone" and "no_icf"
+ for those targets that support it. */
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ && attributes
+ && lookup_attribute ("noipa", attributes) != NULL
+ && lookup_attribute_spec (get_identifier ("noipa")))
+ {
+ if (lookup_attribute ("noinline", attributes) == NULL)
+ attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
+
+ if (lookup_attribute ("noclone", attributes) == NULL)
+ attributes = tree_cons (get_identifier ("noclone"), NULL, attributes);
+
+ if (lookup_attribute ("no_icf", attributes) == NULL)
+ attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes);
+ }
+
targetm.insert_attributes (*node, &attributes);
for (a = attributes; a; a = TREE_CHAIN (a))
diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
index 91fa5cf0bbe..db1bd5bba2c 100644
--- a/gcc/auto-inc-dec.c
+++ b/gcc/auto-inc-dec.c
@@ -769,6 +769,12 @@ parse_add_or_inc (rtx_insn *insn, bool before_mem)
inc_insn.pat = pat;
inc_insn.reg_res = SET_DEST (pat);
inc_insn.reg0 = XEXP (SET_SRC (pat), 0);
+
+ /* Block any auto increment of the frame pointer since it expands into
+ an addition and cannot be removed by copy propagation. */
+ if (inc_insn.reg0 == frame_pointer_rtx)
+ return false;
+
if (rtx_equal_p (inc_insn.reg_res, inc_insn.reg0))
inc_insn.form = before_mem ? FORM_PRE_INC : FORM_POST_INC;
else
diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
index 973d7af37ff..9226e202d50 100644
--- a/gcc/auto-profile.c
+++ b/gcc/auto-profile.c
@@ -774,15 +774,15 @@ autofdo_source_profile::update_inlined_ind_target (gcall *stmt,
hot any more. Will avoid promote the original target.
To check if original promoted target is still hot, we check the total
- count of the unpromoted targets (stored in old_info). If it is no less
- than half of the callsite count (stored in INFO), the original promoted
- target is considered not hot any more. */
- if (total >= info->count / 2)
+ count of the unpromoted targets (stored in TOTAL). If a callsite count
+ (stored in INFO) is smaller than half of the total count, the original
+ promoted target is considered not hot any more. */
+ if (info->count < total / 2)
{
if (dump_file)
- fprintf (dump_file, " not hot anymore %ld >= %ld",
- (long)total,
- (long)info->count /2);
+ fprintf (dump_file, " not hot anymore %ld < %ld",
+ (long)info->count,
+ (long)total /2);
return false;
}
@@ -1151,7 +1151,7 @@ afdo_set_bb_count (basic_block bb, const stmt_set &promoted)
FOR_EACH_EDGE (e, ei, bb->succs)
afdo_source_profile->mark_annotated (e->goto_locus);
- bb->count = profile_count::from_gcov_type (max_count);
+ bb->count = profile_count::from_gcov_type (max_count).afdo ();
return true;
}
@@ -1228,7 +1228,7 @@ afdo_propagate_edge (bool is_succ, bb_set *annotated_bb,
edge e, unknown_edge = NULL;
edge_iterator ei;
int num_unknown_edge = 0;
- profile_count total_known_count = profile_count::zero ();
+ profile_count total_known_count = profile_count::zero ().afdo ();
FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds)
if (!is_edge_annotated (e, *annotated_edge))
@@ -1346,10 +1346,11 @@ afdo_propagate_circuit (const bb_set &annotated_bb, edge_set *annotated_edge)
continue;
total++;
only_one = ep;
- if (e->probability == 0 && !is_edge_annotated (ep, *annotated_edge))
+ if (!e->probability.initialized_p ()
+ && !is_edge_annotated (ep, *annotated_edge))
{
- ep->probability = 0;
- ep->count = profile_count::zero ();
+ ep->probability = profile_probability::never ();
+ ep->count = profile_count::zero ().afdo ();
set_edge_annotated (ep, annotated_edge);
}
}
@@ -1536,9 +1537,9 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts)
if (s == NULL)
return;
cgraph_node::get (current_function_decl)->count
- = profile_count::from_gcov_type (s->head_count ());
+ = profile_count::from_gcov_type (s->head_count ()).afdo ();
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count
- = profile_count::from_gcov_type (s->head_count ());
+ = profile_count::from_gcov_type (s->head_count ()).afdo ();
profile_count max_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
FOR_EACH_BB_FN (bb, cfun)
@@ -1546,9 +1547,11 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts)
edge e;
edge_iterator ei;
- bb->count = profile_count::uninitialized ();
+ /* As autoFDO uses sampling approach, we have to assume that all
+ counters are zero when not seen by autoFDO. */
+ bb->count = profile_count::zero ().afdo ();
FOR_EACH_EDGE (e, ei, bb->succs)
- e->count = profile_count::uninitialized ();
+ e->count = profile_count::zero ().afdo ();
if (afdo_set_bb_count (bb, promoted_stmts))
set_bb_annotated (bb, &annotated_bb);
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index b08a14a151b..c0c47784c02 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -45,7 +45,7 @@ struct GTY((user)) edge_def {
unsigned int dest_idx;
int flags; /* see cfg-flags.def */
- int probability; /* biased by REG_BR_PROB_BASE */
+ profile_probability probability;
profile_count count; /* Expected number of executions calculated
in profile.c */
};
@@ -300,8 +300,7 @@ enum cfg_bb_flags
? EDGE_SUCC ((bb), 1) : EDGE_SUCC ((bb), 0))
/* Return expected execution frequency of the edge E. */
-#define EDGE_FREQUENCY(e) RDIV ((e)->src->frequency * (e)->probability, \
- REG_BR_PROB_BASE)
+#define EDGE_FREQUENCY(e) e->probability.apply (e->src->frequency)
/* Compute a scale factor (or probability) suitable for scaling of
gcov_type values via apply_probability() and apply_scale(). */
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index c0386f4b37a..dc50546ab63 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -206,8 +206,8 @@ static void find_traces_1_round (int, int, gcov_type, struct trace *, int *,
int, bb_heap_t **, int);
static basic_block copy_bb (basic_block, edge, basic_block, int);
static long bb_to_key (basic_block);
-static bool better_edge_p (const_basic_block, const_edge, int, int, int, int,
- const_edge);
+static bool better_edge_p (const_basic_block, const_edge, profile_probability,
+ int, profile_probability, int, const_edge);
static bool connect_better_edge_p (const_edge, bool, int, const_edge,
struct trace *);
static void connect_traces (int, struct trace *);
@@ -513,11 +513,12 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
do
{
- int prob, freq;
+ profile_probability prob;
+ int freq;
bool ends_in_call;
/* The probability and frequency of the best edge. */
- int best_prob = INT_MIN / 2;
+ profile_probability best_prob = profile_probability::uninitialized ();
int best_freq = INT_MIN / 2;
best_edge = NULL;
@@ -565,7 +566,9 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
successor (i.e. it is unsuitable successor). When optimizing
for size, ignore the probability and frequency. */
if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX)
- || ((prob < branch_th || EDGE_FREQUENCY (e) < exec_th
+ || !prob.initialized_p ()
+ || ((prob.to_reg_br_prob_base () < branch_th
+ || EDGE_FREQUENCY (e) < exec_th
|| e->count < count_th) && (!for_size)))
continue;
@@ -648,7 +651,9 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
if (!(e->flags & EDGE_CAN_FALLTHRU)
|| (e->flags & EDGE_COMPLEX)
- || prob < branch_th || freq < exec_th
+ || !prob.initialized_p ()
+ || prob.to_reg_br_prob_base () < branch_th
+ || freq < exec_th
|| e->count < count_th)
{
/* When partitioning hot/cold basic blocks, make sure
@@ -936,14 +941,15 @@ bb_to_key (basic_block bb)
BEST_PROB; similarly for frequency. */
static bool
-better_edge_p (const_basic_block bb, const_edge e, int prob, int freq,
- int best_prob, int best_freq, const_edge cur_best_edge)
+better_edge_p (const_basic_block bb, const_edge e, profile_probability prob,
+ int freq, profile_probability best_prob, int best_freq,
+ const_edge cur_best_edge)
{
bool is_better_edge;
/* The BEST_* values do not have to be best, but can be a bit smaller than
maximum values. */
- int diff_prob = best_prob / 10;
+ profile_probability diff_prob = best_prob.apply_scale (1, 10);
int diff_freq = best_freq / 10;
/* The smaller one is better to keep the original order. */
@@ -951,7 +957,14 @@ better_edge_p (const_basic_block bb, const_edge e, int prob, int freq,
return !cur_best_edge
|| cur_best_edge->dest->index > e->dest->index;
- if (prob > best_prob + diff_prob)
+ /* Those edges are so expensive that continuing a trace is not useful
+ performance wise. */
+ if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
+ return false;
+
+ if (prob > best_prob + diff_prob
+ || (!best_prob.initialized_p ()
+ && prob > profile_probability::guessed_never ()))
/* The edge has higher probability than the temporary best edge. */
is_better_edge = true;
else if (prob < best_prob - diff_prob)
@@ -1289,16 +1302,15 @@ connect_traces (int n_traces, struct trace *traces)
}
}
- if (crtl->has_bb_partition)
- try_copy = false;
-
/* Copy tiny blocks always; copy larger blocks only when the
edge is traversed frequently enough. */
if (try_copy
+ && BB_PARTITION (best->src) == BB_PARTITION (best->dest)
&& copy_bb_p (best->dest,
optimize_edge_for_speed_p (best)
&& EDGE_FREQUENCY (best) >= freq_threshold
- && best->count >= count_threshold))
+ && (!best->count.initialized_p ()
+ || best->count >= count_threshold)))
{
basic_block new_bb;
@@ -1440,11 +1452,13 @@ fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
new_bb = create_basic_block (new_label, jump, last_bb);
new_bb->aux = last_bb->aux;
+ new_bb->frequency = post_bb->frequency;
+ new_bb->count = post_bb->count;
last_bb->aux = new_bb;
emit_barrier_after_bb (new_bb);
- make_edge (new_bb, post_bb, 0);
+ make_single_succ_edge (new_bb, post_bb, 0);
/* Make sure new bb is in the other partition. */
new_partition = BB_PARTITION (old_bb);
@@ -1494,7 +1508,8 @@ sanitize_hot_paths (bool walk_up, unsigned int cold_bb_count,
vec<edge, va_gc> *edges = walk_up ? bb->preds : bb->succs;
edge e;
edge_iterator ei;
- int highest_probability = 0;
+ profile_probability highest_probability
+ = profile_probability::uninitialized ();
int highest_freq = 0;
profile_count highest_count = profile_count::uninitialized ();
bool found = false;
@@ -1509,6 +1524,11 @@ sanitize_hot_paths (bool walk_up, unsigned int cold_bb_count,
if (e->flags & EDGE_DFS_BACK)
continue;
+ /* Do not expect profile insanities when profile was not adjusted. */
+ if (e->probability == profile_probability::never ()
+ || e->count == profile_count::zero ())
+ continue;
+
if (BB_PARTITION (reach_bb) != BB_COLD_PARTITION)
{
found = true;
@@ -1517,12 +1537,13 @@ sanitize_hot_paths (bool walk_up, unsigned int cold_bb_count,
/* The following loop will look for the hottest edge via
the edge count, if it is non-zero, then fallback to the edge
frequency and finally the edge probability. */
- if (e->count > highest_count)
+ if (!highest_count.initialized_p () || e->count > highest_count)
highest_count = e->count;
int edge_freq = EDGE_FREQUENCY (e);
if (edge_freq > highest_freq)
highest_freq = edge_freq;
- if (e->probability > highest_probability)
+ if (!highest_probability.initialized_p ()
+ || e->probability > highest_probability)
highest_probability = e->probability;
}
@@ -1538,6 +1559,10 @@ sanitize_hot_paths (bool walk_up, unsigned int cold_bb_count,
{
if (e->flags & EDGE_DFS_BACK)
continue;
+ /* Do not expect profile insanities when profile was not adjusted. */
+ if (e->probability == profile_probability::never ()
+ || e->count == profile_count::zero ())
+ continue;
/* Select the hottest edge using the edge count, if it is non-zero,
then fallback to the edge frequency and finally the edge
probability. */
@@ -1559,6 +1584,10 @@ sanitize_hot_paths (bool walk_up, unsigned int cold_bb_count,
/* We have a hot bb with an immediate dominator that is cold.
The dominator needs to be re-marked hot. */
BB_SET_PARTITION (reach_bb, BB_HOT_PARTITION);
+ if (dump_file)
+ fprintf (dump_file, "Promoting bb %i to hot partition to sanitize "
+ "profile of bb %i in %s walk\n", reach_bb->index,
+ bb->index, walk_up ? "backward" : "forward");
cold_bb_count--;
/* Now we need to examine newly-hot reach_bb to see if it is also
@@ -1586,6 +1615,8 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
unsigned int cold_bb_count = 0;
auto_vec<basic_block> bbs_in_hot_partition;
+ propagate_unlikely_bbs_forward ();
+
/* Mark which partition (hot/cold) each basic block belongs in. */
FOR_EACH_BB_FN (bb, cfun)
{
@@ -1634,6 +1665,12 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
&bbs_in_hot_partition);
if (cold_bb_count)
sanitize_hot_paths (false, cold_bb_count, &bbs_in_hot_partition);
+
+ hash_set <basic_block> set;
+ find_bbs_reachable_by_hot_paths (&set);
+ FOR_EACH_BB_FN (bb, cfun)
+ if (!set.contains (bb))
+ BB_SET_PARTITION (bb, BB_COLD_PARTITION);
}
/* The format of .gcc_except_table does not allow landing pads to
@@ -1804,18 +1841,14 @@ static void
fix_up_fall_thru_edges (void)
{
basic_block cur_bb;
- basic_block new_bb;
- edge succ1;
- edge succ2;
- edge fall_thru;
- edge cond_jump = NULL;
- bool cond_jump_crosses;
- int invert_worked;
- rtx_insn *old_jump;
- rtx_code_label *fall_thru_label;
FOR_EACH_BB_FN (cur_bb, cfun)
{
+ edge succ1;
+ edge succ2;
+ edge fall_thru = NULL;
+ edge cond_jump = NULL;
+
fall_thru = NULL;
if (EDGE_COUNT (cur_bb->succs) > 0)
succ1 = EDGE_SUCC (cur_bb, 0);
@@ -1841,20 +1874,8 @@ fix_up_fall_thru_edges (void)
fall_thru = succ2;
cond_jump = succ1;
}
- else if (succ1
- && (block_ends_with_call_p (cur_bb)
- || can_throw_internal (BB_END (cur_bb))))
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, cur_bb->succs)
- if (e->flags & EDGE_FALLTHRU)
- {
- fall_thru = e;
- break;
- }
- }
+ else if (succ2 && EDGE_COUNT (cur_bb->succs) > 2)
+ fall_thru = find_fallthru_edge (cur_bb->succs);
if (fall_thru && (fall_thru->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)))
{
@@ -1865,9 +1886,9 @@ fix_up_fall_thru_edges (void)
/* The fall_thru edge crosses; now check the cond jump edge, if
it exists. */
- cond_jump_crosses = true;
- invert_worked = 0;
- old_jump = BB_END (cur_bb);
+ bool cond_jump_crosses = true;
+ int invert_worked = 0;
+ rtx_insn *old_jump = BB_END (cur_bb);
/* Find the jump instruction, if there is one. */
@@ -1887,12 +1908,13 @@ fix_up_fall_thru_edges (void)
/* Find label in fall_thru block. We've already added
any missing labels, so there must be one. */
- fall_thru_label = block_label (fall_thru->dest);
+ rtx_code_label *fall_thru_label
+ = block_label (fall_thru->dest);
if (old_jump && fall_thru_label)
{
- rtx_jump_insn *old_jump_insn =
- dyn_cast <rtx_jump_insn *> (old_jump);
+ rtx_jump_insn *old_jump_insn
+ = dyn_cast <rtx_jump_insn *> (old_jump);
if (old_jump_insn)
invert_worked = invert_jump (old_jump_insn,
fall_thru_label, 0);
@@ -1923,7 +1945,7 @@ fix_up_fall_thru_edges (void)
becomes EDGE_CROSSING. */
fall_thru->flags &= ~EDGE_CROSSING;
- new_bb = force_nonfallthru (fall_thru);
+ basic_block new_bb = force_nonfallthru (fall_thru);
if (new_bb)
{
@@ -2125,7 +2147,7 @@ fix_crossing_conditional_branches (void)
for 'dest'. */
if (EDGE_COUNT (new_bb->succs) == 0)
- new_edge = make_edge (new_bb, dest, 0);
+ new_edge = make_single_succ_edge (new_bb, dest, 0);
else
new_edge = EDGE_SUCC (new_bb, 0);
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 7bebeecca55..03f6923db2f 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -273,7 +273,7 @@ bitmap_obstack_release (bitmap_obstack *bit_obstack)
it on the default bitmap obstack. */
bitmap
-bitmap_obstack_alloc_stat (bitmap_obstack *bit_obstack MEM_STAT_DECL)
+bitmap_alloc (bitmap_obstack *bit_obstack MEM_STAT_DECL)
{
bitmap map;
@@ -284,7 +284,7 @@ bitmap_obstack_alloc_stat (bitmap_obstack *bit_obstack MEM_STAT_DECL)
bit_obstack->heads = (struct bitmap_head *) map->first;
else
map = XOBNEW (&bit_obstack->obstack, bitmap_head);
- bitmap_initialize_stat (map, bit_obstack PASS_MEM_STAT);
+ bitmap_initialize (map, bit_obstack PASS_MEM_STAT);
if (GATHER_STATISTICS)
register_overhead (map, sizeof (bitmap_head));
@@ -295,12 +295,12 @@ bitmap_obstack_alloc_stat (bitmap_obstack *bit_obstack MEM_STAT_DECL)
/* Create a new GCd bitmap. */
bitmap
-bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
+bitmap_gc_alloc (ALONE_MEM_STAT_DECL)
{
bitmap map;
map = ggc_alloc<bitmap_head> ();
- bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
+ bitmap_initialize (map, NULL PASS_MEM_STAT);
if (GATHER_STATISTICS)
register_overhead (map, sizeof (bitmap_head));
diff --git a/gcc/bitmap.h b/gcc/bitmap.h
index ad5398409d6..348032360f2 100644
--- a/gcc/bitmap.h
+++ b/gcc/bitmap.h
@@ -335,20 +335,19 @@ extern void dump_bitmap_statistics (void);
to allocate from, NULL for GC'd bitmap. */
static inline void
-bitmap_initialize_stat (bitmap head, bitmap_obstack *obstack MEM_STAT_DECL)
+bitmap_initialize (bitmap head, bitmap_obstack *obstack CXX_MEM_STAT_INFO)
{
head->first = head->current = NULL;
head->obstack = obstack;
if (GATHER_STATISTICS)
bitmap_register (head PASS_MEM_STAT);
}
-#define bitmap_initialize(h,o) bitmap_initialize_stat (h,o MEM_STAT_INFO)
/* Allocate and free bitmaps from obstack, malloc and gc'd memory. */
-extern bitmap bitmap_obstack_alloc_stat (bitmap_obstack *obstack MEM_STAT_DECL);
-#define bitmap_obstack_alloc(t) bitmap_obstack_alloc_stat (t MEM_STAT_INFO)
-extern bitmap bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL);
-#define bitmap_gc_alloc() bitmap_gc_alloc_stat (ALONE_MEM_STAT_INFO)
+extern bitmap bitmap_alloc (bitmap_obstack *obstack CXX_MEM_STAT_INFO);
+#define BITMAP_ALLOC bitmap_alloc
+extern bitmap bitmap_gc_alloc (ALONE_CXX_MEM_STAT_INFO);
+#define BITMAP_GGC_ALLOC bitmap_gc_alloc
extern void bitmap_obstack_free (bitmap);
/* A few compatibility/functions macros for compatibility with sbitmaps */
@@ -365,12 +364,6 @@ extern unsigned bitmap_last_set_bit (const_bitmap);
/* Compute bitmap hash (for purposes of hashing etc.) */
extern hashval_t bitmap_hash (const_bitmap);
-/* Allocate a bitmap from a bit obstack. */
-#define BITMAP_ALLOC(OBSTACK) bitmap_obstack_alloc (OBSTACK)
-
-/* Allocate a gc'd bitmap. */
-#define BITMAP_GGC_ALLOC() bitmap_gc_alloc ()
-
/* Do any cleanup needed on a bitmap when it is no longer used. */
#define BITMAP_FREE(BITMAP) \
((void) (bitmap_obstack_free ((bitmap) BITMAP), (BITMAP) = (bitmap) NULL))
diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog
index 1b1a1eb523f..f7c82f44107 100644
--- a/gcc/brig/ChangeLog
+++ b/gcc/brig/ChangeLog
@@ -1,3 +1,15 @@
+2017-07-05 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * brig-c.h (brig_type_for_mode): Remove "enum" before "machine_mode".
+ * brig-lang.c (brig_langhook_type_for_mode): Likewise.
+
+2017-07-04 Jakub Jelinek <jakub@redhat.com>
+
+ * brigfrontend/brig-function.cc: Include profile-count.h.
+ * brigfrontend/brig-to-generic.cc: Likewise.
+
2017-05-18 Thomas Schwinge <thomas@codesourcery.com>
* brigfrontend/brig-to-generic.h (class brig_to_generic): Use
diff --git a/gcc/brig/brig-c.h b/gcc/brig/brig-c.h
index be3e282beb9..ae7eefe03ce 100644
--- a/gcc/brig/brig-c.h
+++ b/gcc/brig/brig-c.h
@@ -44,7 +44,7 @@ extern void brig_parse_input_files (const char **, unsigned int,
extern void brig_write_globals (void);
extern tree brig_type_for_size (unsigned int bits, int unsignedp);
-extern tree brig_type_for_mode (enum machine_mode, int unsignedp);
+extern tree brig_type_for_mode (machine_mode, int unsignedp);
/* Functions defined in the GCC interface called by the Brig frontend
proper. */
diff --git a/gcc/brig/brig-lang.c b/gcc/brig/brig-lang.c
index bd5310d466f..13e738e1937 100644
--- a/gcc/brig/brig-lang.c
+++ b/gcc/brig/brig-lang.c
@@ -241,7 +241,7 @@ brig_langhook_type_for_size (unsigned int bits,
}
static tree
-brig_langhook_type_for_mode (enum machine_mode mode, int unsignedp)
+brig_langhook_type_for_mode (machine_mode mode, int unsignedp)
{
if (mode == TYPE_MODE (void_type_node))
return void_type_node;
diff --git a/gcc/brig/brigfrontend/brig-function.cc b/gcc/brig/brigfrontend/brig-function.cc
index 382bec01a52..0ca9ebe8b0e 100644
--- a/gcc/brig/brigfrontend/brig-function.cc
+++ b/gcc/brig/brigfrontend/brig-function.cc
@@ -38,6 +38,7 @@
#include "phsa.h"
#include "tree-pretty-print.h"
#include "dumpfile.h"
+#include "profile-count.h"
#include "tree-cfg.h"
#include "errors.h"
#include "function.h"
diff --git a/gcc/brig/brigfrontend/brig-to-generic.cc b/gcc/brig/brigfrontend/brig-to-generic.cc
index d113bdcacf5..7559c055c3b 100644
--- a/gcc/brig/brigfrontend/brig-to-generic.cc
+++ b/gcc/brig/brigfrontend/brig-to-generic.cc
@@ -45,6 +45,7 @@
#include "phsa.h"
#include "tree-pretty-print.h"
#include "dumpfile.h"
+#include "profile-count.h"
#include "tree-cfg.h"
#include "errors.h"
#include "fold-const.h"
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 2a51d258355..a0d7d40ac36 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -107,6 +107,10 @@ DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex_long_double_type_node)
DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node)
DEF_PRIMITIVE_TYPE (BT_FILEPTR, fileptr_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_TM_PTR, const_tm_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FENV_T_PTR, fenv_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_FENV_T_PTR, const_fenv_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FEXCEPT_T_PTR, fexcept_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_FEXCEPT_T_PTR, const_fexcept_t_ptr_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_PTR, const_ptr_type_node)
DEF_PRIMITIVE_TYPE (BT_VOLATILE_PTR,
build_pointer_type
@@ -298,6 +302,8 @@ DEF_FUNCTION_TYPE_1 (BT_FN_BND_CONST_PTR, BT_BND, BT_CONST_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_BND, BT_CONST_PTR, BT_BND)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT32, BT_UINT16, BT_UINT32)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT16, BT_UINT32, BT_UINT16)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_FENV_T_PTR, BT_INT, BT_FENV_T_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_FENV_T_PTR, BT_INT, BT_CONST_FENV_T_PTR)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@@ -471,6 +477,10 @@ DEF_FUNCTION_TYPE_2 (BT_FN_CONST_PTR_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST
DEF_FUNCTION_TYPE_2 (BT_FN_BND_CONST_PTR_SIZE, BT_BND, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT32_UINT64_PTR,
BT_UINT32, BT_UINT64, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_FEXCEPT_T_PTR_INT, BT_INT, BT_FEXCEPT_T_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_FEXCEPT_T_PTR_INT, BT_INT,
+ BT_CONST_FEXCEPT_T_PTR, BT_INT)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 7e829ef1408..2deef725620 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4962,6 +4962,24 @@ expand_builtin_alloca (tree exp)
return result;
}
+/* Emit a call to __asan_allocas_unpoison call in EXP. Replace second argument
+ of the call with virtual_stack_dynamic_rtx because in asan pass we emit a
+ dummy value into second parameter relying on this function to perform the
+ change. See motivation for this in comment to handle_builtin_stack_restore
+ function. */
+
+static rtx
+expand_asan_emit_allocas_unpoison (tree exp)
+{
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
+ rtx bot = convert_memory_address (ptr_mode, virtual_stack_dynamic_rtx);
+ rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
+ ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, top,
+ ptr_mode, bot, ptr_mode);
+ return ret;
+}
+
/* Expand a call to bswap builtin in EXP.
Return NULL_RTX if a normal call should be emitted rather than expanding the
function in-line. If convenient, the result should be placed in TARGET.
@@ -6763,6 +6781,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return target;
break;
+ case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
+ return expand_asan_emit_allocas_unpoison (exp);
+
case BUILT_IN_STACK_SAVE:
return expand_stack_save ();
@@ -8739,13 +8760,12 @@ fold_builtin_FILE (location_t loc)
static inline tree
fold_builtin_FUNCTION ()
{
+ const char *name = "";
+
if (current_function_decl)
- {
- const char *name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
- return build_string_literal (strlen (name) + 1, name);
- }
+ name = lang_hooks.decl_printable_name (current_function_decl, 0);
- return build_string_literal (1, "");
+ return build_string_literal (strlen (name) + 1, name);
}
/* Fold a call to __builtin_LINE to an integer constant. */
diff --git a/gcc/builtins.def b/gcc/builtins.def
index f242137a1cb..1c1efceea21 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -365,6 +365,17 @@ DEF_GCC_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128
DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_FECLEAREXCEPT, "feclearexcept", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETENV, "fegetenv", BT_FN_INT_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETEXCEPTFLAG, "fegetexceptflag", BT_FN_INT_FEXCEPT_T_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETROUND, "fegetround", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEHOLDEXCEPT, "feholdexcept", BT_FN_INT_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FERAISEEXCEPT, "feraiseexcept", BT_FN_INT_INT, ATTR_NULL)
+DEF_C99_BUILTIN (BUILT_IN_FESETENV, "fesetenv", BT_FN_INT_CONST_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FESETEXCEPTFLAG, "fesetexceptflag", BT_FN_INT_CONST_FEXCEPT_T_PTR_INT, ATTR_NULL)
+DEF_C99_BUILTIN (BUILT_IN_FESETROUND, "fesetround", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FETESTEXCEPT, "fetestexcept", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEUPDATEENV, "feupdateenv", BT_FN_INT_CONST_FENV_T_PTR, ATTR_NULL)
DEF_LIB_BUILTIN (BUILT_IN_FLOOR, "floor", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORF, "floorf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORL, "floorl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index a61bb56ee80..1b6d7cfb903 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,108 @@
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81530
+ * c-ubsan.c (ubsan_maybe_instrument_array_ref):
+ Guard condition with flag_sanitize_p also with current_function_decl
+ non-null equality.
+ (ubsan_maybe_instrument_reference_or_call): Likewise.
+
+2017-07-30 Uros Bizjak <ubizjak@gmail.com>
+
+ * c-format.c (asm_fprintf_char_table): Add 'z' to format_chars.
+
+2017-07-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.c (dump_generic_ada_node): Take into account signedness
+ for enumeral types.
+ (print_ada_declaration): Add missing guard for record types.
+
+2017-07-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/45784
+ * c-omp.c (c_finish_omp_for): If the condition is wrapped in
+ rhs of COMPOUND_EXPR(s), skip them and readd their lhs into
+ new COMPOUND_EXPRs around the rhs of the comparison.
+
+2017-07-27 Marek Polacek <polacek@redhat.com>
+
+ PR c/81417
+ * c-warn.c (warn_for_sign_compare): Tweak the warning message. Print
+ the types.
+
+2017-07-27 Jakub Jelinek <jakub@redhat.com>
+
+ * c-attribs.c (c_common_attribute_table): Add noipa attribute.
+ (handle_noipa_attribute): New function.
+
+2017-07-07 Torsten Duwe <duwe@suse.de>
+
+ * c-attribs.c (c_common_attribute_table): Add entry for
+ "patchable_function_entry".
+
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ Remove TYPE_METHODS.
+ * c-ada-spec.c (is_tagged_type, has_nontrivial_methods,
+ dump_ada_template, print_ada_methods,
+ print_ada_declaration): Member fns are on TYPE_FIELDS.
+
+2017-07-18 Nathan Sidwell <nathan@acm.org>
+
+ * c-warn.c (warn_for_memset): Use TYPE_{MIN,MAX}_VALUE.
+
+2017-07-14 David Malcolm <dmalcolm@redhat.com>
+
+ * c-common.c (try_to_locate_new_include_insertion_point): New
+ function.
+ (per_file_includes_t): New typedef.
+ (added_includes_t): New typedef.
+ (added_includes): New variable.
+ (maybe_add_include_fixit): New function.
+ * c-common.h (maybe_add_include_fixit): New decl.
+
+2017-07-10 Martin Sebor <msebor@redhat.com>
+
+ PR other/81345
+ * c.opt (-Wstringop-overflow): Set defaults in LangEnabledBy.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ * c-common.c (selftest::c_family_tests): New.
+ * c-common.h (selftest::run_c_tests): Move decl to c/c-lang.h.
+ (selftest::c_family_tests): New decl.
+
+2017-07-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/81231
+ * c-common.c (sync_resolve_size): Give error for pointers to incomplete
+ types.
+
+2017-07-04 Marek Polacek <polacek@redhat.com>
+
+ * c-warn.c (warn_if_unused_value): Remove WITH_CLEANUP_EXPR handling.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81128
+ * c-attribs.c (handle_alias_ifunc_attribute): Append ifunc alias
+ to a function declaration.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR driver/79659
+ * c.opt: Add IntegerRange to various options.
+
+2017-06-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/80116
+ * c-common.h (warn_for_multistatement_macros): Declare.
+ * c-warn.c: Include "c-family/c-indentation.h".
+ (warn_for_multistatement_macros): New function.
+ * c.opt (Wmultistatement-macros): New option.
+ * c-indentation.c (guard_tinfo_to_string): No longer static.
+ Change the parameter type to "enum rid". Handle RID_SWITCH.
+ * c-indentation.h (guard_tinfo_to_string): Declare.
+
2017-06-23 Marc Glisse <marc.glisse@inria.fr>
* c-common.c (c_common_nodes_and_builtins): Use builtin_structptr_types.
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 6cf298a126a..de549501440 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -1070,16 +1070,11 @@ has_static_fields (const_tree type)
static bool
is_tagged_type (const_tree type)
{
- tree tmp;
-
if (!type || !RECORD_OR_UNION_TYPE_P (type))
return false;
- /* TYPE_METHODS is only set on the main variant. */
- type = TYPE_MAIN_VARIANT (type);
-
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (TREE_CODE (tmp) == FUNCTION_DECL && DECL_VINDEX (tmp))
+ for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+ if (TREE_CODE (fld) == FUNCTION_DECL && DECL_VINDEX (fld))
return true;
return false;
@@ -1093,8 +1088,6 @@ is_tagged_type (const_tree type)
static bool
has_nontrivial_methods (tree type)
{
- tree tmp;
-
if (!type || !RECORD_OR_UNION_TYPE_P (type))
return false;
@@ -1106,12 +1099,9 @@ has_nontrivial_methods (tree type)
if (!cpp_check (type, IS_TRIVIAL))
return true;
- /* TYPE_METHODS is only set on the main variant. */
- type = TYPE_MAIN_VARIANT (type);
-
/* If there are user-defined methods, they are deemed non-trivial. */
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (!DECL_ARTIFICIAL (tmp))
+ for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+ if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE && !DECL_ARTIFICIAL (fld))
return true;
return false;
@@ -1896,7 +1886,7 @@ dump_ada_template (pretty_printer *buffer, tree t, int spc)
if (TREE_VEC_LENGTH (types) == 0)
break;
- if (!RECORD_OR_UNION_TYPE_P (instance) || !TYPE_METHODS (instance))
+ if (!RECORD_OR_UNION_TYPE_P (instance))
break;
/* We are interested in concrete template instantiations only: skip
@@ -2065,7 +2055,10 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
}
else
{
- pp_string (buffer, "unsigned");
+ if (TYPE_UNSIGNED (node))
+ pp_string (buffer, "unsigned");
+ else
+ pp_string (buffer, "int");
for (; value; value = TREE_CHAIN (value))
{
pp_semicolon (buffer);
@@ -2442,25 +2435,23 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
static int
print_ada_methods (pretty_printer *buffer, tree node, int spc)
{
- tree t;
- int res;
-
if (!has_nontrivial_methods (node))
return 0;
pp_semicolon (buffer);
- res = 1;
- for (t = TYPE_METHODS (node); t; t = TREE_CHAIN (t))
- {
- if (res)
- {
- pp_newline (buffer);
- pp_newline (buffer);
- }
-
- res = print_ada_declaration (buffer, t, node, spc);
- }
+ int res = 1;
+ for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld))
+ if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE)
+ {
+ if (res)
+ {
+ pp_newline (buffer);
+ pp_newline (buffer);
+ }
+
+ res = print_ada_declaration (buffer, fld, node, spc);
+ }
return 1;
}
@@ -2961,19 +2952,13 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
dump_generic_ada_node (buffer, ret_type, type, spc, false, true);
}
- if (is_constructor
- && RECORD_OR_UNION_TYPE_P (type)
- && TYPE_METHODS (type))
- {
- tree tmp;
-
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (cpp_check (tmp, IS_ABSTRACT))
- {
- is_abstract_class = true;
- break;
- }
- }
+ if (is_constructor && RECORD_OR_UNION_TYPE_P (type))
+ for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+ if (cpp_check (fld, IS_ABSTRACT))
+ {
+ is_abstract_class = true;
+ break;
+ }
if (is_abstract || is_abstract_class)
pp_string (buffer, " is abstract");
@@ -3028,35 +3013,33 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
pp_string (buffer, " is ");
- /* Check whether we have an Ada interface compatible class. */
+ /* Check whether we have an Ada interface compatible class.
+ That is only have a vtable non-static data member and no
+ non-abstract methods. */
if (cpp_check
- && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
- && TYPE_METHODS (TREE_TYPE (t)))
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
{
- int num_fields = 0;
- tree tmp;
+ is_interface = -1;
/* Check that there are no fields other than the virtual table. */
- for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
+ for (tree fld = TYPE_FIELDS (TREE_TYPE (t));
+ fld; fld = TREE_CHAIN (fld))
{
- if (TREE_CODE (tmp) == TYPE_DECL)
- continue;
- num_fields++;
- }
-
- if (num_fields == 1)
- is_interface = 1;
-
- /* Also check that there are only pure virtual methods. Since the
- class is empty, we can skip implicit constructors/destructors. */
- for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (DECL_ARTIFICIAL (tmp))
- continue;
- if (cpp_check (tmp, IS_ABSTRACT))
- is_abstract_record = 1;
- else
- is_interface = 0;
+ if (TREE_CODE (fld) == FIELD_DECL)
+ {
+ if (is_interface < 0 && DECL_VIRTUAL_P (fld))
+ is_interface = 1;
+ else
+ is_interface = 0;
+ }
+ else if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE
+ && !DECL_ARTIFICIAL (fld))
+ {
+ if (cpp_check (fld, IS_ABSTRACT))
+ is_abstract_record = 1;
+ else
+ is_interface = 0;
+ }
}
}
@@ -3117,7 +3100,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
if (TYPE_NAME (TREE_TYPE (t)))
dump_generic_ada_node
(buffer, TREE_TYPE (t), t, spc, false, true);
- else
+ else if (type)
dump_ada_double_name (buffer, type, t);
}
else
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 2b6845f2cbd..0d9ab2d6ae0 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -66,6 +66,7 @@ static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
@@ -142,6 +143,8 @@ static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *)
static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
+static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
+ int, bool *);
/* Table of machine-independent attributes common to all C-like languages.
@@ -176,6 +179,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_noclone_attribute, false },
{ "no_icf", 0, 0, true, false, false,
handle_noicf_attribute, false },
+ { "noipa", 0, 0, true, false, false,
+ handle_noipa_attribute, false },
{ "leaf", 0, 0, true, false, false,
handle_leaf_attribute, false },
{ "always_inline", 0, 0, true, false, false,
@@ -351,6 +356,9 @@ const struct attribute_spec c_common_attribute_table[] =
handle_bnd_instrument, false },
{ "fallthrough", 0, 0, false, false, false,
handle_fallthrough_attribute, false },
+ { "patchable_function_entry", 1, 2, true, false, false,
+ handle_patchable_function_entry_attribute,
+ false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -699,6 +707,21 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int,
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
+
+ return NULL_TREE;
+}
+
+/* Handle a "noipa" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noipa_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
else
DECL_ATTRIBUTES (*node)
= tree_cons (get_identifier ("stack_protect"),
@@ -1846,9 +1869,14 @@ handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
TREE_STATIC (decl) = 1;
if (!is_alias)
- /* ifuncs are also aliases, so set that attribute too. */
- DECL_ATTRIBUTES (decl)
- = tree_cons (get_identifier ("alias"), args, DECL_ATTRIBUTES (decl));
+ {
+ /* ifuncs are also aliases, so set that attribute too. */
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (get_identifier ("alias"), args,
+ DECL_ATTRIBUTES (decl));
+ DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
+ NULL, DECL_ATTRIBUTES (decl));
+ }
}
else
{
@@ -3255,3 +3283,10 @@ handle_fallthrough_attribute (tree *, tree name, tree, int,
*no_add_attrs = true;
return NULL_TREE;
}
+
+static tree
+handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
+{
+ /* Nothing to be done here. */
+ return NULL_TREE;
+}
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index f6a9d05c3da..feb0904bcbf 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6485,6 +6485,9 @@ sync_resolve_size (tree function, vec<tree, va_gc> *params, bool fetch)
if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
goto incompatible;
+ if (!COMPLETE_TYPE_P (type))
+ goto incompatible;
+
if (fetch && TREE_CODE (type) == BOOLEAN_TYPE)
goto incompatible;
@@ -8000,4 +8003,151 @@ c_flt_eval_method (bool maybe_c11_only_p)
return c_ts18661_flt_eval_method ();
}
+#if CHECKING_P
+
+namespace selftest {
+
+/* Run all of the tests within c-family. */
+
+void
+c_family_tests (void)
+{
+ c_format_c_tests ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+/* Attempt to locate a suitable location within FILE for a
+ #include directive to be inserted before. FILE should
+ be a string from libcpp (pointer equality is used).
+ LOC is the location of the relevant diagnostic.
+
+ Attempt to return the location within FILE immediately
+ after the last #include within that file, or the start of
+ that file if it has no #include directives.
+
+ Return UNKNOWN_LOCATION if no suitable location is found,
+ or if an error occurs. */
+
+static location_t
+try_to_locate_new_include_insertion_point (const char *file, location_t loc)
+{
+ /* Locate the last ordinary map within FILE that ended with a #include. */
+ const line_map_ordinary *last_include_ord_map = NULL;
+
+ /* ...and the next ordinary map within FILE after that one. */
+ const line_map_ordinary *last_ord_map_after_include = NULL;
+
+ /* ...and the first ordinary map within FILE. */
+ const line_map_ordinary *first_ord_map_in_file = NULL;
+
+ /* Get ordinary map containing LOC (or its expansion). */
+ const line_map_ordinary *ord_map_for_loc = NULL;
+ loc = linemap_resolve_location (line_table, loc, LRK_MACRO_EXPANSION_POINT,
+ &ord_map_for_loc);
+ gcc_assert (ord_map_for_loc);
+
+ for (unsigned int i = 0; i < LINEMAPS_ORDINARY_USED (line_table); i++)
+ {
+ 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 (from->to_file == file)
+ {
+ last_include_ord_map = from;
+ last_ord_map_after_include = NULL;
+ }
+
+ if (ord_map->to_file == file)
+ {
+ if (!first_ord_map_in_file)
+ first_ord_map_in_file = ord_map;
+ if (last_include_ord_map && !last_ord_map_after_include)
+ last_ord_map_after_include = ord_map;
+ }
+
+ /* Stop searching when reaching the ord_map containing LOC,
+ as it makes no sense to provide fix-it hints that appear
+ after the diagnostic in question. */
+ if (ord_map == ord_map_for_loc)
+ break;
+ }
+
+ /* Determine where to insert the #include. */
+ const line_map_ordinary *ord_map_for_insertion;
+
+ /* We want the next ordmap in the file after the last one that's a
+ #include, but failing that, the start of the file. */
+ if (last_ord_map_after_include)
+ ord_map_for_insertion = last_ord_map_after_include;
+ else
+ ord_map_for_insertion = first_ord_map_in_file;
+
+ if (!ord_map_for_insertion)
+ return UNKNOWN_LOCATION;
+
+ /* The "start_location" is column 0, meaning "the whole line".
+ rich_location and edit_context can't cope with this, so use
+ column 1 instead. */
+ location_t col_0 = ord_map_for_insertion->start_location;
+ return linemap_position_for_loc_and_offset (line_table, col_0, 1);
+}
+
+/* A map from filenames to sets of headers added to them, for
+ ensuring idempotency within maybe_add_include_fixit. */
+
+/* The values within the map. We need string comparison as there's
+ no guarantee that two different diagnostics that are recommending
+ adding e.g. "<stdio.h>" are using the same buffer. */
+
+typedef hash_set <const char *, nofree_string_hash> per_file_includes_t;
+
+/* The map itself. We don't need string comparison for the filename keys,
+ as they come from libcpp. */
+
+typedef hash_map <const char *, per_file_includes_t *> added_includes_t;
+static added_includes_t *added_includes;
+
+/* Attempt to add a fix-it hint to RICHLOC, adding "#include HEADER\n"
+ in a suitable location within the file of RICHLOC's primary
+ location.
+
+ This function is idempotent: a header will be added at most once to
+ any given file. */
+
+void
+maybe_add_include_fixit (rich_location *richloc, const char *header)
+{
+ location_t loc = richloc->get_loc ();
+ const char *file = LOCATION_FILE (loc);
+ if (!file)
+ return;
+
+ /* Idempotency: don't add the same header more than once to a given file. */
+ if (!added_includes)
+ added_includes = new added_includes_t ();
+ per_file_includes_t *&set = added_includes->get_or_insert (file);
+ if (set)
+ if (set->contains (header))
+ /* ...then we've already added HEADER to that file. */
+ return;
+ if (!set)
+ set = new per_file_includes_t ();
+ set->add (header);
+
+ /* Attempt to locate a suitable place for the new directive. */
+ location_t include_insert_loc
+ = try_to_locate_new_include_insertion_point (file, loc);
+ if (include_insert_loc == UNKNOWN_LOCATION)
+ return;
+
+ char *text = xasprintf ("#include %s\n", header);
+ richloc->add_fixit_insert_before (include_insert_loc, text);
+ free (text);
+}
+
#include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 1748c1979aa..a29f1ade25d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1539,6 +1539,8 @@ extern bool maybe_warn_shift_overflow (location_t, tree, tree);
extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
extern bool diagnose_mismatched_attributes (tree, tree);
extern tree do_warn_duplicated_branches_r (tree *, int *, void *);
+extern void warn_for_multistatement_macros (location_t, location_t,
+ location_t, enum rid);
/* In c-attribs.c. */
extern bool attribute_takes_identifier_p (const_tree);
@@ -1554,10 +1556,16 @@ 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 *);
+
#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 run_c_tests (void);
+
+ /* The entrypoint for running all of the above tests. */
+ extern void c_family_tests (void);
} // namespace selftest
#endif /* #if CHECKING_P */
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 732339b9b5e..0a5cc03fd4e 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -672,6 +672,7 @@ static const format_char_info asm_fprintf_char_table[] =
{ "L", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ "U", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
+ { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ "@", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
index 8300788db10..7ca21e83347 100644
--- a/gcc/c-family/c-indentation.c
+++ b/gcc/c-family/c-indentation.c
@@ -542,10 +542,10 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
/* Return the string identifier corresponding to the given guard token. */
-static const char *
-guard_tinfo_to_string (const token_indent_info &guard_tinfo)
+const char *
+guard_tinfo_to_string (enum rid keyword)
{
- switch (guard_tinfo.keyword)
+ switch (keyword)
{
case RID_FOR:
return "for";
@@ -557,6 +557,8 @@ guard_tinfo_to_string (const token_indent_info &guard_tinfo)
return "while";
case RID_DO:
return "do";
+ case RID_SWITCH:
+ return "switch";
default:
gcc_unreachable ();
}
@@ -605,10 +607,10 @@ warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
{
if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation,
"this %qs clause does not guard...",
- guard_tinfo_to_string (guard_tinfo)))
+ guard_tinfo_to_string (guard_tinfo.keyword)))
inform (next_tinfo.location,
"...this statement, but the latter is misleadingly indented"
" as if it were guarded by the %qs",
- guard_tinfo_to_string (guard_tinfo));
+ guard_tinfo_to_string (guard_tinfo.keyword));
}
}
diff --git a/gcc/c-family/c-indentation.h b/gcc/c-family/c-indentation.h
index a4366971e96..e4cad26cdad 100644
--- a/gcc/c-family/c-indentation.h
+++ b/gcc/c-family/c-indentation.h
@@ -48,5 +48,7 @@ extern void
warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
const token_indent_info &body_tinfo,
const token_indent_info &next_tinfo);
+extern const char *
+guard_tinfo_to_string (enum rid keyword);
#endif /* ! GCC_C_INDENTATION_H */
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 519c4e4ce66..977cb0ea153 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -531,6 +531,12 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
{
bool cond_ok = false;
+ /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
+ evaluation of the vla VAR_DECL. We need to readd
+ them to the non-decl operand. See PR45784. */
+ while (TREE_CODE (cond) == COMPOUND_EXPR)
+ cond = TREE_OPERAND (cond, 1);
+
if (EXPR_HAS_LOCATION (cond))
elocus = EXPR_LOCATION (cond);
@@ -605,6 +611,21 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
else if (code != CILK_SIMD && code != CILK_FOR)
cond_ok = false;
}
+
+ if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
+ {
+ tree ce = NULL_TREE, *pce = &ce;
+ tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
+ for (tree c = TREE_VEC_ELT (condv, i); c != cond;
+ c = TREE_OPERAND (c, 1))
+ {
+ *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
+ TREE_OPERAND (cond, 1));
+ pce = &TREE_OPERAND (*pce, 1);
+ }
+ TREE_OPERAND (cond, 1) = ce;
+ TREE_VEC_ELT (condv, i) = cond;
+ }
}
if (!cond_ok)
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index a072d19eda6..541b53009c2 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -373,7 +373,8 @@ void
ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
{
if (!ubsan_array_ref_instrumented_p (*expr_p)
- && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT))
+ && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT)
+ && current_function_decl != NULL_TREE)
{
tree op0 = TREE_OPERAND (*expr_p, 0);
tree op1 = TREE_OPERAND (*expr_p, 1);
@@ -393,7 +394,8 @@ static tree
ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
enum ubsan_null_ckind ckind)
{
- if (!sanitize_flags_p (SANITIZE_ALIGNMENT | SANITIZE_NULL))
+ if (!sanitize_flags_p (SANITIZE_ALIGNMENT | SANITIZE_NULL)
+ || current_function_decl == NULL_TREE)
return NULL_TREE;
tree type = TREE_TYPE (ptype);
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 056a058ca77..505070e5586 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "gcc-rich-location.h"
#include "gimplify.h"
+#include "c-family/c-indentation.h"
/* Print a warning if a constant expression had overflow in folding.
Invoke this function on every expression that the language
@@ -464,7 +465,6 @@ warn_if_unused_value (const_tree exp, location_t locus)
case TARGET_EXPR:
case CALL_EXPR:
case TRY_CATCH_EXPR:
- case WITH_CLEANUP_EXPR:
case EXIT_EXPR:
case VA_ARG_EXPR:
return false;
@@ -1799,12 +1799,12 @@ warn_for_memset (location_t loc, tree arg0, tree arg2,
tree domain = TYPE_DOMAIN (type);
if (!integer_onep (TYPE_SIZE_UNIT (elt_type))
&& domain != NULL_TREE
- && TYPE_MAXVAL (domain)
- && TYPE_MINVAL (domain)
- && integer_zerop (TYPE_MINVAL (domain))
+ && TYPE_MAX_VALUE (domain)
+ && TYPE_MIN_VALUE (domain)
+ && integer_zerop (TYPE_MIN_VALUE (domain))
&& integer_onep (fold_build2 (MINUS_EXPR, domain,
arg2,
- TYPE_MAXVAL (domain))))
+ TYPE_MAX_VALUE (domain))))
warning_at (loc, OPT_Wmemset_elt_size,
"%<memset%> used with length equal to "
"number of elements without multiplication "
@@ -1891,9 +1891,10 @@ warn_for_sign_compare (location_t location,
c_common_signed_type (base_type)))
/* OK */;
else
- warning_at (location,
- OPT_Wsign_compare,
- "comparison between signed and unsigned integer expressions");
+ warning_at (location, OPT_Wsign_compare,
+ "comparison of integer expressions of different "
+ "signedness: %qT and %qT", TREE_TYPE (orig_op0),
+ TREE_TYPE (orig_op1));
}
/* Warn if two unsigned values are being compared in a size larger
@@ -2401,3 +2402,91 @@ do_warn_duplicated_branches_r (tree *tp, int *, void *)
do_warn_duplicated_branches (*tp);
return NULL_TREE;
}
+
+/* Implementation of -Wmultistatement-macros. This warning warns about
+ cases when a macro expands to multiple statements not wrapped in
+ do {} while (0) or ({ }) and is used as a body of if/else/for/while
+ conditionals. For example,
+
+ #define DOIT x++; y++
+
+ if (c)
+ DOIT;
+
+ will increment y unconditionally.
+
+ BODY_LOC is the location of the first token in the body after labels
+ have been parsed, NEXT_LOC is the location of the next token after the
+ body of the conditional has been parsed, and GUARD_LOC is the location
+ of the conditional. */
+
+void
+warn_for_multistatement_macros (location_t body_loc, location_t next_loc,
+ location_t guard_loc, enum rid keyword)
+{
+ if (!warn_multistatement_macros)
+ return;
+
+ /* Ain't got time to waste. We only care about macros here. */
+ if (!from_macro_expansion_at (body_loc)
+ || !from_macro_expansion_at (next_loc))
+ return;
+
+ /* Let's skip macros defined in system headers. */
+ if (in_system_header_at (body_loc)
+ || in_system_header_at (next_loc))
+ return;
+
+ /* Find the actual tokens in the macro definition. BODY_LOC and
+ NEXT_LOC have to come from the same spelling location, but they
+ will resolve to different locations in the context of the macro
+ definition. */
+ location_t body_loc_exp
+ = linemap_resolve_location (line_table, body_loc,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+ location_t next_loc_exp
+ = linemap_resolve_location (line_table, next_loc,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+ location_t guard_loc_exp
+ = linemap_resolve_location (line_table, guard_loc,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+ /* These are some funky cases we don't want to warn about. */
+ if (body_loc_exp == guard_loc_exp
+ || next_loc_exp == guard_loc_exp
+ || body_loc_exp == next_loc_exp)
+ return;
+
+ /* Find the macro map for the macro expansion BODY_LOC. */
+ const line_map *map = linemap_lookup (line_table, body_loc);
+ const line_map_macro *macro_map = linemap_check_macro (map);
+
+ /* Now see if the following token is coming from the same macro
+ expansion. If it is, it's a problem, because it should've been
+ parsed at this point. We only look at odd-numbered indexes
+ within the MACRO_MAP_LOCATIONS array, i.e. the spelling locations
+ of the tokens. */
+ bool found_guard = false;
+ bool found_next = false;
+ for (unsigned int i = 1;
+ i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (macro_map);
+ i += 2)
+ {
+ if (MACRO_MAP_LOCATIONS (macro_map)[i] == next_loc_exp)
+ found_next = true;
+ if (MACRO_MAP_LOCATIONS (macro_map)[i] == guard_loc_exp)
+ found_guard = true;
+ }
+
+ /* The conditional itself must not come from the same expansion, because
+ we don't want to warn about
+ #define IF if (x) x++; y++
+ and similar. */
+ if (!found_next || found_guard)
+ return;
+
+ 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 "
+ "this %qs clause", guard_tinfo_to_string (keyword));
+}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 363d1043397..e0ad3ab10b8 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -541,7 +541,7 @@ C ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning LangEnabledBy(C ObjC C++ O
Warn about format strings that are not literals.
Wformat-overflow
-C ObjC C++ LTO ObjC++ Warning Alias(Wformat-overflow=, 1, 0)
+C ObjC C++ LTO ObjC++ Warning Alias(Wformat-overflow=, 1, 0) IntegerRange(0, 2)
Warn about function calls with format strings that write past the end
of the destination region. Same as -Wformat-overflow=1.
@@ -567,16 +567,16 @@ C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++
Warn about zero-length formats.
Wformat=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0)
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 2)
Warn about printf/scanf/strftime/strfmon format string anomalies.
Wformat-overflow=
-C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_overflow) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_overflow) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
Warn about function calls with format strings that write past the end
of the destination region.
Wformat-truncation=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
Warn about calls to snprintf and similar functions that truncate output.
Wignored-qualifiers
@@ -698,6 +698,10 @@ Wmissing-field-initializers
C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra)
Warn about missing fields in struct initializers.
+Wmultistatement-macros
+C ObjC C++ ObjC++ Var(warn_multistatement_macros) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about unsafe macros expanding to multiple statements used as a body of a clause such as if, else, while, switch, or for.
+
Wmultiple-inheritance
C++ ObjC++ Var(warn_multiple_inheritance) Warning
Warn on direct multiple inheritance.
@@ -728,7 +732,7 @@ Warn about buffer overflow in string manipulation functions like memcpy
and strcpy.
Wstringop-overflow=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall)
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall, 2, 0) IntegerRange(0, 4)
Under the control of Object Size type, warn about buffer overflow in string
manipulation functions like memcpy and strcpy.
@@ -932,7 +936,7 @@ C++ Warning Alias(Wplacement-new=, 1, 0)
Warn for placement new expressions with undefined behavior.
Wplacement-new=
-C++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning
+C++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning IntegerRange(0, 2)
Warn for placement new expressions with undefined behavior.
Wredundant-decls
@@ -972,7 +976,7 @@ C ObjC C++ ObjC++ Warning Alias(Wshift-overflow=, 1, 0)
Warn if left shift of a signed value overflows.
Wshift-overflow=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_shift_overflow) Init(-1) Warning
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_shift_overflow) Init(-1) Warning IntegerRange(0, 2)
Warn if left shift of a signed value overflows.
Wshift-count-negative
@@ -1012,11 +1016,11 @@ C ObjC Var(warn_strict_prototypes) Warning
Warn about unprototyped function declarations.
Wstrict-aliasing=
-C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 3, 0)
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 3, 0) IntegerRange(0, 3)
;
Wstrict-overflow=
-C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0)
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 5)
;
Wstrict-selector-match
@@ -1104,7 +1108,7 @@ C ObjC C++ ObjC++ Warning Alias(Wunused-const-variable=, 2, 0)
Warn when a const variable is unused.
Wunused-const-variable=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning LangEnabledBy(C ObjC,Wunused-variable, 1, 0)
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning LangEnabledBy(C ObjC,Wunused-variable, 1, 0) IntegerRange(0, 2)
Warn when a const variable is unused.
Wvariadic-macros
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 58d59a65871..aff4866d915 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,58 @@
+2017-07-31 Jan Hubicka <hubicka@ucw.cz>
+ Martin Liska <mliska@suse.cz>
+
+ * c-typeck.c (c_finish_goto_label): Build gimple predict
+ stament.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81530
+ * c-convert.c (convert): Guard condition with flag_sanitize_p
+ also with current_function_decl non-null equality.
+ * c-decl.c (grokdeclarator): Likewise.
+ * c-typeck.c (build_binary_op): Likewise.
+
+2017-07-25 Marek Polacek <polacek@redhat.com>
+
+ * c-decl.c (grokfield): Remove local variable.
+
+2017-07-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/81364
+ * c-parser.c (c_parser_else_body): Don't warn about multistatement
+ macro expansion if the body is in { }.
+ (c_parser_while_statement): Likewise.
+ (c_parser_for_statement): Likewise.
+
+2017-07-18 Nathan Sidwell <nathan@acm.org>
+
+ * c-parser.c (c_parser_array_notation): Use TYPE_{MIN,MAX}_VALUE.
+
+2017-07-14 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (implicitly_declare): When suggesting a missing
+ #include, provide a fix-it hint.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ * c-lang.c (selftest::run_c_tests): Move body to c_family_tests,
+ and call that instead.
+ * c-tree.h (selftest::run_c_tests): New decl.
+
+2017-06-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/80116
+ * c-parser.c (c_parser_if_body): Set the location of the
+ body of the conditional after parsing all the labels. Call
+ warn_for_multistatement_macros.
+ (c_parser_else_body): Likewise.
+ (c_parser_switch_statement): Likewise.
+ (c_parser_while_statement): Likewise.
+ (c_parser_for_statement): Likewise.
+ (c_parser_statement): Add a default argument. Save the location
+ after labels have been parsed.
+ (c_parser_c99_block_statement): Likewise.
+
2017-06-19 Richard Biener <rguenther@suse.de>
* gimple-parser.c (c_parser_gimple_postfix_expression): Handle
diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c
index 33c9143e354..bc649178f4c 100644
--- a/gcc/c/c-convert.c
+++ b/gcc/c/c-convert.c
@@ -108,6 +108,7 @@ convert (tree type, tree expr)
case INTEGER_TYPE:
case ENUMERAL_TYPE:
if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
+ && current_function_decl != NULL_TREE
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
&& COMPLETE_TYPE_P (type))
{
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 317d5cdd099..a54e1218434 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3386,8 +3386,14 @@ implicitly_declare (location_t loc, tree functionid)
const char *header
= header_for_builtin_fn (DECL_FUNCTION_CODE (decl));
if (header != NULL && warned)
- inform (loc, "include %qs or provide a declaration of %qD",
- header, decl);
+ {
+ rich_location richloc (line_table, loc);
+ maybe_add_include_fixit (&richloc, header);
+ inform_at_rich_loc
+ (&richloc,
+ "include %qs or provide a declaration of %qD",
+ header, decl);
+ }
newtype = TREE_TYPE (decl);
}
}
@@ -6046,6 +6052,7 @@ grokdeclarator (const struct c_declarator *declarator,
this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
if (sanitize_flags_p (SANITIZE_VLA)
+ && current_function_decl != NULL_TREE
&& decl_context == NORMAL)
{
/* Evaluate the array size only once. */
@@ -7553,10 +7560,9 @@ grokfield (location_t loc,
that took root before someone noticed the bug... */
tree type = declspecs->type;
- bool type_ok = RECORD_OR_UNION_TYPE_P (type);
bool ok = false;
- if (type_ok
+ if (RECORD_OR_UNION_TYPE_P (type)
&& (flag_ms_extensions
|| flag_plan9_extensions
|| !declspecs->typedef_p))
diff --git a/gcc/c/c-lang.c b/gcc/c/c-lang.c
index 510b7e7de47..e05741dadba 100644
--- a/gcc/c/c-lang.c
+++ b/gcc/c/c-lang.c
@@ -58,7 +58,10 @@ namespace selftest {
void
run_c_tests (void)
{
- c_format_c_tests ();
+ /* Run selftests shared within the C family. */
+ c_family_tests ();
+
+ /* Additional C-specific tests. */
}
} // namespace selftest
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 6f954f21fa2..16cd3579972 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1218,9 +1218,11 @@ static void c_parser_initval (c_parser *, struct c_expr *,
static tree c_parser_compound_statement (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *);
-static void c_parser_statement (c_parser *, bool *);
+static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
static void c_parser_statement_after_labels (c_parser *, bool *,
vec<tree> * = NULL);
+static tree c_parser_c99_block_statement (c_parser *, bool *,
+ location_t * = NULL);
static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
static void c_parser_switch_statement (c_parser *, bool *);
static void c_parser_while_statement (c_parser *, bool, bool *);
@@ -5204,9 +5206,11 @@ c_parser_label (c_parser *parser)
implement -Wparentheses. */
static void
-c_parser_statement (c_parser *parser, bool *if_p)
+c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
{
c_parser_all_labels (parser);
+ if (loc_after_labels)
+ *loc_after_labels = c_parser_peek_token (parser)->location;
c_parser_statement_after_labels (parser, if_p, NULL);
}
@@ -5466,11 +5470,12 @@ c_parser_paren_condition (c_parser *parser)
implement -Wparentheses. */
static tree
-c_parser_c99_block_statement (c_parser *parser, bool *if_p)
+c_parser_c99_block_statement (c_parser *parser, bool *if_p,
+ location_t *loc_after_labels)
{
tree block = c_begin_compound_stmt (flag_isoc99);
location_t loc = c_parser_peek_token (parser)->location;
- c_parser_statement (parser, if_p);
+ c_parser_statement (parser, if_p, loc_after_labels);
return c_end_compound_stmt (loc, block, flag_isoc99);
}
@@ -5492,6 +5497,7 @@ c_parser_if_body (c_parser *parser, bool *if_p,
{
tree block = c_begin_compound_stmt (flag_isoc99);
location_t body_loc = c_parser_peek_token (parser)->location;
+ location_t body_loc_after_labels = UNKNOWN_LOCATION;
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5508,11 +5514,18 @@ c_parser_if_body (c_parser *parser, bool *if_p,
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
- c_parser_statement_after_labels (parser, if_p);
+ {
+ body_loc_after_labels = c_parser_peek_token (parser)->location;
+ c_parser_statement_after_labels (parser, if_p);
+ }
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
+ if (body_loc_after_labels != UNKNOWN_LOCATION
+ && next_tinfo.type != CPP_SEMICOLON)
+ warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
+ if_tinfo.location, RID_IF);
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
@@ -5530,6 +5543,7 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
tree block = c_begin_compound_stmt (flag_isoc99);
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
+ location_t body_loc_after_labels = UNKNOWN_LOCATION;
c_parser_all_labels (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -5542,11 +5556,19 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
c_parser_consume_token (parser);
}
else
- c_parser_statement_after_labels (parser, NULL, chain);
+ {
+ if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ body_loc_after_labels = c_parser_peek_token (parser)->location;
+ c_parser_statement_after_labels (parser, NULL, chain);
+ }
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
+ if (body_loc_after_labels != UNKNOWN_LOCATION
+ && next_tinfo.type != CPP_SEMICOLON)
+ warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
+ else_tinfo.location, RID_ELSE);
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
@@ -5732,7 +5754,13 @@ c_parser_switch_statement (c_parser *parser, bool *if_p)
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser, if_p);
+ location_t loc_after_labels;
+ bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
+ body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
+ location_t next_loc = c_parser_peek_token (parser)->location;
+ if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
+ warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
+ RID_SWITCH);
c_finish_case (body, ce.original_type);
if (c_break_label)
{
@@ -5783,7 +5811,9 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser, if_p);
+ location_t loc_after_labels;
+ bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
+ body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_parser_maybe_reclassify_token (parser);
@@ -5792,6 +5822,10 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
+ if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
+ warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
+ while_tinfo.location, RID_WHILE);
+
c_break_label = save_break;
c_cont_label = save_cont;
}
@@ -6076,7 +6110,9 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser, if_p);
+ location_t loc_after_labels;
+ bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
+ body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
@@ -6089,6 +6125,10 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
+ if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
+ warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
+ for_tinfo.location, RID_FOR);
+
c_break_label = save_break;
c_cont_label = save_cont;
}
@@ -18201,18 +18241,18 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return error_mark_node;
}
- start_index = TYPE_MINVAL (array_type_domain);
+ start_index = TYPE_MIN_VALUE (array_type_domain);
start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node,
start_index);
- if (!TYPE_MAXVAL (array_type_domain)
- || !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
+ if (!TYPE_MAX_VALUE (array_type_domain)
+ || !TREE_CONSTANT (TYPE_MAX_VALUE (array_type_domain)))
{
error_at (loc, "start-index and length fields necessary for "
"using array notations in variable-length arrays");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
- end_index = TYPE_MAXVAL (array_type_domain);
+ end_index = TYPE_MAX_VALUE (array_type_domain);
end_index = fold_build2 (PLUS_EXPR, TREE_TYPE (end_index),
end_index, integer_one_node);
end_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, end_index);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index ce25fae0b87..a8197eb768d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -764,4 +764,11 @@ extern tree decl_constant_value_for_optimization (tree);
extern vec<tree> incomplete_record_decls;
+#if CHECKING_P
+namespace selftest {
+ extern void run_c_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
+
#endif /* ! GCC_C_TREE_H */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4d067e96dd3..71d01350186 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9824,6 +9824,7 @@ c_finish_goto_label (location_t loc, tree label)
return NULL_TREE;
TREE_USED (decl) = 1;
{
+ add_stmt (build_predict_expr (PRED_GOTO, NOT_TAKEN));
tree t = build1 (GOTO_EXPR, void_type_node, decl);
SET_EXPR_LOCATION (t, loc);
return add_stmt (t);
@@ -11838,6 +11839,7 @@ build_binary_op (location_t location, enum tree_code code,
if (sanitize_flags_p ((SANITIZE_SHIFT
| SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ && current_function_decl != NULL_TREE
&& (doing_div_or_mod || doing_shift)
&& !require_constant_value)
{
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index 92ca133d842..4fa3ebdc422 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -38,6 +38,29 @@ along with GCC; see the file COPYING3. If not see
#include "ccmp.h"
#include "predict.h"
+/* Check whether T is a simple boolean variable or a SSA name
+ set by a comparison operator in the same basic block. */
+static bool
+ccmp_tree_comparison_p (tree t, basic_block bb)
+{
+ gimple *g = get_gimple_for_ssa_name (t);
+ tree_code tcode;
+
+ /* If we have a boolean variable allow it and generate a compare
+ to zero reg when expanding. */
+ if (!g)
+ return (TREE_CODE (TREE_TYPE (t)) == BOOLEAN_TYPE);
+
+ /* Check to see if SSA name is set by a comparison operator in
+ the same basic block. */
+ if (!is_gimple_assign (g))
+ return false;
+ if (bb != gimple_bb (g))
+ return false;
+ tcode = gimple_assign_rhs_code (g);
+ return TREE_CODE_CLASS (tcode) == tcc_comparison;
+}
+
/* The following functions expand conditional compare (CCMP) instructions.
Here is a short description about the over all algorithm:
* ccmp_candidate_p is used to identify the CCMP candidate
@@ -71,49 +94,69 @@ along with GCC; see the file COPYING3. If not see
static bool
ccmp_candidate_p (gimple *g)
{
- tree rhs = gimple_assign_rhs_to_tree (g);
+ tree rhs;
tree lhs, op0, op1;
gimple *gs0, *gs1;
- tree_code tcode, tcode0, tcode1;
- tcode = TREE_CODE (rhs);
+ tree_code tcode;
+ basic_block bb;
+
+ if (!g)
+ return false;
+ rhs = gimple_assign_rhs_to_tree (g);
+ tcode = TREE_CODE (rhs);
if (tcode != BIT_AND_EXPR && tcode != BIT_IOR_EXPR)
return false;
lhs = gimple_assign_lhs (g);
op0 = TREE_OPERAND (rhs, 0);
op1 = TREE_OPERAND (rhs, 1);
+ bb = gimple_bb (g);
if ((TREE_CODE (op0) != SSA_NAME) || (TREE_CODE (op1) != SSA_NAME)
|| !has_single_use (lhs))
return false;
- gs0 = get_gimple_for_ssa_name (op0);
- gs1 = get_gimple_for_ssa_name (op1);
- if (!gs0 || !gs1 || !is_gimple_assign (gs0) || !is_gimple_assign (gs1)
- /* g, gs0 and gs1 must be in the same basic block, since current stage
- is out-of-ssa. We can not guarantee the correctness when forwording
- the gs0 and gs1 into g whithout DATAFLOW analysis. */
- || gimple_bb (gs0) != gimple_bb (gs1)
- || gimple_bb (gs0) != gimple_bb (g))
- return false;
+ gs0 = get_gimple_for_ssa_name (op0); /* gs0 may be NULL */
+ gs1 = get_gimple_for_ssa_name (op1); /* gs1 may be NULL */
- tcode0 = gimple_assign_rhs_code (gs0);
- tcode1 = gimple_assign_rhs_code (gs1);
- if (TREE_CODE_CLASS (tcode0) == tcc_comparison
- && TREE_CODE_CLASS (tcode1) == tcc_comparison)
+ if (ccmp_tree_comparison_p (op0, bb) && ccmp_tree_comparison_p (op1, bb))
return true;
- if (TREE_CODE_CLASS (tcode0) == tcc_comparison
- && ccmp_candidate_p (gs1))
+ if (ccmp_tree_comparison_p (op0, bb) && ccmp_candidate_p (gs1))
return true;
- else if (TREE_CODE_CLASS (tcode1) == tcc_comparison
- && ccmp_candidate_p (gs0))
+ if (ccmp_tree_comparison_p (op1, bb) && ccmp_candidate_p (gs0))
return true;
/* We skip ccmp_candidate_p (gs1) && ccmp_candidate_p (gs0) since
- there is no way to set the CC flag. */
+ there is no way to set and maintain the CC flag on both sides of
+ the logical operator at the same time. */
return false;
}
+/* Extract the comparison we want to do from the tree. */
+void
+get_compare_parts (tree t, int *up, rtx_code *rcode,
+ tree *rhs1, tree *rhs2)
+{
+ tree_code code;
+ gimple *g = get_gimple_for_ssa_name (t);
+ if (g)
+ {
+ *up = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
+ code = gimple_assign_rhs_code (g);
+ *rcode = get_rtx_code (code, *up);
+ *rhs1 = gimple_assign_rhs1 (g);
+ *rhs2 = gimple_assign_rhs2 (g);
+ }
+ else
+ {
+ /* If g is not a comparison operator create a compare to zero. */
+ *up = 1;
+ *rcode = NE;
+ *rhs1 = t;
+ *rhs2 = build_zero_cst (TREE_TYPE (t));
+ }
+}
+
/* PREV is a comparison with the CC register which represents the
result of the previous CMP or CCMP. The function expands the
next compare based on G which is ANDed/ORed with the previous
@@ -121,20 +164,16 @@ ccmp_candidate_p (gimple *g)
PREP_SEQ returns all insns to prepare opearands for compare.
GEN_SEQ returns all compare insns. */
static rtx
-expand_ccmp_next (gimple *g, tree_code code, rtx prev,
+expand_ccmp_next (tree op, tree_code code, rtx prev,
rtx_insn **prep_seq, rtx_insn **gen_seq)
{
rtx_code rcode;
- int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
-
- gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
-
- rcode = get_rtx_code (gimple_assign_rhs_code (g), unsignedp);
+ int unsignedp;
+ tree rhs1, rhs2;
+ get_compare_parts(op, &unsignedp, &rcode, &rhs1, &rhs2);
return targetm.gen_ccmp_next (prep_seq, gen_seq, prev, rcode,
- gimple_assign_rhs1 (g),
- gimple_assign_rhs2 (g),
- get_rtx_code (code, 0));
+ rhs1, rhs2, get_rtx_code (code, 0));
}
/* Expand conditional compare gimple G. A typical CCMP sequence is like:
@@ -153,39 +192,42 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
{
tree exp = gimple_assign_rhs_to_tree (g);
tree_code code = TREE_CODE (exp);
- gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0));
- gimple *gs1 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 1));
+ basic_block bb = gimple_bb (g);
+
+ tree op0 = TREE_OPERAND (exp, 0);
+ tree op1 = TREE_OPERAND (exp, 1);
+ gimple *gs0 = get_gimple_for_ssa_name (op0);
+ gimple *gs1 = get_gimple_for_ssa_name (op1);
rtx tmp;
- tree_code code0 = gimple_assign_rhs_code (gs0);
- tree_code code1 = gimple_assign_rhs_code (gs1);
gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
- gcc_assert (gs0 && gs1 && is_gimple_assign (gs0) && is_gimple_assign (gs1));
- if (TREE_CODE_CLASS (code0) == tcc_comparison)
+ if (ccmp_tree_comparison_p (op0, bb))
{
- if (TREE_CODE_CLASS (code1) == tcc_comparison)
+ if (ccmp_tree_comparison_p (op1, bb))
{
int unsignedp0, unsignedp1;
rtx_code rcode0, rcode1;
+ tree logical_op0_rhs1, logical_op0_rhs2;
+ tree logical_op1_rhs1, logical_op1_rhs2;
int speed_p = optimize_insn_for_speed_p ();
+
rtx tmp2 = NULL_RTX, ret = NULL_RTX, ret2 = NULL_RTX;
unsigned cost1 = MAX_COST;
unsigned cost2 = MAX_COST;
- unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0)));
- unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1)));
- rcode0 = get_rtx_code (code0, unsignedp0);
- rcode1 = get_rtx_code (code1, unsignedp1);
+ get_compare_parts (op0, &unsignedp0, &rcode0,
+ &logical_op0_rhs1, &logical_op0_rhs2);
+
+ get_compare_parts (op1, &unsignedp1, &rcode1,
+ &logical_op1_rhs1, &logical_op1_rhs2);
rtx_insn *prep_seq_1, *gen_seq_1;
tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0,
- gimple_assign_rhs1 (gs0),
- gimple_assign_rhs2 (gs0));
-
+ logical_op0_rhs1, logical_op0_rhs2);
if (tmp != NULL)
{
- ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1);
+ ret = expand_ccmp_next (op1, code, tmp, &prep_seq_1, &gen_seq_1);
cost1 = seq_cost (prep_seq_1, speed_p);
cost1 += seq_cost (gen_seq_1, speed_p);
}
@@ -197,27 +239,22 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
rtx_insn *prep_seq_2, *gen_seq_2;
if (tmp == NULL || cost1 < COSTS_N_INSNS (25))
tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
- gimple_assign_rhs1 (gs1),
- gimple_assign_rhs2 (gs1));
-
+ logical_op1_rhs1, logical_op1_rhs2);
if (!tmp && !tmp2)
return NULL_RTX;
-
if (tmp2 != NULL)
{
- ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2,
+ ret2 = expand_ccmp_next (op0, code, tmp2, &prep_seq_2,
&gen_seq_2);
cost2 = seq_cost (prep_seq_2, speed_p);
cost2 += seq_cost (gen_seq_2, speed_p);
}
-
if (cost2 < cost1)
{
*prep_seq = prep_seq_2;
*gen_seq = gen_seq_2;
return ret2;
}
-
*prep_seq = prep_seq_1;
*gen_seq = gen_seq_1;
return ret;
@@ -227,28 +264,18 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq);
if (!tmp)
return NULL_RTX;
-
- return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq);
+ return expand_ccmp_next (op0, code, tmp, prep_seq, gen_seq);
}
}
else
{
gcc_assert (gimple_assign_rhs_code (gs0) == BIT_AND_EXPR
|| gimple_assign_rhs_code (gs0) == BIT_IOR_EXPR);
-
- if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison)
- {
- tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
- if (!tmp)
- return NULL_RTX;
-
- return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
- }
- else
- {
- gcc_assert (gimple_assign_rhs_code (gs1) == BIT_AND_EXPR
- || gimple_assign_rhs_code (gs1) == BIT_IOR_EXPR);
- }
+ gcc_assert (ccmp_tree_comparison_p (op1, bb));
+ tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
+ if (!tmp)
+ return NULL_RTX;
+ return expand_ccmp_next (op1, code, tmp, prep_seq, gen_seq);
}
return NULL_RTX;
@@ -258,7 +285,7 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
Return NULL_RTX if G is not a legal candidate or expand fail.
Otherwise return the target. */
rtx
-expand_ccmp_expr (gimple *g)
+expand_ccmp_expr (gimple *g, machine_mode mode)
{
rtx_insn *last;
rtx tmp;
@@ -275,7 +302,6 @@ expand_ccmp_expr (gimple *g)
{
insn_code icode;
machine_mode cc_mode = CCmode;
- tree lhs = gimple_assign_lhs (g);
rtx_code cmp_code = GET_CODE (tmp);
#ifdef SELECT_CC_MODE
@@ -284,7 +310,6 @@ expand_ccmp_expr (gimple *g)
icode = optab_handler (cstore_optab, cc_mode);
if (icode != CODE_FOR_nothing)
{
- machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
rtx target = gen_reg_rtx (mode);
emit_insn (prep_seq);
@@ -300,4 +325,3 @@ expand_ccmp_expr (gimple *g)
delete_insns_since (last);
return NULL_RTX;
}
-
diff --git a/gcc/ccmp.h b/gcc/ccmp.h
index bc1aafbc65e..93d10491eb9 100644
--- a/gcc/ccmp.h
+++ b/gcc/ccmp.h
@@ -20,6 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_CCMP_H
#define GCC_CCMP_H
-extern rtx expand_ccmp_expr (gimple *);
+extern rtx expand_ccmp_expr (gimple *, machine_mode);
#endif /* GCC_CCMP_H */
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 3cbe684b743..01e68aeda51 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -264,6 +264,7 @@ unchecked_make_edge (basic_block src, basic_block dst, int flags)
n_edges_for_fn (cfun)++;
e->count = profile_count::uninitialized ();
+ e->probability = profile_probability::uninitialized ();
e->src = src;
e->dest = dst;
e->flags = flags;
@@ -332,7 +333,7 @@ make_single_succ_edge (basic_block src, basic_block dest, int flags)
{
edge e = make_edge (src, dest, flags);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = src->count;
return e;
}
@@ -400,7 +401,6 @@ static void
check_bb_profile (basic_block bb, FILE * file, int indent)
{
edge e;
- int sum = 0;
edge_iterator ei;
struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
char *s_indent = (char *) alloca ((size_t) indent + 1);
@@ -413,21 +413,38 @@ check_bb_profile (basic_block bb, FILE * file, int indent)
if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
{
bool found = false;
+ profile_probability sum = profile_probability::never ();
+ int isum = 0;
+
FOR_EACH_EDGE (e, ei, bb->succs)
{
- if (!(e->flags & EDGE_EH))
+ if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
found = true;
sum += e->probability;
+ if (e->probability.initialized_p ())
+ isum += e->probability.to_reg_br_prob_base ();
}
/* Only report mismatches for non-EH control flow. If there are only EH
edges it means that the BB ends by noreturn call. Here the control
flow may just terminate. */
if (found)
{
- if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
- fprintf (file,
- ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
- s_indent, sum * 100.0 / REG_BR_PROB_BASE);
+ if (sum.differs_from_p (profile_probability::always ()))
+ {
+ fprintf (file,
+ ";; %sInvalid sum of outgoing probabilities ",
+ s_indent);
+ sum.dump (file);
+ fprintf (file, "\n");
+ }
+ /* Probabilities caps to 100% and thus the previous test will never
+ fire if the sum of probabilities is too large. */
+ else if (isum > REG_BR_PROB_BASE + 100)
+ {
+ fprintf (file,
+ ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
+ s_indent, isum * 100.0 / REG_BR_PROB_BASE);
+ }
profile_count lsum = profile_count::zero ();
FOR_EACH_EDGE (e, ei, bb->succs)
lsum += e->count;
@@ -442,9 +459,9 @@ check_bb_profile (basic_block bb, FILE * file, int indent)
}
}
}
- if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
+ if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
{
- sum = 0;
+ int sum = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
sum += EDGE_FREQUENCY (e);
if (abs (sum - bb->frequency) > 100)
@@ -498,8 +515,12 @@ dump_edge_info (FILE *file, edge e, dump_flags_t flags, int do_succ)
else
fprintf (file, " %d", side->index);
- if (e->probability && do_details)
- fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
+ if (e->probability.initialized_p () && do_details)
+ {
+ fprintf (file, " [");
+ e->probability.dump (file);
+ fprintf (file, "] ");
+ }
if (e->count.initialized_p () && do_details)
{
@@ -860,7 +881,7 @@ update_bb_profile_for_threading (basic_block bb, int edge_frequency,
profile_count count, edge taken_edge)
{
edge c;
- int prob;
+ profile_probability prob;
edge_iterator ei;
if (bb->count < count)
@@ -878,59 +899,51 @@ update_bb_profile_for_threading (basic_block bb, int edge_frequency,
/* Compute the probability of TAKEN_EDGE being reached via threaded edge.
Watch for overflows. */
if (bb->frequency)
- prob = GCOV_COMPUTE_SCALE (edge_frequency, bb->frequency);
+ /* FIXME: We should get edge frequency as count. */
+ prob = profile_probability::probability_in_gcov_type
+ (edge_frequency, bb->frequency);
else
- prob = 0;
+ prob = profile_probability::never ();
if (prob > taken_edge->probability)
{
if (dump_file)
- fprintf (dump_file, "Jump threading proved probability of edge "
- "%i->%i too small (it is %i, should be %i).\n",
- taken_edge->src->index, taken_edge->dest->index,
- taken_edge->probability, prob);
- prob = taken_edge->probability * 6 / 8;
+ {
+ fprintf (dump_file, "Jump threading proved probability of edge "
+ "%i->%i too small (it is ",
+ taken_edge->src->index, taken_edge->dest->index);
+ taken_edge->probability.dump (dump_file);
+ fprintf (dump_file, " should be ");
+ prob.dump (dump_file);
+ fprintf (dump_file, ")\n");
+ }
+ prob = taken_edge->probability.apply_scale (6, 8);
}
/* Now rescale the probabilities. */
taken_edge->probability -= prob;
- prob = REG_BR_PROB_BASE - prob;
- if (prob <= 0)
+ prob = prob.invert ();
+ if (prob == profile_probability::never ())
{
if (dump_file)
fprintf (dump_file, "Edge frequencies of bb %i has been reset, "
"frequency of block should end up being 0, it is %i\n",
bb->index, bb->frequency);
- EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (bb, 0)->probability = profile_probability::guessed_always ();
ei = ei_start (bb->succs);
ei_next (&ei);
for (; (c = ei_safe_edge (ei)); ei_next (&ei))
- c->probability = 0;
+ c->probability = profile_probability::guessed_never ();
}
- else if (prob != REG_BR_PROB_BASE)
+ else if (!(prob == profile_probability::always ()))
{
- int scale = RDIV (65536 * REG_BR_PROB_BASE, prob);
-
FOR_EACH_EDGE (c, ei, bb->succs)
- {
- /* Protect from overflow due to additional scaling. */
- if (c->probability > prob)
- c->probability = REG_BR_PROB_BASE;
- else
- {
- c->probability = RDIV (c->probability * scale, 65536);
- if (c->probability > REG_BR_PROB_BASE)
- c->probability = REG_BR_PROB_BASE;
- }
- }
+ c->probability /= prob;
}
gcc_assert (bb == taken_edge->src);
- if (taken_edge->count < count)
- {
- if (dump_file)
- fprintf (dump_file, "edge %i->%i count became negative after threading",
- taken_edge->src->index, taken_edge->dest->index);
- }
+ if (dump_file && taken_edge->count < count)
+ fprintf (dump_file, "edge %i->%i count became negative after threading",
+ taken_edge->src->index, taken_edge->dest->index);
taken_edge->count -= count;
}
@@ -1038,6 +1051,26 @@ scale_bbs_frequencies_profile_count (basic_block *bbs, int nbbs,
}
}
+/* Multiply all frequencies of basic blocks in array BBS of length NBBS
+ by NUM/DEN, in profile_count arithmetic. More accurate than previous
+ function but considerably slower. */
+void
+scale_bbs_frequencies (basic_block *bbs, int nbbs,
+ profile_probability p)
+{
+ int i;
+ edge e;
+
+ for (i = 0; i < nbbs; i++)
+ {
+ edge_iterator ei;
+ bbs[i]->frequency = p.apply (bbs[i]->frequency);
+ bbs[i]->count = bbs[i]->count.apply_probability (p);
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ e->count = e->count.apply_probability (p);
+ }
+}
+
/* Helper types for hash tables. */
struct htab_bb_copy_original_entry
diff --git a/gcc/cfg.h b/gcc/cfg.h
index 365a580a0db..81b243a1a9e 100644
--- a/gcc/cfg.h
+++ b/gcc/cfg.h
@@ -109,6 +109,7 @@ extern void scale_bbs_frequencies_gcov_type (basic_block *, int, gcov_type,
gcov_type);
extern void scale_bbs_frequencies_profile_count (basic_block *, int,
profile_count, profile_count);
+extern void scale_bbs_frequencies (basic_block *, int, profile_probability);
extern void initialize_original_copy_tables (void);
extern void reset_original_copy_tables (void);
extern void free_original_copy_tables (void);
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index a3a6ea86994..792ea62cc56 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -610,7 +610,10 @@ connect_infinite_loops_to_exit (void)
break;
basic_block deadend_block = dfs_find_deadend (unvisited_block);
- make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ edge e = make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FAKE);
+ e->count = profile_count::zero ();
+ e->probability = profile_probability::never ();
dfs.add_bb (deadend_block);
}
}
diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index af73a5e131c..2fe74c40851 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -545,10 +545,11 @@ compute_outgoing_frequencies (basic_block b)
{
probability = XINT (note, 0);
e = BRANCH_EDGE (b);
- e->probability = probability;
- e->count = b->count.apply_probability (probability);
+ e->probability
+ = profile_probability::from_reg_br_prob_note (probability);
+ e->count = b->count.apply_probability (e->probability);
f = FALLTHRU_EDGE (b);
- f->probability = REG_BR_PROB_BASE - probability;
+ f->probability = e->probability.invert ();
f->count = b->count - e->count;
return;
}
@@ -560,7 +561,7 @@ compute_outgoing_frequencies (basic_block b)
else if (single_succ_p (b))
{
e = single_succ_edge (b);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = b->count;
return;
}
@@ -656,7 +657,8 @@ find_many_sub_basic_blocks (sbitmap blocks)
}
else
uninitialized_src = true;
- bb->frequency += EDGE_FREQUENCY (e);
+ if (e->probability.initialized_p ())
+ bb->frequency += EDGE_FREQUENCY (e);
}
/* When some edges are missing with read profile, this is
most likely because RTL expansion introduced loop.
@@ -671,10 +673,18 @@ find_many_sub_basic_blocks (sbitmap blocks)
&& profile_status_for_fn (cfun) != PROFILE_READ))
bb->count = profile_count::uninitialized ();
}
- else
- /* If nothing changed, there is no need to create new BBs. */
- if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+ /* If nothing changed, there is no need to create new BBs. */
+ else if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+ {
+ /* In rare occassions RTL expansion might have mistakely assigned
+ a probabilities different from what is in CFG. This happens
+ when we try to split branch to two but optimize out the
+ second branch during the way. See PR81030. */
+ if (JUMP_P (BB_END (bb)) && any_condjump_p (BB_END (bb))
+ && EDGE_COUNT (bb->succs) >= 2)
+ update_br_prob_note (bb);
continue;
+ }
compute_outgoing_frequencies (bb);
}
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 1201148fa88..365c971effb 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -559,7 +559,7 @@ try_forward_edges (int mode, basic_block b)
{
/* Save the values now, as the edge may get removed. */
profile_count edge_count = e->count;
- int edge_probability = e->probability;
+ profile_probability edge_probability = e->probability;
int edge_frequency;
int n = 0;
@@ -585,7 +585,7 @@ try_forward_edges (int mode, basic_block b)
/* We successfully forwarded the edge. Now update profile
data: for each edge we traversed in the chain, remove
the original edge's execution count. */
- edge_frequency = apply_probability (b->frequency, edge_probability);
+ edge_frequency = edge_probability.apply (b->frequency);
do
{
@@ -1435,6 +1435,13 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx_insn **f1,
if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
break;
+ /* Do not turn corssing edge to non-crossing or vice versa after
+ reload. */
+ if (BB_PARTITION (BLOCK_FOR_INSN (i1))
+ != BB_PARTITION (BLOCK_FOR_INSN (i2))
+ && reload_completed)
+ break;
+
dir = merge_dir (dir, old_insns_match_p (0, i1, i2));
if (dir == dir_none || (!dir_p && dir != dir_both))
break;
@@ -1710,24 +1717,28 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
&& optimize_bb_for_speed_p (bb1)
&& optimize_bb_for_speed_p (bb2))
{
- int prob2;
+ profile_probability prob2;
if (b1->dest == b2->dest)
prob2 = b2->probability;
else
/* Do not use f2 probability as f2 may be forwarded. */
- prob2 = REG_BR_PROB_BASE - b2->probability;
+ prob2 = b2->probability.invert ();
/* Fail if the difference in probabilities is greater than 50%.
This rules out two well-predicted branches with opposite
outcomes. */
- if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
+ if (b1->probability.differs_lot_from_p (prob2))
{
if (dump_file)
- fprintf (dump_file,
- "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
- bb1->index, bb2->index, b1->probability, prob2);
-
+ {
+ fprintf (dump_file,
+ "Outcomes of branch in bb %i and %i differ too"
+ " much (", bb1->index, bb2->index);
+ b1->probability.dump (dump_file);
+ prob2.dump (dump_file);
+ fprintf (dump_file, ")\n");
+ }
return false;
}
}
@@ -1954,18 +1965,6 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
newpos1 = newpos2 = NULL;
- /* If we have partitioned hot/cold basic blocks, it is a bad idea
- to try this optimization.
-
- Basic block partitioning may result in some jumps that appear to
- be optimizable (or blocks that appear to be mergeable), but which really
- must be left untouched (they are required to make it safely across
- partition boundaries). See the comments at the top of
- bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
-
- if (crtl->has_bb_partition && reload_completed)
- return false;
-
/* Search backward through forwarder blocks. We don't need to worry
about multiple entry or chained forwarders, as they will be optimized
away. We do this to look past the unconditional jump following a
@@ -1999,6 +1998,11 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0)
return false;
+ /* Do not turn corssing edge to non-crossing or vice versa after reload. */
+ if (BB_PARTITION (src1) != BB_PARTITION (src2)
+ && reload_completed)
+ return false;
+
/* Look for the common insn sequence, part the first ... */
if (!outgoing_edges_match (mode, src1, src2))
return false;
@@ -2020,12 +2024,10 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
if (dir == dir_backward)
{
-#define SWAP(T, X, Y) do { T tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
- SWAP (basic_block, osrc1, osrc2);
- SWAP (basic_block, src1, src2);
- SWAP (edge, e1, e2);
- SWAP (rtx_insn *, newpos1, newpos2);
-#undef SWAP
+ std::swap (osrc1, osrc2);
+ std::swap (src1, src2);
+ std::swap (e1, e2);
+ std::swap (newpos1, newpos2);
}
/* Don't proceed with the crossjump unless we found a sufficient number
@@ -2149,12 +2151,9 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
}
if (!redirect_edges_to->frequency && !src1->frequency)
- s->probability = (s->probability + s2->probability) / 2;
- else
- s->probability
- = ((s->probability * redirect_edges_to->frequency +
- s2->probability * src1->frequency)
- / (redirect_edges_to->frequency + src1->frequency));
+ s->probability = s->probability.combine_with_freq
+ (redirect_edges_to->frequency,
+ s2->probability, src1->frequency);
}
/* Adjust count and frequency for the block. An earlier jump
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c1f80727d30..c9d8118ed45 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2241,6 +2241,11 @@ expand_used_vars (void)
expand_stack_vars (NULL, &data);
}
+ if (asan_sanitize_allocas_p () && cfun->calls_alloca)
+ var_end_seq = asan_emit_allocas_unpoison (virtual_stack_dynamic_rtx,
+ virtual_stack_vars_rtx,
+ var_end_seq);
+
fini_vars_expansion ();
/* If there were any artificial non-ignored vars without rtl
@@ -2389,7 +2394,6 @@ static basic_block
expand_gimple_cond (basic_block bb, gcond *stmt)
{
basic_block new_bb, dest;
- edge new_edge;
edge true_edge;
edge false_edge;
rtx_insn *last2, *last;
@@ -2508,9 +2512,7 @@ expand_gimple_cond (basic_block bb, gcond *stmt)
if (loop->latch == bb
&& loop->header == dest)
loop->latch = new_bb;
- new_edge = make_edge (new_bb, dest, 0);
- new_edge->probability = REG_BR_PROB_BASE;
- new_edge->count = new_bb->count;
+ make_single_succ_edge (new_bb, dest, 0);
if (BARRIER_P (BB_END (new_bb)))
BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
update_bb_for_insn (new_bb);
@@ -3168,7 +3170,7 @@ expand_asm_stmt (gasm *stmt)
rtx body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
: GET_MODE (output_rvec[0])),
ggc_strdup (gimple_asm_string (stmt)),
- empty_string, 0, argvec, constraintvec,
+ "", 0, argvec, constraintvec,
labelvec, locus);
MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt);
@@ -3566,7 +3568,13 @@ expand_gimple_stmt_1 (gimple *stmt)
case GIMPLE_PREDICT:
break;
case GIMPLE_SWITCH:
- expand_case (as_a <gswitch *> (stmt));
+ {
+ gswitch *swtch = as_a <gswitch *> (stmt);
+ if (gimple_switch_num_labels (swtch) == 1)
+ expand_goto (CASE_LABEL (gimple_switch_default_label (swtch)));
+ else
+ expand_case (swtch);
+ }
break;
case GIMPLE_ASM:
expand_asm_stmt (as_a <gasm *> (stmt));
@@ -3782,7 +3790,7 @@ expand_gimple_tailcall (basic_block bb, gcall *stmt, bool *can_fallthru)
rtx_insn *last2, *last;
edge e;
edge_iterator ei;
- int probability;
+ profile_probability probability;
last2 = last = expand_gimple_stmt (stmt);
@@ -3807,7 +3815,7 @@ expand_gimple_tailcall (basic_block bb, gcall *stmt, bool *can_fallthru)
all edges here, or redirecting the existing fallthru edge to
the exit block. */
- probability = 0;
+ probability = profile_probability::never ();
profile_count count = profile_count::zero ();
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
@@ -5489,8 +5497,6 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
if (elt)
emit_label (*elt);
- /* Java emits line number notes in the top of labels.
- ??? Make this go away once line number notes are obsoleted. */
BB_HEAD (bb) = NEXT_INSN (last);
if (NOTE_P (BB_HEAD (bb)))
BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb));
@@ -5833,12 +5839,11 @@ construct_init_block (void)
{
first_block = e->dest;
redirect_edge_succ (e, init_block);
- e = make_edge (init_block, first_block, flags);
+ e = make_single_succ_edge (init_block, first_block, flags);
}
else
- e = make_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+ e = make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FALLTHRU);
update_bb_for_insn (init_block);
return init_block;
@@ -5918,9 +5923,8 @@ construct_exit_block (void)
ix++;
}
- e = make_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = EXIT_BLOCK_PTR_FOR_FN (cfun)->count;
+ e = make_single_succ_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FALLTHRU);
FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
if (e2 != e)
{
@@ -6476,6 +6480,11 @@ pass_expand::execute (function *fun)
if (fun->eh->region_tree != NULL)
finish_eh_generation ();
+ /* BB subdivision may have created basic blocks that are are only reachable
+ from unlikely bbs but not marked as such in the profile. */
+ if (optimize)
+ propagate_unlikely_bbs_forward ();
+
/* Remove unreachable blocks, otherwise we cannot compute dominators
which are needed for loop state verification. As a side-effect
this also compacts blocks.
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index bcda422d89a..18dc49a035e 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -160,10 +160,10 @@ verify_flow_info (void)
e->src->index, e->dest->index);
err = 1;
}
- if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
+ if (!e->probability.verify ())
{
- error ("verify_flow_info: Wrong probability of edge %i->%i %i",
- e->src->index, e->dest->index, e->probability);
+ error ("verify_flow_info: Wrong probability of edge %i->%i",
+ e->src->index, e->dest->index);
err = 1;
}
if (!e->count.verify ())
@@ -443,8 +443,6 @@ redirect_edge_succ_nodup (edge e, basic_block new_succ)
{
s->flags |= e->flags;
s->probability += e->probability;
- if (s->probability > REG_BR_PROB_BASE)
- s->probability = REG_BR_PROB_BASE;
s->count += e->count;
/* FIXME: This should be called via a hook and only for IR_GIMPLE. */
redirect_edge_var_map_dup (s, e);
@@ -640,7 +638,7 @@ split_edge (edge e)
ret = cfg_hooks->split_edge (e);
ret->count = count;
ret->frequency = freq;
- single_succ_edge (ret)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (ret)->probability = profile_probability::always ();
single_succ_edge (ret)->count = count;
if (irr)
@@ -1451,17 +1449,17 @@ account_profile_record (struct profile_record *record, int after_pass)
basic_block bb;
edge_iterator ei;
edge e;
- int sum;
FOR_ALL_BB_FN (bb, cfun)
{
if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
&& profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
- sum = 0;
+ profile_probability sum = profile_probability::never ();
FOR_EACH_EDGE (e, ei, bb->succs)
sum += e->probability;
- if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
+ if (EDGE_COUNT (bb->succs)
+ && sum.differs_from_p (profile_probability::always ()))
record->num_mismatched_freq_out[after_pass]++;
profile_count lsum = profile_count::zero ();
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1472,7 +1470,7 @@ account_profile_record (struct profile_record *record, int after_pass)
if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
&& profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
- sum = 0;
+ int sum = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
sum += EDGE_FREQUENCY (e);
if (abs (sum - bb->frequency) > 100
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index a8bec1d48af..e7ffa236437 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -114,7 +114,8 @@ struct GTY ((chain_next ("%h.next"))) control_iv {
/* Structure to hold information for each natural loop. */
struct GTY ((chain_next ("%h.next"))) loop {
- /* Index into loops array. */
+ /* Index into loops array. Note indices will never be reused after loop
+ is destroyed. */
int num;
/* Number of loop insns. */
@@ -225,6 +226,16 @@ struct GTY ((chain_next ("%h.next"))) loop {
builtins. */
tree simduid;
+ /* In loop optimization, it's common to generate loops from the original
+ loop. This field records the index of the original loop which can be
+ used to track the original loop from newly generated loops. This can
+ be done by calling function get_loop (cfun, orig_loop_num). Note the
+ original loop could be destroyed for various reasons thus no longer
+ exists, as a result, function call to get_loop returns NULL pointer.
+ In this case, this field should not be used and needs to be cleared
+ whenever possible. */
+ int orig_loop_num;
+
/* Upper bound on number of iterations of a loop. */
struct nb_iter_bound *bounds;
diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c
index a9537637115..73710abac6e 100644
--- a/gcc/cfgloopanal.c
+++ b/gcc/cfgloopanal.c
@@ -469,16 +469,12 @@ single_likely_exit (struct loop *loop)
exits = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (exits, i, ex)
{
- if (ex->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
- continue;
- /* The constant of 5 is set in a way so noreturn calls are
- ruled out by this test. The static branch prediction algorithm
- will not assign such a low probability to conditionals for usual
- reasons.
- FIXME: Turn to likely_never_executed */
- if ((profile_status_for_fn (cfun) != PROFILE_ABSENT
- && ex->probability < 5)
- || ex->count == profile_count::zero ())
+ if (probably_never_executed_edge_p (cfun, ex)
+ /* We want to rule out paths to noreturns but not low probabilities
+ resulting from adjustments or combining.
+ FIXME: once we have better quality tracking, make this more
+ robust. */
+ || ex->probability <= profile_probability::very_unlikely ())
continue;
if (!found)
found = ex;
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index d764ab9a8c7..fd335c3fe1d 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -488,38 +488,42 @@ add_loop (struct loop *loop, struct loop *outer)
free (bbs);
}
-/* Multiply all frequencies in LOOP by NUM/DEN. */
+/* Scale profile of loop by P. */
void
-scale_loop_frequencies (struct loop *loop, int num, int den)
+scale_loop_frequencies (struct loop *loop, profile_probability p)
{
basic_block *bbs;
bbs = get_loop_body (loop);
- scale_bbs_frequencies_int (bbs, loop->num_nodes, num, den);
+ scale_bbs_frequencies (bbs, loop->num_nodes, p);
free (bbs);
}
-/* Multiply all frequencies in LOOP by SCALE/REG_BR_PROB_BASE.
+/* Scale profile in LOOP by P.
If ITERATION_BOUND is non-zero, scale even further if loop is predicted
to iterate too many times. */
void
-scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound)
+scale_loop_profile (struct loop *loop, profile_probability p,
+ gcov_type iteration_bound)
{
gcov_type iterations = expected_loop_iterations_unbounded (loop);
edge e;
edge_iterator ei;
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Scaling loop %i with scale %f, "
- "bounding iterations to %i from guessed %i\n",
- loop->num, (double)scale / REG_BR_PROB_BASE,
- (int)iteration_bound, (int)iterations);
+ {
+ fprintf (dump_file, ";; Scaling loop %i with scale ",
+ loop->num);
+ p.dump (dump_file);
+ fprintf (dump_file, " bounding iterations to %i from guessed %i\n",
+ (int)iteration_bound, (int)iterations);
+ }
/* See if loop is predicted to iterate too many times. */
if (iteration_bound && iterations > 0
- && apply_probability (iterations, scale) > iteration_bound)
+ && p.apply (iterations) > iteration_bound)
{
/* Fixing loop profile for different trip count is not trivial; the exit
probabilities has to be updated to match and frequencies propagated down
@@ -542,8 +546,9 @@ scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound)
/* Probability of exit must be 1/iterations. */
freq_delta = EDGE_FREQUENCY (e);
- e->probability = REG_BR_PROB_BASE / iteration_bound;
- other_e->probability = inverse_probability (e->probability);
+ e->probability = profile_probability::always ()
+ .apply_scale (1, iteration_bound);
+ other_e->probability = e->probability.invert ();
freq_delta -= EDGE_FREQUENCY (e);
/* Adjust counts accordingly. */
@@ -568,7 +573,7 @@ scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound)
/* Roughly speaking we want to reduce the loop body profile by the
difference of loop iterations. We however can do better if
we look at the actual profile, if it is available. */
- scale = RDIV (iteration_bound * scale, iterations);
+ p = p.apply_scale (iteration_bound, iterations);
bool determined = false;
if (loop->header->count.initialized_p ())
@@ -581,13 +586,12 @@ scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound)
if (count_in > profile_count::zero () )
{
- scale = GCOV_COMPUTE_SCALE (count_in.to_gcov_type ()
- * iteration_bound,
- loop->header->count.to_gcov_type ());
+ p = count_in.probability_in (loop->header->count.apply_scale
+ (iteration_bound, 1));
determined = true;
}
}
- if (!determined)
+ if (!determined && loop->header->frequency)
{
int freq_in = 0;
@@ -596,18 +600,19 @@ scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound)
freq_in += EDGE_FREQUENCY (e);
if (freq_in != 0)
- scale = GCOV_COMPUTE_SCALE (freq_in * iteration_bound,
- loop->header->frequency);
+ p = profile_probability::probability_in_gcov_type
+ (freq_in * iteration_bound, loop->header->frequency);
}
- if (!scale)
- scale = 1;
+ if (!(p > profile_probability::never ()))
+ p = profile_probability::very_unlikely ();
}
- if (scale == REG_BR_PROB_BASE)
+ if (p >= profile_probability::always ()
+ || !p.initialized_p ())
return;
/* Scale the actual probabilities. */
- scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
+ scale_loop_frequencies (loop, p);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, ";; guessed iterations are now %i\n",
(int)expected_loop_iterations_unbounded (loop));
@@ -777,7 +782,6 @@ create_empty_loop_on_edge (edge entry_edge,
gcond *cond_expr;
tree exit_test;
edge exit_e;
- int prob;
gcc_assert (entry_edge && initial_value && stride && upper_bound && iv);
@@ -801,9 +805,7 @@ create_empty_loop_on_edge (edge entry_edge,
add_loop (loop, outer);
/* TODO: Fix frequencies and counts. */
- prob = REG_BR_PROB_BASE / 2;
-
- scale_loop_frequencies (loop, REG_BR_PROB_BASE - prob, REG_BR_PROB_BASE);
+ scale_loop_frequencies (loop, profile_probability::even ());
/* Update dominators. */
update_dominators_in_loop (loop);
@@ -861,7 +863,8 @@ create_empty_loop_on_edge (edge entry_edge,
struct loop *
loopify (edge latch_edge, edge header_edge,
basic_block switch_bb, edge true_edge, edge false_edge,
- bool redirect_all_edges, unsigned true_scale, unsigned false_scale)
+ bool redirect_all_edges, profile_probability true_scale,
+ profile_probability false_scale)
{
basic_block succ_bb = latch_edge->dest;
basic_block pred_bb = header_edge->src;
@@ -914,8 +917,8 @@ loopify (edge latch_edge, edge header_edge,
e->count = switch_bb->count.apply_probability (e->probability);
}
}
- scale_loop_frequencies (loop, false_scale, REG_BR_PROB_BASE);
- scale_loop_frequencies (succ_bb->loop_father, true_scale, REG_BR_PROB_BASE);
+ scale_loop_frequencies (loop, false_scale);
+ scale_loop_frequencies (succ_bb->loop_father, true_scale);
update_dominators_in_loop (loop);
return loop;
@@ -1101,43 +1104,6 @@ can_duplicate_loop_p (const struct loop *loop)
return ret;
}
-/* Sets probability and count of edge E to zero. The probability and count
- is redistributed evenly to the remaining edges coming from E->src. */
-
-static void
-set_zero_probability (edge e)
-{
- basic_block bb = e->src;
- edge_iterator ei;
- edge ae, last = NULL;
- unsigned n = EDGE_COUNT (bb->succs);
- profile_count cnt = e->count, cnt1;
- unsigned prob = e->probability, prob1;
-
- gcc_assert (n > 1);
- cnt1 = cnt.apply_scale (1, (n - 1));
- prob1 = prob / (n - 1);
-
- FOR_EACH_EDGE (ae, ei, bb->succs)
- {
- if (ae == e)
- continue;
-
- ae->probability += prob1;
- ae->count += cnt1;
- last = ae;
- }
-
- /* Move the rest to one of the edges. */
- last->probability += prob % (n - 1);
- /* TODO: Remove once we have fractional counts. */
- if (cnt.initialized_p ())
- last->count += profile_count::from_gcov_type (cnt.to_gcov_type () % (n - 1));
-
- e->probability = 0;
- e->count = profile_count::zero ();
-}
-
/* Duplicates body of LOOP to given edge E NDUPL times. Takes care of updating
loop structure and dominators. E's destination must be LOOP header for
this to work, i.e. it must be entry or latch edge of this loop; these are
@@ -1224,14 +1190,18 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
prob_pass_wont_exit =
RDIV (REG_BR_PROB_BASE * (freq_le + freq_out_orig), freq_in);
- if (orig
- && REG_BR_PROB_BASE - orig->probability != 0)
+ if (orig && orig->probability.initialized_p ()
+ && !(orig->probability == profile_probability::always ()))
{
/* The blocks that are dominated by a removed exit edge ORIG have
frequencies scaled by this. */
- scale_after_exit
- = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
- REG_BR_PROB_BASE - orig->probability);
+ if (orig->probability.initialized_p ())
+ scale_after_exit
+ = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
+ REG_BR_PROB_BASE
+ - orig->probability.to_reg_br_prob_base ());
+ else
+ scale_after_exit = REG_BR_PROB_BASE;
bbs_to_scale = BITMAP_ALLOC (NULL);
for (i = 0; i < n; i++)
{
@@ -1387,7 +1357,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
{
if (to_remove)
to_remove->safe_push (new_spec_edges[SE_ORIG]);
- set_zero_probability (new_spec_edges[SE_ORIG]);
+ force_edge_cold (new_spec_edges[SE_ORIG], true);
/* Scale the frequencies of the blocks dominated by the exit. */
if (bbs_to_scale)
@@ -1423,7 +1393,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
{
if (to_remove)
to_remove->safe_push (orig);
- set_zero_probability (orig);
+ force_edge_cold (orig, true);
/* Scale the frequencies of the blocks dominated by the exit. */
if (bbs_to_scale)
@@ -1653,12 +1623,14 @@ force_single_succ_latches (void)
THEN_PROB is the probability of then branch of the condition.
ELSE_PROB is the probability of else branch. Note that they may be both
- REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED. */
+ REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED or
+ IFN_LOOP_DIST_ALIAS. */
static basic_block
lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
- edge e, void *cond_expr, unsigned then_prob,
- unsigned else_prob)
+ edge e, void *cond_expr,
+ profile_probability then_prob,
+ profile_probability else_prob)
{
basic_block new_head = NULL;
edge e1;
@@ -1713,8 +1685,8 @@ lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
struct loop *
loop_version (struct loop *loop,
void *cond_expr, basic_block *condition_bb,
- unsigned then_prob, unsigned else_prob,
- unsigned then_scale, unsigned else_scale,
+ profile_probability then_prob, profile_probability else_prob,
+ profile_probability then_scale, profile_probability else_scale,
bool place_after)
{
basic_block first_head, second_head;
diff --git a/gcc/cfgloopmanip.h b/gcc/cfgloopmanip.h
index 7ad3bf5d7d4..2eab70f3ada 100644
--- a/gcc/cfgloopmanip.h
+++ b/gcc/cfgloopmanip.h
@@ -37,14 +37,14 @@ extern edge mfb_kj_edge;
extern bool remove_path (edge, bool * = NULL, bitmap = NULL);
extern void place_new_loop (struct function *, struct loop *);
extern void add_loop (struct loop *, struct loop *);
-extern void scale_loop_frequencies (struct loop *, int, int);
-extern void scale_loop_profile (struct loop *, int, gcov_type);
+extern void scale_loop_frequencies (struct loop *, profile_probability);
+extern void scale_loop_profile (struct loop *, profile_probability, gcov_type);
extern edge create_empty_if_region_on_edge (edge, tree);
extern struct loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree,
tree *, tree *, struct loop *);
extern struct loop *loopify (edge, edge,
basic_block, edge, edge, bool,
- unsigned, unsigned);
+ profile_probability, profile_probability);
extern void unloop (struct loop *, bool *, bitmap);
extern void copy_loop_info (struct loop *loop, struct loop *target);
extern struct loop * duplicate_loop (struct loop *, struct loop *);
@@ -58,7 +58,8 @@ basic_block create_preheader (struct loop *, int);
extern void create_preheaders (int);
extern void force_single_succ_latches (void);
struct loop * loop_version (struct loop *, void *,
- basic_block *, unsigned, unsigned,
- unsigned, unsigned, bool);
+ basic_block *,
+ profile_probability, profile_probability,
+ profile_probability, profile_probability, bool);
#endif /* GCC_CFGLOOPMANIP_H */
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 623d04f4499..6ef47b7e61f 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1155,7 +1155,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
else
e->flags = 0;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = src->count;
if (e->dest != target)
@@ -1504,12 +1504,10 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
{
int prob = XINT (note, 0);
- b->probability = prob;
- b->count = e->count.apply_probability (prob);
+ b->probability = profile_probability::from_reg_br_prob_note (prob);
+ b->count = e->count.apply_probability (b->probability);
e->probability -= e->probability;
e->count -= b->count;
- if (e->probability < 0)
- e->probability = 0;
}
}
@@ -1618,7 +1616,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
{
rtx_insn *new_head;
profile_count count = e->count;
- int probability = e->probability;
+ profile_probability probability = e->probability;
/* Create the new structures. */
/* If the old block ended with a tablejump, skip its table
@@ -1646,7 +1644,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
/* Redirect old edge. */
redirect_edge_pred (e, jump_block);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
/* If e->src was previously region crossing, it no longer is
and the reg crossing note should be removed. */
@@ -1656,7 +1654,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
add also edge from asm goto bb to target. */
if (asm_goto_edge)
{
- new_edge->probability /= 2;
+ new_edge->probability = new_edge->probability.apply_scale (1, 2);
new_edge->count = new_edge->count.apply_scale (1, 2);
jump_block->count = jump_block->count.apply_scale (1, 2);
jump_block->frequency /= 2;
@@ -2111,8 +2109,6 @@ commit_edge_insertions (void)
static void
rtl_dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
{
- rtx_insn *insn;
- rtx_insn *last;
char *s_indent;
s_indent = (char *) alloca ((size_t) indent + 1);
@@ -2126,18 +2122,22 @@ rtl_dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
}
if (bb->index != ENTRY_BLOCK && bb->index != EXIT_BLOCK)
- for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb)); insn != last;
- insn = NEXT_INSN (insn))
- {
- if (flags & TDF_DETAILS)
- df_dump_insn_top (insn, outf);
- if (! (flags & TDF_SLIM))
- print_rtl_single (outf, insn);
- else
- dump_insn_slim (outf, insn);
- if (flags & TDF_DETAILS)
- df_dump_insn_bottom (insn, outf);
- }
+ {
+ rtx_insn *last = BB_END (bb);
+ if (last)
+ last = NEXT_INSN (last);
+ for (rtx_insn *insn = BB_HEAD (bb); insn != last; insn = NEXT_INSN (insn))
+ {
+ if (flags & TDF_DETAILS)
+ df_dump_insn_top (insn, outf);
+ if (! (flags & TDF_SLIM))
+ print_rtl_single (outf, insn);
+ else
+ dump_insn_slim (outf, insn);
+ if (flags & TDF_DETAILS)
+ df_dump_insn_bottom (insn, outf);
+ }
+ }
if (df && (flags & TDF_DETAILS))
{
@@ -2251,12 +2251,13 @@ void
update_br_prob_note (basic_block bb)
{
rtx note;
- if (!JUMP_P (BB_END (bb)))
+ if (!JUMP_P (BB_END (bb)) || !BRANCH_EDGE (bb)->probability.initialized_p ())
return;
note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
- if (!note || XINT (note, 0) == BRANCH_EDGE (bb)->probability)
+ if (!note
+ || XINT (note, 0) == BRANCH_EDGE (bb)->probability.to_reg_br_prob_note ())
return;
- XINT (note, 0) = BRANCH_EDGE (bb)->probability;
+ XINT (note, 0) = BRANCH_EDGE (bb)->probability.to_reg_br_prob_note ();
}
/* Get the last insn associated with block BB (that includes barriers and
@@ -2283,6 +2284,29 @@ get_last_bb_insn (basic_block bb)
return end;
}
+/* Add all BBs reachable from entry via hot paths into the SET. */
+
+void
+find_bbs_reachable_by_hot_paths (hash_set<basic_block> *set)
+{
+ auto_vec<basic_block, 64> worklist;
+
+ set->add (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ worklist.safe_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+
+ while (worklist.length () > 0)
+ {
+ basic_block bb = worklist.pop ();
+ edge_iterator ei;
+ edge e;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (BB_PARTITION (e->dest) != BB_COLD_PARTITION
+ && !set->add (e->dest))
+ worklist.safe_push (e->dest);
+ }
+}
+
/* Sanity check partition hotness to ensure that basic blocks in
  the cold partition don't dominate basic blocks in the hot partition.
If FLAG_ONLY is true, report violations as errors. Otherwise
@@ -2296,49 +2320,25 @@ find_partition_fixes (bool flag_only)
basic_block bb;
vec<basic_block> bbs_in_cold_partition = vNULL;
vec<basic_block> bbs_to_fix = vNULL;
+ hash_set<basic_block> set;
/* Callers check this. */
gcc_checking_assert (crtl->has_bb_partition);
- FOR_EACH_BB_FN (bb, cfun)
- if ((BB_PARTITION (bb) == BB_COLD_PARTITION))
- bbs_in_cold_partition.safe_push (bb);
-
- if (bbs_in_cold_partition.is_empty ())
- return vNULL;
-
- bool dom_calculated_here = !dom_info_available_p (CDI_DOMINATORS);
-
- if (dom_calculated_here)
- calculate_dominance_info (CDI_DOMINATORS);
-
- while (! bbs_in_cold_partition.is_empty ())
- {
- bb = bbs_in_cold_partition.pop ();
- /* Any blocks dominated by a block in the cold section
- must also be cold. */
- basic_block son;
- for (son = first_dom_son (CDI_DOMINATORS, bb);
- son;
- son = next_dom_son (CDI_DOMINATORS, son))
- {
- /* If son is not yet cold, then mark it cold here and
- enqueue it for further processing. */
- if ((BB_PARTITION (son) != BB_COLD_PARTITION))
- {
- if (flag_only)
- error ("non-cold basic block %d dominated "
- "by a block in the cold partition (%d)", son->index, bb->index);
- else
- BB_SET_PARTITION (son, BB_COLD_PARTITION);
- bbs_to_fix.safe_push (son);
- bbs_in_cold_partition.safe_push (son);
- }
- }
- }
+ find_bbs_reachable_by_hot_paths (&set);
- if (dom_calculated_here)
- free_dominance_info (CDI_DOMINATORS);
+ FOR_EACH_BB_FN (bb, cfun)
+ if (!set.contains (bb)
+ && BB_PARTITION (bb) != BB_COLD_PARTITION)
+ {
+ if (flag_only)
+ error ("non-cold basic block %d reachable only "
+ "by paths crossing the cold partition", bb->index);
+ else
+ BB_SET_PARTITION (bb, BB_COLD_PARTITION);
+ bbs_to_fix.safe_push (bb);
+ bbs_in_cold_partition.safe_push (bb);
+ }
return bbs_to_fix;
}
@@ -2447,11 +2447,22 @@ rtl_verify_edges (void)
&& EDGE_COUNT (bb->succs) >= 2
&& any_condjump_p (BB_END (bb)))
{
- if (XINT (note, 0) != BRANCH_EDGE (bb)->probability
- && profile_status_for_fn (cfun) != PROFILE_ABSENT)
+ if (!BRANCH_EDGE (bb)->probability.initialized_p ())
+ {
+ if (profile_status_for_fn (cfun) != PROFILE_ABSENT)
+ {
+ error ("verify_flow_info: "
+ "REG_BR_PROB is set but cfg probability is not");
+ err = 1;
+ }
+ }
+ else if (XINT (note, 0)
+ != BRANCH_EDGE (bb)->probability.to_reg_br_prob_note ()
+ && profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
- XINT (note, 0), BRANCH_EDGE (bb)->probability);
+ XINT (note, 0),
+ BRANCH_EDGE (bb)->probability.to_reg_br_prob_note ());
err = 1;
}
}
@@ -3143,7 +3154,7 @@ purge_dead_edges (basic_block bb)
/* Redistribute probabilities. */
if (single_succ_p (bb))
{
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
single_succ_edge (bb)->count = bb->count;
}
else
@@ -3154,8 +3165,9 @@ purge_dead_edges (basic_block bb)
b = BRANCH_EDGE (bb);
f = FALLTHRU_EDGE (bb);
- b->probability = XINT (note, 0);
- f->probability = REG_BR_PROB_BASE - b->probability;
+ b->probability = profile_probability::from_reg_br_prob_note
+ (XINT (note, 0));
+ f->probability = b->probability.invert ();
b->count = bb->count.apply_probability (b->probability);
f->count = bb->count.apply_probability (f->probability);
}
@@ -3208,7 +3220,7 @@ purge_dead_edges (basic_block bb)
gcc_assert (single_succ_p (bb));
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
single_succ_edge (bb)->count = bb->count;
if (dump_file)
@@ -3781,7 +3793,8 @@ fixup_reorder_chain (void)
rtx note = find_reg_note (bb_end_jump, REG_BR_PROB, 0);
if (note
- && XINT (note, 0) < REG_BR_PROB_BASE / 2
+ && profile_probability::from_reg_br_prob_note
+ (XINT (note, 0)) < profile_probability::even ()
&& invert_jump (bb_end_jump,
(e_fall->dest
== EXIT_BLOCK_PTR_FOR_FN (cfun)
@@ -4891,7 +4904,9 @@ rtl_flow_call_edges_add (sbitmap blocks)
blocks_split++;
}
- make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ edge ne = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ ne->probability = profile_probability::guessed_never ();
+ ne->count = profile_count::guessed_zero ();
}
if (insn == BB_HEAD (bb))
@@ -4931,7 +4946,8 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
start_sequence ();
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
- do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label, -1);
+ do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
jump = get_last_insn ();
JUMP_LABEL (jump) = label;
LABEL_NUSES (label)++;
diff --git a/gcc/cfgrtl.h b/gcc/cfgrtl.h
index 9235b50ed66..93cb75d041e 100644
--- a/gcc/cfgrtl.h
+++ b/gcc/cfgrtl.h
@@ -54,5 +54,6 @@ extern void cfg_layout_initialize (int);
extern void cfg_layout_finalize (void);
extern void break_superblocks (void);
extern void init_rtl_bb_info (basic_block);
+extern void find_bbs_reachable_by_hot_paths (hash_set <basic_block> *);
#endif /* GCC_CFGRTL_H */
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 81aed5c357c..d7c9ba61795 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -20,8 +20,9 @@ along with GCC; see the file COPYING3. If not see
/* This file contains basic routines manipulating call graph
- The call-graph is a data structure designed for intra-procedural optimization.
- It represents a multi-graph where nodes are functions and edges are call sites. */
+ The call-graph is a data structure designed for inter-procedural
+ optimization. It represents a multi-graph where nodes are functions
+ (symbols within symbol table) and edges are call sites. */
#include "config.h"
#include "system.h"
@@ -1314,16 +1315,19 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
}
gcc_assert (e2->speculative);
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+
+ profile_probability prob = e->count.probability_in (e->count
+ + e2->count);
+ if (prob.initialized_p ())
+ ;
+ else if (e->frequency || e2->frequency)
+ prob = profile_probability::probability_in_gcov_type
+ (e->frequency, e->frequency + e2->frequency).guessed ();
+ else
+ prob = profile_probability::even ();
new_stmt = gimple_ic (e->call_stmt,
dyn_cast<cgraph_node *> (ref->referred),
- e->count > profile_count::zero ()
- || e2->count > profile_count::zero ()
- ? e->count.probability_in (e->count + e2->count)
- : e->frequency || e2->frequency
- ? RDIV (e->frequency * REG_BR_PROB_BASE,
- e->frequency + e2->frequency)
- : REG_BR_PROB_BASE / 2,
- e->count, e->count + e2->count);
+ prob, e->count, e->count + e2->count);
e->speculative = false;
e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
false);
@@ -2315,7 +2319,8 @@ cgraph_node::get_availability (symtab_node *ref)
avail = AVAIL_AVAILABLE;
else if (transparent_alias)
ultimate_alias_target (&avail, ref);
- else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+ else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("noipa", DECL_ATTRIBUTES (decl)))
avail = AVAIL_INTERPOSABLE;
else if (!externally_visible)
avail = AVAIL_AVAILABLE;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 77209046d9a..6072c567bc3 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -449,6 +449,8 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
node->definition = true;
notice_global_symbol (decl);
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
+ if (!flag_toplevel_reorder)
+ node->no_reorder = true;
/* With -fkeep-inline-functions we are keeping all inline functions except
for extern inline ones. */
@@ -471,7 +473,8 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
declared inline and nested functions. These were optimized out
in the original implementation and it is unclear whether we want
to change the behavior here. */
- if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions)
+ if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions
+ || node->no_reorder)
&& !node->cpp_implicit_alias
&& !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl)
@@ -840,13 +843,13 @@ varpool_node::finalize_decl (tree decl)
it is available to notice_global_symbol. */
node->definition = true;
notice_global_symbol (decl);
+ if (!flag_toplevel_reorder)
+ node->no_reorder = true;
if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
/* Traditionally we do not eliminate static variables when not
optimizing and when not doing toplevel reoder. */
- || node->no_reorder
- || ((!flag_toplevel_reorder
- && !DECL_COMDAT (node->decl)
- && !DECL_ARTIFICIAL (node->decl))))
+ || (node->no_reorder && !DECL_COMDAT (node->decl)
+ && !DECL_ARTIFICIAL (node->decl)))
node->force_output = true;
if (symtab->state == CONSTRUCTION
@@ -857,8 +860,8 @@ varpool_node::finalize_decl (tree decl)
/* Some frontends produce various interface variables after compilation
finished. */
if (symtab->state == FINISHED
- || (!flag_toplevel_reorder
- && symtab->state == EXPANSION))
+ || (node->no_reorder
+ && symtab->state == EXPANSION))
node->assemble_decl ();
if (DECL_INITIAL (decl))
@@ -1506,18 +1509,18 @@ init_lowered_empty_function (tree decl, bool in_ssa, profile_count count)
/* Create BB for body of the function and connect it properly. */
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = count;
- ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
+ ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
EXIT_BLOCK_PTR_FOR_FN (cfun)->count = count;
- EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
+ EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
bb = create_basic_block (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun));
bb->count = count;
bb->frequency = BB_FREQ_MAX;
e = make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, EDGE_FALLTHRU);
e->count = count;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
e->count = count;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
add_bb_to_loop (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father);
return bb;
@@ -1891,19 +1894,18 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
NULL_TREE, NULL_TREE);
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
e = make_edge (bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 16;
+ e->probability = profile_probability::guessed_always ()
+ .apply_scale (1, 16);
e->count = count - count.apply_scale (1, 16);
e = make_edge (bb, else_bb, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE / 16;
+ e->probability = profile_probability::guessed_always ()
+ .apply_scale (1, 16);
e->count = count.apply_scale (1, 16);
- e = make_edge (return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- e->count = count;
- e = make_edge (then_bb, return_bb, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = count - count.apply_scale (1, 16);
+ make_single_succ_edge (return_bb,
+ EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ make_single_succ_edge (then_bb, return_bb, EDGE_FALLTHRU);
e = make_edge (else_bb, return_bb, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = count.apply_scale (1, 16);
bsi = gsi_last_bb (then_bb);
}
@@ -2227,11 +2229,10 @@ struct cgraph_order_sort
according to their order fields, which is the order in which they
appeared in the file. This implements -fno-toplevel-reorder. In
this mode we may output functions and variables which don't really
- need to be output.
- When NO_REORDER is true only do this for symbols marked no reorder. */
+ need to be output. */
static void
-output_in_order (bool no_reorder)
+output_in_order (void)
{
int max;
cgraph_order_sort *nodes;
@@ -2246,7 +2247,7 @@ output_in_order (bool no_reorder)
{
if (pf->process && !pf->thunk.thunk_p && !pf->alias)
{
- if (no_reorder && !pf->no_reorder)
+ if (!pf->no_reorder)
continue;
i = pf->order;
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
@@ -2259,7 +2260,7 @@ output_in_order (bool no_reorder)
Please keep them in sync. */
FOR_EACH_VARIABLE (pv)
{
- if (no_reorder && !pv->no_reorder)
+ if (!pv->no_reorder)
continue;
if (DECL_HARD_REGISTER (pv->decl)
|| DECL_HAS_VALUE_EXPR_P (pv->decl))
@@ -2533,16 +2534,11 @@ symbol_table::compile (void)
state = EXPANSION;
- if (!flag_toplevel_reorder)
- output_in_order (false);
- else
- {
- /* Output first asm statements and anything ordered. The process
- flag is cleared for these nodes, so we skip them later. */
- output_in_order (true);
- expand_all_functions ();
- output_variables ();
- }
+ /* Output first asm statements and anything ordered. The process
+ flag is cleared for these nodes, so we skip them later. */
+ output_in_order ();
+ expand_all_functions ();
+ output_variables ();
process_new_functions ();
state = FINISHED;
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
index 9cbe03f8e02..edde4711869 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "langhooks.h"
#include "explow.h"
+#include "profile-count.h"
#include "expr.h"
#include "tree-iterator.h"
#include "gimplify.h"
diff --git a/gcc/combine.c b/gcc/combine.c
index 66f80b64bb4..e47a4f20a62 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1213,8 +1213,10 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
INSN_COST (insn) = insn_rtx_cost (PATTERN (insn),
optimize_this_for_speed_p);
if (dump_file)
- fprintf (dump_file, "insn_cost %d: %d\n",
- INSN_UID (insn), INSN_COST (insn));
+ {
+ fprintf (dump_file, "insn_cost %d for ", INSN_COST (insn));
+ dump_insn_slim (dump_file, insn);
+ }
}
}
@@ -6582,7 +6584,7 @@ simplify_if_then_else (rtx x)
&& (i = exact_log2 (UINTVAL (true_rtx) & GET_MODE_MASK (mode))) >= 0)
{
rtx val = XEXP (cond, 0);
- enum machine_mode val_mode = GET_MODE (val);
+ machine_mode val_mode = GET_MODE (val);
if (val_mode == mode)
return val;
else if (GET_MODE_PRECISION (val_mode) < GET_MODE_PRECISION (mode))
@@ -7954,18 +7956,9 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
XEXP (inner_x0, 1),
i, 1, 0, in_code == COMPARE);
- if (new_rtx)
- {
- /* If we narrowed the mode when dropping the subreg, then
- we must zero-extend to keep the semantics of the AND. */
- if (GET_MODE_SIZE (inner_mode) >= GET_MODE_SIZE (mode))
- ;
- else if (SCALAR_INT_MODE_P (inner_mode))
- new_rtx = simplify_gen_unary (ZERO_EXTEND, mode,
- new_rtx, inner_mode);
- else
- new_rtx = NULL;
- }
+ /* If we narrowed the mode when dropping the subreg, then we lose. */
+ if (GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (mode))
+ new_rtx = NULL;
/* If that didn't give anything, see if the AND simplifies on
its own. */
diff --git a/gcc/common.opt b/gcc/common.opt
index 4f9c3dcac3e..78cfa568a95 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -163,6 +163,13 @@ bool flag_stack_usage_info = false
Variable
int flag_debug_asm
+; How many NOP insns to place at each function entry by default
+Variable
+HOST_WIDE_INT function_entry_patch_area_size
+
+; And how far the real asm entry point is into this area
+Variable
+HOST_WIDE_INT function_entry_patch_area_start
; Balance between GNAT encodings and standard DWARF to emit.
Variable
@@ -546,7 +553,7 @@ Common Var(warn_array_bounds) Warning
Warn if an array is accessed out of bounds.
Warray-bounds=
-Common Joined RejectNegative UInteger Var(warn_array_bounds) Warning
+Common Joined RejectNegative UInteger Var(warn_array_bounds) Warning IntegerRange(0, 2)
Warn if an array is accessed out of bounds.
Wattributes
@@ -601,7 +608,7 @@ Wimplicit-fallthrough
Common Alias(Wimplicit-fallthrough=,3,0) Warning
Wimplicit-fallthrough=
-Common Var(warn_implicit_fallthrough) RejectNegative Joined UInteger Warning
+Common Var(warn_implicit_fallthrough) RejectNegative Joined UInteger Warning IntegerRange(0, 5)
Warn when a switch case falls through.
Winline
@@ -1778,7 +1785,7 @@ Specify the algorithm to partition symbols and vars at linktime.
; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
flto-compression-level=
-Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1)
+Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 9)
-flto-compression-level=<number> Use zlib compression level <number> for IL.
flto-odr-type-merging
@@ -2030,6 +2037,10 @@ fprofile-reorder-functions
Common Report Var(flag_profile_reorder_functions)
Enable function reordering that improves code placement.
+fpatchable-function-entry=
+Common Joined Optimization
+Insert NOP instructions at each function entry.
+
frandom-seed
Common Var(common_deferred_options) Defer
@@ -2061,7 +2072,7 @@ Tell DSE that the storage for a C++ object is dead when the constructor
starts and when the destructor finishes.
flifetime-dse=
-Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization
+Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2)
flive-range-shrinkage
Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
diff --git a/gcc/common/config/arm/arm-common.c b/gcc/common/config/arm/arm-common.c
index d06c39bd667..38bd3a725b1 100644
--- a/gcc/common/config/arm/arm-common.c
+++ b/gcc/common/config/arm/arm-common.c
@@ -144,7 +144,7 @@ arm_rewrite_march (int argc, const char **argv)
return arm_rewrite_selected_arch (argv[argc - 1]);
}
-#include "config/arm/arm-cpu-cdata.h"
+#include "arm-cpu-cdata.h"
/* Scan over a raw feature array BITS checking for BIT being present.
This is slower than the normal bitmask checks, but we would spend longer
@@ -761,6 +761,63 @@ arm_canon_arch_option (int argc, const char **argv)
return canonical_arch;
}
+/* If building big-endian on a BE8 target generate a --be8 option for
+ the linker. Takes four types of option: "little" - little-endian;
+ "big" - big-endian; "be8" - force be8 iff big-endian; and "arch"
+ "<arch-name>" (two arguments) - the target architecture. The
+ parameter names are generated by the driver from the command-line
+ options. */
+const char *
+arm_be8_option (int argc, const char **argv)
+{
+ int endian = TARGET_ENDIAN_DEFAULT;
+ const char *arch = NULL;
+ int arg;
+ bool force = false;
+
+ for (arg = 0; arg < argc; arg++)
+ {
+ if (strcmp (argv[arg], "little") == 0)
+ endian = 0;
+ else if (strcmp (argv[arg], "big") == 0)
+ endian = 1;
+ else if (strcmp (argv[arg], "be8") == 0)
+ force = true;
+ else if (strcmp (argv[arg], "arch") == 0)
+ {
+ arg++;
+ gcc_assert (arg < argc);
+ arch = argv[arg];
+ }
+ else
+ gcc_unreachable ();
+ }
+
+ /* Little endian - no be8 option. */
+ if (!endian)
+ return "";
+
+ if (force)
+ return "--be8";
+
+ /* Arch might not be set iff arm_canon_arch (above) detected an
+ error. Do nothing in that case. */
+ if (!arch)
+ return "";
+
+ const arch_option *selected_arch
+ = arm_parse_arch_option_name (all_architectures, "-march", arch);
+
+ /* Similarly if the given arch option was itself invalid. */
+ if (!selected_arch)
+ return "";
+
+ if (check_isa_bits_for (selected_arch->common.isa_bits, isa_bit_be8))
+ return "--be8";
+
+ return "";
+}
+
#undef ARM_CPU_NAME_LENGTH
diff --git a/gcc/common/config/avr/avr-common.c b/gcc/common/config/avr/avr-common.c
index eaaf211e41c..4bee9d670d9 100644
--- a/gcc/common/config/avr/avr-common.c
+++ b/gcc/common/config/avr/avr-common.c
@@ -31,6 +31,7 @@ static const struct default_options avr_option_optimization_table[] =
// The only effect of -fcaller-saves might be that it triggers
// a frame without need when it tries to be smart around calls.
{ OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_mgas_isr_prologues, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index d357d16c3dc..7e557a245b5 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -279,7 +279,7 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
return false;
/* New mode must be compatible with the previous compare mode. */
- enum machine_mode new_mode
+ machine_mode new_mode
= targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode);
if (new_mode == VOIDmode)
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 7c083622c1b..215784030e3 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -457,9 +457,10 @@ powerpc*-*-*spe*)
;;
powerpc*-*-*)
cpu_type=rs6000
- extra_objs="rs6000-string.o"
+ extra_objs="rs6000-string.o rs6000-p8swap.o"
extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h"
- extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h x86intrin.h"
+ extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h"
+ extra_headers="${extra_headers} mmintrin.h x86intrin.h"
extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h"
extra_headers="${extra_headers} paired.h"
case x$with_cpu in
@@ -475,7 +476,7 @@ riscv*)
;;
rs6000*-*-*)
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
- extra_objs="rs6000-string.o"
+ extra_objs="rs6000-string.o rs6000-p8swap.o"
;;
sparc*-*-*)
cpu_type=sparc
@@ -797,31 +798,10 @@ case ${target} in
gas=yes
gnu_ld=yes
use_gcc_stdint=wrap
-
- # NetBSD 2.0 and later get POSIX threads enabled by default.
- # Allow them to be explicitly enabled on any other version.
case ${enable_threads} in
- "")
- case ${target} in
- *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
- thread_file='posix'
- tm_defines="${tm_defines} NETBSD_ENABLE_PTHREADS"
- ;;
- esac
- ;;
- yes | posix)
- thread_file='posix'
- tm_defines="${tm_defines} NETBSD_ENABLE_PTHREADS"
- ;;
- esac
-
- # NetBSD 2.0 and later provide __cxa_atexit(), which we use by
- # default (unless overridden by --disable-__cxa_atexit).
- case ${target} in
- *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
- default_use_cxa_atexit=yes
- ;;
+ "" | yes | posix) thread_file='posix' ;;
esac
+ default_use_cxa_atexit=yes
;;
*-*-openbsd*)
tmake_file="t-openbsd"
@@ -929,6 +909,11 @@ case ${target} in
"" | yes | vxworks) thread_file='vxworks' ;;
*) echo 'Unknown thread configuration for VxWorks'; exit 1 ;;
esac
+ case $target in
+ *-*-vxworks7*)
+ tm_defines="$tm_defines TARGET_VXWORKS7=1"
+ ;;
+ esac
;;
*-*-elf|arc*-*-elf*)
# Assume that newlib is being used and so __cxa_atexit is provided.
@@ -1056,7 +1041,7 @@ arc*-*-elf*)
big*) tm_file="arc/big.h ${tm_file}"
esac
;;
-arc*-*-linux-uclibc*)
+arc*-*-linux*)
tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}"
tmake_file="${tmake_file} arc/t-arc"
extra_gcc_objs="driver-arc.o"
@@ -1684,8 +1669,15 @@ i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
esac
fi
;;
-i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
- tm_file="${tm_file} i386/unix.h i386/att.h elfos.h vx-common.h"
+i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae|i[4567]86-wrs-vxworks7|x86_64-wrs-vxworks7)
+ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h"
+ case ${target} in
+ x86_64-*)
+ need_64bit_isa=yes
+ tm_file="${tm_file} i386/x86-64.h"
+ ;;
+ esac
+ tm_file="${tm_file} vx-common.h"
case ${target} in
*-vxworksae*)
tm_file="${tm_file} vxworksae.h i386/vxworks.h i386/vxworksae.h"
@@ -2057,7 +2049,7 @@ riscv*-*-linux*)
# automatically detect that GAS supports it, yet we require it.
gcc_cv_initfini_array=yes
;;
-riscv*-*-elf*)
+riscv*-*-elf* | riscv*-*-rtems*)
tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
case "x${enable_multilib}" in
xno) ;;
@@ -2070,6 +2062,11 @@ riscv*-*-elf*)
# Force .init_array support. The configure script cannot always
# automatically detect that GAS supports it, yet we require it.
gcc_cv_initfini_array=yes
+ case ${target} in
+ riscv*-*-rtems*)
+ tm_file="${tm_file} rtems.h riscv/rtems.h"
+ ;;
+ esac
;;
mips*-*-netbsd*) # NetBSD/mips, either endian.
target_cpu_default="MASK_ABICALLS"
@@ -2441,7 +2438,7 @@ powerpc-*-rtems*spe*)
tmake_file="${tmake_file} powerpcspe/t-fprules powerpcspe/t-rtems powerpcspe/t-ppccomm"
;;
powerpc-*-rtems*)
- tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/rtems.h rtems.h"
+ tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"
extra_options="${extra_options} rs6000/sysv4.opt"
tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm"
;;
@@ -3109,6 +3106,16 @@ powerpc*-*-* | rs6000-*-*)
tm_file="${tm_file} ${cpu_type}/option-defaults.h"
esac
+# non-glibc systems
+case ${target} in
+*-linux-musl*)
+ tmake_file="${tmake_file} t-musl"
+ ;;
+*-linux-uclibc*)
+ tmake_file="${tmake_file} t-uclibc"
+ ;;
+esac
+
# Build mkoffload tool
case ${target} in
*-intelmic-* | *-intelmicemul-*)
@@ -4388,7 +4395,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 | arch3 | arch5 | arch6 | arch7 | arch8 | arch9 | arch10 | arch11 | arch12)
+ "" | native | g5 | g6 | z900 | z990 | z9-109 | z9-ec | z10 | z196 | zEC12 | z13 | z14 | arch3 | arch5 | arch6 | arch7 | arch8 | arch9 | arch10 | arch11 | arch12)
# OK
;;
*)
@@ -4440,7 +4447,7 @@ case "${target}" in
| sparclite | f930 | f934 | sparclite86x \
| sparclet | tsc701 \
| v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \
- | niagara3 | niagara4 | niagara7)
+ | niagara3 | niagara4 | niagara7 | m8)
# OK
;;
*)
diff --git a/gcc/config.in b/gcc/config.in
index bf2aa7b2e7d..89d7108e8db 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -284,6 +284,12 @@
#endif
+/* Define if your avr assembler supports -mgcc-isr option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_AVR_MGCCISR_OPTION
+#endif
+
+
/* Define if your avr assembler supports --mlink-relax option. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_AVR_MLINK_RELAX_OPTION
@@ -661,6 +667,12 @@
#endif
+/* Define if your assembler supports SPARC6 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC6
+#endif
+
+
/* Define if your assembler and linker support GOTDATA_OP relocs. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_SPARC_GOTDATA_OP
@@ -1460,6 +1472,13 @@
#endif
+/* Define if your default avr linker script for avrxmega3 leaves .rodata in
+ flash. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
+#endif
+
+
/* Define if your linker supports -z bndplt */
#ifndef USED_FOR_TARGET
#undef HAVE_LD_BNDPLT_SUPPORT
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index f09399f4c15..d30009ba441 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -530,7 +530,7 @@ aarch64_mangle_builtin_type (const_tree type)
}
static tree
-aarch64_simd_builtin_std_type (enum machine_mode mode,
+aarch64_simd_builtin_std_type (machine_mode mode,
enum aarch64_type_qualifiers q)
{
#define QUAL_TYPE(M) \
@@ -566,7 +566,7 @@ aarch64_simd_builtin_std_type (enum machine_mode mode,
}
static tree
-aarch64_lookup_simd_builtin_type (enum machine_mode mode,
+aarch64_lookup_simd_builtin_type (machine_mode mode,
enum aarch64_type_qualifiers q)
{
int i;
@@ -585,7 +585,7 @@ aarch64_lookup_simd_builtin_type (enum machine_mode mode,
}
static tree
-aarch64_simd_builtin_type (enum machine_mode mode,
+aarch64_simd_builtin_type (machine_mode mode,
bool unsigned_p, bool poly_p)
{
if (poly_p)
@@ -649,7 +649,7 @@ aarch64_init_simd_builtin_types (void)
for (i = 0; i < nelts; i++)
{
tree eltype = aarch64_simd_types[i].eltype;
- enum machine_mode mode = aarch64_simd_types[i].mode;
+ machine_mode mode = aarch64_simd_types[i].mode;
if (aarch64_simd_types[i].itype == NULL)
{
@@ -1015,7 +1015,7 @@ typedef enum
static rtx
aarch64_simd_expand_args (rtx target, int icode, int have_retval,
tree exp, builtin_simd_arg *args,
- enum machine_mode builtin_mode)
+ machine_mode builtin_mode)
{
rtx pat;
rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
@@ -1040,7 +1040,7 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval,
else
{
tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
- enum machine_mode mode = insn_data[icode].operand[opc].mode;
+ machine_mode mode = insn_data[icode].operand[opc].mode;
op[opc] = expand_normal (arg);
switch (thisarg)
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index f8342ca722d..b8d0ba6b69e 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -65,8 +65,8 @@ AARCH64_CORE("thunderxt83", thunderxt83, thunderx, 8A, AARCH64_FL_FOR_ARCH
AARCH64_CORE("xgene1", xgene1, xgene1, 8A, AARCH64_FL_FOR_ARCH8, xgene1, 0x50, 0x000, -1)
/* Qualcomm ('Q') cores. */
-AARCH64_CORE("falkor", falkor, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx, 0x51, 0xC00, -1)
-AARCH64_CORE("qdf24xx", qdf24xx, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx, 0x51, 0xC00, -1)
+AARCH64_CORE("falkor", falkor, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1)
+AARCH64_CORE("qdf24xx", qdf24xx, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1)
/* Samsung ('S') cores. */
AARCH64_CORE("exynos-m1", exynosm1, exynosm1, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1, 0x53, 0x001, -1)
diff --git a/gcc/config/aarch64/aarch64-fusion-pairs.def b/gcc/config/aarch64/aarch64-fusion-pairs.def
index f0e6dbcdd81..300cd00e4bf 100644
--- a/gcc/config/aarch64/aarch64-fusion-pairs.def
+++ b/gcc/config/aarch64/aarch64-fusion-pairs.def
@@ -34,5 +34,6 @@ AARCH64_FUSION_PAIR ("movk+movk", MOVK_MOVK)
AARCH64_FUSION_PAIR ("adrp+ldr", ADRP_LDR)
AARCH64_FUSION_PAIR ("cmp+branch", CMP_BRANCH)
AARCH64_FUSION_PAIR ("aes+aesmc", AES_AESMC)
+AARCH64_FUSION_PAIR ("alu+branch", ALU_BRANCH)
#undef AARCH64_FUSION_PAIR
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index c0752ce3470..c4f059ab7c5 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -63,4 +63,8 @@ AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, 0, "fphp asimdhp")
/* Enabling or disabling "rcpc" only changes "rcpc". */
AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, "lrcpc")
+/* Enabling "rdma" also enables "fp", "simd".
+ Disabling "rdma" just disables "rdma". */
+AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "rdma")
+
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index bfe44a75e12..beff28e2272 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -319,6 +319,7 @@ unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode);
int aarch64_branch_cost (bool, bool);
enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx);
+bool aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode);
bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
bool aarch64_constant_address_p (rtx);
bool aarch64_emit_approx_div (rtx, rtx, rtx);
@@ -326,6 +327,7 @@ bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
void aarch64_expand_call (rtx, rtx, bool);
bool aarch64_expand_movmem (rtx *);
bool aarch64_float_const_zero_rtx_p (rtx);
+bool aarch64_float_const_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
bool aarch64_fusion_enabled_p (enum aarch64_fusion_pairs);
bool aarch64_gen_movmemqi (rtx *);
@@ -342,8 +344,8 @@ bool aarch64_modes_tieable_p (machine_mode mode1,
bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
bool aarch64_mov_operand_p (rtx, machine_mode);
-int aarch64_simd_attr_length_rglist (enum machine_mode);
-rtx aarch64_reverse_mask (enum machine_mode);
+int aarch64_simd_attr_length_rglist (machine_mode);
+rtx aarch64_reverse_mask (machine_mode);
bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
@@ -351,9 +353,9 @@ bool aarch64_pad_arg_upward (machine_mode, const_tree);
bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
bool aarch64_regno_ok_for_base_p (int, bool);
bool aarch64_regno_ok_for_index_p (int, bool);
+bool aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *fail);
bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode,
bool high);
-bool aarch64_simd_imm_scalar_p (rtx x, machine_mode mode);
bool aarch64_simd_imm_zero_p (rtx, machine_mode);
bool aarch64_simd_scalar_immediate_valid_for_move (rtx, machine_mode);
bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
@@ -411,7 +413,7 @@ void aarch64_save_restore_target_globals (tree);
/* Initialize builtins for SIMD intrinsics. */
void init_aarch64_simd_builtins (void);
-void aarch64_simd_emit_reg_reg_move (rtx *, enum machine_mode, unsigned int);
+void aarch64_simd_emit_reg_reg_move (rtx *, machine_mode, unsigned int);
/* Expand builtins for SIMD intrinsics. */
rtx aarch64_simd_expand_builtin (int, tree, rtx);
@@ -444,7 +446,7 @@ bool aarch64_atomic_ldop_supported_p (enum rtx_code);
void aarch64_gen_atomic_ldop (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
void aarch64_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx);
-bool aarch64_gen_adjusted_ldpstp (rtx *, bool, enum machine_mode, RTX_CODE);
+bool aarch64_gen_adjusted_ldpstp (rtx *, bool, machine_mode, RTX_CODE);
#endif /* RTX_CODE */
void aarch64_init_builtins (void);
@@ -468,11 +470,11 @@ extern void aarch64_final_prescan_insn (rtx_insn *);
extern bool
aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *);
-int aarch64_ccmp_mode_to_code (enum machine_mode mode);
+int aarch64_ccmp_mode_to_code (machine_mode mode);
bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset);
-bool aarch64_operands_ok_for_ldpstp (rtx *, bool, enum machine_mode);
-bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, enum machine_mode);
+bool aarch64_operands_ok_for_ldpstp (rtx *, bool, machine_mode);
+bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, machine_mode);
extern void aarch64_asm_output_pool_epilogue (FILE *, const char *,
tree, HOST_WIDE_INT);
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 264a9c047ce..011fcec0795 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -1033,6 +1033,18 @@
[(set_attr "type" "neon_mla_<Vetype>_scalar<q>")]
)
+(define_insn "*aarch64_mla_elt_merge<mode>"
+ [(set (match_operand:VDQHS 0 "register_operand" "=w")
+ (plus:VDQHS
+ (mult:VDQHS (vec_duplicate:VDQHS
+ (match_operand:<VEL> 1 "register_operand" "w"))
+ (match_operand:VDQHS 2 "register_operand" "w"))
+ (match_operand:VDQHS 3 "register_operand" "0")))]
+ "TARGET_SIMD"
+ "mla\t%0.<Vtype>, %2.<Vtype>, %1.<Vetype>[0]"
+ [(set_attr "type" "neon_mla_<Vetype>_scalar<q>")]
+)
+
(define_insn "aarch64_mls<mode>"
[(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
(minus:VDQ_BHSI (match_operand:VDQ_BHSI 1 "register_operand" "0")
@@ -1080,6 +1092,18 @@
[(set_attr "type" "neon_mla_<Vetype>_scalar<q>")]
)
+(define_insn "*aarch64_mls_elt_merge<mode>"
+ [(set (match_operand:VDQHS 0 "register_operand" "=w")
+ (minus:VDQHS
+ (match_operand:VDQHS 1 "register_operand" "0")
+ (mult:VDQHS (vec_duplicate:VDQHS
+ (match_operand:<VEL> 2 "register_operand" "w"))
+ (match_operand:VDQHS 3 "register_operand" "w"))))]
+ "TARGET_SIMD"
+ "mls\t%0.<Vtype>, %3.<Vtype>, %2.<Vetype>[0]"
+ [(set_attr "type" "neon_mla_<Vetype>_scalar<q>")]
+)
+
;; Max/Min operations.
(define_insn "<su><maxmin><mode>3"
[(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
@@ -2809,38 +2833,10 @@
(match_operand:VDC 2 "register_operand")]
"TARGET_SIMD"
{
- rtx op1, op2;
- if (BYTES_BIG_ENDIAN)
- {
- op1 = operands[2];
- op2 = operands[1];
- }
- else
- {
- op1 = operands[1];
- op2 = operands[2];
- }
- emit_insn (gen_aarch64_combine_internal<mode> (operands[0], op1, op2));
- DONE;
-}
-)
+ aarch64_split_simd_combine (operands[0], operands[1], operands[2]);
-(define_insn_and_split "aarch64_combine_internal<mode>"
- [(set (match_operand:<VDBL> 0 "register_operand" "=&w")
- (vec_concat:<VDBL> (match_operand:VDC 1 "register_operand" "w")
- (match_operand:VDC 2 "register_operand" "w")))]
- "TARGET_SIMD"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- if (BYTES_BIG_ENDIAN)
- aarch64_split_simd_combine (operands[0], operands[2], operands[1]);
- else
- aarch64_split_simd_combine (operands[0], operands[1], operands[2]);
DONE;
}
-[(set_attr "type" "multiple")]
)
(define_expand "aarch64_simd_combine<mode>"
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 95592f9fa17..055ebafb830 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -147,6 +147,8 @@ static bool aarch64_builtin_support_vector_misalignment (machine_mode mode,
const_tree type,
int misalignment,
bool is_packed);
+static machine_mode
+aarch64_simd_container_mode (machine_mode mode, unsigned width);
/* Major revision number of the ARM Architecture implemented by the target. */
unsigned aarch64_architecture_version;
@@ -206,22 +208,6 @@ static const struct cpu_addrcost_table generic_addrcost_table =
0 /* imm_offset */
};
-static const struct cpu_addrcost_table cortexa57_addrcost_table =
-{
- {
- 1, /* hi */
- 0, /* si */
- 0, /* di */
- 1, /* ti */
- },
- 0, /* pre_modify */
- 0, /* post_modify */
- 0, /* register_offset */
- 0, /* register_sextend */
- 0, /* register_zextend */
- 0, /* imm_offset */
-};
-
static const struct cpu_addrcost_table exynosm1_addrcost_table =
{
{
@@ -254,22 +240,6 @@ static const struct cpu_addrcost_table xgene1_addrcost_table =
0, /* imm_offset */
};
-static const struct cpu_addrcost_table qdf24xx_addrcost_table =
-{
- {
- 1, /* hi */
- 0, /* si */
- 0, /* di */
- 1, /* ti */
- },
- 0, /* pre_modify */
- 0, /* post_modify */
- 0, /* register_offset */
- 0, /* register_sextend */
- 0, /* register_zextend */
- 0 /* imm_offset */
-};
-
static const struct cpu_addrcost_table thunderx2t99_addrcost_table =
{
{
@@ -390,13 +360,13 @@ static const struct cpu_vector_cost thunderx_vector_cost =
3, /* scalar_load_cost */
1, /* scalar_store_cost */
4, /* vec_int_stmt_cost */
- 4, /* vec_fp_stmt_cost */
+ 1, /* vec_fp_stmt_cost */
4, /* vec_permute_cost */
2, /* vec_to_scalar_cost */
2, /* scalar_to_vec_cost */
3, /* vec_align_load_cost */
- 10, /* vec_unalign_load_cost */
- 10, /* vec_unalign_store_cost */
+ 5, /* vec_unalign_load_cost */
+ 5, /* vec_unalign_store_cost */
1, /* vec_store_cost */
3, /* cond_taken_branch_cost */
3 /* cond_not_taken_branch_cost */
@@ -488,20 +458,6 @@ static const struct cpu_branch_cost generic_branch_cost =
3 /* Unpredictable. */
};
-/* Branch costs for Cortex-A57. */
-static const struct cpu_branch_cost cortexa57_branch_cost =
-{
- 1, /* Predictable. */
- 3 /* Unpredictable. */
-};
-
-/* Branch costs for Vulcan. */
-static const struct cpu_branch_cost thunderx2t99_branch_cost =
-{
- 1, /* Predictable. */
- 3 /* Unpredictable. */
-};
-
/* Generic approximation modes. */
static const cpu_approx_modes generic_approx_modes =
{
@@ -612,7 +568,7 @@ static const struct tune_params cortexa35_tunings =
&generic_addrcost_table,
&cortexa53_regmove_cost,
&generic_vector_cost,
- &cortexa57_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost */
1, /* issue_rate */
@@ -638,7 +594,7 @@ static const struct tune_params cortexa53_tunings =
&generic_addrcost_table,
&cortexa53_regmove_cost,
&generic_vector_cost,
- &cortexa57_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost */
2, /* issue_rate */
@@ -661,10 +617,10 @@ static const struct tune_params cortexa53_tunings =
static const struct tune_params cortexa57_tunings =
{
&cortexa57_extra_costs,
- &cortexa57_addrcost_table,
+ &generic_addrcost_table,
&cortexa57_regmove_cost,
&cortexa57_vector_cost,
- &cortexa57_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost */
3, /* issue_rate */
@@ -687,10 +643,10 @@ static const struct tune_params cortexa57_tunings =
static const struct tune_params cortexa72_tunings =
{
&cortexa57_extra_costs,
- &cortexa57_addrcost_table,
+ &generic_addrcost_table,
&cortexa57_regmove_cost,
&cortexa57_vector_cost,
- &cortexa57_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost */
3, /* issue_rate */
@@ -713,10 +669,10 @@ static const struct tune_params cortexa72_tunings =
static const struct tune_params cortexa73_tunings =
{
&cortexa57_extra_costs,
- &cortexa57_addrcost_table,
+ &generic_addrcost_table,
&cortexa57_regmove_cost,
&cortexa57_vector_cost,
- &cortexa57_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost. */
2, /* issue_rate. */
@@ -842,7 +798,7 @@ static const struct tune_params xgene1_tunings =
static const struct tune_params qdf24xx_tunings =
{
&qdf24xx_extra_costs,
- &qdf24xx_addrcost_table,
+ &generic_addrcost_table,
&qdf24xx_regmove_cost,
&generic_vector_cost,
&generic_branch_cost,
@@ -871,11 +827,12 @@ static const struct tune_params thunderx2t99_tunings =
&thunderx2t99_addrcost_table,
&thunderx2t99_regmove_cost,
&thunderx2t99_vector_cost,
- &thunderx2t99_branch_cost,
+ &generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost. */
4, /* issue_rate. */
- (AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_AES_AESMC), /* fusible_ops */
+ (AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_AES_AESMC
+ | AARCH64_FUSE_ALU_BRANCH), /* fusible_ops */
16, /* function_align. */
8, /* jump_align. */
16, /* loop_align. */
@@ -1031,7 +988,7 @@ static reg_class_t
aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
reg_class_t best_class)
{
- enum machine_mode mode;
+ machine_mode mode;
if (allocno_class != ALL_REGS)
return allocno_class;
@@ -1044,7 +1001,7 @@ aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
}
static unsigned int
-aarch64_min_divisions_for_recip_mul (enum machine_mode mode)
+aarch64_min_divisions_for_recip_mul (machine_mode mode)
{
if (GET_MODE_UNIT_SIZE (mode) == 4)
return aarch64_tune_params.min_div_recip_mul_sf;
@@ -1053,7 +1010,7 @@ aarch64_min_divisions_for_recip_mul (enum machine_mode mode)
static int
aarch64_reassociation_width (unsigned opc ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ machine_mode mode)
{
if (VECTOR_MODE_P (mode))
return aarch64_tune_params.vec_reassoc_width;
@@ -1732,41 +1689,41 @@ aarch64_split_simd_combine (rtx dst, rtx src1, rtx src2)
machine_mode dst_mode = GET_MODE (dst);
gcc_assert (VECTOR_MODE_P (dst_mode));
+ gcc_assert (register_operand (dst, dst_mode)
+ && register_operand (src1, src_mode)
+ && register_operand (src2, src_mode));
- if (REG_P (dst) && REG_P (src1) && REG_P (src2))
- {
- rtx (*gen) (rtx, rtx, rtx);
-
- switch (src_mode)
- {
- case V8QImode:
- gen = gen_aarch64_simd_combinev8qi;
- break;
- case V4HImode:
- gen = gen_aarch64_simd_combinev4hi;
- break;
- case V2SImode:
- gen = gen_aarch64_simd_combinev2si;
- break;
- case V4HFmode:
- gen = gen_aarch64_simd_combinev4hf;
- break;
- case V2SFmode:
- gen = gen_aarch64_simd_combinev2sf;
- break;
- case DImode:
- gen = gen_aarch64_simd_combinedi;
- break;
- case DFmode:
- gen = gen_aarch64_simd_combinedf;
- break;
- default:
- gcc_unreachable ();
- }
+ rtx (*gen) (rtx, rtx, rtx);
- emit_insn (gen (dst, src1, src2));
- return;
+ switch (src_mode)
+ {
+ case V8QImode:
+ gen = gen_aarch64_simd_combinev8qi;
+ break;
+ case V4HImode:
+ gen = gen_aarch64_simd_combinev4hi;
+ break;
+ case V2SImode:
+ gen = gen_aarch64_simd_combinev2si;
+ break;
+ case V4HFmode:
+ gen = gen_aarch64_simd_combinev4hf;
+ break;
+ case V2SFmode:
+ gen = gen_aarch64_simd_combinev2sf;
+ break;
+ case DImode:
+ gen = gen_aarch64_simd_combinedi;
+ break;
+ case DFmode:
+ gen = gen_aarch64_simd_combinedf;
+ break;
+ default:
+ gcc_unreachable ();
}
+
+ emit_insn (gen (dst, src1, src2));
+ return;
}
/* Split a complex SIMD move. */
@@ -1875,6 +1832,31 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
return 1;
}
+ /* Check to see if the low 32 bits are either 0xffffXXXX or 0xXXXXffff
+ (with XXXX non-zero). In that case check to see if the move can be done in
+ a smaller mode. */
+ val2 = val & 0xffffffff;
+ if (mode == DImode
+ && aarch64_move_imm (val2, SImode)
+ && (((val >> 32) & 0xffff) == 0 || (val >> 48) == 0))
+ {
+ if (generate)
+ emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+
+ /* Check if we have to emit a second instruction by checking to see
+ if any of the upper 32 bits of the original DI mode value is set. */
+ if (val == val2)
+ return 1;
+
+ i = (val >> 48) ? 48 : 32;
+
+ if (generate)
+ emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+ GEN_INT ((val >> i) & 0xffff)));
+
+ return 2;
+ }
+
if ((val >> 32) == 0 || mode == SImode)
{
if (generate)
@@ -2002,6 +1984,8 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
gcc_assert (can_create_pseudo_p ());
base = gen_reg_rtx (ptr_mode);
aarch64_expand_mov_immediate (base, XEXP (mem, 0));
+ if (ptr_mode != Pmode)
+ base = convert_memory_address (Pmode, base);
mem = gen_rtx_MEM (ptr_mode, base);
}
@@ -4720,6 +4704,69 @@ aarch64_legitimize_address_displacement (rtx *disp, rtx *off, machine_mode mode)
return true;
}
+/* Return the binary representation of floating point constant VALUE in INTVAL.
+ If the value cannot be converted, return false without setting INTVAL.
+ The conversion is done in the given MODE. */
+bool
+aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
+{
+
+ /* We make a general exception for 0. */
+ if (aarch64_float_const_zero_rtx_p (value))
+ {
+ *intval = 0;
+ return true;
+ }
+
+ machine_mode mode = GET_MODE (value);
+ if (GET_CODE (value) != CONST_DOUBLE
+ || !SCALAR_FLOAT_MODE_P (mode)
+ || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
+ /* Only support up to DF mode. */
+ || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (DFmode))
+ return false;
+
+ unsigned HOST_WIDE_INT ival = 0;
+
+ long res[2];
+ real_to_target (res,
+ CONST_DOUBLE_REAL_VALUE (value),
+ REAL_MODE_FORMAT (mode));
+
+ ival = zext_hwi (res[0], 32);
+ if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (DFmode))
+ ival |= (zext_hwi (res[1], 32) << 32);
+
+ *intval = ival;
+ return true;
+}
+
+/* Return TRUE if rtx X is an immediate constant that can be moved using a
+ single MOV(+MOVK) followed by an FMOV. */
+bool
+aarch64_float_const_rtx_p (rtx x)
+{
+ machine_mode mode = GET_MODE (x);
+ if (mode == VOIDmode)
+ return false;
+
+ /* Determine whether it's cheaper to write float constants as
+ mov/movk pairs over ldr/adrp pairs. */
+ unsigned HOST_WIDE_INT ival;
+
+ if (GET_CODE (x) == CONST_DOUBLE
+ && SCALAR_FLOAT_MODE_P (mode)
+ && aarch64_reinterpret_float_as_int (x, &ival))
+ {
+ machine_mode imode = mode == HFmode ? SImode : int_mode_for_mode (mode);
+ int num_instr = aarch64_internal_mov_immediate
+ (NULL_RTX, gen_int_mode (ival, imode), false, imode);
+ return num_instr < 3;
+ }
+
+ return false;
+}
+
/* Return TRUE if rtx X is immediate constant 0.0 */
bool
aarch64_float_const_zero_rtx_p (rtx x)
@@ -4732,6 +4779,49 @@ aarch64_float_const_zero_rtx_p (rtx x)
return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0);
}
+/* Return TRUE if rtx X is immediate constant that fits in a single
+ MOVI immediate operation. */
+bool
+aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
+{
+ if (!TARGET_SIMD)
+ return false;
+
+ /* We make a general exception for 0. */
+ if (aarch64_float_const_zero_rtx_p (x))
+ return true;
+
+ machine_mode vmode, imode;
+ unsigned HOST_WIDE_INT ival;
+
+ if (GET_CODE (x) == CONST_DOUBLE
+ && SCALAR_FLOAT_MODE_P (mode))
+ {
+ if (!aarch64_reinterpret_float_as_int (x, &ival))
+ return false;
+
+ imode = int_mode_for_mode (mode);
+ }
+ else if (GET_CODE (x) == CONST_INT
+ && SCALAR_INT_MODE_P (mode))
+ {
+ imode = mode;
+ ival = INTVAL (x);
+ }
+ else
+ return false;
+
+ /* use a 64 bit mode for everything except for DI/DF mode, where we use
+ a 128 bit vector mode. */
+ int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
+
+ vmode = aarch64_simd_container_mode (imode, width);
+ rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, ival);
+
+ return aarch64_simd_valid_immediate (v_op, vmode, false, NULL);
+}
+
+
/* Return the fixed registers used for condition codes. */
static bool
@@ -4884,7 +4974,7 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
}
static int
-aarch64_get_condition_code_1 (enum machine_mode, enum rtx_code);
+aarch64_get_condition_code_1 (machine_mode, enum rtx_code);
int
aarch64_get_condition_code (rtx x)
@@ -4898,7 +4988,7 @@ aarch64_get_condition_code (rtx x)
}
static int
-aarch64_get_condition_code_1 (enum machine_mode mode, enum rtx_code comp_code)
+aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code)
{
switch (mode)
{
@@ -5050,12 +5140,43 @@ static const int aarch64_nzcv_codes[] =
0 /* NV, Any. */
};
+/* Print operand X to file F in a target specific manner according to CODE.
+ The acceptable formatting commands given by CODE are:
+ 'c': An integer or symbol address without a preceding #
+ sign.
+ 'e': Print the sign/zero-extend size as a character 8->b,
+ 16->h, 32->w.
+ 'p': Prints N such that 2^N == X (X must be power of 2 and
+ const int).
+ 'P': Print the number of non-zero bits in X (a const_int).
+ 'H': Print the higher numbered register of a pair (TImode)
+ of regs.
+ 'm': Print a condition (eq, ne, etc).
+ 'M': Same as 'm', but invert condition.
+ 'b/h/s/d/q': Print a scalar FP/SIMD register name.
+ 'S/T/U/V': Print a FP/SIMD register name for a register list.
+ The register printed is the FP/SIMD register name
+ of X + 0/1/2/3 for S/T/U/V.
+ 'R': Print a scalar FP/SIMD register name + 1.
+ 'X': Print bottom 16 bits of integer constant in hex.
+ 'w/x': Print a general register name or the zero register
+ (32-bit or 64-bit).
+ '0': Print a normal operand, if it's a general register,
+ then we assume DImode.
+ 'k': Print NZCV for conditional compare instructions.
+ 'A': Output address constant representing the first
+ argument of X, specifying a relocation offset
+ if appropriate.
+ 'L': Output constant address specified by X
+ with a relocation offset if appropriate.
+ 'G': Prints address of X, specifying a PC relative
+ relocation mode if appropriate. */
+
static void
aarch64_print_operand (FILE *f, rtx x, int code)
{
switch (code)
{
- /* An integer or symbol address without a preceding # sign. */
case 'c':
switch (GET_CODE (x))
{
@@ -5082,7 +5203,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'e':
- /* Print the sign/zero-extend size as a character 8->b, 16->h, 32->w. */
{
int n;
@@ -5115,7 +5235,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
{
int n;
- /* Print N such that 2^N == X. */
if (!CONST_INT_P (x) || (n = exact_log2 (INTVAL (x))) < 0)
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -5127,7 +5246,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'P':
- /* Print the number of non-zero bits in X (a const_int). */
if (!CONST_INT_P (x))
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -5138,7 +5256,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'H':
- /* Print the higher numbered register of a pair (TImode) of regs. */
if (!REG_P (x) || !GP_REGNUM_P (REGNO (x) + 1))
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -5152,8 +5269,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case 'm':
{
int cond_code;
- /* Print a condition (eq, ne, etc) or its inverse. */
-
/* CONST_TRUE_RTX means al/nv (al is the default, don't print it). */
if (x == const_true_rtx)
{
@@ -5181,7 +5296,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case 's':
case 'd':
case 'q':
- /* Print a scalar FP/SIMD register name. */
if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
{
output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code);
@@ -5194,7 +5308,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case 'T':
case 'U':
case 'V':
- /* Print the first FP/SIMD register name in a list. */
if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
{
output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code);
@@ -5204,7 +5317,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'R':
- /* Print a scalar FP/SIMD register name + 1. */
if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
{
output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code);
@@ -5214,7 +5326,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'X':
- /* Print bottom 16 bits of integer constant in hex. */
if (!CONST_INT_P (x))
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -5225,8 +5336,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case 'w':
case 'x':
- /* Print a general register name or the zero register (32-bit or
- 64-bit). */
if (x == const0_rtx
|| (CONST_DOUBLE_P (x) && aarch64_float_const_zero_rtx_p (x)))
{
@@ -5249,8 +5358,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
/* Fall through */
case 0:
- /* Print a normal operand, if it's a general register, then we
- assume DImode. */
if (x == NULL)
{
output_operand_lossage ("missing operand");
@@ -5265,6 +5372,8 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case MEM:
output_address (GET_MODE (x), XEXP (x, 0));
+ /* Check all memory references are Pmode - even with ILP32. */
+ gcc_assert (GET_MODE (XEXP (x, 0)) == Pmode);
break;
case CONST:
@@ -5401,7 +5510,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'G':
-
switch (aarch64_classify_symbolic_expression (x))
{
case SYMBOL_TLSLE24:
@@ -5416,7 +5524,6 @@ aarch64_print_operand (FILE *f, rtx x, int code)
case 'k':
{
HOST_WIDE_INT cond_code;
- /* Print nzcv. */
if (!CONST_INT_P (x))
{
@@ -5909,12 +6016,6 @@ aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
return NO_REGS;
}
- /* If it's an integer immediate that MOVI can't handle, then
- FP_REGS is not an option, so we return NO_REGS instead. */
- if (CONST_INT_P (x) && reg_class_subset_p (regclass, FP_REGS)
- && !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
- return NO_REGS;
-
/* Register eliminiation can result in a request for
SP+constant->FP_REGS. We cannot support such operations which
use SP as source and an FP_REG as destination, so reject out
@@ -6864,6 +6965,25 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
return true;
case CONST_DOUBLE:
+
+ /* First determine number of instructions to do the move
+ as an integer constant. */
+ if (!aarch64_float_const_representable_p (x)
+ && !aarch64_can_const_movi_rtx_p (x, mode)
+ && aarch64_float_const_rtx_p (x))
+ {
+ unsigned HOST_WIDE_INT ival;
+ bool succeed = aarch64_reinterpret_float_as_int (x, &ival);
+ gcc_assert (succeed);
+
+ machine_mode imode = mode == HFmode ? SImode
+ : int_mode_for_mode (mode);
+ int ncost = aarch64_internal_mov_immediate
+ (NULL_RTX, gen_int_mode (ival, imode), false, imode);
+ *cost += COSTS_N_INSNS (ncost);
+ return true;
+ }
+
if (speed)
{
/* mov[df,sf]_aarch64. */
@@ -7537,17 +7657,26 @@ cost_plus:
}
else
{
- if (speed)
+ if (VECTOR_MODE_P (mode))
{
- if (VECTOR_MODE_P (mode))
- {
- /* Vector shift (register). */
- *cost += extra_cost->vect.alu;
- }
- else
+ if (speed)
+ /* Vector shift (register). */
+ *cost += extra_cost->vect.alu;
+ }
+ else
+ {
+ if (speed)
+ /* LSLV. */
+ *cost += extra_cost->alu.shift_reg;
+
+ if (GET_CODE (op1) == AND && REG_P (XEXP (op1, 0))
+ && CONST_INT_P (XEXP (op1, 1))
+ && INTVAL (XEXP (op1, 1)) == GET_MODE_BITSIZE (mode) - 1)
{
- /* LSLV. */
- *cost += extra_cost->alu.shift_reg;
+ *cost += rtx_cost (op0, mode, (rtx_code) code, 0, speed);
+ /* We already demanded XEXP (op1, 0) to be REG_P, so
+ don't recurse into it. */
+ return true;
}
}
return false; /* All arguments need to be in registers. */
@@ -7576,14 +7705,27 @@ cost_plus:
}
else
{
-
- /* ASR (register) and friends. */
- if (speed)
+ if (VECTOR_MODE_P (mode))
{
- if (VECTOR_MODE_P (mode))
+ if (speed)
+ /* Vector shift (register). */
*cost += extra_cost->vect.alu;
- else
+ }
+ else
+ {
+ if (speed)
+ /* ASR (register) and friends. */
*cost += extra_cost->alu.shift_reg;
+
+ if (GET_CODE (op1) == AND && REG_P (XEXP (op1, 0))
+ && CONST_INT_P (XEXP (op1, 1))
+ && INTVAL (XEXP (op1, 1)) == GET_MODE_BITSIZE (mode) - 1)
+ {
+ *cost += rtx_cost (op0, mode, (rtx_code) code, 0, speed);
+ /* We already demanded XEXP (op1, 0) to be REG_P, so
+ don't recurse into it. */
+ return true;
+ }
}
return false; /* All arguments need to be in registers. */
}
@@ -10151,7 +10293,7 @@ aarch64_classify_symbol (rtx x, rtx offset)
/* This is alright even in PIC code as the constant
pool reference is always PC relative and within
the same translation unit. */
- if (CONSTANT_POOL_ADDRESS_P (x))
+ if (!aarch64_pcrelative_literal_loads && CONSTANT_POOL_ADDRESS_P (x))
return SYMBOL_SMALL_ABSOLUTE;
else
return SYMBOL_FORCE_TO_MEM;
@@ -10186,18 +10328,16 @@ aarch64_legitimate_pic_operand_p (rtx x)
/* Return true if X holds either a quarter-precision or
floating-point +0.0 constant. */
static bool
-aarch64_valid_floating_const (machine_mode mode, rtx x)
+aarch64_valid_floating_const (rtx x)
{
if (!CONST_DOUBLE_P (x))
return false;
- if (aarch64_float_const_zero_rtx_p (x))
+ /* This call determines which constants can be used in mov<mode>
+ as integer moves instead of constant loads. */
+ if (aarch64_float_const_rtx_p (x))
return true;
- /* We only handle moving 0.0 to a TFmode register. */
- if (!(mode == SFmode || mode == DFmode))
- return false;
-
return aarch64_float_const_representable_p (x);
}
@@ -10209,11 +10349,15 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
if (TARGET_SIMD && aarch64_vect_struct_mode_p (mode))
return false;
- /* This could probably go away because
- we now decompose CONST_INTs according to expand_mov_immediate. */
+ /* For these cases we never want to use a literal load.
+ As such we have to prevent the compiler from forcing these
+ to memory. */
if ((GET_CODE (x) == CONST_VECTOR
&& aarch64_simd_valid_immediate (x, mode, false, NULL))
- || CONST_INT_P (x) || aarch64_valid_floating_const (mode, x))
+ || CONST_INT_P (x)
+ || aarch64_valid_floating_const (x)
+ || aarch64_can_const_movi_rtx_p (x, mode)
+ || aarch64_float_const_rtx_p (x))
return !targetm.cannot_force_const_mem (mode, x);
if (GET_CODE (x) == HIGH
@@ -11496,23 +11640,6 @@ aarch64_mask_from_zextract_ops (rtx width, rtx pos)
}
bool
-aarch64_simd_imm_scalar_p (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT imm = INTVAL (x);
- int i;
-
- for (i = 0; i < 8; i++)
- {
- unsigned int byte = imm & 0xff;
- if (byte != 0xff && byte != 0)
- return false;
- imm >>= 8;
- }
-
- return true;
-}
-
-bool
aarch64_mov_operand_p (rtx x, machine_mode mode)
{
if (GET_CODE (x) == HIGH
@@ -11666,7 +11793,7 @@ aarch64_simd_mem_operand_p (rtx op)
COUNT is the number of components into which the copy needs to be
decomposed. */
void
-aarch64_simd_emit_reg_reg_move (rtx *operands, enum machine_mode mode,
+aarch64_simd_emit_reg_reg_move (rtx *operands, machine_mode mode,
unsigned int count)
{
unsigned int i;
@@ -11687,7 +11814,7 @@ aarch64_simd_emit_reg_reg_move (rtx *operands, enum machine_mode mode,
/* Compute and return the length of aarch64_simd_reglist<mode>, where <mode> is
one of VSTRUCT modes: OI, CI, or XI. */
int
-aarch64_simd_attr_length_rglist (enum machine_mode mode)
+aarch64_simd_attr_length_rglist (machine_mode mode)
{
return (GET_MODE_SIZE (mode) / UNITS_PER_VREG) * 4;
}
@@ -12119,10 +12246,8 @@ aarch64_emit_store_exclusive (machine_mode mode, rtx bval,
static void
aarch64_emit_unlikely_jump (rtx insn)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
-
rtx_insn *jump = emit_jump_insn (insn);
- add_int_reg_note (jump, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (jump, profile_probability::very_unlikely ());
}
/* Expand a compare and swap pattern. */
@@ -12905,15 +13030,28 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
}
char*
-aarch64_output_scalar_simd_mov_immediate (rtx immediate,
- machine_mode mode)
+aarch64_output_scalar_simd_mov_immediate (rtx immediate, machine_mode mode)
{
+
+ /* If a floating point number was passed and we desire to use it in an
+ integer mode do the conversion to integer. */
+ if (CONST_DOUBLE_P (immediate) && GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ unsigned HOST_WIDE_INT ival;
+ if (!aarch64_reinterpret_float_as_int (immediate, &ival))
+ gcc_unreachable ();
+ immediate = gen_int_mode (ival, mode);
+ }
+
machine_mode vmode;
+ /* use a 64 bit mode for everything except for DI/DF mode, where we use
+ a 128 bit vector mode. */
+ int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
gcc_assert (!VECTOR_MODE_P (mode));
- vmode = aarch64_simd_container_mode (mode, 64);
+ vmode = aarch64_simd_container_mode (mode, width);
rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate));
- return aarch64_output_simd_mov_immediate (v_op, vmode, 64);
+ return aarch64_output_simd_mov_immediate (v_op, vmode, width);
}
/* Split operands into moves from op[1] + op[2] into op[0]. */
@@ -13678,7 +13816,7 @@ aarch64_vectorize_vec_perm_const_ok (machine_mode vmode,
}
rtx
-aarch64_reverse_mask (enum machine_mode mode)
+aarch64_reverse_mask (machine_mode mode)
{
/* We have to reverse each vector because we dont have
a permuted load that can reverse-load according to ABI rules. */
@@ -14278,13 +14416,68 @@ aarch_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
{
enum attr_type prev_type = get_attr_type (prev);
- /* FIXME: this misses some which is considered simple arthematic
- instructions for ThunderX. Simple shifts are missed here. */
- if (prev_type == TYPE_ALUS_SREG
- || prev_type == TYPE_ALUS_IMM
- || prev_type == TYPE_LOGICS_REG
- || prev_type == TYPE_LOGICS_IMM)
- return true;
+ unsigned int condreg1, condreg2;
+ rtx cc_reg_1;
+ aarch64_fixed_condition_code_regs (&condreg1, &condreg2);
+ cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
+
+ if (reg_referenced_p (cc_reg_1, PATTERN (curr))
+ && prev
+ && modified_in_p (cc_reg_1, prev))
+ {
+ /* FIXME: this misses some which is considered simple arthematic
+ instructions for ThunderX. Simple shifts are missed here. */
+ if (prev_type == TYPE_ALUS_SREG
+ || prev_type == TYPE_ALUS_IMM
+ || prev_type == TYPE_LOGICS_REG
+ || prev_type == TYPE_LOGICS_IMM)
+ return true;
+ }
+ }
+
+ if (prev_set
+ && curr_set
+ && aarch64_fusion_enabled_p (AARCH64_FUSE_ALU_BRANCH)
+ && any_condjump_p (curr))
+ {
+ /* We're trying to match:
+ prev (alu_insn) == (set (r0) plus ((r0) (r1/imm)))
+ curr (cbz) == (set (pc) (if_then_else (eq/ne) (r0)
+ (const_int 0))
+ (label_ref ("SYM"))
+ (pc)) */
+ if (SET_DEST (curr_set) == (pc_rtx)
+ && GET_CODE (SET_SRC (curr_set)) == IF_THEN_ELSE
+ && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
+ && REG_P (SET_DEST (prev_set))
+ && REGNO (SET_DEST (prev_set))
+ == REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)))
+ {
+ /* Fuse ALU operations followed by conditional branch instruction. */
+ switch (get_attr_type (prev))
+ {
+ case TYPE_ALU_IMM:
+ case TYPE_ALU_SREG:
+ case TYPE_ADC_REG:
+ case TYPE_ADC_IMM:
+ case TYPE_ADCS_REG:
+ case TYPE_ADCS_IMM:
+ case TYPE_LOGIC_REG:
+ case TYPE_LOGIC_IMM:
+ case TYPE_CSEL:
+ case TYPE_ADR:
+ case TYPE_MOV_IMM:
+ case TYPE_SHIFT_REG:
+ case TYPE_SHIFT_IMM:
+ case TYPE_BFM:
+ case TYPE_RBIT:
+ case TYPE_REV:
+ case TYPE_EXTEND:
+ return true;
+
+ default:;
+ }
+ }
}
return false;
@@ -14468,7 +14661,7 @@ aarch64_sched_adjust_priority (rtx_insn *insn, int priority)
bool
aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
- enum machine_mode mode)
+ machine_mode mode)
{
HOST_WIDE_INT offval_1, offval_2, msize;
enum reg_class rclass_1, rclass_2;
@@ -14575,7 +14768,7 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
bool
aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
- enum machine_mode mode)
+ machine_mode mode)
{
enum reg_class rclass_1, rclass_2, rclass_3, rclass_4;
HOST_WIDE_INT offval_1, offval_2, offval_3, offval_4, msize;
@@ -14709,7 +14902,7 @@ aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
bool
aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
- enum machine_mode mode, RTX_CODE code)
+ machine_mode mode, RTX_CODE code)
{
rtx base, offset, t1, t2;
rtx mem_1, mem_2, mem_3, mem_4;
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 3b3f27e2f95..7f91edb5713 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -98,14 +98,24 @@
&& (ALIGN) < BITS_PER_WORD) \
? BITS_PER_WORD : ALIGN)
-#define DATA_ALIGNMENT(EXP, ALIGN) \
- ((((ALIGN) < BITS_PER_WORD) \
- && (TREE_CODE (EXP) == ARRAY_TYPE \
- || TREE_CODE (EXP) == UNION_TYPE \
- || TREE_CODE (EXP) == RECORD_TYPE)) \
- ? BITS_PER_WORD : (ALIGN))
-
-#define LOCAL_ALIGNMENT(EXP, ALIGN) DATA_ALIGNMENT(EXP, ALIGN)
+/* 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 AARCH64_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) \
+ AARCH64_EXPAND_ALIGNMENT (!optimize_size, EXP, ALIGN)
+
+/* Similarly, make sure that objects on the stack are sensibly aligned. */
+#define LOCAL_ALIGNMENT(EXP, ALIGN) \
+ AARCH64_EXPAND_ALIGNMENT (!flag_conserve_stack, EXP, ALIGN)
#define STRUCTURE_SIZE_BOUNDARY 8
@@ -134,7 +144,8 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_FL_CRC (1 << 3) /* Has CRC. */
/* ARMv8.1-A architecture extensions. */
#define AARCH64_FL_LSE (1 << 4) /* Has Large System Extensions. */
-#define AARCH64_FL_V8_1 (1 << 5) /* Has ARMv8.1-A extensions. */
+#define AARCH64_FL_RDMA (1 << 5) /* Has Round Double Multiply Add. */
+#define AARCH64_FL_V8_1 (1 << 6) /* Has ARMv8.1-A extensions. */
/* ARMv8.2-A architecture extensions. */
#define AARCH64_FL_V8_2 (1 << 8) /* Has ARMv8.2-A features. */
#define AARCH64_FL_F16 (1 << 9) /* Has ARMv8.2-A FP16 extensions. */
@@ -151,7 +162,8 @@ extern unsigned aarch64_architecture_version;
/* Architecture flags that effect instruction selection. */
#define AARCH64_FL_FOR_ARCH8 (AARCH64_FL_FPSIMD)
#define AARCH64_FL_FOR_ARCH8_1 \
- (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC | AARCH64_FL_V8_1)
+ (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC \
+ | AARCH64_FL_RDMA | AARCH64_FL_V8_1)
#define AARCH64_FL_FOR_ARCH8_2 \
(AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
#define AARCH64_FL_FOR_ARCH8_3 \
@@ -164,7 +176,7 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_ISA_FP (aarch64_isa_flags & AARCH64_FL_FP)
#define AARCH64_ISA_SIMD (aarch64_isa_flags & AARCH64_FL_SIMD)
#define AARCH64_ISA_LSE (aarch64_isa_flags & AARCH64_FL_LSE)
-#define AARCH64_ISA_RDMA (aarch64_isa_flags & AARCH64_FL_V8_1)
+#define AARCH64_ISA_RDMA (aarch64_isa_flags & AARCH64_FL_RDMA)
#define AARCH64_ISA_V8_2 (aarch64_isa_flags & AARCH64_FL_V8_2)
#define AARCH64_ISA_F16 (aarch64_isa_flags & AARCH64_FL_F16)
#define AARCH64_ISA_V8_3 (aarch64_isa_flags & AARCH64_FL_V8_3)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 6bdbf650d92..fc799479c81 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -181,6 +181,11 @@
;; will be disabled when !TARGET_FLOAT.
(define_attr "fp" "no,yes" (const_string "no"))
+;; 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"))
+
;; 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.
@@ -194,11 +199,14 @@
;; 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))))
- (const_string "no")
+ (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))))
+ (const_string "no")
] (const_string "yes")))
;; Attribute that specifies whether we are dealing with a branch to a
@@ -920,8 +928,8 @@
)
(define_insn_and_split "*movsi_aarch64"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w,r,*w")
- (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r ,*w, r,*w,w")
+ (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Ds"))]
"(register_operand (operands[0], SImode)
|| aarch64_reg_or_zero (operands[1], SImode))"
"@
@@ -938,8 +946,9 @@
adrp\\t%x0, %A1
fmov\\t%s0, %w1
fmov\\t%w0, %s1
- fmov\\t%s0, %s1"
- "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+ fmov\\t%s0, %s1
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
+ "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
&& REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
[(const_int 0)]
"{
@@ -947,13 +956,14 @@
DONE;
}"
[(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
- adr,adr,f_mcr,f_mrc,fmov")
- (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes")]
+ adr,adr,f_mcr,f_mrc,fmov,neon_move")
+ (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
+ (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
)
(define_insn_and_split "*movdi_aarch64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,*w,m, m,r,r, *w,r,*w,w")
- (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r,*w,m, m,r,r, *w,r,*w,w")
+ (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,m, m,rZ,*w,Usa,Ush,rZ,w,*w,Dd"))]
"(register_operand (operands[0], DImode)
|| aarch64_reg_or_zero (operands[1], DImode))"
"@
@@ -961,6 +971,7 @@
mov\\t%0, %x1
mov\\t%x0, %1
mov\\t%x0, %1
+ mov\\t%w0, %1
#
ldr\\t%x0, %1
ldr\\t%d0, %1
@@ -971,7 +982,7 @@
fmov\\t%d0, %x1
fmov\\t%x0, %d1
fmov\\t%d0, %d1
- movi\\t%d0, %1"
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
"(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
&& REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
[(const_int 0)]
@@ -979,10 +990,10 @@
aarch64_expand_mov_immediate (operands[0], operands[1]);
DONE;
}"
- [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,load1,load1,store1,store1,\
- adr,adr,f_mcr,f_mrc,fmov,neon_move")
- (set_attr "fp" "*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
- (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
+ [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load1,\
+ load1,store1,store1,adr,adr,f_mcr,f_mrc,fmov,neon_move")
+ (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
+ (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")]
)
(define_insn "insv_imm<mode>"
@@ -1062,65 +1073,94 @@
)
(define_insn "*movhf_aarch64"
- [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w,m,r,m ,r")
- (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,m,w,m,rY,r"))]
+ [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r")
+ (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
"TARGET_FLOAT && (register_operand (operands[0], HFmode)
- || aarch64_reg_or_fp_zero (operands[1], HFmode))"
+ || aarch64_reg_or_fp_float (operands[1], HFmode))"
"@
movi\\t%0.4h, #0
- mov\\t%0.h[0], %w1
+ fmov\\t%h0, %w1
umov\\t%w0, %1.h[0]
mov\\t%0.h[0], %1.h[0]
+ fmov\\t%h0, %1
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
ldr\\t%h0, %1
str\\t%h1, %0
ldrh\\t%w0, %1
strh\\t%w1, %0
mov\\t%w0, %w1"
- [(set_attr "type" "neon_move,neon_from_gp,neon_to_gp,neon_move,\
- f_loads,f_stores,load1,store1,mov_reg")
- (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
+ [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
+ neon_move,f_loads,f_stores,load1,store1,mov_reg")
+ (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
+ (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")]
)
(define_insn "*movsf_aarch64"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
- (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
+ (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
"TARGET_FLOAT && (register_operand (operands[0], SFmode)
- || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+ || aarch64_reg_or_fp_float (operands[1], SFmode))"
"@
movi\\t%0.2s, #0
fmov\\t%s0, %w1
fmov\\t%w0, %s1
fmov\\t%s0, %s1
fmov\\t%s0, %1
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
ldr\\t%s0, %1
str\\t%s1, %0
ldr\\t%w0, %1
str\\t%w1, %0
- mov\\t%w0, %w1"
- [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,\
- f_loads,f_stores,load1,store1,mov_reg")
- (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
+ mov\\t%w0, %w1
+ mov\\t%w0, %1"
+ [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
+ f_loads,f_stores,load1,store1,mov_reg,\
+ fconsts")
+ (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
)
(define_insn "*movdf_aarch64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
- (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
+ (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
"TARGET_FLOAT && (register_operand (operands[0], DFmode)
- || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+ || aarch64_reg_or_fp_float (operands[1], DFmode))"
"@
movi\\t%d0, #0
fmov\\t%d0, %x1
fmov\\t%x0, %d1
fmov\\t%d0, %d1
fmov\\t%d0, %1
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
ldr\\t%d0, %1
str\\t%d1, %0
ldr\\t%x0, %1
str\\t%x1, %0
- mov\\t%x0, %x1"
- [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,\
- f_loadd,f_stored,load1,store1,mov_reg")
- (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
+ mov\\t%x0, %x1
+ mov\\t%x0, %1"
+ [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
+ f_loadd,f_stored,load1,store1,mov_reg,\
+ fconstd")
+ (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
+)
+
+(define_split
+ [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
+ (match_operand:GPF_HF 1 "general_operand"))]
+ "can_create_pseudo_p ()
+ && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
+ && !aarch64_float_const_representable_p (operands[1])
+ && aarch64_float_const_rtx_p (operands[1])"
+ [(const_int 0)]
+ {
+ unsigned HOST_WIDE_INT ival;
+ if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
+ FAIL;
+
+ rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
+ emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
+ emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
+ DONE;
+ }
)
(define_insn "*movtf_aarch64"
@@ -1905,6 +1945,17 @@
[(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
)
+(define_insn "aarch64_sub<mode>_compare0"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (minus:GPI (match_operand:GPI 0 "register_operand" "r")
+ (match_operand:GPI 1 "aarch64_plus_operand" "r"))
+ (const_int 0)))]
+ ""
+ "cmp\\t%<w>0, %<w>1"
+ [(set_attr "type" "alus_sreg")]
+)
+
(define_insn "*compare_neg<mode>"
[(set (reg:CC_Z CC_REGNUM)
(compare:CC_Z
@@ -3824,6 +3875,22 @@
[(set_attr "type" "logics_reg,logics_imm")]
)
+(define_split
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:GPI (match_operand:GPI 0 "register_operand")
+ (match_operand:GPI 1 "aarch64_mov_imm_operand"))
+ (const_int 0)))
+ (clobber (match_operand:SI 2 "register_operand"))]
+ ""
+ [(set (match_dup 2) (match_dup 1))
+ (set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:GPI (match_dup 0)
+ (match_dup 2))
+ (const_int 0)))]
+)
+
(define_insn "*and<mode>3nr_compare0_zextract"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
@@ -3859,6 +3926,26 @@
[(set_attr "type" "logics_shift_imm")]
)
+(define_split
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:GPI (SHIFT:GPI
+ (match_operand:GPI 0 "register_operand")
+ (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
+ (match_operand:GPI 2 "aarch64_mov_imm_operand"))
+ (const_int 0)))
+ (clobber (match_operand:SI 3 "register_operand"))]
+ ""
+ [(set (match_dup 3) (match_dup 2))
+ (set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:GPI (SHIFT:GPI
+ (match_dup 0)
+ (match_dup 1))
+ (match_dup 3))
+ (const_int 0)))]
+)
+
;; -------------------------------------------------------------------
;; Shifts
;; -------------------------------------------------------------------
@@ -3942,6 +4029,97 @@
}
)
+;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
+;; they truncate the shift/rotate amount by the size of the registers they
+;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
+;; such redundant masking instructions. GCC can do that automatically when
+;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
+;; because some of the SISD shift alternatives don't perform this truncations.
+;; So this pattern exists to catch such cases.
+
+(define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (SHIFT:GPI
+ (match_operand:GPI 1 "register_operand" "r")
+ (match_operator 4 "subreg_lowpart_operator"
+ [(and:GPI (match_operand:GPI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand" "n"))])))]
+ "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
+ "<shift>\t%<w>0, %<w>1, %<w>2"
+ [(set_attr "type" "shift_reg")]
+)
+
+(define_insn_and_split "*aarch64_reg_<mode>3_neg_mask2"
+ [(set (match_operand:GPI 0 "register_operand" "=&r")
+ (SHIFT:GPI
+ (match_operand:GPI 1 "register_operand" "r")
+ (match_operator 4 "subreg_lowpart_operator"
+ [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand" "n")))])))]
+ "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
+ "#"
+ "&& true"
+ [(const_int 0)]
+ {
+ rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
+ : operands[0]);
+ emit_insn (gen_negsi2 (tmp, operands[2]));
+
+ rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
+ rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
+ SUBREG_BYTE (operands[4]));
+ emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
+ DONE;
+ }
+)
+
+(define_insn_and_split "*aarch64_reg_<mode>3_minus_mask"
+ [(set (match_operand:GPI 0 "register_operand" "=&r")
+ (ashift:GPI
+ (match_operand:GPI 1 "register_operand" "r")
+ (minus:QI (match_operand 2 "const_int_operand" "n")
+ (match_operator 5 "subreg_lowpart_operator"
+ [(and:SI (match_operand:SI 3 "register_operand" "r")
+ (match_operand 4 "const_int_operand" "n"))]))))]
+ "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
+ && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
+ "#"
+ "&& true"
+ [(const_int 0)]
+ {
+ rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
+ : operands[0]);
+
+ emit_insn (gen_negsi2 (tmp, operands[3]));
+
+ rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
+ rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
+ SUBREG_BYTE (operands[5]));
+
+ emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
+ DONE;
+ }
+)
+
+(define_insn "*aarch64_<optab>_reg_di3_mask2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (SHIFT:DI
+ (match_operand:DI 1 "register_operand" "r")
+ (match_operator 4 "subreg_lowpart_operator"
+ [(and:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "aarch64_shift_imm_di" "Usd"))])))]
+ "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1)) == 0)"
+{
+ rtx xop[3];
+ xop[0] = operands[0];
+ xop[1] = operands[1];
+ xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
+ output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
+ return "";
+}
+ [(set_attr "type" "shift_reg")]
+)
+
;; Logical left shift using SISD or Integer instruction
(define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
[(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 0753da32f59..d7b30b0e5ee 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -12162,7 +12162,7 @@ vbslq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c)
/* ARMv8.1-A instrinsics. */
#pragma GCC push_options
-#pragma GCC target ("arch=armv8.1-a")
+#pragma GCC target ("+nothing+rdma")
__extension__ extern __inline int16x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 88e840f2898..9ce3d4efaf3 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -176,6 +176,12 @@
(and (match_code "const_double")
(match_test "aarch64_float_const_representable_p (op)")))
+(define_constraint "Uvi"
+ "A floating point constant which can be used with a\
+ MOVI immediate operation."
+ (and (match_code "const_double")
+ (match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))")))
+
(define_constraint "Dn"
"@internal
A constraint that matches vector of immediates."
@@ -220,9 +226,17 @@
(define_constraint "Dd"
"@internal
- A constraint that matches an immediate operand valid for AdvSIMD scalar."
+ A constraint that matches an integer immediate operand valid\
+ for AdvSIMD scalar operations in DImode."
+ (and (match_code "const_int")
+ (match_test "aarch64_can_const_movi_rtx_p (op, DImode)")))
+
+(define_constraint "Ds"
+ "@internal
+ A constraint that matches an integer immediate operand valid\
+ for AdvSIMD scalar operations in SImode."
(and (match_code "const_int")
- (match_test "aarch64_simd_imm_scalar_p (op, GET_MODE (op))")))
+ (match_test "aarch64_can_const_movi_rtx_p (op, SImode)")))
(define_address_constraint "Dp"
"@internal
diff --git a/gcc/config/aarch64/cortex-a57-fma-steering.c b/gcc/config/aarch64/cortex-a57-fma-steering.c
index 94d7f9c5869..fa8c56aab02 100644
--- a/gcc/config/aarch64/cortex-a57-fma-steering.c
+++ b/gcc/config/aarch64/cortex-a57-fma-steering.c
@@ -603,7 +603,7 @@ fma_node::rename (fma_forest *forest)
{
rtx_insn *insn = this->m_insn;
HARD_REG_SET unavailable;
- enum machine_mode mode;
+ machine_mode mode;
int reg;
if (dump_file)
@@ -973,10 +973,17 @@ func_fma_steering::analyze ()
break;
}
- /* We didn't find a chain with a def for this instruction. */
- gcc_assert (i < dest_op_info->n_chains);
-
- this->analyze_fma_fmul_insn (forest, chain, head);
+ /* Due to implementation of regrename, dest register can slip away
+ from regrename's analysis. As a result, there is no chain for
+ the destination register of insn. We simply skip the insn even
+ it is a fmul/fmac instruction. This can happen when the dest
+ register is also a source register of insn and one of the below
+ conditions is satisfied:
+ 1) the source reg is setup in larger mode than this insn;
+ 2) the source reg is uninitialized;
+ 3) the source reg is passed in as parameter. */
+ if (i < dest_op_info->n_chains)
+ this->analyze_fma_fmul_insn (forest, chain, head);
}
}
free (bb_dfs_preorder);
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 43be7fd3611..067cef78533 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -44,6 +44,9 @@
;; Iterator for all scalar floating point modes (HF, SF, DF)
(define_mode_iterator GPF_F16 [(HF "AARCH64_ISA_F16") SF DF])
+;; Iterator for all scalar floating point modes (HF, SF, DF)
+(define_mode_iterator GPF_HF [HF SF DF])
+
;; Iterator for all scalar floating point modes (HF, SF, DF and TF)
(define_mode_iterator GPF_TF_F16 [HF SF DF TF])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index cd7ded98663..95d28cfa33c 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -35,6 +35,10 @@
(and (match_code "const_int")
(match_test "op == CONST0_RTX (mode)")))
+(define_special_predicate "subreg_lowpart_operator"
+ (and (match_code "subreg")
+ (match_test "subreg_lowpart_p (op)")))
+
(define_predicate "aarch64_ccmp_immediate"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), -31, 31)")))
@@ -53,6 +57,11 @@
(ior (match_operand 0 "register_operand")
(match_test "op == const0_rtx"))))
+(define_predicate "aarch64_reg_or_fp_float"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "const_double")
+ (match_test "aarch64_float_const_rtx_p (op)"))))
+
(define_predicate "aarch64_reg_or_fp_zero"
(ior (match_operand 0 "register_operand")
(and (match_code "const_double")
@@ -110,6 +119,10 @@
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_logical_immediate")))
+(define_predicate "aarch64_mov_imm_operand"
+ (and (match_code "const_int")
+ (match_test "aarch64_move_imm (INTVAL (op), mode)")))
+
(define_predicate "aarch64_logical_and_immediate"
(and (match_code "const_int")
(match_test "aarch64_and_bitmask_imm (INTVAL (op), mode)")))
diff --git a/gcc/config/aarch64/rtems.h b/gcc/config/aarch64/rtems.h
index b48e28afda0..07c5679d5c1 100644
--- a/gcc/config/aarch64/rtems.h
+++ b/gcc/config/aarch64/rtems.h
@@ -1,20 +1,25 @@
/* Definitions for RTEMS based AARCH64 system.
Copyright (C) 2016-2017 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
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#define HAS_INIT_SECTION
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 00a69c1a08d..9f5dae29054 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "gimple.h"
#include "df.h"
+#include "predict.h"
#include "tm_p.h"
#include "ssa.h"
#include "expmed.h"
@@ -4319,10 +4320,9 @@ alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
static void
emit_unlikely_jump (rtx cond, rtx label)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
rtx_insn *insn = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
- add_int_reg_note (insn, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (insn, profile_probability::very_unlikely ());
}
/* A subroutine of the atomic operation splitters. Emit a load-locked
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 93a64cfebac..8a9af46486e 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -45,13 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void arc_split_compare_and_swap (rtx *);
extern void arc_expand_compare_and_swap (rtx *);
extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
+extern int arc_return_address_register (unsigned int);
+extern unsigned int arc_compute_function_type (struct function *);
#endif /* RTX_CODE */
-#ifdef TREE_CODE
-extern enum arc_function_type arc_compute_function_type (struct function *);
-#endif /* TREE_CODE */
-
-
extern unsigned int arc_compute_frame_size (int);
extern bool arc_ccfsm_branch_deleted_p (void);
extern void arc_ccfsm_record_branch_deleted (void);
@@ -64,10 +61,8 @@ extern rtx arc_return_addr_rtx (int , rtx);
extern bool check_if_valid_regno_const (rtx *, int);
extern bool check_if_valid_sleep_operand (rtx *, int);
extern bool arc_legitimate_constant_p (machine_mode, rtx);
-extern bool arc_legitimate_pc_offset_p (rtx);
extern bool arc_legitimate_pic_addr_p (rtx);
extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
-extern bool arc_legitimate_pic_operand_p (rtx);
extern bool arc_is_longcall_p (rtx);
extern bool arc_is_shortcall_p (rtx);
extern bool valid_brcc_with_delay_p (rtx *);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index d9ad1390416..be5f1bd2003 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -211,6 +211,7 @@ static int rgf_banked_register_count;
static int get_arc_condition_code (rtx);
static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
+static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
/* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */
@@ -229,6 +230,9 @@ const struct attribute_spec arc_attribute_table[] =
/* And these functions are always known to reside within the 21 bit
addressing range of blcc. */
{ "short_call", 0, 0, false, true, true, NULL, false },
+ /* Function which are not having the prologue and epilogue generated
+ by the compiler. */
+ { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
static int arc_comp_type_attributes (const_tree, const_tree);
@@ -245,7 +249,6 @@ static rtx arc_expand_builtin (tree, rtx, rtx, machine_mode, int);
static int branch_dest (rtx);
static void arc_output_pic_addr_const (FILE *, rtx, int);
-bool arc_legitimate_pic_operand_p (rtx);
static bool arc_function_ok_for_sibcall (tree, tree);
static rtx arc_function_value (const_tree, const_tree, bool);
const char * output_shift (rtx *);
@@ -276,8 +279,7 @@ const arc_cpu_t *arc_selected_cpu;
register, an immediate or an long immediate. */
static bool
-legitimate_offset_address_p (enum machine_mode mode, rtx x, bool index,
- bool strict)
+legitimate_offset_address_p (machine_mode mode, rtx x, bool index, bool strict)
{
if (GET_CODE (x) != PLUS)
return false;
@@ -513,6 +515,12 @@ static void arc_finalize_pic (void);
#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
#define TARGET_SPILL_CLASS arc_spill_class
+#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
+#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
+
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
+
#include "target-def.h"
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -1856,6 +1864,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
return NULL_TREE;
}
+static tree
+arc_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;
+}
+
+/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
+
+static bool
+arc_allocate_stack_slots_for_args (void)
+{
+ /* Naked functions should not allocate stack slots for arguments. */
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ return !ARC_NAKED_P(fn_type);
+}
+
+/* Implement `TARGET_WARN_FUNC_RETURN'. */
+
+static bool
+arc_warn_func_return (tree decl)
+{
+ struct function *func = DECL_STRUCT_FUNCTION (decl);
+ unsigned int fn_type = arc_compute_function_type (func);
+
+ return !ARC_NAKED_P (fn_type);
+}
+
/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
and two if they are nearly compatible (which causes a warning to be
generated). */
@@ -2359,7 +2403,7 @@ struct GTY (()) arc_frame_info
typedef struct GTY (()) machine_function
{
- enum arc_function_type fn_type;
+ unsigned int fn_type;
struct arc_frame_info frame_info;
/* To keep track of unalignment caused by short insns. */
int unalign;
@@ -2377,43 +2421,40 @@ typedef struct GTY (()) machine_function
The result is cached. To reset the cache at the end of a function,
call with DECL = NULL_TREE. */
-enum arc_function_type
+unsigned int
arc_compute_function_type (struct function *fun)
{
- tree decl = fun->decl;
- tree a;
- enum arc_function_type fn_type = fun->machine->fn_type;
+ tree attr, decl = fun->decl;
+ unsigned int fn_type = fun->machine->fn_type;
if (fn_type != ARC_FUNCTION_UNKNOWN)
return fn_type;
- /* Assume we have a normal function (not an interrupt handler). */
- fn_type = ARC_FUNCTION_NORMAL;
+ /* Check if it is a naked function. */
+ if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+ fn_type |= ARC_FUNCTION_NAKED;
+ else
+ fn_type |= ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
- for (a = DECL_ATTRIBUTES (decl);
- a;
- a = TREE_CHAIN (a))
- {
- tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
- if (name == get_identifier ("interrupt")
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- tree value = TREE_VALUE (args);
-
- if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
- || !strcmp (TREE_STRING_POINTER (value), "ilink"))
- fn_type = ARC_FUNCTION_ILINK1;
- else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
- fn_type = ARC_FUNCTION_ILINK2;
- else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
- fn_type = ARC_FUNCTION_FIRQ;
- else
- gcc_unreachable ();
- break;
- }
+ attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
+ if (attr != NULL_TREE)
+ {
+ tree value, args = TREE_VALUE (attr);
+
+ gcc_assert (list_length (args) == 1);
+ value = TREE_VALUE (args);
+ gcc_assert (TREE_CODE (value) == STRING_CST);
+
+ if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
+ || !strcmp (TREE_STRING_POINTER (value), "ilink"))
+ fn_type |= ARC_FUNCTION_ILINK1;
+ else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ fn_type |= ARC_FUNCTION_ILINK2;
+ else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
+ fn_type |= ARC_FUNCTION_FIRQ;
+ else
+ gcc_unreachable ();
}
return fun->machine->fn_type = fn_type;
@@ -2434,7 +2475,7 @@ arc_compute_function_type (struct function *fun)
static bool
arc_must_save_register (int regno, struct function *func)
{
- enum arc_function_type fn_type = arc_compute_function_type (func);
+ unsigned int fn_type = arc_compute_function_type (func);
bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
&& ARC_AUTO_IRQ_P (fn_type));
bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
@@ -2879,7 +2920,11 @@ arc_expand_prologue (void)
Change the stack layout so that we rather store a high register with the
PRE_MODIFY, thus enabling more short insn generation.) */
int first_offset = 0;
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ /* Naked functions don't have prologue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
size = ARC_STACK_ALIGN (size);
@@ -2990,7 +3035,7 @@ void
arc_expand_epilogue (int sibcall_p)
{
int size = get_frame_size ();
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ unsigned int fn_type = arc_compute_function_type (cfun);
size = ARC_STACK_ALIGN (size);
size = (!cfun->machine->frame_info.initialized
@@ -3006,6 +3051,10 @@ arc_expand_epilogue (int sibcall_p)
int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
rtx insn;
+ /* Naked functions don't have epilogue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
+
size_to_deallocate = size;
frame_size = size - (pretend_size +
@@ -5005,57 +5054,6 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
}
-/* Helper used by arc_legitimate_pc_offset_p. */
-
-static bool
-arc_needs_pcl_p (rtx x)
-{
- register const char *fmt;
- register int i, j;
-
- if ((GET_CODE (x) == UNSPEC)
- && (XVECLEN (x, 0) == 1)
- && (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF))
- switch (XINT (x, 1))
- {
- case ARC_UNSPEC_GOT:
- case ARC_UNSPEC_GOTOFFPC:
- case UNSPEC_TLS_GD:
- case UNSPEC_TLS_IE:
- return true;
- default:
- break;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (arc_needs_pcl_p (XEXP (x, i)))
- return true;
- }
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (arc_needs_pcl_p (XVECEXP (x, i, j)))
- return true;
- }
-
- return false;
-}
-
-/* Return true if ADDR is an address that needs to be expressed as an
- explicit sum of pcl + offset. */
-
-bool
-arc_legitimate_pc_offset_p (rtx addr)
-{
- if (GET_CODE (addr) != CONST)
- return false;
-
- return arc_needs_pcl_p (addr);
-}
-
/* Return true if ADDR is a valid pic address.
A valid pic address on arc should look like
const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
@@ -5063,8 +5061,6 @@ arc_legitimate_pc_offset_p (rtx addr)
bool
arc_legitimate_pic_addr_p (rtx addr)
{
- if (GET_CODE (addr) == LABEL_REF)
- return true;
if (GET_CODE (addr) != CONST)
return false;
@@ -5768,16 +5764,6 @@ arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
}
-/* Nonzero if the constant value X is a legitimate general operand
- when generating PIC code. It is given that flag_pic is on and
- that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-bool
-arc_legitimate_pic_operand_p (rtx x)
-{
- return !arc_raw_symbolic_reference_mentioned_p (x, true);
-}
-
/* Determine if a given RTX is a valid constant. We already know this
satisfies CONSTANT_P. */
@@ -5793,40 +5779,12 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
switch (GET_CODE (x))
{
case CONST:
- x = XEXP (x, 0);
-
- if (GET_CODE (x) == PLUS)
+ if (flag_pic)
{
- if (flag_pic
- ? GET_CODE (XEXP (x, 1)) != CONST_INT
- : !arc_legitimate_constant_p (mode, XEXP (x, 1)))
- return false;
- x = XEXP (x, 0);
- }
-
- /* Only some unspecs are valid as "constants". */
- if (GET_CODE (x) == UNSPEC)
- switch (XINT (x, 1))
- {
- case ARC_UNSPEC_PLT:
- case ARC_UNSPEC_GOTOFF:
- case ARC_UNSPEC_GOTOFFPC:
- case ARC_UNSPEC_GOT:
- case UNSPEC_TLS_GD:
- case UNSPEC_TLS_IE:
- case UNSPEC_TLS_OFF:
+ if (arc_legitimate_pic_addr_p (x))
return true;
-
- default:
- gcc_unreachable ();
- }
-
- /* We must have drilled down to a symbol. */
- if (arc_raw_symbolic_reference_mentioned_p (x, false))
- return false;
-
- /* Return true. */
- break;
+ }
+ return arc_legitimate_constant_p (mode, XEXP (x, 0));
case SYMBOL_REF:
if (SYMBOL_REF_TLS_MODEL (x))
@@ -5836,13 +5794,53 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
if (flag_pic)
return false;
/* Fall through. */
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return true;
+
+ case NEG:
+ return arc_legitimate_constant_p (mode, XEXP (x, 0));
+
+ case PLUS:
+ case MINUS:
+ {
+ bool t1 = arc_legitimate_constant_p (mode, XEXP (x, 0));
+ bool t2 = arc_legitimate_constant_p (mode, XEXP (x, 1));
+
+ return (t1 && t2);
+ }
+
+ case CONST_VECTOR:
+ switch (mode)
+ {
+ case V2HImode:
+ return TARGET_PLUS_DMPY;
+ case V2SImode:
+ case V4HImode:
+ return TARGET_PLUS_QMACW;
+ default:
+ return false;
+ }
+
+ case UNSPEC:
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_TLS_GD:
+ case UNSPEC_TLS_OFF:
+ case UNSPEC_TLS_IE:
+ return true;
+ default:
+ /* Any other unspec ending here are pic related, hence the above
+ constant pic address checking returned false. */
+ return false;
+ }
+ /* Fall through. */
default:
- break;
+ fatal_insn ("unrecognized supposed constant", x);
}
- /* Otherwise we handle everything else in the move patterns. */
- return true;
+ gcc_unreachable ();
}
static bool
@@ -5879,9 +5877,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
if ((GET_MODE_SIZE (mode) != 16) && CONSTANT_P (x))
{
- if (flag_pic ? arc_legitimate_pic_addr_p (x)
- : arc_legitimate_constant_p (Pmode, x))
- return true;
+ return arc_legitimate_constant_p (mode, x);
}
if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
|| GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
@@ -9789,37 +9785,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
return true;
}
-int arc_return_address_regs[5] =
- {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
+/* Return the register number of the register holding the return address
+ for a function of type TYPE. */
-/* Implement EPILOGUE__USES.
+int
+arc_return_address_register (unsigned int fn_type)
+{
+ int regno = 0;
+
+ if (ARC_INTERRUPT_P (fn_type))
+ {
+ if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
+ regno = ILINK1_REGNUM;
+ else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
+ regno = ILINK2_REGNUM;
+ else
+ gcc_unreachable ();
+ }
+ else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
+ regno = RETURN_ADDR_REGNUM;
+
+ gcc_assert (regno != 0);
+ return regno;
+}
+
+/* Implement EPILOGUE_USES.
Return true if REGNO should be added to the deemed uses of the epilogue.
- We use the return address
- arc_return_address_regs[arc_compute_function_type (cfun)]. But
- also, we have to make sure all the register restore instructions
- are known to be live in interrupt functions, plus the blink
- register if it is clobbered by the isr. */
+ We have to make sure all the register restore instructions are
+ known to be live in interrupt functions, plus the blink register if
+ it is clobbered by the isr. */
bool
arc_epilogue_uses (int regno)
{
+ unsigned int fn_type;
+
if (regno == arc_tp_regno)
return true;
+
+ fn_type = arc_compute_function_type (cfun);
if (reload_completed)
{
if (ARC_INTERRUPT_P (cfun->machine->fn_type))
{
if (!fixed_regs[regno])
return true;
- return ((regno == arc_return_address_regs[cfun->machine->fn_type])
+ return ((regno == arc_return_address_register (fn_type))
|| (regno == RETURN_ADDR_REGNUM));
}
else
return regno == RETURN_ADDR_REGNUM;
}
else
- return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
+ return regno == arc_return_address_register (fn_type);
}
/* Helper for EH_USES macro. */
@@ -9980,10 +9999,8 @@ arc_post_atomic_barrier (enum memmodel model)
static void
emit_unlikely_jump (rtx insn)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
-
rtx_insn *jump = emit_jump_insn (insn);
- add_int_reg_note (jump, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (jump, profile_probability::very_unlikely ());
}
/* Expand code to perform a 8 or 16-bit compare and swap by doing
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 5627eb488cf..9216f9417e0 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -901,10 +901,10 @@ extern int arc_initial_elimination_offset(int from, int to);
a special predicate for the memory operand of stores, like for the SH. */
/* Recognize any constant value that is a valid address. */
-#define CONSTANT_ADDRESS_P(X) \
-(flag_pic?arc_legitimate_pic_addr_p (X): \
-(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
+#define CONSTANT_ADDRESS_P(X) \
+ (flag_pic ? (arc_legitimate_pic_addr_p (X) || LABEL_P (X)): \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
/* Is the argument a const_int rtx, containing an exact power of 2 */
#define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
@@ -1083,7 +1083,8 @@ arc_select_cc_mode (OP, X, Y)
check it either. You need not define this macro if all constants
(including SYMBOL_REF) can be immediate operands when generating
position independent code. */
-#define LEGITIMATE_PIC_OPERAND_P(X) (arc_legitimate_pic_operand_p(X))
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ (!arc_raw_symbolic_reference_mentioned_p ((X), true))
/* PIC and small data don't mix on ARC because they use the same register. */
#define SDATA_BASE_REGNUM 26
@@ -1262,6 +1263,13 @@ extern char rname56[], rname57[], rname58[], rname59[];
"lp_start", "lp_end" \
}
+#define ADDITIONAL_REGISTER_NAMES \
+{ \
+ {"ilink", 29}, \
+ {"r29", 29}, \
+ {"r30", 30} \
+}
+
/* Entry to the insn conditionalizer. */
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
@@ -1363,10 +1371,6 @@ do { \
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
-/* To translate the return value of arc_function_type into a register number
- to jump through for function return. */
-extern int arc_return_address_regs[5];
-
/* Debugging information. */
/* Generate DBX and DWARF debugging information. */
@@ -1499,22 +1503,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
/* ARC function types. */
enum arc_function_type {
- ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
+ /* No function should have the unknown type. This value is used to
+ indicate the that function type has not yet been computed. */
+ ARC_FUNCTION_UNKNOWN = 0,
+
+ /* The normal function type indicates that the function has the
+ standard prologue and epilogue. */
+ ARC_FUNCTION_NORMAL = 1 << 0,
/* These are interrupt handlers. The name corresponds to the register
name that contains the return address. */
- ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
+ ARC_FUNCTION_ILINK1 = 1 << 1,
+ ARC_FUNCTION_ILINK2 = 1 << 2,
/* Fast interrupt is only available on ARCv2 processors. */
- ARC_FUNCTION_FIRQ
+ ARC_FUNCTION_FIRQ = 1 << 3,
+ /* The naked function type indicates that the function does not have
+ prologue or epilogue, and that no stack frame is available. */
+ ARC_FUNCTION_NAKED = 1 << 4
};
-#define ARC_INTERRUPT_P(TYPE) \
- (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \
- || ((TYPE) == ARC_FUNCTION_FIRQ))
-#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
+/* Check if a function is an interrupt function. */
+#define ARC_INTERRUPT_P(TYPE) \
+ (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2 \
+ | ARC_FUNCTION_FIRQ)) != 0)
+
+/* Check if a function is a fast interrupt function. */
+#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
+
+/* Check if a function is normal, that is, has standard prologue and
+ epilogue. */
+#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
-/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
-struct function;
-extern enum arc_function_type arc_compute_function_type (struct function *);
+/* Check if a function is naked. */
+#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
/* Called by crtstuff.c to make calls to function FUNCTION that are defined in
SECTION_OP, and then to switch back to text section. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 9aa9cd7ae29..6fb0f17cee1 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -505,8 +505,8 @@
(cond [(eq_attr "in_delay_slot" "false")
(const_string "no")
(match_test "regno_clobbered_p
- (arc_return_address_regs
- [arc_compute_function_type (cfun)],
+ (arc_return_address_register
+ (arc_compute_function_type (cfun)),
insn, SImode, 1)")
(const_string "no")]
(const_string "yes")))
@@ -2649,30 +2649,7 @@
(match_operand:DI 2 "nonmemory_operand" "")))
(clobber (reg:CC CC_REG))])]
""
-{
- if (TARGET_EXPAND_ADDDI)
- {
- rtx l0 = gen_lowpart (SImode, operands[0]);
- rtx h0 = disi_highpart (operands[0]);
- rtx l1 = gen_lowpart (SImode, operands[1]);
- rtx h1 = disi_highpart (operands[1]);
- rtx l2 = gen_lowpart (SImode, operands[2]);
- rtx h2 = disi_highpart (operands[2]);
- rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
-
- if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
- {
- emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
- emit_insn (gen_sbc (h0, h1,
- gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
- cc_c));
- DONE;
- }
- emit_insn (gen_add_f (l0, l1, l2));
- emit_insn (gen_adc (h0, h1, h2));
- DONE;
- }
-})
+{})
; This assumes that there can be no strictly partial overlap between
; operands[1] and operands[2].
@@ -2911,20 +2888,6 @@
{
if (!register_operand (operands[2], DImode))
operands[1] = force_reg (DImode, operands[1]);
- if (TARGET_EXPAND_ADDDI)
- {
- rtx l0 = gen_lowpart (SImode, operands[0]);
- rtx h0 = disi_highpart (operands[0]);
- rtx l1 = gen_lowpart (SImode, operands[1]);
- rtx h1 = disi_highpart (operands[1]);
- rtx l2 = gen_lowpart (SImode, operands[2]);
- rtx h2 = disi_highpart (operands[2]);
- rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
-
- emit_insn (gen_sub_f (l0, l1, l2));
- emit_insn (gen_sbc (h0, h1, h2, cc_c));
- DONE;
- }
})
(define_insn_and_split "subdi3_i"
@@ -4533,9 +4496,21 @@
(set_attr "type" "two_cycle_core,two_cycle_core")])
(define_expand "clzsi2"
- [(set (match_operand:SI 0 "dest_reg_operand" "")
- (clz:SI (match_operand:SI 1 "register_operand" "")))]
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (clz:SI (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_NORM"
+ "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);")
+
+(define_insn_and_split "*arc_clzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (reg:CC_ZN CC_REG))]
+ "TARGET_NORM"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
emit_insn (gen_norm_f (operands[0], operands[1]));
emit_insn
@@ -4552,9 +4527,23 @@
})
(define_expand "ctzsi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (ctz:SI (match_operand:SI 1 "register_operand" "")))]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "")]
"TARGET_NORM"
+ "
+ emit_insn (gen_arc_ctzsi2 (operands[0], operands[1]));
+ DONE;
+")
+
+(define_insn_and_split "arc_ctzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ctz:SI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (reg:CC_ZN CC_REG))
+ (clobber (match_scratch:SI 2 "=&r"))]
+ "TARGET_NORM"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
rtx temp = operands[0];
@@ -4562,10 +4551,10 @@
|| (REGNO (temp) < FIRST_PSEUDO_REGISTER
&& !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
REGNO (temp))))
- temp = gen_reg_rtx (SImode);
+ temp = operands[2];
emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
- emit_insn (gen_clrsbsi2 (temp, temp));
+ emit_insn (gen_clrsbsi2 (operands[0], temp));
emit_insn
(gen_rtx_COND_EXEC
(VOIDmode,
@@ -4575,7 +4564,8 @@
(gen_rtx_COND_EXEC
(VOIDmode,
gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
- gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
+ gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31),
+ operands[0]))));
DONE;
})
@@ -4859,7 +4849,8 @@
{
rtx reg
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_V2
&& ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
@@ -4908,7 +4899,8 @@
xop[0] = operands[0];
xop[1]
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_PAD_RETURN)
arc_pad_return ();
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index f01a2ff0e58..ad2df2605e9 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -270,11 +270,11 @@ Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
Tune for ARC700 R4.2 Cpu with XMAC block.
mindexed-loads
-Target Var(TARGET_INDEXED_LOADS)
+Target Var(TARGET_INDEXED_LOADS) Init(TARGET_INDEXED_LOADS_DEFAULT)
Enable the use of indexed loads.
mauto-modify-reg
-Target Var(TARGET_AUTO_MODIFY_REG)
+Target Var(TARGET_AUTO_MODIFY_REG) Init(TARGET_AUTO_MODIFY_REG_DEFAULT)
Enable the use of pre/post modify with register displacement.
mmul32x16
@@ -328,7 +328,7 @@ Target Var(TARGET_Q_CLASS)
Enable 'q' instruction alternatives.
mexpand-adddi
-Target Var(TARGET_EXPAND_ADDDI)
+Target Warn(%qs is deprecated)
Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index edab41c3e67..6620daf18e3 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -403,7 +403,7 @@
(define_constraint "Cpc"
"pc-relative constant"
- (match_test "arc_legitimate_pc_offset_p (op)"))
+ (match_test "arc_legitimate_pic_addr_p (op)"))
(define_constraint "Clb"
"label"
@@ -412,12 +412,12 @@
(define_constraint "Cal"
"constant for arithmetic/logical operations"
- (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pc_offset_p (op)"))
+ (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op)"))
(define_constraint "C32"
"32 bit constant for arithmetic/logical operations"
(match_test "immediate_operand (op, VOIDmode)
- && !arc_legitimate_pc_offset_p (op)
+ && !arc_legitimate_pic_addr_p (op)
&& !satisfies_constraint_I (op)"))
; Note that the 'cryptic' register constraints will not make reload use the
diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
index c5794f8f785..43f3408bc08 100644
--- a/gcc/config/arc/elf.h
+++ b/gcc/config/arc/elf.h
@@ -58,3 +58,11 @@ along with GCC; see the file COPYING3. If not see
/* Bare-metal toolchains do not need a thread pointer register. */
#undef TARGET_ARC_TP_REGNO_DEFAULT
#define TARGET_ARC_TP_REGNO_DEFAULT -1
+
+/* Indexed loads are default. */
+#undef TARGET_INDEXED_LOADS_DEFAULT
+#define TARGET_INDEXED_LOADS_DEFAULT 1
+
+/* Pre/post modify with register displacement are default. */
+#undef TARGET_AUTO_MODIFY_REG_DEFAULT
+#define TARGET_AUTO_MODIFY_REG_DEFAULT 1
diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
index 83e5a1d61f2..d8e006307fc 100644
--- a/gcc/config/arc/linux.h
+++ b/gcc/config/arc/linux.h
@@ -83,3 +83,11 @@ along with GCC; see the file COPYING3. If not see
#define SUBTARGET_CPP_SPEC "\
%{pthread:-D_REENTRANT} \
"
+
+/* Indexed loads are default off. */
+#undef TARGET_INDEXED_LOADS_DEFAULT
+#define TARGET_INDEXED_LOADS_DEFAULT 0
+
+/* Pre/post modify with register displacement are default off. */
+#undef TARGET_AUTO_MODIFY_REG_DEFAULT
+#define TARGET_AUTO_MODIFY_REG_DEFAULT 0
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index 35d2d96c9fd..a51121193ce 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -25,7 +25,6 @@
extern int aarch_accumulator_forwarding (rtx_insn *, rtx_insn *);
extern int aarch_crypto_can_dual_issue (rtx_insn *, rtx_insn *);
-extern int aarch_forward_to_shift_is_not_shifted_reg (rtx_insn *, rtx_insn *);
extern bool aarch_rev16_p (rtx);
extern bool aarch_rev16_shleft_mask_imm_p (rtx, machine_mode);
extern bool aarch_rev16_shright_mask_imm_p (rtx, machine_mode);
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 6a04711335d..979f86e5bed 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -272,12 +272,7 @@ arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
return 0;
if ((early_op = arm_find_shift_sub_rtx (op)))
- {
- if (REG_P (early_op))
- early_op = op;
-
- return !reg_overlap_mentioned_p (value, early_op);
- }
+ return !reg_overlap_mentioned_p (value, early_op);
return 0;
}
@@ -508,38 +503,6 @@ aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer)
return (REGNO (dest) == REGNO (accumulator));
}
-/* Return nonzero if the CONSUMER instruction is some sort of
- arithmetic or logic + shift operation, and the register we are
- writing in PRODUCER is not used in a register shift by register
- operation. */
-
-int
-aarch_forward_to_shift_is_not_shifted_reg (rtx_insn *producer,
- rtx_insn *consumer)
-{
- rtx value, op;
- rtx early_op;
-
- if (!arm_get_set_operands (producer, consumer, &value, &op))
- return 0;
-
- if ((early_op = arm_find_shift_sub_rtx (op)))
- {
- if (REG_P (early_op))
- early_op = op;
-
- /* Any other canonicalisation of a shift is a shift-by-constant
- so we don't care. */
- if (GET_CODE (early_op) == ASHIFT)
- return (!REG_P (XEXP (early_op, 0))
- || !REG_P (XEXP (early_op, 1)));
- else
- return 1;
- }
-
- return 0;
-}
-
/* Return non-zero if the consumer (a multiply-accumulate instruction)
has an accumulator dependency on the result of the producer (a
multiplication instruction) and no other dependency on that result. */
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 8d14e58d916..7504ed581c6 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -27,6 +27,7 @@
#include "gimple-expr.h"
#include "memmodel.h"
#include "tm_p.h"
+#include "profile-count.h"
#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
@@ -807,7 +808,7 @@ arm_mangle_builtin_type (const_tree type)
}
static tree
-arm_simd_builtin_std_type (enum machine_mode mode,
+arm_simd_builtin_std_type (machine_mode mode,
enum arm_type_qualifiers q)
{
#define QUAL_TYPE(M) \
@@ -845,7 +846,7 @@ arm_simd_builtin_std_type (enum machine_mode mode,
}
static tree
-arm_lookup_simd_builtin_type (enum machine_mode mode,
+arm_lookup_simd_builtin_type (machine_mode mode,
enum arm_type_qualifiers q)
{
int i;
@@ -867,8 +868,7 @@ arm_lookup_simd_builtin_type (enum machine_mode mode,
}
static tree
-arm_simd_builtin_type (enum machine_mode mode,
- bool unsigned_p, bool poly_p)
+arm_simd_builtin_type (machine_mode mode, bool unsigned_p, bool poly_p)
{
if (poly_p)
return arm_lookup_simd_builtin_type (mode, qualifier_poly);
@@ -942,7 +942,7 @@ arm_init_simd_builtin_types (void)
for (i = 0; i < nelts; i++)
{
tree eltype = arm_simd_types[i].eltype;
- enum machine_mode mode = arm_simd_types[i].mode;
+ machine_mode mode = arm_simd_types[i].mode;
if (arm_simd_types[i].itype == NULL)
arm_simd_types[i].itype =
@@ -2232,7 +2232,7 @@ arm_expand_builtin_args (rtx target, machine_mode map_mode, int fcode,
gcc_assert (argc > 0);
if (CONST_INT_P (op[argc]))
{
- enum machine_mode vmode = mode[argc - 1];
+ machine_mode vmode = mode[argc - 1];
neon_lane_bounds (op[argc], 0, GET_MODE_NUNITS (vmode), exp);
}
/* If the lane index isn't a constant then the next
@@ -3098,7 +3098,7 @@ arm_builtin_vectorized_function (unsigned int fn, tree type_out, tree type_in)
NULL_TREE is returned if no such builtin is available. */
#undef ARM_CHECK_BUILTIN_MODE
#define ARM_CHECK_BUILTIN_MODE(C) \
- (TARGET_FPU_ARMV8 \
+ (TARGET_VFP5 \
&& flag_unsafe_math_optimizations \
&& ARM_CHECK_BUILTIN_MODE_1 (C))
diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index a3daa3220a2..9178937b6d9 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -96,7 +96,7 @@ arm_cpu_builtins (struct cpp_reader* pfile)
|| TARGET_ARM_ARCH_ISA_THUMB >=2));
def_or_undef_macro (pfile, "__ARM_FEATURE_NUMERIC_MAXMIN",
- TARGET_ARM_ARCH >= 8 && TARGET_NEON && TARGET_FPU_ARMV8);
+ TARGET_ARM_ARCH >= 8 && TARGET_NEON && TARGET_VFP5);
def_or_undef_macro (pfile, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD);
diff --git a/gcc/config/arm/arm-cpu-cdata.h b/gcc/config/arm/arm-cpu-cdata.h
deleted file mode 100644
index 8406fa05423..00000000000
--- a/gcc/config/arm/arm-cpu-cdata.h
+++ /dev/null
@@ -1,2584 +0,0 @@
-/* -*- buffer-read-only: t -*-
- Generated automatically by parsecpu.awk from arm-cpus.in.
- Do not edit.
-
- Copyright (C) 2011-2017 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/>. */
-
-static const cpu_arch_extension cpu_opttab_arm9e[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm946es[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm966es[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm968es[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm10e[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm1020e[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm1022e[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm926ejs[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_arm1026ejs[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_genericv7a[] = {
- {
- "vfpv3-d16", false, false,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv3", false, false,
- { ISA_VFPv3,ISA_FP_D32, isa_nobit }
- },
- {
- "vfpv3-d16-fp16", false, false,
- { ISA_VFPv3,ISA_FP_DBL,isa_bit_fp16conv, isa_nobit }
- },
- {
- "vfpv3-fp16", false, false,
- { ISA_VFPv3,ISA_FP_D32,isa_bit_fp16conv, isa_nobit }
- },
- {
- "vfpv4-d16", false, false,
- { ISA_VFPv4,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv4", false, false,
- { ISA_VFPv4,ISA_FP_D32, isa_nobit }
- },
- {
- "simd", false, false,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-fp16", false, false,
- { ISA_VFPv3,ISA_NEON,isa_bit_fp16conv, isa_nobit }
- },
- {
- "neon-vfpv4", false, false,
- { ISA_VFPv4,ISA_NEON, isa_nobit }
- },
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "neon", false, true,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-vfpv3", false, true,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa5[] = {
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa7[] = {
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa8[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa9[] = {
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa12[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa15[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa17[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexr5[] = {
- {
- "nofp.dp", true, false,
- { ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexr7[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexr8[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexm7[] = {
- {
- "nofp.dp", true, false,
- { ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexm4[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa15cortexa7[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa17cortexa7[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa32[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa35[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa53[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa57[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa72[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa73[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_exynosm1[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_xgene1[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa57cortexa53[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa72cortexa53[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa73cortexa35[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexa73cortexa53[] = {
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const cpu_arch_extension cpu_opttab_cortexm33[] = {
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-const cpu_option all_cores[] =
-{
- {
- {
- "arm2",
- NULL,
- {
- ISA_ARMv2,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv2
- },
- {
- {
- "arm250",
- NULL,
- {
- ISA_ARMv2,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv2
- },
- {
- {
- "arm3",
- NULL,
- {
- ISA_ARMv2,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv2
- },
- {
- {
- "arm6",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm60",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm600",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm610",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm620",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7d",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7di",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm70",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm700",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm700i",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm710",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm720",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm710c",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7100",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7500",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7500fe",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3
- },
- {
- {
- "arm7m",
- NULL,
- {
- ISA_ARMv3m,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3m
- },
- {
- {
- "arm7dm",
- NULL,
- {
- ISA_ARMv3m,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3m
- },
- {
- {
- "arm7dmi",
- NULL,
- {
- ISA_ARMv3m,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv3m
- },
- {
- {
- "arm8",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "arm810",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "strongarm",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "strongarm110",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "strongarm1100",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "strongarm1110",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "fa526",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "fa626",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4
- },
- {
- {
- "arm7tdmi",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm7tdmi-s",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm710t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm720t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm740t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm9",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm9tdmi",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm920",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm920t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm922t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm940t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "ep9312",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv4t
- },
- {
- {
- "arm10tdmi",
- NULL,
- {
- ISA_ARMv5t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5t
- },
- {
- {
- "arm1020t",
- NULL,
- {
- ISA_ARMv5t,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5t
- },
- {
- {
- "arm9e",
- cpu_opttab_arm9e,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm946e-s",
- cpu_opttab_arm946es,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm966e-s",
- cpu_opttab_arm966es,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm968e-s",
- cpu_opttab_arm968es,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm10e",
- cpu_opttab_arm10e,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm1020e",
- cpu_opttab_arm1020e,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm1022e",
- cpu_opttab_arm1022e,
- {
- ISA_ARMv5te,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "xscale",
- NULL,
- {
- ISA_ARMv5te,
- isa_bit_xscale,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "iwmmxt",
- NULL,
- {
- ISA_ARMv5te,isa_bit_xscale,isa_bit_iwmmxt,
- isa_nobit
- }
- },
- TARGET_ARCH_iwmmxt
- },
- {
- {
- "iwmmxt2",
- NULL,
- {
- ISA_ARMv5te,isa_bit_xscale,isa_bit_iwmmxt,isa_bit_iwmmxt2,
- isa_nobit
- }
- },
- TARGET_ARCH_iwmmxt2
- },
- {
- {
- "fa606te",
- NULL,
- {
- ISA_ARMv5te,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "fa626te",
- NULL,
- {
- ISA_ARMv5te,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "fmp626",
- NULL,
- {
- ISA_ARMv5te,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "fa726te",
- NULL,
- {
- ISA_ARMv5te,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5te
- },
- {
- {
- "arm926ej-s",
- cpu_opttab_arm926ejs,
- {
- ISA_ARMv5tej,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5tej
- },
- {
- {
- "arm1026ej-s",
- cpu_opttab_arm1026ejs,
- {
- ISA_ARMv5tej,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv5tej
- },
- {
- {
- "arm1136j-s",
- NULL,
- {
- ISA_ARMv6j,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6j
- },
- {
- {
- "arm1136jf-s",
- NULL,
- {
- ISA_ARMv6j,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6j
- },
- {
- {
- "arm1176jz-s",
- NULL,
- {
- ISA_ARMv6kz,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6kz
- },
- {
- {
- "arm1176jzf-s",
- NULL,
- {
- ISA_ARMv6kz,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6kz
- },
- {
- {
- "mpcorenovfp",
- NULL,
- {
- ISA_ARMv6k,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6k
- },
- {
- {
- "mpcore",
- NULL,
- {
- ISA_ARMv6k,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6k
- },
- {
- {
- "arm1156t2-s",
- NULL,
- {
- ISA_ARMv6t2,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6t2
- },
- {
- {
- "arm1156t2f-s",
- NULL,
- {
- ISA_ARMv6t2,
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6t2
- },
- {
- {
- "cortex-m1",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "cortex-m0",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "cortex-m0plus",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "cortex-m1.small-multiply",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "cortex-m0.small-multiply",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "cortex-m0plus.small-multiply",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- }
- },
- TARGET_ARCH_armv6_m
- },
- {
- {
- "generic-armv7-a",
- cpu_opttab_genericv7a,
- {
- ISA_ARMv7a,
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_a
- },
- {
- {
- "cortex-a5",
- cpu_opttab_cortexa5,
- {
- ISA_ARMv7a,
- ISA_VFPv3,ISA_NEON,isa_bit_fp16conv,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_a
- },
- {
- {
- "cortex-a7",
- cpu_opttab_cortexa7,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-a8",
- cpu_opttab_cortexa8,
- {
- ISA_ARMv7a,
- ISA_VFPv3,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_a
- },
- {
- {
- "cortex-a9",
- cpu_opttab_cortexa9,
- {
- ISA_ARMv7a,
- ISA_VFPv3,ISA_NEON,isa_bit_fp16conv,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_a
- },
- {
- {
- "cortex-a12",
- cpu_opttab_cortexa12,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-a15",
- cpu_opttab_cortexa15,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-a17",
- cpu_opttab_cortexa17,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-r4",
- NULL,
- {
- ISA_ARMv7r,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_r
- },
- {
- {
- "cortex-r4f",
- NULL,
- {
- ISA_ARMv7r,
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_r
- },
- {
- {
- "cortex-r5",
- cpu_opttab_cortexr5,
- {
- ISA_ARMv7r,
- isa_bit_adiv,
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_r
- },
- {
- {
- "cortex-r7",
- cpu_opttab_cortexr7,
- {
- ISA_ARMv7r,
- isa_bit_adiv,
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_r
- },
- {
- {
- "cortex-r8",
- cpu_opttab_cortexr8,
- {
- ISA_ARMv7r,
- isa_bit_adiv,
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_r
- },
- {
- {
- "cortex-m7",
- cpu_opttab_cortexm7,
- {
- ISA_ARMv7em,
- ISA_FPv5,ISA_FP_DBL,
- isa_quirk_no_volatile_ce,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7e_m
- },
- {
- {
- "cortex-m4",
- cpu_opttab_cortexm4,
- {
- ISA_ARMv7em,
- ISA_VFPv4,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7e_m
- },
- {
- {
- "cortex-m3",
- NULL,
- {
- ISA_ARMv7m,
- isa_quirk_cm3_ldrd,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_m
- },
- {
- {
- "marvell-pj4",
- NULL,
- {
- ISA_ARMv7a,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7_a
- },
- {
- {
- "cortex-a15.cortex-a7",
- cpu_opttab_cortexa15cortexa7,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-a17.cortex-a7",
- cpu_opttab_cortexa17cortexa7,
- {
- ISA_ARMv7ve,
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv7ve
- },
- {
- {
- "cortex-a32",
- cpu_opttab_cortexa32,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a35",
- cpu_opttab_cortexa35,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a53",
- cpu_opttab_cortexa53,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a57",
- cpu_opttab_cortexa57,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a72",
- cpu_opttab_cortexa72,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a73",
- cpu_opttab_cortexa73,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "exynos-m1",
- cpu_opttab_exynosm1,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "xgene1",
- cpu_opttab_xgene1,
- {
- ISA_ARMv8a,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a57.cortex-a53",
- cpu_opttab_cortexa57cortexa53,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a72.cortex-a53",
- cpu_opttab_cortexa72cortexa53,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a73.cortex-a35",
- cpu_opttab_cortexa73cortexa35,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-a73.cortex-a53",
- cpu_opttab_cortexa73cortexa53,
- {
- ISA_ARMv8a,
- isa_bit_crc32,
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_a
- },
- {
- {
- "cortex-m23",
- NULL,
- {
- ISA_ARMv8m_base,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_m_base
- },
- {
- {
- "cortex-m33",
- cpu_opttab_cortexm33,
- {
- ISA_ARMv8m_main,
- isa_bit_ARMv7em,
- ISA_FPv5,
- isa_nobit
- }
- },
- TARGET_ARCH_armv8_m_main
- },
- {{NULL, NULL, {isa_nobit}}, TARGET_ARCH_arm_none}
-};
-static const struct cpu_arch_extension arch_opttab_armv5e[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv5te[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv5tej[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6j[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6k[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6z[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6kz[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6zk[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv6t2[] = {
- {
- "fp", false, false,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv2", false, true,
- { ISA_VFPv2,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv7[] = {
- {
- "fp", false, false,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv3-d16", false, true,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv7_a[] = {
- {
- "fp", false, false,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv3", false, false,
- { ISA_VFPv3,ISA_FP_D32, isa_nobit }
- },
- {
- "vfpv3-d16-fp16", false, false,
- { ISA_VFPv3,ISA_FP_DBL,isa_bit_fp16conv, isa_nobit }
- },
- {
- "vfpv3-fp16", false, false,
- { ISA_VFPv3,ISA_FP_DBL,ISA_FP_D32,isa_bit_fp16conv, isa_nobit }
- },
- {
- "vfpv4-d16", false, false,
- { ISA_VFPv4,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv4", false, false,
- { ISA_VFPv4,ISA_FP_D32, isa_nobit }
- },
- {
- "simd", false, false,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-fp16", false, false,
- { ISA_VFPv3,ISA_NEON,isa_bit_fp16conv, isa_nobit }
- },
- {
- "neon-vfpv4", false, false,
- { ISA_VFPv4,ISA_NEON, isa_nobit }
- },
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv3-d16", false, true,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "neon", false, true,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-vfpv3", false, true,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv7ve[] = {
- {
- "vfpv3-d16", false, false,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv3", false, false,
- { ISA_VFPv3,ISA_FP_D32, isa_nobit }
- },
- {
- "vfpv3-d16-fp16", false, false,
- { ISA_VFPv3,ISA_FP_DBL,isa_bit_fp16conv, isa_nobit }
- },
- {
- "vfpv3-fp16", false, false,
- { ISA_VFPv3,ISA_FP_DBL,ISA_FP_D32,isa_bit_fp16conv, isa_nobit }
- },
- {
- "fp", false, false,
- { ISA_VFPv4,ISA_FP_DBL, isa_nobit }
- },
- {
- "vfpv4", false, false,
- { ISA_VFPv4,ISA_FP_D32, isa_nobit }
- },
- {
- "neon", false, false,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-fp16", false, false,
- { ISA_VFPv3,ISA_NEON,isa_bit_fp16conv, isa_nobit }
- },
- {
- "simd", false, false,
- { ISA_VFPv4,ISA_NEON, isa_nobit }
- },
- {
- "nosimd", true, false,
- { ISA_ALL_SIMD, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv4-d16", false, true,
- { ISA_VFPv4,ISA_FP_DBL, isa_nobit }
- },
- {
- "neon-vfpv3", false, true,
- { ISA_VFPv3,ISA_NEON, isa_nobit }
- },
- {
- "neon-vfpv4", false, true,
- { ISA_VFPv4,ISA_NEON, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv7_r[] = {
- {
- "fp.sp", false, false,
- { ISA_VFPv3, isa_nobit }
- },
- {
- "fp", false, false,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- {
- "idiv", false, false,
- { isa_bit_adiv, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "noidiv", true, false,
- { isa_bit_adiv, isa_nobit }
- },
- {
- "vfpv3xd", false, true,
- { ISA_VFPv3, isa_nobit }
- },
- {
- "vfpv3-d16", false, true,
- { ISA_VFPv3,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv7e_m[] = {
- {
- "fp", false, false,
- { ISA_VFPv4, isa_nobit }
- },
- {
- "fpv5", false, false,
- { ISA_FPv5, isa_nobit }
- },
- {
- "fp.dp", false, false,
- { ISA_FPv5,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv8_a[] = {
- {
- "crc", false, false,
- { isa_bit_crc32, isa_nobit }
- },
- {
- "simd", false, false,
- { ISA_FP_ARMv8,ISA_NEON, isa_nobit }
- },
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nocrypto", true, false,
- { ISA_ALL_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv8_1_a[] = {
- {
- "simd", false, false,
- { ISA_FP_ARMv8,ISA_NEON, isa_nobit }
- },
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nocrypto", true, false,
- { ISA_ALL_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "vfpv4-sp-d16", false, true,
- { ISA_VFPv4, isa_nobit }
- },
- {
- "fpv5-d16", false, true,
- { ISA_FPv5,ISA_FP_DBL, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv8_2_a[] = {
- {
- "simd", false, false,
- { ISA_FP_ARMv8,ISA_NEON, isa_nobit }
- },
- {
- "fp16", false, false,
- { isa_bit_fp16,ISA_FP_ARMv8,ISA_NEON, isa_nobit }
- },
- {
- "crypto", false, false,
- { ISA_FP_ARMv8,ISA_CRYPTO, isa_nobit }
- },
- {
- "nocrypto", true, false,
- { ISA_ALL_CRYPTO, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-static const struct cpu_arch_extension arch_opttab_armv8_m_main[] = {
- {
- "dsp", false, false,
- { isa_bit_ARMv7em, isa_nobit }
- },
- {
- "fp", false, false,
- { ISA_FPv5, isa_nobit }
- },
- {
- "fp.dp", false, false,
- { ISA_FPv5,ISA_FP_DBL, isa_nobit }
- },
- {
- "nofp", true, false,
- { ISA_ALL_FP, isa_nobit }
- },
- {
- "nodsp", true, false,
- { isa_bit_ARMv7em, isa_nobit }
- },
- { NULL, false, false, {isa_nobit}}
-};
-
-const arch_option all_architectures[] =
-{
- {
- "armv2",
- NULL,
- {
- ISA_ARMv2,isa_bit_mode26,
- isa_nobit
- },
- "2", BASE_ARCH_2,
- TARGET_CPU_arm2,
- },
- {
- "armv2a",
- NULL,
- {
- ISA_ARMv2,isa_bit_mode26,
- isa_nobit
- },
- "2", BASE_ARCH_2,
- TARGET_CPU_arm2,
- },
- {
- "armv3",
- NULL,
- {
- ISA_ARMv3,isa_bit_mode26,
- isa_nobit
- },
- "3", BASE_ARCH_3,
- TARGET_CPU_arm6,
- },
- {
- "armv3m",
- NULL,
- {
- ISA_ARMv3m,isa_bit_mode26,
- isa_nobit
- },
- "3M", BASE_ARCH_3M,
- TARGET_CPU_arm7m,
- },
- {
- "armv4",
- NULL,
- {
- ISA_ARMv4,isa_bit_mode26,
- isa_nobit
- },
- "4", BASE_ARCH_4,
- TARGET_CPU_arm7tdmi,
- },
- {
- "armv4t",
- NULL,
- {
- ISA_ARMv4t,
- isa_nobit
- },
- "4T", BASE_ARCH_4T,
- TARGET_CPU_arm7tdmi,
- },
- {
- "armv5",
- NULL,
- {
- ISA_ARMv5,
- isa_nobit
- },
- "5", BASE_ARCH_5,
- TARGET_CPU_arm10tdmi,
- },
- {
- "armv5t",
- NULL,
- {
- ISA_ARMv5t,
- isa_nobit
- },
- "5T", BASE_ARCH_5T,
- TARGET_CPU_arm10tdmi,
- },
- {
- "armv5e",
- arch_opttab_armv5e,
- {
- ISA_ARMv5e,
- isa_nobit
- },
- "5E", BASE_ARCH_5E,
- TARGET_CPU_arm1026ejs,
- },
- {
- "armv5te",
- arch_opttab_armv5te,
- {
- ISA_ARMv5te,
- isa_nobit
- },
- "5TE", BASE_ARCH_5TE,
- TARGET_CPU_arm1026ejs,
- },
- {
- "armv5tej",
- arch_opttab_armv5tej,
- {
- ISA_ARMv5tej,
- isa_nobit
- },
- "5TEJ", BASE_ARCH_5TEJ,
- TARGET_CPU_arm1026ejs,
- },
- {
- "armv6",
- arch_opttab_armv6,
- {
- ISA_ARMv6,
- isa_nobit
- },
- "6", BASE_ARCH_6,
- TARGET_CPU_arm1136js,
- },
- {
- "armv6j",
- arch_opttab_armv6j,
- {
- ISA_ARMv6j,
- isa_nobit
- },
- "6J", BASE_ARCH_6J,
- TARGET_CPU_arm1136js,
- },
- {
- "armv6k",
- arch_opttab_armv6k,
- {
- ISA_ARMv6k,
- isa_nobit
- },
- "6K", BASE_ARCH_6K,
- TARGET_CPU_mpcore,
- },
- {
- "armv6z",
- arch_opttab_armv6z,
- {
- ISA_ARMv6z,
- isa_nobit
- },
- "6Z", BASE_ARCH_6Z,
- TARGET_CPU_arm1176jzs,
- },
- {
- "armv6kz",
- arch_opttab_armv6kz,
- {
- ISA_ARMv6kz,
- isa_nobit
- },
- "6KZ", BASE_ARCH_6KZ,
- TARGET_CPU_arm1176jzs,
- },
- {
- "armv6zk",
- arch_opttab_armv6zk,
- {
- ISA_ARMv6kz,
- isa_nobit
- },
- "6KZ", BASE_ARCH_6KZ,
- TARGET_CPU_arm1176jzs,
- },
- {
- "armv6t2",
- arch_opttab_armv6t2,
- {
- ISA_ARMv6t2,
- isa_nobit
- },
- "6T2", BASE_ARCH_6T2,
- TARGET_CPU_arm1156t2s,
- },
- {
- "armv6-m",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- },
- "6M", BASE_ARCH_6M,
- TARGET_CPU_cortexm1,
- },
- {
- "armv6s-m",
- NULL,
- {
- ISA_ARMv6m,
- isa_nobit
- },
- "6M", BASE_ARCH_6M,
- TARGET_CPU_cortexm1,
- },
- {
- "armv7",
- arch_opttab_armv7,
- {
- ISA_ARMv7,
- isa_nobit
- },
- "7", BASE_ARCH_7,
- TARGET_CPU_cortexa8,
- },
- {
- "armv7-a",
- arch_opttab_armv7_a,
- {
- ISA_ARMv7a,
- isa_nobit
- },
- "7A", BASE_ARCH_7A,
- TARGET_CPU_cortexa8,
- },
- {
- "armv7ve",
- arch_opttab_armv7ve,
- {
- ISA_ARMv7ve,
- isa_nobit
- },
- "7A", BASE_ARCH_7A,
- TARGET_CPU_cortexa8,
- },
- {
- "armv7-r",
- arch_opttab_armv7_r,
- {
- ISA_ARMv7r,
- isa_nobit
- },
- "7R", BASE_ARCH_7R,
- TARGET_CPU_cortexr4,
- },
- {
- "armv7-m",
- NULL,
- {
- ISA_ARMv7m,
- isa_nobit
- },
- "7M", BASE_ARCH_7M,
- TARGET_CPU_cortexm3,
- },
- {
- "armv7e-m",
- arch_opttab_armv7e_m,
- {
- ISA_ARMv7em,
- isa_nobit
- },
- "7EM", BASE_ARCH_7EM,
- TARGET_CPU_cortexm4,
- },
- {
- "armv8-a",
- arch_opttab_armv8_a,
- {
- ISA_ARMv8a,
- isa_nobit
- },
- "8A", BASE_ARCH_8A,
- TARGET_CPU_cortexa53,
- },
- {
- "armv8.1-a",
- arch_opttab_armv8_1_a,
- {
- ISA_ARMv8_1a,
- isa_nobit
- },
- "8A", BASE_ARCH_8A,
- TARGET_CPU_cortexa53,
- },
- {
- "armv8.2-a",
- arch_opttab_armv8_2_a,
- {
- ISA_ARMv8_2a,
- isa_nobit
- },
- "8A", BASE_ARCH_8A,
- TARGET_CPU_cortexa53,
- },
- {
- "armv8-m.base",
- NULL,
- {
- ISA_ARMv8m_base,
- isa_nobit
- },
- "8M_BASE", BASE_ARCH_8M_BASE,
- TARGET_CPU_cortexm23,
- },
- {
- "armv8-m.main",
- arch_opttab_armv8_m_main,
- {
- ISA_ARMv8m_main,
- isa_nobit
- },
- "8M_MAIN", BASE_ARCH_8M_MAIN,
- TARGET_CPU_cortexm7,
- },
- {
- "iwmmxt",
- NULL,
- {
- ISA_ARMv5te,isa_bit_xscale,isa_bit_iwmmxt,
- isa_nobit
- },
- "5TE", BASE_ARCH_5TE,
- TARGET_CPU_iwmmxt,
- },
- {
- "iwmmxt2",
- NULL,
- {
- ISA_ARMv5te,isa_bit_xscale,isa_bit_iwmmxt,isa_bit_iwmmxt2,
- isa_nobit
- },
- "5TE", BASE_ARCH_5TE,
- TARGET_CPU_iwmmxt2,
- },
- {{NULL, NULL, {isa_nobit}},
- NULL, BASE_ARCH_0, TARGET_CPU_arm_none}
-};
-
-const arm_fpu_desc all_fpus[] =
-{
- {
- "vfp",
- {
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- {
- "vfpv2",
- {
- ISA_VFPv2,ISA_FP_DBL,
- isa_nobit
- }
- },
- {
- "vfpv3",
- {
- ISA_VFPv3,ISA_FP_D32,
- isa_nobit
- }
- },
- {
- "vfpv3-fp16",
- {
- ISA_VFPv3,ISA_FP_D32,isa_bit_fp16conv,
- isa_nobit
- }
- },
- {
- "vfpv3-d16",
- {
- ISA_VFPv3,ISA_FP_DBL,
- isa_nobit
- }
- },
- {
- "vfpv3-d16-fp16",
- {
- ISA_VFPv3,ISA_FP_DBL,isa_bit_fp16conv,
- isa_nobit
- }
- },
- {
- "vfpv3xd",
- {
- ISA_VFPv3,
- isa_nobit
- }
- },
- {
- "vfpv3xd-fp16",
- {
- ISA_VFPv3,isa_bit_fp16conv,
- isa_nobit
- }
- },
- {
- "neon",
- {
- ISA_VFPv3,ISA_NEON,
- isa_nobit
- }
- },
- {
- "neon-vfpv3",
- {
- ISA_VFPv3,ISA_NEON,
- isa_nobit
- }
- },
- {
- "neon-fp16",
- {
- ISA_VFPv3,ISA_NEON,isa_bit_fp16conv,
- isa_nobit
- }
- },
- {
- "vfpv4",
- {
- ISA_VFPv4,ISA_FP_D32,
- isa_nobit
- }
- },
- {
- "neon-vfpv4",
- {
- ISA_VFPv4,ISA_NEON,
- isa_nobit
- }
- },
- {
- "vfpv4-d16",
- {
- ISA_VFPv4,ISA_FP_DBL,
- isa_nobit
- }
- },
- {
- "fpv4-sp-d16",
- {
- ISA_VFPv4,
- isa_nobit
- }
- },
- {
- "fpv5-sp-d16",
- {
- ISA_FPv5,
- isa_nobit
- }
- },
- {
- "fpv5-d16",
- {
- ISA_FPv5,ISA_FP_DBL,
- isa_nobit
- }
- },
- {
- "fp-armv8",
- {
- ISA_FP_ARMv8,ISA_FP_D32,
- isa_nobit
- }
- },
- {
- "neon-fp-armv8",
- {
- ISA_FP_ARMv8,ISA_NEON,
- isa_nobit
- }
- },
- {
- "crypto-neon-fp-armv8",
- {
- ISA_FP_ARMv8,ISA_CRYPTO,
- isa_nobit
- }
- },
- {
- "vfp3",
- {
- ISA_VFPv3,ISA_FP_D32,
- isa_nobit
- }
- },
-};
diff --git a/gcc/config/arm/arm-cpu-data.h b/gcc/config/arm/arm-cpu-data.h
deleted file mode 100644
index d42021d15c7..00000000000
--- a/gcc/config/arm/arm-cpu-data.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/* -*- buffer-read-only: t -*-
- Generated automatically by parsecpu.awk from arm-cpus.in.
- Do not edit.
-
- Copyright (C) 2011-2017 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/>. */
-
-static const cpu_tune all_tunes[] =
-{
- { /* arm2. */
- TARGET_CPU_arm2,
- (TF_CO_PROC | TF_NO_MODE32),
- &arm_slowmul_tune
- },
- { /* arm250. */
- TARGET_CPU_arm250,
- (TF_CO_PROC | TF_NO_MODE32),
- &arm_slowmul_tune
- },
- { /* arm3. */
- TARGET_CPU_arm3,
- (TF_CO_PROC | TF_NO_MODE32),
- &arm_slowmul_tune
- },
- { /* arm6. */
- TARGET_CPU_arm6,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm60. */
- TARGET_CPU_arm60,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm600. */
- TARGET_CPU_arm600,
- (TF_CO_PROC | TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm610. */
- TARGET_CPU_arm610,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm620. */
- TARGET_CPU_arm620,
- (TF_CO_PROC | TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm7. */
- TARGET_CPU_arm7,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm7d. */
- TARGET_CPU_arm7d,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm7di. */
- TARGET_CPU_arm7di,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm70. */
- TARGET_CPU_arm70,
- (TF_CO_PROC),
- &arm_slowmul_tune
- },
- { /* arm700. */
- TARGET_CPU_arm700,
- (TF_CO_PROC | TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm700i. */
- TARGET_CPU_arm700i,
- (TF_CO_PROC | TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm710. */
- TARGET_CPU_arm710,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm720. */
- TARGET_CPU_arm720,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm710c. */
- TARGET_CPU_arm710c,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm7100. */
- TARGET_CPU_arm7100,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm7500. */
- TARGET_CPU_arm7500,
- (TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm7500fe. */
- TARGET_CPU_arm7500fe,
- (TF_CO_PROC | TF_WBUF),
- &arm_slowmul_tune
- },
- { /* arm7m. */
- TARGET_CPU_arm7m,
- (TF_CO_PROC),
- &arm_fastmul_tune
- },
- { /* arm7dm. */
- TARGET_CPU_arm7dm,
- (TF_CO_PROC),
- &arm_fastmul_tune
- },
- { /* arm7dmi. */
- TARGET_CPU_arm7dmi,
- (TF_CO_PROC),
- &arm_fastmul_tune
- },
- { /* arm8. */
- TARGET_CPU_arm8,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm810. */
- TARGET_CPU_arm810,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* strongarm. */
- TARGET_CPU_strongarm,
- (TF_LDSCHED | TF_STRONG),
- &arm_strongarm_tune
- },
- { /* strongarm110. */
- TARGET_CPU_strongarm110,
- (TF_LDSCHED | TF_STRONG),
- &arm_strongarm_tune
- },
- { /* strongarm1100. */
- TARGET_CPU_strongarm1100,
- (TF_LDSCHED | TF_STRONG),
- &arm_strongarm_tune
- },
- { /* strongarm1110. */
- TARGET_CPU_strongarm1110,
- (TF_LDSCHED | TF_STRONG),
- &arm_strongarm_tune
- },
- { /* fa526. */
- TARGET_CPU_fa526,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* fa626. */
- TARGET_CPU_fa626,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm7tdmi. */
- TARGET_CPU_arm7tdmi,
- (TF_CO_PROC),
- &arm_fastmul_tune
- },
- { /* arm7tdmi-s. */
- TARGET_CPU_arm7tdmis,
- (TF_CO_PROC),
- &arm_fastmul_tune
- },
- { /* arm710t. */
- TARGET_CPU_arm710t,
- (TF_WBUF),
- &arm_fastmul_tune
- },
- { /* arm720t. */
- TARGET_CPU_arm720t,
- (TF_WBUF),
- &arm_fastmul_tune
- },
- { /* arm740t. */
- TARGET_CPU_arm740t,
- (TF_WBUF),
- &arm_fastmul_tune
- },
- { /* arm9. */
- TARGET_CPU_arm9,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm9tdmi. */
- TARGET_CPU_arm9tdmi,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm920. */
- TARGET_CPU_arm920,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm920t. */
- TARGET_CPU_arm920t,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm922t. */
- TARGET_CPU_arm922t,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm940t. */
- TARGET_CPU_arm940t,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* ep9312. */
- TARGET_CPU_ep9312,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm10tdmi. */
- TARGET_CPU_arm10tdmi,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm1020t. */
- TARGET_CPU_arm1020t,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm9e. */
- TARGET_CPU_arm9e,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm946e-s. */
- TARGET_CPU_arm946es,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm966e-s. */
- TARGET_CPU_arm966es,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm968e-s. */
- TARGET_CPU_arm968es,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm10e. */
- TARGET_CPU_arm10e,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm1020e. */
- TARGET_CPU_arm1020e,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* arm1022e. */
- TARGET_CPU_arm1022e,
- (TF_LDSCHED),
- &arm_fastmul_tune
- },
- { /* xscale. */
- TARGET_CPU_xscale,
- (TF_LDSCHED | TF_XSCALE),
- &arm_xscale_tune
- },
- { /* iwmmxt. */
- TARGET_CPU_iwmmxt,
- (TF_LDSCHED | TF_XSCALE),
- &arm_xscale_tune
- },
- { /* iwmmxt2. */
- TARGET_CPU_iwmmxt2,
- (TF_LDSCHED | TF_XSCALE),
- &arm_xscale_tune
- },
- { /* fa606te. */
- TARGET_CPU_fa606te,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* fa626te. */
- TARGET_CPU_fa626te,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* fmp626. */
- TARGET_CPU_fmp626,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* fa726te. */
- TARGET_CPU_fa726te,
- (TF_LDSCHED),
- &arm_fa726te_tune
- },
- { /* arm926ej-s. */
- TARGET_CPU_arm926ejs,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1026ej-s. */
- TARGET_CPU_arm1026ejs,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1136j-s. */
- TARGET_CPU_arm1136js,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1136jf-s. */
- TARGET_CPU_arm1136jfs,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1176jz-s. */
- TARGET_CPU_arm1176jzs,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1176jzf-s. */
- TARGET_CPU_arm1176jzfs,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* mpcorenovfp. */
- TARGET_CPU_mpcorenovfp,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* mpcore. */
- TARGET_CPU_mpcore,
- (TF_LDSCHED),
- &arm_9e_tune
- },
- { /* arm1156t2-s. */
- TARGET_CPU_arm1156t2s,
- (TF_LDSCHED),
- &arm_v6t2_tune
- },
- { /* arm1156t2f-s. */
- TARGET_CPU_arm1156t2fs,
- (TF_LDSCHED),
- &arm_v6t2_tune
- },
- { /* cortex-m1. */
- TARGET_CPU_cortexm1,
- (TF_LDSCHED),
- &arm_v6m_tune
- },
- { /* cortex-m0. */
- TARGET_CPU_cortexm0,
- (TF_LDSCHED),
- &arm_v6m_tune
- },
- { /* cortex-m0plus. */
- TARGET_CPU_cortexm0plus,
- (TF_LDSCHED),
- &arm_v6m_tune
- },
- { /* cortex-m1.small-multiply. */
- TARGET_CPU_cortexm1,
- (TF_LDSCHED | TF_SMALLMUL),
- &arm_v6m_tune
- },
- { /* cortex-m0.small-multiply. */
- TARGET_CPU_cortexm0,
- (TF_LDSCHED | TF_SMALLMUL),
- &arm_v6m_tune
- },
- { /* cortex-m0plus.small-multiply. */
- TARGET_CPU_cortexm0plus,
- (TF_LDSCHED | TF_SMALLMUL),
- &arm_v6m_tune
- },
- { /* generic-armv7-a. */
- TARGET_CPU_genericv7a,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-a5. */
- TARGET_CPU_cortexa5,
- (TF_LDSCHED),
- &arm_cortex_a5_tune
- },
- { /* cortex-a7. */
- TARGET_CPU_cortexa7,
- (TF_LDSCHED),
- &arm_cortex_a7_tune
- },
- { /* cortex-a8. */
- TARGET_CPU_cortexa8,
- (TF_LDSCHED),
- &arm_cortex_a8_tune
- },
- { /* cortex-a9. */
- TARGET_CPU_cortexa9,
- (TF_LDSCHED),
- &arm_cortex_a9_tune
- },
- { /* cortex-a12. */
- TARGET_CPU_cortexa17,
- (TF_LDSCHED),
- &arm_cortex_a12_tune
- },
- { /* cortex-a15. */
- TARGET_CPU_cortexa15,
- (TF_LDSCHED),
- &arm_cortex_a15_tune
- },
- { /* cortex-a17. */
- TARGET_CPU_cortexa17,
- (TF_LDSCHED),
- &arm_cortex_a12_tune
- },
- { /* cortex-r4. */
- TARGET_CPU_cortexr4,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-r4f. */
- TARGET_CPU_cortexr4f,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-r5. */
- TARGET_CPU_cortexr5,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-r7. */
- TARGET_CPU_cortexr7,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-r8. */
- TARGET_CPU_cortexr7,
- (TF_LDSCHED),
- &arm_cortex_tune
- },
- { /* cortex-m7. */
- TARGET_CPU_cortexm7,
- (TF_LDSCHED),
- &arm_cortex_m7_tune
- },
- { /* cortex-m4. */
- TARGET_CPU_cortexm4,
- (TF_LDSCHED),
- &arm_v7m_tune
- },
- { /* cortex-m3. */
- TARGET_CPU_cortexm3,
- (TF_LDSCHED),
- &arm_v7m_tune
- },
- { /* marvell-pj4. */
- TARGET_CPU_marvell_pj4,
- (TF_LDSCHED),
- &arm_marvell_pj4_tune
- },
- { /* cortex-a15.cortex-a7. */
- TARGET_CPU_cortexa7,
- (TF_LDSCHED),
- &arm_cortex_a15_tune
- },
- { /* cortex-a17.cortex-a7. */
- TARGET_CPU_cortexa7,
- (TF_LDSCHED),
- &arm_cortex_a12_tune
- },
- { /* cortex-a32. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a35_tune
- },
- { /* cortex-a35. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a35_tune
- },
- { /* cortex-a53. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a53_tune
- },
- { /* cortex-a57. */
- TARGET_CPU_cortexa57,
- (TF_LDSCHED),
- &arm_cortex_a57_tune
- },
- { /* cortex-a72. */
- TARGET_CPU_cortexa57,
- (TF_LDSCHED),
- &arm_cortex_a57_tune
- },
- { /* cortex-a73. */
- TARGET_CPU_cortexa57,
- (TF_LDSCHED),
- &arm_cortex_a73_tune
- },
- { /* exynos-m1. */
- TARGET_CPU_exynosm1,
- (TF_LDSCHED),
- &arm_exynosm1_tune
- },
- { /* xgene1. */
- TARGET_CPU_xgene1,
- (TF_LDSCHED),
- &arm_xgene1_tune
- },
- { /* cortex-a57.cortex-a53. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a57_tune
- },
- { /* cortex-a72.cortex-a53. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a57_tune
- },
- { /* cortex-a73.cortex-a35. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a73_tune
- },
- { /* cortex-a73.cortex-a53. */
- TARGET_CPU_cortexa53,
- (TF_LDSCHED),
- &arm_cortex_a73_tune
- },
- { /* cortex-m23. */
- TARGET_CPU_cortexm23,
- (TF_LDSCHED),
- &arm_v6m_tune
- },
- { /* cortex-m33. */
- TARGET_CPU_cortexm33,
- (TF_LDSCHED),
- &arm_v7m_tune
- },
- {TARGET_CPU_arm_none, 0, NULL}
-};
diff --git a/gcc/config/arm/arm-cpu.h b/gcc/config/arm/arm-cpu.h
deleted file mode 100644
index e27634c6dd9..00000000000
--- a/gcc/config/arm/arm-cpu.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/* -*- buffer-read-only: t -*-
- Generated automatically by parsecpu.awk from arm-cpus.in.
- Do not edit.
-
- Copyright (C) 2011-2017 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 processor_type
-{
- TARGET_CPU_arm2,
- TARGET_CPU_arm250,
- TARGET_CPU_arm3,
- TARGET_CPU_arm6,
- TARGET_CPU_arm60,
- TARGET_CPU_arm600,
- TARGET_CPU_arm610,
- TARGET_CPU_arm620,
- TARGET_CPU_arm7,
- TARGET_CPU_arm7d,
- TARGET_CPU_arm7di,
- TARGET_CPU_arm70,
- TARGET_CPU_arm700,
- TARGET_CPU_arm700i,
- TARGET_CPU_arm710,
- TARGET_CPU_arm720,
- TARGET_CPU_arm710c,
- TARGET_CPU_arm7100,
- TARGET_CPU_arm7500,
- TARGET_CPU_arm7500fe,
- TARGET_CPU_arm7m,
- TARGET_CPU_arm7dm,
- TARGET_CPU_arm7dmi,
- TARGET_CPU_arm8,
- TARGET_CPU_arm810,
- TARGET_CPU_strongarm,
- TARGET_CPU_strongarm110,
- TARGET_CPU_strongarm1100,
- TARGET_CPU_strongarm1110,
- TARGET_CPU_fa526,
- TARGET_CPU_fa626,
- TARGET_CPU_arm7tdmi,
- TARGET_CPU_arm7tdmis,
- TARGET_CPU_arm710t,
- TARGET_CPU_arm720t,
- TARGET_CPU_arm740t,
- TARGET_CPU_arm9,
- TARGET_CPU_arm9tdmi,
- TARGET_CPU_arm920,
- TARGET_CPU_arm920t,
- TARGET_CPU_arm922t,
- TARGET_CPU_arm940t,
- TARGET_CPU_ep9312,
- TARGET_CPU_arm10tdmi,
- TARGET_CPU_arm1020t,
- TARGET_CPU_arm9e,
- TARGET_CPU_arm946es,
- TARGET_CPU_arm966es,
- TARGET_CPU_arm968es,
- TARGET_CPU_arm10e,
- TARGET_CPU_arm1020e,
- TARGET_CPU_arm1022e,
- TARGET_CPU_xscale,
- TARGET_CPU_iwmmxt,
- TARGET_CPU_iwmmxt2,
- TARGET_CPU_fa606te,
- TARGET_CPU_fa626te,
- TARGET_CPU_fmp626,
- TARGET_CPU_fa726te,
- TARGET_CPU_arm926ejs,
- TARGET_CPU_arm1026ejs,
- TARGET_CPU_arm1136js,
- TARGET_CPU_arm1136jfs,
- TARGET_CPU_arm1176jzs,
- TARGET_CPU_arm1176jzfs,
- TARGET_CPU_mpcorenovfp,
- TARGET_CPU_mpcore,
- TARGET_CPU_arm1156t2s,
- TARGET_CPU_arm1156t2fs,
- TARGET_CPU_cortexm1,
- TARGET_CPU_cortexm0,
- TARGET_CPU_cortexm0plus,
- TARGET_CPU_cortexm1smallmultiply,
- TARGET_CPU_cortexm0smallmultiply,
- TARGET_CPU_cortexm0plussmallmultiply,
- TARGET_CPU_genericv7a,
- TARGET_CPU_cortexa5,
- TARGET_CPU_cortexa7,
- TARGET_CPU_cortexa8,
- TARGET_CPU_cortexa9,
- TARGET_CPU_cortexa12,
- TARGET_CPU_cortexa15,
- TARGET_CPU_cortexa17,
- TARGET_CPU_cortexr4,
- TARGET_CPU_cortexr4f,
- TARGET_CPU_cortexr5,
- TARGET_CPU_cortexr7,
- TARGET_CPU_cortexr8,
- TARGET_CPU_cortexm7,
- TARGET_CPU_cortexm4,
- TARGET_CPU_cortexm3,
- TARGET_CPU_marvell_pj4,
- TARGET_CPU_cortexa15cortexa7,
- TARGET_CPU_cortexa17cortexa7,
- TARGET_CPU_cortexa32,
- TARGET_CPU_cortexa35,
- TARGET_CPU_cortexa53,
- TARGET_CPU_cortexa57,
- TARGET_CPU_cortexa72,
- TARGET_CPU_cortexa73,
- TARGET_CPU_exynosm1,
- TARGET_CPU_xgene1,
- TARGET_CPU_cortexa57cortexa53,
- TARGET_CPU_cortexa72cortexa53,
- TARGET_CPU_cortexa73cortexa35,
- TARGET_CPU_cortexa73cortexa53,
- TARGET_CPU_cortexm23,
- TARGET_CPU_cortexm33,
- TARGET_CPU_arm_none
-};
-
-enum arch_type
-{
- TARGET_ARCH_armv2,
- TARGET_ARCH_armv2a,
- TARGET_ARCH_armv3,
- TARGET_ARCH_armv3m,
- TARGET_ARCH_armv4,
- TARGET_ARCH_armv4t,
- TARGET_ARCH_armv5,
- TARGET_ARCH_armv5t,
- TARGET_ARCH_armv5e,
- TARGET_ARCH_armv5te,
- TARGET_ARCH_armv5tej,
- TARGET_ARCH_armv6,
- TARGET_ARCH_armv6j,
- TARGET_ARCH_armv6k,
- TARGET_ARCH_armv6z,
- TARGET_ARCH_armv6kz,
- TARGET_ARCH_armv6zk,
- TARGET_ARCH_armv6t2,
- TARGET_ARCH_armv6_m,
- TARGET_ARCH_armv6s_m,
- TARGET_ARCH_armv7,
- TARGET_ARCH_armv7_a,
- TARGET_ARCH_armv7ve,
- TARGET_ARCH_armv7_r,
- TARGET_ARCH_armv7_m,
- TARGET_ARCH_armv7e_m,
- TARGET_ARCH_armv8_a,
- TARGET_ARCH_armv8_1_a,
- TARGET_ARCH_armv8_2_a,
- TARGET_ARCH_armv8_m_base,
- TARGET_ARCH_armv8_m_main,
- TARGET_ARCH_iwmmxt,
- TARGET_ARCH_iwmmxt2,
- TARGET_ARCH_arm_none
-};
-
-enum fpu_type
-{
- TARGET_FPU_vfp,
- TARGET_FPU_vfpv2,
- TARGET_FPU_vfpv3,
- TARGET_FPU_vfpv3_fp16,
- TARGET_FPU_vfpv3_d16,
- TARGET_FPU_vfpv3_d16_fp16,
- TARGET_FPU_vfpv3xd,
- TARGET_FPU_vfpv3xd_fp16,
- TARGET_FPU_neon,
- TARGET_FPU_neon_vfpv3,
- TARGET_FPU_neon_fp16,
- TARGET_FPU_vfpv4,
- TARGET_FPU_neon_vfpv4,
- TARGET_FPU_vfpv4_d16,
- TARGET_FPU_fpv4_sp_d16,
- TARGET_FPU_fpv5_sp_d16,
- TARGET_FPU_fpv5_d16,
- TARGET_FPU_fp_armv8,
- TARGET_FPU_neon_fp_armv8,
- TARGET_FPU_crypto_neon_fp_armv8,
- TARGET_FPU_vfp3,
- TARGET_FPU_auto
-};
diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index 43f4ebcc5f7..d009a9e18ac 100644
--- a/gcc/config/arm/arm-cpus.in
+++ b/gcc/config/arm/arm-cpus.in
@@ -46,6 +46,7 @@
# tune for <cpu>
# [tune flags <list>]
# base <name>
+# [profile <A|R|M>]
# isa <isa-flags-list>
# end arch <name>
#
@@ -211,12 +212,14 @@ end arch armv6t2
begin arch armv6-m
tune for cortex-m1
base 6M
+ profile M
isa ARMv6m
end arch armv6-m
begin arch armv6s-m
tune for cortex-m1
base 6M
+ profile M
isa ARMv6m
end arch armv6s-m
@@ -235,6 +238,7 @@ begin arch armv7-a
tune for cortex-a8
tune flags CO_PROC
base 7A
+ profile A
isa ARMv7a
# fp => VFPv3-d16, simd => neon-vfpv3
option fp add VFPv3 FP_DBL
@@ -257,6 +261,7 @@ begin arch armv7ve
tune for cortex-a8
tune flags CO_PROC
base 7A
+ profile A
isa ARMv7ve
# fp => VFPv4-d16, simd => neon-vfpv4
option vfpv3-d16 add VFPv3 FP_DBL
@@ -279,6 +284,7 @@ begin arch armv7-r
tune for cortex-r4
tune flags CO_PROC
base 7R
+ profile R
isa ARMv7r
# ARMv7-r uses VFPv3-d16
option fp.sp add VFPv3
@@ -294,6 +300,7 @@ begin arch armv7-m
tune for cortex-m3
tune flags CO_PROC
base 7M
+ profile M
isa ARMv7m
# In theory FP is permitted in v7-m, but in practice no implementations exist.
# leave it out for now.
@@ -303,6 +310,7 @@ begin arch armv7e-m
tune for cortex-m4
tune flags CO_PROC
base 7EM
+ profile M
isa ARMv7em
# fp => VFPv4-sp-d16; fpv5 => FPv5-sp-d16; fp.dp => FPv5-d16
option fp add VFPv4
@@ -317,6 +325,7 @@ begin arch armv8-a
tune for cortex-a53
tune flags CO_PROC
base 8A
+ profile A
isa ARMv8a
option crc add bit_crc32
option simd add FP_ARMv8 NEON
@@ -329,6 +338,7 @@ begin arch armv8.1-a
tune for cortex-a53
tune flags CO_PROC
base 8A
+ profile A
isa ARMv8_1a
option simd add FP_ARMv8 NEON
option crypto add FP_ARMv8 CRYPTO
@@ -340,6 +350,7 @@ begin arch armv8.2-a
tune for cortex-a53
tune flags CO_PROC
base 8A
+ profile A
isa ARMv8_2a
option simd add FP_ARMv8 NEON
option fp16 add bit_fp16 FP_ARMv8 NEON
@@ -351,6 +362,7 @@ end arch armv8.2-a
begin arch armv8-m.base
tune for cortex-m23
base 8M_BASE
+ profile M
isa ARMv8m_base
end arch armv8-m.base
@@ -358,6 +370,7 @@ begin arch armv8-m.main
tune for cortex-m7
tune flags CO_PROC
base 8M_MAIN
+ profile M
isa ARMv8m_main
option dsp add bit_ARMv7em
# fp => FPv5-sp-d16; fp.dp => FPv5-d16
@@ -367,6 +380,22 @@ begin arch armv8-m.main
option nodsp remove bit_ARMv7em
end arch armv8-m.main
+begin arch armv8-r
+ tune for cortex-r52
+ tune flags CO_PROC
+ base 8R
+ profile R
+ isa ARMv8r
+ option crc add bit_crc32
+# fp.sp => fp-armv8 (d16); simd => simd + fp-armv8 + d32 + double precision
+# note: no fp option for fp-armv8 (d16) + double precision at the moment
+ option fp.sp add FPv5
+ option simd add FP_ARMv8 NEON
+ option crypto add FP_ARMv8 CRYPTO
+ option nocrypto remove ALL_CRYPTO
+ option nofp remove ALL_FP
+end arch armv8-r
+
begin arch iwmmxt
tune for iwmmxt
tune flags LDSCHED STRONG XSCALE
@@ -1193,7 +1222,6 @@ begin cpu xgene1
costs xgene1
end cpu xgene1
-
# V8 A-profile big.LITTLE implementations
begin cpu cortex-a57.cortex-a53
cname cortexa57cortexa53
@@ -1236,6 +1264,40 @@ begin cpu cortex-a73.cortex-a53
end cpu cortex-a73.cortex-a53
+# ARMv8.2 A-profile Architecture Processors
+begin cpu cortex-a55
+ cname cortexa55
+ tune for cortex-a53
+ tune flags LDSCHED
+ architecture armv8.2-a+fp16
+ fpu neon-fp-armv8
+ option crypto add FP_ARMv8 CRYPTO
+ option nofp remove ALL_FP
+ costs cortex_a53
+end cpu cortex-a55
+
+begin cpu cortex-a75
+ cname cortexa75
+ tune for cortex-a57
+ tune flags LDSCHED
+ architecture armv8.2-a+fp16
+ fpu neon-fp-armv8
+ option crypto add FP_ARMv8 CRYPTO
+ costs cortex_a73
+end cpu cortex-a75
+
+
+# ARMv8.2 A-profile ARM DynamIQ big.LITTLE implementations
+begin cpu cortex-a75.cortex-a55
+ cname cortexa75cortexa55
+ tune for cortex-a53
+ tune flags LDSCHED
+ architecture armv8.2-a+fp16
+ fpu neon-fp-armv8
+ option crypto add FP_ARMv8 CRYPTO
+ costs cortex_a73
+end cpu cortex-a75.cortex-a55
+
# V8 M-profile implementations.
begin cpu cortex-m23
cname cortexm23
@@ -1253,6 +1315,16 @@ begin cpu cortex-m33
costs v7m
end cpu cortex-m33
+# V8 R-profile implementations.
+begin cpu cortex-r52
+ cname cortexr52
+ tune flags LDSCHED
+ architecture armv8-r+crc+simd
+ fpu neon-fp-armv8
+ option nofp.dp remove FP_DBL ALL_SIMD
+ costs cortex
+end cpu cortex-r52
+
# FPU entries
# format:
# begin fpu <name>
@@ -1328,7 +1400,7 @@ begin fpu fpv5-d16
end fpu fpv5-d16
begin fpu fp-armv8
- isa FP_ARMv8 FP_D32
+ isa FP_ARMv8
end fpu fp-armv8
begin fpu neon-fp-armv8
diff --git a/gcc/config/arm/arm-isa.h b/gcc/config/arm/arm-isa.h
index 4b5a0f658e6..dbd29eaa52f 100644
--- a/gcc/config/arm/arm-isa.h
+++ b/gcc/config/arm/arm-isa.h
@@ -40,7 +40,8 @@ enum isa_feature
isa_bit_ARMv6, /* Architecture rel 6. */
isa_bit_ARMv6k, /* Architecture rel 6k. */
isa_bit_thumb2, /* Thumb-2. */
- isa_bit_notm, /* Instructions that are not present in 'M' profile. */
+ isa_bit_notm, /* Instructions not present in 'M' profile. */
+ isa_bit_be8, /* Architecture uses be8 mode in big-endian. */
isa_bit_tdiv, /* Thumb division instructions. */
isa_bit_ARMv7em, /* Architecture rel 7e-m. */
isa_bit_ARMv7, /* Architecture rel 7. */
@@ -59,7 +60,6 @@ enum isa_feature
isa_bit_VFPv4, /* Vector floating point v4. */
isa_bit_FPv5, /* Floating point v5. */
isa_bit_lpae, /* ARMv7-A LPAE. */
- isa_bit_FP_ARMv8, /* ARMv8 floating-point extension. */
isa_bit_neon, /* Advanced SIMD instructions. */
isa_bit_fp16conv, /* Conversions to/from fp16 (VFPv3 extension). */
isa_bit_fp_dbl, /* Double precision operations supported. */
@@ -101,7 +101,7 @@ enum isa_feature
#define ISA_ARMv5e ISA_ARMv5, isa_bit_ARMv5e
#define ISA_ARMv5te ISA_ARMv5e, isa_bit_thumb
#define ISA_ARMv5tej ISA_ARMv5te
-#define ISA_ARMv6 ISA_ARMv5te, isa_bit_ARMv6
+#define ISA_ARMv6 ISA_ARMv5te, isa_bit_ARMv6, isa_bit_be8
#define ISA_ARMv6j ISA_ARMv6
#define ISA_ARMv6k ISA_ARMv6, isa_bit_ARMv6k
#define ISA_ARMv6z ISA_ARMv6
@@ -126,6 +126,7 @@ enum isa_feature
#define ISA_ARMv8_2a ISA_ARMv8_1a, isa_bit_ARMv8_2
#define ISA_ARMv8m_base ISA_ARMv6m, isa_bit_ARMv8, isa_bit_cmse, isa_bit_tdiv
#define ISA_ARMv8m_main ISA_ARMv7m, isa_bit_ARMv8, isa_bit_cmse
+#define ISA_ARMv8r ISA_ARMv8a
/* List of all cryptographic extensions to stripout if crypto is
disabled. Currently, that's trivial, but we define it anyway for
@@ -141,7 +142,7 @@ enum isa_feature
default. isa_bit_fp16 is deliberately missing from this list. */
#define ISA_ALL_FPU_INTERNAL \
isa_bit_VFPv2, isa_bit_VFPv3, isa_bit_VFPv4, isa_bit_FPv5, \
- isa_bit_FP_ARMv8, isa_bit_fp16conv, isa_bit_fp_dbl, ISA_ALL_SIMD
+ isa_bit_fp16conv, isa_bit_fp_dbl, ISA_ALL_SIMD
/* Similarly, but including fp16 and other extensions that aren't part of
-mfpu support. */
@@ -152,10 +153,10 @@ enum isa_feature
#define ISA_VFPv3 ISA_VFPv2, isa_bit_VFPv3
#define ISA_VFPv4 ISA_VFPv3, isa_bit_VFPv4, isa_bit_fp16conv
#define ISA_FPv5 ISA_VFPv4, isa_bit_FPv5
-#define ISA_FP_ARMv8 ISA_FPv5, isa_bit_FP_ARMv8
#define ISA_FP_DBL isa_bit_fp_dbl
#define ISA_FP_D32 ISA_FP_DBL, isa_bit_fp_d32
+#define ISA_FP_ARMv8 ISA_FPv5, ISA_FP_D32
#define ISA_NEON ISA_FP_D32, isa_bit_neon
#define ISA_CRYPTO ISA_NEON, isa_bit_crypto
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 25210e2375a..25fb10c32d1 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -47,7 +47,7 @@ extern unsigned int arm_dbx_register_number (unsigned int);
extern void arm_output_fn_unwind (FILE *, bool);
extern rtx arm_expand_builtin (tree exp, rtx target, rtx subtarget
- ATTRIBUTE_UNUSED, enum machine_mode mode
+ ATTRIBUTE_UNUSED, machine_mode mode
ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED);
extern tree arm_builtin_decl (unsigned code, bool initialize_p
ATTRIBUTE_UNUSED);
@@ -464,6 +464,8 @@ struct arm_build_target
const char *arch_pp_name;
/* The base architecture value. */
enum base_architecture base_arch;
+ /* The profile letter for the architecture, upper case by convention. */
+ char profile;
/* Bitmap encapsulating the isa_bits for the target environment. */
sbitmap isa;
/* Flags used for tuning. Long term, these move into tune_params. */
@@ -507,6 +509,8 @@ struct arch_option
const char *arch;
/* Base architecture, from which this specific architecture is derived. */
enum base_architecture base_arch;
+ /* The profile letter for the architecture, upper case by convention. */
+ const char profile;
/* Default tune target (in the absence of any more specific data). */
enum processor_type tune_id;
};
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index 0f50c64f4b1..4e508b1555a 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -343,11 +343,23 @@ EnumValue
Enum(processor_type) String(cortex-a73.cortex-a53) Value( TARGET_CPU_cortexa73cortexa53)
EnumValue
+Enum(processor_type) String(cortex-a55) Value( TARGET_CPU_cortexa55)
+
+EnumValue
+Enum(processor_type) String(cortex-a75) Value( TARGET_CPU_cortexa75)
+
+EnumValue
+Enum(processor_type) String(cortex-a75.cortex-a55) Value( TARGET_CPU_cortexa75cortexa55)
+
+EnumValue
Enum(processor_type) String(cortex-m23) Value( TARGET_CPU_cortexm23)
EnumValue
Enum(processor_type) String(cortex-m33) Value( TARGET_CPU_cortexm33)
+EnumValue
+Enum(processor_type) String(cortex-r52) Value( TARGET_CPU_cortexr52)
+
Enum
Name(arm_arch) Type(int)
Known ARM architectures (for use with the -march= option):
@@ -446,10 +458,13 @@ EnumValue
Enum(arm_arch) String(armv8-m.main) Value(30)
EnumValue
-Enum(arm_arch) String(iwmmxt) Value(31)
+Enum(arm_arch) String(armv8-r) Value(31)
+
+EnumValue
+Enum(arm_arch) String(iwmmxt) Value(32)
EnumValue
-Enum(arm_arch) String(iwmmxt2) Value(32)
+Enum(arm_arch) String(iwmmxt2) Value(33)
Enum
Name(arm_fpu) Type(enum fpu_type)
diff --git a/gcc/config/arm/arm-tune.md b/gcc/config/arm/arm-tune.md
index 6252d42d4d8..1b3f7a94cc7 100644
--- a/gcc/config/arm/arm-tune.md
+++ b/gcc/config/arm/arm-tune.md
@@ -56,5 +56,7 @@
cortexa53,cortexa57,cortexa72,
cortexa73,exynosm1,xgene1,
cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,
- cortexa73cortexa53,cortexm23,cortexm33"
+ cortexa73cortexa53,cortexa55,cortexa75,
+ cortexa75cortexa55,cortexm23,cortexm33,
+ cortexr52"
(const (symbol_ref "((enum attr_tune) arm_tune)")))
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f3b2715185b..25677d19e20 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -110,6 +110,7 @@ static void arm_print_operand_address (FILE *, machine_mode, rtx);
static bool arm_print_operand_punct_valid_p (unsigned char code);
static const char *fp_const_from_val (REAL_VALUE_TYPE *);
static arm_cc get_arm_condition_code (rtx);
+static bool arm_fixed_condition_code_regs (unsigned int *, unsigned int *);
static const char *output_multi_immediate (rtx *, const char *, const char *,
int, HOST_WIDE_INT);
static const char *shift_op (rtx, HOST_WIDE_INT *);
@@ -775,6 +776,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS arm_fixed_condition_code_regs
+
/* Obstack for minipool constant handling. */
static struct obstack minipool_obstack;
@@ -3273,6 +3277,7 @@ arm_configure_build_target (struct arm_build_target *target,
/* Finish initializing the target structure. */
target->arch_pp_name = arm_selected_arch->arch;
target->base_arch = arm_selected_arch->base_arch;
+ target->profile = arm_selected_arch->profile;
target->tune_flags = tune_data->tune_flags;
target->tune = tune_data->tune;
@@ -3484,6 +3489,8 @@ arm_option_override (void)
}
else
{
+ warning (0, "option %<-mstructure-size-boundary%> is deprecated");
+
if (arm_structure_size_boundary != 8
&& arm_structure_size_boundary != 32
&& !(ARM_DOUBLEWORD_ALIGN && arm_structure_size_boundary == 64))
@@ -10750,7 +10757,7 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
{
if (speed_p)
*cost += extra_cost->fp[mode == DFmode].widen;
- if (!TARGET_FPU_ARMV8
+ if (!TARGET_VFP5
&& GET_MODE (XEXP (x, 0)) == HFmode)
{
/* Pre v8, widening HF->DF is a two-step process, first
@@ -10844,7 +10851,7 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
return true;
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && TARGET_FPU_ARMV8)
+ && TARGET_VFP5)
{
if (speed_p)
*cost += extra_cost->fp[mode == DFmode].roundint;
@@ -13614,10 +13621,7 @@ gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
offset = 0;
if (!TARGET_THUMB1)
- {
- base_reg = regs[0];
- base_reg_rtx = newbase;
- }
+ base_reg_rtx = newbase;
}
for (i = 0; i < nops; i++)
@@ -14141,7 +14145,6 @@ arm_gen_movmemqi (rtx *operands)
{
HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
HOST_WIDE_INT srcoffset, dstoffset;
- int i;
rtx src, dst, srcbase, dstbase;
rtx part_bytes_reg = NULL;
rtx mem;
@@ -14171,7 +14174,7 @@ arm_gen_movmemqi (rtx *operands)
if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)
part_bytes_reg = gen_rtx_REG (SImode, (in_words_to_go - 1) & 3);
- for (i = 0; in_words_to_go >= 2; i+=4)
+ while (in_words_to_go >= 2)
{
if (in_words_to_go > 4)
emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, src,
@@ -21725,8 +21728,8 @@ arm_expand_prologue (void)
will prevent the scheduler from moving stores to the frame
before the stack adjustment. */
if (frame_pointer_needed)
- insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
- hard_frame_pointer_rtx));
+ emit_insn (gen_stack_tie (stack_pointer_rtx,
+ hard_frame_pointer_rtx));
}
@@ -22931,6 +22934,20 @@ get_arm_condition_code (rtx comparison)
return code;
}
+/* Implement TARGET_FIXED_CONDITION_CODE_REGS. We only have condition
+ code registers when not targetting Thumb1. The VFP condition register
+ only exists when generating hard-float code. */
+static bool
+arm_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+{
+ if (!TARGET_32BIT)
+ return false;
+
+ *p1 = CC_REGNUM;
+ *p2 = TARGET_HARD_FLOAT ? VFPCC_REGNUM : INVALID_REGNUM;
+ return true;
+}
+
/* Tell arm_asm_output_opcode to output IT blocks for conditionally executed
instructions. */
void
@@ -23811,7 +23828,6 @@ thumb_pop (FILE *f, unsigned long mask)
{
int regno;
int lo_mask = mask & 0xFF;
- int pushed_words = 0;
gcc_assert (mask);
@@ -23834,8 +23850,6 @@ thumb_pop (FILE *f, unsigned long mask)
if ((lo_mask & ~1) != 0)
fprintf (f, ", ");
-
- pushed_words++;
}
}
@@ -24105,9 +24119,6 @@ thumb_exit (FILE *f, int reg_containing_return_addr)
move_to = number_of_first_bit_set (regs_to_pop);
asm_fprintf (f, "\tmov\t%r, %r\n", move_to, popped_into);
-
- regs_to_pop &= ~(1 << move_to);
-
--pops_needed;
}
@@ -28259,10 +28270,8 @@ arm_emit_store_exclusive (machine_mode mode, rtx bval, rtx rval,
static void
emit_unlikely_jump (rtx insn)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
-
rtx_insn *jump = emit_jump_insn (insn);
- add_int_reg_note (jump, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (jump, profile_probability::very_unlikely ());
}
/* Expand a compare and swap pattern. */
@@ -31215,12 +31224,15 @@ namespace selftest {
inconsistencies in the option extensions at present (extensions
that duplicate others but aren't marked as aliases). Furthermore,
for correct canonicalization later options must never be a subset
- of an earlier option. */
+ of an earlier option. Any extension should also only specify other
+ feature bits and never an architecture bit. The architecture is inferred
+ from the declaration of the extension. */
static void
arm_test_cpu_arch_data (void)
{
const arch_option *arch;
const cpu_option *cpu;
+ auto_sbitmap target_isa (isa_num_bits);
auto_sbitmap isa1 (isa_num_bits);
auto_sbitmap isa2 (isa_num_bits);
@@ -31231,6 +31243,8 @@ arm_test_cpu_arch_data (void)
if (arch->common.extensions == NULL)
continue;
+ arm_initialize_isa (target_isa, arch->common.isa_bits);
+
for (ext1 = arch->common.extensions; ext1->name != NULL; ++ext1)
{
if (ext1->alias)
@@ -31243,7 +31257,13 @@ arm_test_cpu_arch_data (void)
continue;
arm_initialize_isa (isa2, ext2->isa_bits);
+ /* If the option is a subset of the parent option, it doesn't
+ add anything and so isn't useful. */
ASSERT_TRUE (!bitmap_subset_p (isa2, isa1));
+
+ /* If the extension specifies any architectural bits then
+ disallow it. Extensions should only specify feature bits. */
+ ASSERT_TRUE (!bitmap_intersect_p (isa2, target_isa));
}
}
}
@@ -31255,6 +31275,8 @@ arm_test_cpu_arch_data (void)
if (cpu->common.extensions == NULL)
continue;
+ arm_initialize_isa (target_isa, arch->common.isa_bits);
+
for (ext1 = cpu->common.extensions; ext1->name != NULL; ++ext1)
{
if (ext1->alias)
@@ -31267,7 +31289,13 @@ arm_test_cpu_arch_data (void)
continue;
arm_initialize_isa (isa2, ext2->isa_bits);
+ /* If the option is a subset of the parent option, it doesn't
+ add anything and so isn't useful. */
ASSERT_TRUE (!bitmap_subset_p (isa2, isa1));
+
+ /* If the extension specifies any architectural bits then
+ disallow it. Extensions should only specify feature bits. */
+ ASSERT_TRUE (!bitmap_intersect_p (isa2, target_isa));
}
}
}
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 43d44778bdc..4f53583cf02 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -196,10 +196,6 @@ extern tree arm_fp16_type_node;
/* FPU supports fused-multiply-add operations. */
#define TARGET_FMA (bitmap_bit_p (arm_active_target.isa, isa_bit_VFPv4))
-/* FPU is ARMv8 compatible. */
-#define TARGET_FPU_ARMV8 \
- (bitmap_bit_p (arm_active_target.isa, isa_bit_FP_ARMv8))
-
/* FPU supports Crypto extensions. */
#define TARGET_CRYPTO (bitmap_bit_p (arm_active_target.isa, isa_bit_crypto))
@@ -216,7 +212,7 @@ extern tree arm_fp16_type_node;
/* FPU supports the floating point FP16 instructions for ARMv8.2 and later. */
#define TARGET_VFP_FP16INST \
- (TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 && arm_fp16_inst)
+ (TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP5 && arm_fp16_inst)
/* FPU supports the AdvSIMD FP16 instructions for ARMv8.2 and later. */
#define TARGET_NEON_FP16INST (TARGET_VFP_FP16INST && TARGET_NEON_RDMA)
@@ -384,7 +380,8 @@ enum base_architecture
BASE_ARCH_7EM = 7,
BASE_ARCH_8A = 8,
BASE_ARCH_8M_BASE = 8,
- BASE_ARCH_8M_MAIN = 8
+ BASE_ARCH_8M_MAIN = 8,
+ BASE_ARCH_8R = 8
};
/* The major revision number of the ARM Architecture implemented by the target. */
@@ -2189,13 +2186,7 @@ extern int making_const_table;
/* Expands to an upper-case char of the target's architectural
profile. */
#define TARGET_ARM_ARCH_PROFILE \
- (!arm_arch_notm \
- ? 'M' \
- : (arm_arch7 \
- ? (strlen (arm_arch_name) >=3 \
- ? (arm_arch_name[strlen (arm_arch_name) - 3]) \
- : 0) \
- : 0))
+ (arm_active_target.profile)
/* Bit-field indicating what size LDREX/STREX loads/stores are available.
Bit 0 for bytes, up to bit 3 for double-words. */
@@ -2263,11 +2254,16 @@ const char *arm_canon_arch_option (int argc, const char **argv);
#define CANON_ARCH_SPEC_FUNCTION \
{ "canon_arch", arm_canon_arch_option },
+const char *arm_be8_option (int argc, const char **argv);
+#define BE8_SPEC_FUNCTION \
+ { "be8_linkopt", arm_be8_option },
+
# define EXTRA_SPEC_FUNCTIONS \
MCPU_MTUNE_NATIVE_FUNCTIONS \
ASM_CPU_SPEC_FUNCTIONS \
CANON_ARCH_SPEC_FUNCTION \
- TARGET_MODE_SPEC_FUNCTIONS
+ TARGET_MODE_SPEC_FUNCTIONS \
+ BE8_SPEC_FUNCTION
/* Automatically add -mthumb for Thumb-only targets if mode isn't specified
via the configuration option --with-mode or via the command line. The
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index e6e1ac54a85..049a78edefe 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -7879,7 +7879,7 @@
"<F_constraint>")
(match_operand:SDF 4 "s_register_operand"
"<F_constraint>")))]
- "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
+ "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
"*
{
enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index dad52576872..6060516dd40 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -95,7 +95,7 @@ Target Report RejectNegative Negative(mthumb) InverseMask(THUMB)
Generate code in 32 bit ARM state.
mbig-endian
-Target Report RejectNegative Mask(BIG_END)
+Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_END)
Assume target CPU is configured as big endian.
mcallee-super-interworking
@@ -160,7 +160,7 @@ mhard-float
Target RejectNegative Alias(mfloat-abi=, hard) Undocumented
mlittle-endian
-Target Report RejectNegative InverseMask(BIG_END)
+Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_END)
Assume target CPU is configured as little endian.
mlong-calls
@@ -192,7 +192,7 @@ Target RejectNegative Alias(mfloat-abi=, soft) Undocumented
mstructure-size-boundary=
Target RejectNegative Joined UInteger Var(arm_structure_size_boundary) Init(DEFAULT_STRUCTURE_SIZE_BOUNDARY)
-Specify the minimum bit alignment of structures.
+Specify the minimum bit alignment of structures. (Deprecated).
mthumb
Target Report RejectNegative Negative(marm) Mask(THUMB) Save
@@ -286,3 +286,11 @@ Assume unified syntax for inline assembly code.
mpure-code
Target Report Var(target_pure_code) Init(0)
Do not allow constant data to be placed in code sections.
+
+mbe8
+Target Report RejectNegative Negative(mbe32) Mask(BE8)
+When linking for big-endian targets, generate a BE8 format image.
+
+mbe32
+Target Report RejectNegative Negative(mbe8) InverseMask(BE8)
+When linking for big-endian targets, generate a legacy BE32 format image.
diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 65f36e2c91e..0d436e83d0f 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -28,7 +28,7 @@
#define _GCC_ARM_NEON_H 1
#ifndef __ARM_FP
-#error "NEON intrinsics not available with the soft-float ABI. Please use -mfloat-abi=softp or -mfloat-abi=hard"
+#error "NEON intrinsics not available with the soft-float ABI. Please use -mfloat-abi=softfp or -mfloat-abi=hard"
#else
#pragma GCC push_options
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index d38863a3cd3..2f41c4ffbdb 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -26,7 +26,7 @@
/* Use the AAPCS ABI by default. */
#define ARM_DEFAULT_ABI ARM_ABI_AAPCS
-/* Assume that AAPCS ABIs should adhere to the full BPABI. */
+/* Assume that AAPCS ABIs should adhere to the full BPABI. */
#define TARGET_BPABI (TARGET_AAPCS_BASED)
/* BPABI targets use EABI frame unwinding tables. */
@@ -55,84 +55,11 @@
#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*"\
"|march=armv4|mcpu=fa526|mcpu=fa626:--fix-v4bx}"
-#if TARGET_BIG_ENDIAN_DEFAULT
-#define BE8_LINK_SPEC \
- " %{!mlittle-endian:%{march=armv7-a|mcpu=cortex-a5 \
- |mcpu=cortex-a7 \
- |mcpu=cortex-a8|mcpu=cortex-a9|mcpu=cortex-a15 \
- |mcpu=cortex-a12|mcpu=cortex-a17 \
- |mcpu=cortex-a15.cortex-a7 \
- |mcpu=cortex-a17.cortex-a7 \
- |mcpu=marvell-pj4 \
- |mcpu=cortex-a32 \
- |mcpu=cortex-a35 \
- |mcpu=cortex-a53 \
- |mcpu=cortex-a57 \
- |mcpu=cortex-a57.cortex-a53 \
- |mcpu=cortex-a72 \
- |mcpu=cortex-a72.cortex-a53 \
- |mcpu=cortex-a73 \
- |mcpu=cortex-a73.cortex-a35 \
- |mcpu=cortex-a73.cortex-a53 \
- |mcpu=exynos-m1 \
- |mcpu=xgene1 \
- |mcpu=cortex-m1.small-multiply \
- |mcpu=cortex-m0.small-multiply \
- |mcpu=cortex-m0plus.small-multiply \
- |mcpu=generic-armv7-a \
- |march=armv7ve \
- |march=armv7-m|mcpu=cortex-m3 \
- |march=armv7e-m|mcpu=cortex-m4|mcpu=cortex-m7 \
- |march=armv6-m|mcpu=cortex-m0 \
- |march=armv8-a \
- |march=armv8-a+crc \
- |march=armv8.1-a \
- |march=armv8.1-a+crc \
- |march=armv8.2-a \
- |march=armv8.2-a+fp16 \
- |march=armv8-m.base|mcpu=cortex-m23 \
- |march=armv8-m.main \
- |march=armv8-m.main+dsp|mcpu=cortex-m33 \
- :%{!r:--be8}}}"
-#else
-#define BE8_LINK_SPEC \
- " %{mbig-endian:%{march=armv7-a|mcpu=cortex-a5 \
- |mcpu=cortex-a7 \
- |mcpu=cortex-a8|mcpu=cortex-a9|mcpu=cortex-a15 \
- |mcpu=cortex-a12|mcpu=cortex-a17 \
- |mcpu=cortex-a15.cortex-a7 \
- |mcpu=cortex-a17.cortex-a7 \
- |mcpu=cortex-a35 \
- |mcpu=cortex-a53 \
- |mcpu=cortex-a57 \
- |mcpu=cortex-a57.cortex-a53 \
- |mcpu=cortex-a72 \
- |mcpu=cortex-a72.cortex-a53 \
- |mcpu=cortex-a73 \
- |mcpu=cortex-a73.cortex-a35 \
- |mcpu=cortex-a73.cortex-a53 \
- |mcpu=exynos-m1 \
- |mcpu=xgene1 \
- |mcpu=cortex-m1.small-multiply \
- |mcpu=cortex-m0.small-multiply \
- |mcpu=cortex-m0plus.small-multiply \
- |mcpu=marvell-pj4 \
- |mcpu=generic-armv7-a \
- |march=armv7ve \
- |march=armv7-m|mcpu=cortex-m3 \
- |march=armv7e-m|mcpu=cortex-m4|mcpu=cortex-m7 \
- |march=armv6-m|mcpu=cortex-m0 \
- |march=armv8-a \
- |march=armv8-a+crc \
- |march=armv8.1-a \
- |march=armv8.1-a+crc \
- |march=armv8.2-a \
- |march=armv8.2-a+fp16 \
- |march=armv8-m.base|mcpu=cortex-m23 \
- |march=armv8-m.main \
- |march=armv8-m.main+dsp|mcpu=cortex-m33 \
- :%{!r:--be8}}}"
-#endif
+#define BE8_LINK_SPEC \
+ "%{!r:%{!mbe32:%:be8_linkopt(%{mlittle-endian:little}" \
+ " %{mbig-endian:big}" \
+ " %{mbe8:be8}" \
+ " %{march=*:arch %*})}}"
/* Tell the assembler to build BPABI binaries. */
#undef SUBTARGET_EXTRA_ASM_SPEC
diff --git a/gcc/config/arm/cortex-a53.md b/gcc/config/arm/cortex-a53.md
index 3c613375756..6734e37be49 100644
--- a/gcc/config/arm/cortex-a53.md
+++ b/gcc/config/arm/cortex-a53.md
@@ -211,7 +211,7 @@
(define_bypass 1 "cortex_a53_alu*"
"cortex_a53_alu_shift*"
- "aarch_forward_to_shift_is_not_shifted_reg")
+ "arm_no_early_alu_shift_dep")
(define_bypass 2 "cortex_a53_alu*"
"cortex_a53_alu_*,cortex_a53_shift*")
diff --git a/gcc/config/arm/driver-arm.c b/gcc/config/arm/driver-arm.c
index b034f13fda6..5c29b94caab 100644
--- a/gcc/config/arm/driver-arm.c
+++ b/gcc/config/arm/driver-arm.c
@@ -52,8 +52,13 @@ static struct vendor_cpu arm_cpu_table[] = {
{"0xd07", "armv8-a+crc", "cortex-a57"},
{"0xd08", "armv8-a+crc", "cortex-a72"},
{"0xd09", "armv8-a+crc", "cortex-a73"},
+ {"0xd05", "armv8.2-a+fp16", "cortex-a55"},
+ {"0xd0a", "armv8.2-a+fp16", "cortex-a75"},
{"0xc14", "armv7-r", "cortex-r4"},
{"0xc15", "armv7-r", "cortex-r5"},
+ {"0xc17", "armv7-r", "cortex-r7"},
+ {"0xc18", "armv7-r", "cortex-r8"},
+ {"0xd13", "armv8-r+crc", "cortex-r52"},
{"0xc20", "armv6-m", "cortex-m0"},
{"0xc21", "armv6-m", "cortex-m1"},
{"0xc23", "armv7-m", "cortex-m3"},
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 0ce3fe415e6..235c46da1a1 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -678,7 +678,7 @@
(match_operand:VCVTF 2 "register_operand" "w")
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
- "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ "vfma.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_mla_s<q>")]
)
@@ -688,7 +688,7 @@
(match_operand:VCVTF 2 "register_operand" "w")
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA"
- "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ "vfma.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_mla_s<q>")]
)
@@ -720,7 +720,7 @@
(match_operand:VCVTF 2 "register_operand" "w")
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
- "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ "vfms.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_mla_s<q>")]
)
@@ -731,7 +731,7 @@
(match_operand:VCVTF 2 "register_operand" "w")
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA"
- "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ "vfms.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_mla_s<q>")]
)
@@ -751,8 +751,8 @@
(unspec:VCVTF [(match_operand:VCVTF 1
"s_register_operand" "w")]
NEON_VRINT))]
- "TARGET_NEON && TARGET_FPU_ARMV8"
- "vrint<nvrint_variant>%?.f32\\t%<V_reg>0, %<V_reg>1"
+ "TARGET_NEON && TARGET_VFP5"
+ "vrint<nvrint_variant>.f32\\t%<V_reg>0, %<V_reg>1"
[(set_attr "type" "neon_fp_round_<V_elem_ch><q>")]
)
@@ -761,7 +761,7 @@
(FIXUORS:<V_cmp_result> (unspec:VCVTF
[(match_operand:VCVTF 1 "register_operand" "w")]
NEON_VCVT)))]
- "TARGET_NEON && TARGET_FPU_ARMV8"
+ "TARGET_NEON && TARGET_VFP5"
"vcvt<nvrint_variant>.<su>32.f32\\t%<V_reg>0, %<V_reg>1"
[(set_attr "type" "neon_fp_to_int_<V_elem_ch><q>")
(set_attr "predicable" "no")]
@@ -2901,7 +2901,7 @@
(unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
(match_operand:VCVTF 2 "s_register_operand" "w")]
VMAXMINFNM))]
- "TARGET_NEON && TARGET_FPU_ARMV8"
+ "TARGET_NEON && TARGET_VFP5"
"<fmaxmin_op>.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_minmax_s<q>")]
)
@@ -2912,7 +2912,7 @@
(unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
(match_operand:VCVTF 2 "s_register_operand" "w")]
VMAXMINFNM))]
- "TARGET_NEON && TARGET_FPU_ARMV8"
+ "TARGET_NEON && TARGET_VFP5"
"<fmaxmin_op>.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_minmax_s<q>")]
)
diff --git a/gcc/config/arm/parsecpu.awk b/gcc/config/arm/parsecpu.awk
index b6e50932ddc..070d193b338 100644
--- a/gcc/config/arm/parsecpu.awk
+++ b/gcc/config/arm/parsecpu.awk
@@ -223,10 +223,39 @@ function gen_comm_data () {
if (arch_opt_remove[feats[1],feats[m]] == "true") {
fatal("cannot remove features from architecture specs")
}
- print " " arch_opt_isa[feats[1],feats[m]] ","
+ # The isa_features array that is being initialized here has a length
+ # of max isa_bit_num, which is the last entry in the enum.
+ # Logically this means that the number of features is implicitly
+ # never more than the number of feature bits we have. This is only
+ # true if we don't emit duplicates here. So keep track of which
+ # options we have already emitted so we don't emit them twice.
+ nopts = split (arch_opt_isa[feats[1],feats[m]], opts, ",")
+ for (i = 1; i <= nopts; i++) {
+ if (! (opts[i] in seen)) {
+ print " " opts[i] ","
+ seen[opts[i]]
+ }
+ }
}
- if (cpus[n] in cpu_fpu) print " " fpu_isa[cpu_fpu[cpus[n]]] ","
- if (cpus[n] in cpu_isa) print " " cpu_isa[cpus[n]] ","
+ if (cpus[n] in cpu_fpu) {
+ nopts = split (fpu_isa[cpu_fpu[cpus[n]]], opts, ",")
+ for (i = 1; i <= nopts; i++) {
+ if (! (opts[i] in seen)) {
+ print " " opts[i] ","
+ seen[opts[i]]
+ }
+ }
+ }
+ if (cpus[n] in cpu_isa) {
+ nopts = split (cpu_isa[cpus[n]], opts, ",")
+ for (i = 1; i <= nopts; i++) {
+ if (! (opts[i] in seen)) {
+ print " " opts[i] ","
+ seen[opts[i]]
+ }
+ }
+ }
+ delete seen
print " isa_nobit"
print " }"
print " },"
@@ -299,13 +328,19 @@ function gen_comm_data () {
# arch, base_arch
print " \"" arch_base[archs[n]] "\", BASE_ARCH_" \
arch_base[archs[n]] ","
+ # profile letter code, or zero if none.
+ if (archs[n] in arch_prof) {
+ print " '" arch_prof[archs[n]] "',"
+ } else {
+ print " 0,"
+ }
# tune_id
print " TARGET_CPU_" cpu_cnames[arch_tune_for[archs[n]]] ","
print " },"
}
print " {{NULL, NULL, {isa_nobit}},"
- print " NULL, BASE_ARCH_0, TARGET_CPU_arm_none}"
+ print " NULL, BASE_ARCH_0, 0, TARGET_CPU_arm_none}"
print "};\n"
print "const arm_fpu_desc all_fpus[] ="
@@ -477,6 +512,12 @@ BEGIN {
parse_ok = 1
}
+/^[ ]*profile / {
+ if (arch_name == "") fatal("\"profile\" statement outside of arch block")
+ arch_prof[arch_name] = $2
+ parse_ok = 1
+}
+
/^end arch / {
if (arch_name != $3) fatal("mimatched end arch")
if (! arch_name in arch_tune_for) {
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index afb5d6339a8..3e25cd16b29 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -350,9 +350,9 @@
(define_special_predicate "arm_cond_move_operator"
(if_then_else (match_test "arm_restrict_it")
- (and (match_test "TARGET_FPU_ARMV8")
- (match_operand 0 "arm_vsel_comparison_operator"))
- (match_operand 0 "expandable_comparison_operator")))
+ (and (match_test "TARGET_VFP5")
+ (match_operand 0 "arm_vsel_comparison_operator"))
+ (match_operand 0 "expandable_comparison_operator")))
(define_special_predicate "noov_comparison_operator"
(match_code "lt,ge,eq,ne"))
diff --git a/gcc/config/arm/rtems.h b/gcc/config/arm/rtems.h
index b34bbe8a063..77eb32c1d20 100644
--- a/gcc/config/arm/rtems.h
+++ b/gcc/config/arm/rtems.h
@@ -1,20 +1,25 @@
/* Definitions for RTEMS based ARM systems using EABI.
Copyright (C) 2011-2017 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
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#define HAS_INIT_SECTION
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index b6a3cb40c5d..16177e0bbbc 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -18,7 +18,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-TM_H += $(srcdir)/config/arm/arm-cpu.h
+TM_H += arm-cpu.h
+GTM_H += arm-cpu.h
# All md files - except for arm.md.
# This list should be kept in alphabetical order and updated whenever an md
@@ -75,26 +76,32 @@ $(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/parsecpu.awk \
$(srcdir)/config/arm/arm-tables.opt: $(srcdir)/config/arm/parsecpu.awk \
$(srcdir)/config/arm/arm-cpus.in
$(AWK) -f $(srcdir)/config/arm/parsecpu.awk -v cmd=opt \
- $(srcdir)/config/arm/arm-cpus.in > \
- $(srcdir)/config/arm/arm-tables.opt
+ $(srcdir)/config/arm/arm-cpus.in > arm-tables.new
+ mv arm-tables.new $(srcdir)/config/arm/arm-tables.opt
-$(srcdir)/config/arm/arm-cpu.h: $(srcdir)/config/arm/parsecpu.awk \
+arm-cpu.h: s-arm-cpu ; @true
+s-arm-cpu: $(srcdir)/config/arm/parsecpu.awk \
$(srcdir)/config/arm/arm-cpus.in
$(AWK) -f $(srcdir)/config/arm/parsecpu.awk -v cmd=headers \
- $(srcdir)/config/arm/arm-cpus.in > arm-cpu.new
- mv arm-cpu.new $(srcdir)/config/arm/arm-cpu.h
+ $(srcdir)/config/arm/arm-cpus.in > tmp-arm-cpu.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-arm-cpu.h arm-cpu.h
+ $(STAMP) s-arm-cpu
-$(srcdir)/config/arm/arm-cpu-data.h: $(srcdir)/config/arm/parsecpu.awk \
+arm-cpu-data.h: s-arm-data ; @true
+s-arm-data: $(srcdir)/config/arm/parsecpu.awk \
$(srcdir)/config/arm/arm-cpus.in
$(AWK) -f $(srcdir)/config/arm/parsecpu.awk -v cmd=data \
- $(srcdir)/config/arm/arm-cpus.in > arm-cpu-data.new
- mv arm-cpu-data.new $(srcdir)/config/arm/arm-cpu-data.h
+ $(srcdir)/config/arm/arm-cpus.in > tmp-arm-cpu-data.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-arm-cpu-data.h arm-cpu-data.h
+ $(STAMP) s-arm-data
-$(srcdir)/config/arm/arm-cpu-cdata.h: $(srcdir)/config/arm/parsecpu.awk \
+arm-cpu-cdata.h: s-arm-cdata ; @true
+s-arm-cdata: $(srcdir)/config/arm/parsecpu.awk \
$(srcdir)/config/arm/arm-cpus.in
$(AWK) -f $(srcdir)/config/arm/parsecpu.awk -v cmd=common-data \
- $(srcdir)/config/arm/arm-cpus.in > arm-cpu-cdata.new
- mv arm-cpu-cdata.new $(srcdir)/config/arm/arm-cpu-cdata.h
+ $(srcdir)/config/arm/arm-cpus.in > tmp-arm-cpu-cdata.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-arm-cpu-cdata.h arm-cpu-cdata.h
+ $(STAMP) s-arm-cdata
aarch-common.o: $(srcdir)/config/arm/aarch-common.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TM_P_H) $(RTL_H) $(TREE_H) output.h $(C_COMMON_H)
@@ -109,7 +116,7 @@ arm.o: $(srcdir)/config/arm/arm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \
$(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \
intl.h libfuncs.h $(PARAMS_H) $(OPTS_H) sched-int.h \
- $(srcdir)/config/arm/arm-cpu-data.h \
+ arm-cpu-data.h \
$(srcdir)/config/arm/arm-protos.h \
$(srcdir)/config/arm/arm_neon_builtins.def \
$(srcdir)/config/arm/arm_vfp_builtins.def
@@ -130,4 +137,4 @@ arm-c.o: $(srcdir)/config/arm/arm-c.c $(CONFIG_H) $(SYSTEM_H) \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/arm/arm-c.c
-arm-common.o: $(srcdir)/config/arm/arm-cpu-cdata.h
+arm-common.o: arm-cpu-cdata.h
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index d8f77e2ffe4..23c1d67c9e3 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -1997,7 +1997,7 @@
(FIXUORS:SI (unspec:SDF
[(match_operand:SDF 1
"register_operand" "<F_constraint>")] VCVT)))]
- "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
+ "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
"vcvt<vrint_variant>.<su>32.<V_if_elem>\\t%0, %<V_reg>1"
[(set_attr "predicable" "no")
(set_attr "conds" "unconditional")
diff --git a/gcc/config/arm/vxworks.h b/gcc/config/arm/vxworks.h
index 9af37c7f4f5..f20324f144d 100644
--- a/gcc/config/arm/vxworks.h
+++ b/gcc/config/arm/vxworks.h
@@ -117,3 +117,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* This platform supports the probing method of stack checking (RTP mode).
8K is reserved in the stack to propagate exceptions in case of overflow. */
#define STACK_CHECK_PROTECT 8192
+
+/* Unless overridded by the target options, the default is little-endian. */
+#define TARGET_ENDIAN_DEFAULT 0
diff --git a/gcc/config/avr/avr-arch.h b/gcc/config/avr/avr-arch.h
index e38345b69e3..891f73cb1b1 100644
--- a/gcc/config/avr/avr-arch.h
+++ b/gcc/config/avr/avr-arch.h
@@ -195,7 +195,6 @@ extern const avr_arch_t *avr_arch;
extern const avr_mcu_t avr_mcu_types[];
-extern void avr_inform_devices (void);
extern void avr_inform_core_architectures (void);
#endif /* AVR_ARCH_H */
diff --git a/gcc/config/avr/avr-devices.c b/gcc/config/avr/avr-devices.c
index c391ef9cd8e..9961588eef7 100644
--- a/gcc/config/avr/avr-devices.c
+++ b/gcc/config/avr/avr-devices.c
@@ -128,39 +128,6 @@ avr_mcu_types[] =
#ifndef IN_GEN_AVR_MMCU_TEXI
-/* Copy-pastes from `gen-avr-mmcu-texi.c' follow... */
-
-static const char*
-mcu_name[sizeof avr_mcu_types / sizeof avr_mcu_types[0]];
-
-static int
-comparator (const void *va, const void *vb)
-{
- const char *a = *(const char* const*) va;
- const char *b = *(const char* const*) vb;
-
- while (*a && *b)
- {
- /* Make letters smaller than digits so that `atmega16a' follows
- `atmega16' without `atmega161' etc. between them. */
-
- if (ISALPHA (*a) && ISDIGIT (*b))
- return -1;
-
- if (ISDIGIT (*a) && ISALPHA (*b))
- return 1;
-
- if (*a != *b)
- return *a - *b;
-
- a++;
- b++;
- }
-
- return *a - *b;
-}
-
-
static char*
avr_archs_str (void)
{
@@ -176,39 +143,6 @@ avr_archs_str (void)
}
-static char*
-avr_mcus_str (void)
-{
- size_t n_mcus = 0;
- char *mcus = concat ("", NULL);
-
- // Build array of proper devices' names.
-
- for (const avr_mcu_t *mcu = avr_mcu_types; mcu->name; mcu++)
- if (mcu->macro)
- mcu_name[n_mcus++] = mcu->name;
-
- // Sort MCUs so that they are displayed in the same canonical order as
- // in doc/avr-mcus.texi.
-
- qsort (mcu_name, n_mcus, sizeof (char*), comparator);
-
- for (size_t i = 0; i < n_mcus; i++)
- mcus = concat (mcus, " ", mcu_name[i], NULL);
-
- return mcus;
-}
-
-
-void
-avr_inform_devices (void)
-{
- char *mcus = avr_mcus_str ();
- inform (input_location, "devices natively supported:%s", mcus);
- free (mcus);
-}
-
-
void
avr_inform_core_architectures (void)
{
diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c
index 2b1c43fae39..aacaed04ef1 100644
--- a/gcc/config/avr/avr-log.c
+++ b/gcc/config/avr/avr-log.c
@@ -146,7 +146,13 @@ avr_log_vadump (FILE *file, const char *caller, va_list ap)
}
case 'T':
- print_node_brief (file, "", va_arg (ap, tree), 3);
+ {
+ tree t = va_arg (ap, tree);
+ if (NULL_TREE == t)
+ fprintf (file, "<NULL-TREE>");
+ else
+ print_node_brief (file, "", t, 3);
+ }
break;
case 'd':
@@ -302,6 +308,7 @@ avr_log_set_avr_log (void)
SET_DUMP_DETAIL (address_cost);
SET_DUMP_DETAIL (builtin);
SET_DUMP_DETAIL (constraints);
+ SET_DUMP_DETAIL (insn_addresses);
SET_DUMP_DETAIL (legitimate_address_p);
SET_DUMP_DETAIL (legitimize_address);
SET_DUMP_DETAIL (legitimize_reload_address);
diff --git a/gcc/config/avr/avr-passes.def b/gcc/config/avr/avr-passes.def
index affb99b4723..340823e15c4 100644
--- a/gcc/config/avr/avr-passes.def
+++ b/gcc/config/avr/avr-passes.def
@@ -17,9 +17,12 @@
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* FIXME: We have to add the last pass first, otherwise
- gen-pass-instances.awk won't work as expected. */
-
+/* An analysis pass that runs prior to prologue / epilogue generation.
+ Computes cfun->machine->gasisr.maybe which is used in prologue and
+ epilogue generation provided -mgas-isr-prologues is on. */
+
+INSERT_PASS_BEFORE (pass_thread_prologue_and_epilogue, 1, avr_pass_pre_proep);
+
/* This avr-specific pass (re)computes insn notes, in particular REG_DEAD
notes which are used by `avr.c::reg_unused_after' and branch offset
computations. These notes must be correct, i.e. there must be no
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index abe0575e17c..5d5524b2e65 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -87,7 +87,7 @@ extern bool avr_emit_movmemhi (rtx*);
extern int avr_epilogue_uses (int regno);
extern int avr_starting_frame_offset (void);
-extern void avr_output_addr_vec_elt (FILE *stream, int value);
+extern void avr_output_addr_vec (rtx_insn*, rtx);
extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx, rtx*, int* =NULL, int* =NULL, bool =true);
@@ -158,6 +158,7 @@ extern bool avr_have_dimode;
namespace gcc { class context; }
class rtl_opt_pass;
+extern rtl_opt_pass *make_avr_pass_pre_proep (gcc::context *);
extern rtl_opt_pass *make_avr_pass_recompute_notes (gcc::context *);
extern rtl_opt_pass *make_avr_pass_casesi (gcc::context *);
@@ -175,6 +176,7 @@ typedef struct
unsigned address_cost :1;
unsigned builtin :1;
unsigned constraints :1;
+ unsigned insn_addresses :1;
unsigned legitimate_address_p :1;
unsigned legitimize_address :1;
unsigned legitimize_reload_address :1;
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 4f385d5682f..1f333ccc1b2 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -553,9 +553,9 @@ avr_optimize_casesi (rtx_insn *insns[6], rtx *xop)
HOST_WIDE_INT hig_idx = low_idx + num_idx;
// Maximum ranges of (un)signed QImode resp. HImode.
- int imin = QImode == mode ? INT8_MIN : INT16_MIN;
- int imax = QImode == mode ? INT8_MAX : INT16_MAX;
- unsigned umax = QImode == mode ? UINT8_MAX : UINT16_MAX;
+ unsigned umax = QImode == mode ? 0xff : 0xffff;
+ int imax = QImode == mode ? 0x7f : 0x7fff;
+ int imin = -imax - 1;
// Testing the case range and whether it fits into the range of the
// (un)signed mode. This test should actually always pass because it
@@ -774,6 +774,10 @@ avr_option_override (void)
if (flag_pie == 2)
warning (OPT_fPIE, "-fPIE is not supported");
+#if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
+ TARGET_GASISR_PROLOGUES = 0;
+#endif
+
if (!avr_set_core_architecture())
return;
@@ -1007,6 +1011,15 @@ avr_OS_main_function_p (tree func)
}
+/* Return nonzero if FUNC is a no_gccisr function as specified
+ by the "no_gccisr" attribute. */
+
+static int
+avr_no_gccisr_function_p (tree func)
+{
+ return avr_lookup_function_attribute1 (func, "no_gccisr");
+}
+
/* Implement `TARGET_SET_CURRENT_FUNCTION'. */
/* Sanity cheching for above function attributes. */
@@ -1030,6 +1043,7 @@ avr_set_current_function (tree decl)
cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
+ cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
@@ -1062,12 +1076,6 @@ avr_set_current_function (tree decl)
name = default_strip_name_encoding (name);
- /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
- using this when it switched from SIGNAL and INTERRUPT to ISR. */
-
- if (cfun->machine->is_interrupt)
- cfun->machine->is_signal = 0;
-
/* Interrupt handlers must be void __vector (void) functions. */
if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
@@ -1076,14 +1084,36 @@ avr_set_current_function (tree decl)
if (TREE_CODE (ret) != VOID_TYPE)
error_at (loc, "%qs function cannot return a value", isr);
+#if defined WITH_AVRLIBC
+ /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
+ using this when it switched from SIGNAL and INTERRUPT to ISR. */
+
+ if (cfun->machine->is_interrupt)
+ cfun->machine->is_signal = 0;
+
/* If the function has the 'signal' or 'interrupt' attribute, ensure
that the name of the function is "__vector_NN" so as to catch
when the user misspells the vector name. */
if (!STR_PREFIX_P (name, "__vector"))
warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
- "%s handler, missing __vector prefix", name, isr);
+ "%qs handler, missing %<__vector%> prefix", name, isr);
+#endif // AVR-LibC naming conventions
+ }
+
+#if defined WITH_AVRLIBC
+ // Common problem is using "ISR" without first including avr/interrupt.h.
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ name = default_strip_name_encoding (name);
+ if (0 == strcmp ("ISR", name)
+ || 0 == strcmp ("INTERRUPT", name)
+ || 0 == strcmp ("SIGNAL", name))
+ {
+ warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved indentifier"
+ " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
+ " before using the %qs macro", name, name);
}
+#endif // AVR-LibC naming conventions
/* Don't print the above diagnostics more than once. */
@@ -1220,6 +1250,9 @@ avr_initial_elimination_offset (int from, int to)
int offset = frame_pointer_needed ? 2 : 0;
int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
+ // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
+ // might not have arguments. Hence the following is not affected
+ // by gasisr prologues.
offset += avr_regs_to_save (NULL);
return (get_frame_size () + avr_outgoing_args_size()
+ avr_pc_size + 1 + offset);
@@ -1314,6 +1347,8 @@ avr_return_addr_rtx (int count, rtx tem)
else
r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
+ cfun->machine->use_L__stack_usage = 1;
+
r = gen_rtx_PLUS (Pmode, tem, r);
r = gen_frame_mem (Pmode, memory_address (Pmode, r));
r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
@@ -1394,6 +1429,97 @@ sequent_regs_live (void)
return (cur_seq == live_seq) ? live_seq : 0;
}
+namespace {
+static const pass_data avr_pass_data_pre_proep =
+{
+ RTL_PASS, // type
+ "", // name (will be patched)
+ OPTGROUP_NONE, // optinfo_flags
+ TV_DF_SCAN, // tv_id
+ 0, // properties_required
+ 0, // properties_provided
+ 0, // properties_destroyed
+ 0, // todo_flags_start
+ 0 // todo_flags_finish
+};
+
+
+class avr_pass_pre_proep : public rtl_opt_pass
+{
+public:
+ avr_pass_pre_proep (gcc::context *ctxt, const char *name)
+ : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
+ {
+ this->name = name;
+ }
+
+ void compute_maybe_gasisr (function*);
+
+ virtual unsigned int execute (function *fun)
+ {
+ if (TARGET_GASISR_PROLOGUES
+ // Whether this function is an ISR worth scanning at all.
+ && !fun->machine->is_no_gccisr
+ && (fun->machine->is_interrupt
+ || fun->machine->is_signal)
+ && !cfun->machine->is_naked
+ // Paranoia: Non-local gotos and labels that might escape.
+ && !cfun->calls_setjmp
+ && !cfun->has_nonlocal_label
+ && !cfun->has_forced_label_in_static)
+ {
+ compute_maybe_gasisr (fun);
+ }
+
+ return 0;
+ }
+
+}; // avr_pass_pre_proep
+
+} // anon namespace
+
+rtl_opt_pass*
+make_avr_pass_pre_proep (gcc::context *ctxt)
+{
+ return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
+}
+
+
+/* Set fun->machine->gasisr.maybe provided we don't find anything that
+ prohibits GAS generating parts of ISR prologues / epilogues for us. */
+
+void
+avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
+{
+ // Don't use BB iterators so that we see JUMP_TABLE_DATA.
+
+ for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ // Transparent calls always use [R]CALL and are filtered out by GAS.
+ // ISRs don't use -mcall-prologues, hence what remains to be filtered
+ // out are open coded (tail) calls.
+
+ if (CALL_P (insn))
+ return;
+
+ // __tablejump2__ clobbers something and is targeted by JMP so
+ // that GAS won't see its usage.
+
+ if (AVR_HAVE_JMP_CALL
+ && JUMP_TABLE_DATA_P (insn))
+ return;
+
+ // Non-local gotos not seen in *FUN.
+
+ if (JUMP_P (insn)
+ && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+ return;
+ }
+
+ fun->machine->gasisr.maybe = 1;
+}
+
+
/* Obtain the length sequence of insns. */
int
@@ -1418,6 +1544,46 @@ avr_incoming_return_addr_rtx (void)
return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
}
+
+/* Unset a bit in *SET. If successful, return the respective bit number.
+ Otherwise, return -1 and *SET is unaltered. */
+
+static int
+avr_hregs_split_reg (HARD_REG_SET *set)
+{
+ for (int regno = 0; regno < 32; regno++)
+ if (TEST_HARD_REG_BIT (*set, regno))
+ {
+ // Don't remove a register from *SET which might indicate that
+ // some RAMP* register might need ISR prologue / epilogue treatment.
+
+ if (AVR_HAVE_RAMPX
+ && (REG_X == regno || REG_X + 1 == regno)
+ && TEST_HARD_REG_BIT (*set, REG_X)
+ && TEST_HARD_REG_BIT (*set, REG_X + 1))
+ continue;
+
+ if (AVR_HAVE_RAMPY
+ && !frame_pointer_needed
+ && (REG_Y == regno || REG_Y + 1 == regno)
+ && TEST_HARD_REG_BIT (*set, REG_Y)
+ && TEST_HARD_REG_BIT (*set, REG_Y + 1))
+ continue;
+
+ if (AVR_HAVE_RAMPZ
+ && (REG_Z == regno || REG_Z + 1 == regno)
+ && TEST_HARD_REG_BIT (*set, REG_Z)
+ && TEST_HARD_REG_BIT (*set, REG_Z + 1))
+ continue;
+
+ CLEAR_HARD_REG_BIT (*set, regno);
+ return regno;
+ }
+
+ return -1;
+}
+
+
/* Helper for expand_prologue. Emit a push of a byte register. */
static void
@@ -1438,24 +1604,24 @@ emit_push_byte (unsigned regno, bool frame_related_p)
}
-/* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
+/* Helper for expand_prologue. Emit a push of a SFR via register TREG.
SFR is a MEM representing the memory location of the SFR.
If CLR_P then clear the SFR after the push using zero_reg. */
static void
-emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
+emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
{
rtx_insn *insn;
gcc_assert (MEM_P (sfr));
- /* IN __tmp_reg__, IO(SFR) */
- insn = emit_move_insn (tmp_reg_rtx, sfr);
+ /* IN treg, IO(SFR) */
+ insn = emit_move_insn (all_regs_rtx[treg], sfr);
if (frame_related_p)
RTX_FRAME_RELATED_P (insn) = 1;
- /* PUSH __tmp_reg__ */
- emit_push_byte (AVR_TMP_REGNO, frame_related_p);
+ /* PUSH treg */
+ emit_push_byte (treg, frame_related_p);
if (clr_p)
{
@@ -1759,37 +1925,66 @@ avr_expand_prologue (void)
if (cfun->machine->is_interrupt || cfun->machine->is_signal)
{
+ int treg = AVR_TMP_REGNO;
/* Enable interrupts. */
if (cfun->machine->is_interrupt)
emit_insn (gen_enable_interrupt ());
- /* Push zero reg. */
- emit_push_byte (AVR_ZERO_REGNO, true);
+ if (cfun->machine->gasisr.maybe)
+ {
+ /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
+ ZERO_REG and TMP_REG and one additional, optional register for
+ us in an optimal way. This even scans through inline asm. */
+
+ cfun->machine->gasisr.yes = 1;
+
+ // The optional reg or TMP_REG if we don't need one. If we need one,
+ // remove that reg from SET so that it's not puhed / popped twice.
+ // We also use it below instead of TMP_REG in some places.
+
+ treg = avr_hregs_split_reg (&set);
+ if (treg < 0)
+ treg = AVR_TMP_REGNO;
+ cfun->machine->gasisr.regno = treg;
+
+ // The worst case of pushes. The exact number can be inferred
+ // at assembly time by magic expression __gcc_isr.n_pushed.
+ cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
+
+ // Emit a Prologue chunk. Epilogue chunk(s) might follow.
+ // The final Done chunk is emit by final postscan.
+ emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
+ }
+ else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
+ {
+ /* Push zero reg. */
+ emit_push_byte (AVR_ZERO_REGNO, true);
- /* Push tmp reg. */
- emit_push_byte (AVR_TMP_REGNO, true);
+ /* Push tmp reg. */
+ emit_push_byte (AVR_TMP_REGNO, true);
- /* Push SREG. */
- /* ??? There's no dwarf2 column reserved for SREG. */
- emit_push_sfr (sreg_rtx, false, false /* clr */);
+ /* Push SREG. */
+ /* ??? There's no dwarf2 column reserved for SREG. */
+ emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
- /* Clear zero reg. */
- emit_move_insn (zero_reg_rtx, const0_rtx);
+ /* Clear zero reg. */
+ emit_move_insn (zero_reg_rtx, const0_rtx);
- /* Prevent any attempt to delete the setting of ZERO_REG! */
- emit_use (zero_reg_rtx);
+ /* Prevent any attempt to delete the setting of ZERO_REG! */
+ emit_use (zero_reg_rtx);
+ }
/* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
if (AVR_HAVE_RAMPD)
- emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
+ emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
if (AVR_HAVE_RAMPX
&& TEST_HARD_REG_BIT (set, REG_X)
&& TEST_HARD_REG_BIT (set, REG_X + 1))
{
- emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
+ emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
}
if (AVR_HAVE_RAMPY
@@ -1797,14 +1992,14 @@ avr_expand_prologue (void)
|| (TEST_HARD_REG_BIT (set, REG_Y)
&& TEST_HARD_REG_BIT (set, REG_Y + 1))))
{
- emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
+ emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
}
if (AVR_HAVE_RAMPZ
&& TEST_HARD_REG_BIT (set, REG_Z)
&& TEST_HARD_REG_BIT (set, REG_Z + 1))
{
- emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
+ emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
}
} /* is_interrupt is_signal */
@@ -1846,11 +2041,23 @@ avr_asm_function_end_prologue (FILE *file)
fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
get_frame_size());
- fprintf (file, "/* stack size = %d */\n",
- cfun->machine->stack_usage);
- /* Create symbol stack offset here so all functions have it. Add 1 to stack
- usage for offset so that SP + .L__stack_offset = return address. */
- fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
+
+ if (!cfun->machine->gasisr.yes)
+ {
+ fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
+ // Create symbol stack offset so all functions have it. Add 1 to stack
+ // usage for offset so that SP + .L__stack_offset = return address.
+ fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
+ }
+ else
+ {
+ int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
+ int to = cfun->machine->stack_usage;
+ int from = to - used_by_gasisr;
+ // Number of pushed regs is only known at assembly-time.
+ fprintf (file, "/* stack size = %d...%d */\n", from , to);
+ fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
+ }
}
@@ -2026,6 +2233,15 @@ avr_expand_epilogue (bool sibcall_p)
/* Restore used registers. */
+ int treg = AVR_TMP_REGNO;
+
+ if (isr_p
+ && cfun->machine->gasisr.yes)
+ {
+ treg = cfun->machine->gasisr.regno;
+ CLEAR_HARD_REG_BIT (set, treg);
+ }
+
for (int reg = 31; reg >= 0; --reg)
if (TEST_HARD_REG_BIT (set, reg))
emit_pop_byte (reg);
@@ -2039,8 +2255,8 @@ avr_expand_epilogue (bool sibcall_p)
&& TEST_HARD_REG_BIT (set, REG_Z)
&& TEST_HARD_REG_BIT (set, REG_Z + 1))
{
- emit_pop_byte (TMP_REGNO);
- emit_move_insn (rampz_rtx, tmp_reg_rtx);
+ emit_pop_byte (treg);
+ emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
}
if (AVR_HAVE_RAMPY
@@ -2048,34 +2264,43 @@ avr_expand_epilogue (bool sibcall_p)
|| (TEST_HARD_REG_BIT (set, REG_Y)
&& TEST_HARD_REG_BIT (set, REG_Y + 1))))
{
- emit_pop_byte (TMP_REGNO);
- emit_move_insn (rampy_rtx, tmp_reg_rtx);
+ emit_pop_byte (treg);
+ emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
}
if (AVR_HAVE_RAMPX
&& TEST_HARD_REG_BIT (set, REG_X)
&& TEST_HARD_REG_BIT (set, REG_X + 1))
{
- emit_pop_byte (TMP_REGNO);
- emit_move_insn (rampx_rtx, tmp_reg_rtx);
+ emit_pop_byte (treg);
+ emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
}
if (AVR_HAVE_RAMPD)
{
- emit_pop_byte (TMP_REGNO);
- emit_move_insn (rampd_rtx, tmp_reg_rtx);
+ emit_pop_byte (treg);
+ emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
}
- /* Restore SREG using tmp_reg as scratch. */
+ if (cfun->machine->gasisr.yes)
+ {
+ // Emit an Epilogue chunk.
+ emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
+ GEN_INT (cfun->machine->gasisr.regno)));
+ }
+ else // !TARGET_GASISR_PROLOGUES
+ {
+ /* Restore SREG using tmp_reg as scratch. */
- emit_pop_byte (AVR_TMP_REGNO);
- emit_move_insn (sreg_rtx, tmp_reg_rtx);
+ emit_pop_byte (AVR_TMP_REGNO);
+ emit_move_insn (sreg_rtx, tmp_reg_rtx);
- /* Restore tmp REG. */
- emit_pop_byte (AVR_TMP_REGNO);
+ /* Restore tmp REG. */
+ emit_pop_byte (AVR_TMP_REGNO);
- /* Restore zero REG. */
- emit_pop_byte (AVR_ZERO_REGNO);
+ /* Restore zero REG. */
+ emit_pop_byte (AVR_ZERO_REGNO);
+ }
}
if (!sibcall_p)
@@ -2088,6 +2313,7 @@ avr_expand_epilogue (bool sibcall_p)
static void
avr_asm_function_begin_epilogue (FILE *file)
{
+ app_disable();
fprintf (file, "/* epilogue start */\n");
}
@@ -3088,8 +3314,31 @@ avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
optimize_insn_for_speed_p()));
}
+
+ if (avr_log.insn_addresses)
+ fprintf (asm_out_file, ";; ADDR = %d\n",
+ (int) INSN_ADDRESSES (INSN_UID (insn)));
}
+
+/* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
+/* When GAS generates (parts of) ISR prologue / epilogue for us, we must
+ hint GAS about the end of the code to scan. There migh be code located
+ after the last epilogue. */
+
+static void
+avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
+{
+ if (cfun->machine->gasisr.yes
+ && !next_real_insn (insn))
+ {
+ app_disable();
+ fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
+ cfun->machine->gasisr.regno);
+ }
+}
+
+
/* Return 0 if undefined, 1 if always true or always false. */
int
@@ -3820,7 +4069,7 @@ out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
if (CONSTANT_ADDRESS_P (x))
{
int n_words = AVR_TINY ? 1 : 2;
- return optimize > 0 && io_address_operand (x, QImode)
+ return io_address_operand (x, QImode)
? avr_asm_len ("in %0,%i1", op, plen, -1)
: avr_asm_len ("lds %0,%m1", op, plen, -n_words);
}
@@ -4088,7 +4337,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
else if (CONSTANT_ADDRESS_P (base))
{
int n_words = AVR_TINY ? 2 : 4;
- return optimize > 0 && io_address_operand (base, HImode)
+ return io_address_operand (base, HImode)
? avr_asm_len ("in %A0,%i1" CR_TAB
"in %B0,%i1+1", op, plen, -2)
@@ -5215,7 +5464,7 @@ out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
if (CONSTANT_ADDRESS_P (x))
{
int n_words = AVR_TINY ? 1 : 2;
- return optimize > 0 && io_address_operand (x, QImode)
+ return io_address_operand (x, QImode)
? avr_asm_len ("out %i0,%1", op, plen, -1)
: avr_asm_len ("sts %m0,%1", op, plen, -n_words);
}
@@ -5291,13 +5540,12 @@ avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
if (CONSTANT_ADDRESS_P (base))
{
- int n_words = AVR_TINY ? 2 : 4;
- return optimize > 0 && io_address_operand (base, HImode)
+ return io_address_operand (base, HImode)
? avr_asm_len ("out %i0,%A1" CR_TAB
"out %i0+1,%B1", op, plen, -2)
: avr_asm_len ("sts %m0,%A1" CR_TAB
- "sts %m0+1,%B1", op, plen, -n_words);
+ "sts %m0+1,%B1", op, plen, -4);
}
if (reg_base > 0)
@@ -5477,7 +5725,7 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
if (CONSTANT_ADDRESS_P (base))
{
int n_words = AVR_TINY ? 2 : 4;
- return optimize > 0 && io_address_operand (base, HImode)
+ return io_address_operand (base, HImode)
? avr_asm_len ("out %i0+1,%B1" CR_TAB
"out %i0,%A1", op, plen, -2)
@@ -8297,7 +8545,7 @@ avr_out_addto_sp (rtx *op, int *plen)
}
while (addend++ < 0)
- avr_asm_len ("push __zero_reg__", op, plen, 1);
+ avr_asm_len ("push __tmp_reg__", op, plen, 1);
}
else if (addend > 0)
{
@@ -9138,6 +9386,12 @@ avr_adjust_insn_length (rtx_insn *insn, int len)
rtx *op = recog_data.operand;
enum attr_adjust_len adjust_len;
+ /* As we pretend jump tables in .text, fix branch offsets crossing jump
+ tables now. */
+
+ if (JUMP_TABLE_DATA_P (insn))
+ return 0;
+
/* Some complex insns don't need length adjustment and therefore
the length need not/must not be adjusted for these insns.
It is easier to state this in an insn attribute "adjust_len" than
@@ -9622,6 +9876,8 @@ avr_attribute_table[] =
false },
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
false },
+ { "no_gccisr", 0, 0, true, false, false, avr_handle_fndecl_attribute,
+ false },
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
false },
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
@@ -10001,7 +10257,9 @@ avr_asm_init_sections (void)
resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
we have also to track .rodata because it is located in RAM then. */
+#if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
if (0 == avr_arch->flash_pm_offset)
+#endif
readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
data_section->unnamed.callback = avr_output_data_section_asm_op;
bss_section->unnamed.callback = avr_output_bss_section_asm_op;
@@ -10037,7 +10295,10 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
|| STR_PREFIX_P (name, ".gnu.linkonce.d"));
if (!avr_need_copy_data_p
- && 0 == avr_arch->flash_pm_offset)
+#if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
+ && 0 == avr_arch->flash_pm_offset
+#endif
+ )
avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
|| STR_PREFIX_P (name, ".gnu.linkonce.r"));
@@ -10131,18 +10392,26 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
if (new_decl_p
&& decl && DECL_P (decl)
- && NULL_TREE == DECL_INITIAL (decl)
&& !DECL_EXTERNAL (decl)
&& avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
{
- // Don't warn for (implicit) aliases like in PR80462.
- tree asmname = DECL_ASSEMBLER_NAME (decl);
- varpool_node *node = varpool_node::get_for_asmname (asmname);
- bool alias_p = node && node->alias;
+ if (!TREE_READONLY (decl))
+ {
+ // This might happen with C++ if stuff needs constructing.
+ error ("variable %q+D with dynamic initialization put "
+ "into program memory area", decl);
+ }
+ else if (NULL_TREE == DECL_INITIAL (decl))
+ {
+ // Don't warn for (implicit) aliases like in PR80462.
+ tree asmname = DECL_ASSEMBLER_NAME (decl);
+ varpool_node *node = varpool_node::get_for_asmname (asmname);
+ bool alias_p = node && node->alias;
- if (!alias_p)
- warning (OPT_Wuninitialized, "uninitialized variable %q+D put into "
- "program memory area", decl);
+ if (!alias_p)
+ warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
+ "into program memory area", decl);
+ }
}
default_encode_section_info (decl, rtl, new_decl_p);
@@ -10440,6 +10709,33 @@ avr_memory_move_cost (machine_mode mode,
}
+/* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
+ already stripped off. */
+
+static int
+avr_mul_highpart_cost (rtx x, int)
+{
+ if (AVR_HAVE_MUL
+ && LSHIFTRT == GET_CODE (x)
+ && MULT == GET_CODE (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1)))
+ {
+ // This is the wider mode.
+ machine_mode mode = GET_MODE (x);
+
+ // The middle-end might still have PR81444, i.e. it is calling the cost
+ // functions with strange modes. Fix this now by also considering
+ // PSImode (should actually be SImode instead).
+ if (HImode == mode || PSImode == mode || SImode == mode)
+ {
+ return COSTS_N_INSNS (2);
+ }
+ }
+
+ return 10000;
+}
+
+
/* Mutually recursive subroutine of avr_rtx_cost for calculating the
cost of an RTX operand given its context. X is the rtx of the
operand, MODE is its mode, and OUTER is the rtx_code of this
@@ -10479,7 +10775,7 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
In either case, *TOTAL contains the cost result. */
static bool
-avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
+avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
int opno ATTRIBUTE_UNUSED, int *total, bool speed)
{
enum rtx_code code = GET_CODE (x);
@@ -11133,6 +11429,12 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
return true;
case LSHIFTRT:
+ if (outer_code == TRUNCATE)
+ {
+ *total = avr_mul_highpart_cost (x, speed);
+ return true;
+ }
+
switch (mode)
{
case QImode:
@@ -11310,16 +11612,10 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
return true;
case TRUNCATE:
- if (AVR_HAVE_MUL
- && LSHIFTRT == GET_CODE (XEXP (x, 0))
- && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
- && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
{
- if (QImode == mode || HImode == mode)
- {
- *total = COSTS_N_INSNS (2);
- return true;
- }
+ *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
+ return true;
}
break;
@@ -11367,8 +11663,7 @@ avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
}
else if (CONSTANT_ADDRESS_P (x))
{
- if (optimize > 0
- && io_address_operand (x, QImode))
+ if (io_address_operand (x, QImode))
cost = 2;
if (AVR_TINY
@@ -12309,17 +12604,88 @@ avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
}
-/* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
+/* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
+/* Emit jump tables out-of-line so that branches crossing the table
+ get shorter offsets. If we have JUMP + CALL, then put the tables
+ in a dedicated non-.text section so that CALLs get better chance to
+ be relaxed to RCALLs.
+
+ We emit the tables by hand because `function_rodata_section' does not
+ work as expected, cf. PR71151, and we do *NOT* want the table to be
+ in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
+ use; and setting it to 1 attributes table lengths to branch offsets...
+ Moreover, fincal.c keeps switching section before each table entry
+ which we find too fragile as to rely on section caching. */
void
-avr_output_addr_vec_elt (FILE *stream, int value)
+avr_output_addr_vec (rtx_insn *labl, rtx table)
{
- if (AVR_HAVE_JMP_CALL)
- fprintf (stream, "\t.word gs(.L%d)\n", value);
+ FILE *stream = asm_out_file;
+
+ app_disable();
+
+ // Switch to appropriate (sub)section.
+
+ if (DECL_SECTION_NAME (current_function_decl)
+ && symtab_node::get (current_function_decl)
+ && ! symtab_node::get (current_function_decl)->implicit_section)
+ {
+ // .subsection will emit the code after the function and in the
+ // section as chosen by the user.
+
+ switch_to_section (current_function_section ());
+ fprintf (stream, "\t.subsection\t1\n");
+ }
else
- fprintf (stream, "\trjmp .L%d\n", value);
+ {
+ // Since PR63223 there is no restriction where to put the table; it
+ // may even reside above 128 KiB. We put it in a section as high as
+ // possible and avoid progmem in order not to waste flash <= 64 KiB.
+
+ const char *sec_name = ".jumptables.gcc";
+
+ // The table belongs to its host function, therefore use fine
+ // grained sections so that, if that function is removed by
+ // --gc-sections, the child table(s) may also be removed. */
+
+ tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
+ const char *fname = IDENTIFIER_POINTER (asm_name);
+ fname = targetm.strip_name_encoding (fname);
+ sec_name = ACONCAT ((sec_name, ".", fname, NULL));
+
+ fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
+ AVR_HAVE_JMP_CALL ? "a" : "ax");
+ }
+
+ // Output the label that preceeds the table.
+
+ ASM_OUTPUT_ALIGN (stream, 1);
+ targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
+
+ // Output the table's content.
+
+ int vlen = XVECLEN (table, 0);
+
+ for (int idx = 0; idx < vlen; idx++)
+ {
+ int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
+
+ if (AVR_HAVE_JMP_CALL)
+ fprintf (stream, "\t.word gs(.L%d)\n", value);
+ else
+ fprintf (stream, "\trjmp .L%d\n", value);
+ }
+
+ // Switch back to original section. As we clobbered the section above,
+ // forget the current section before switching back.
+
+ in_section = NULL;
+ switch_to_section (current_function_section ());
}
+
+/* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
+
static void
avr_conditional_register_usage (void)
{
@@ -14286,6 +14652,9 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
#undef TARGET_ASM_SELECT_SECTION
#define TARGET_ASM_SELECT_SECTION avr_asm_select_section
+#undef TARGET_ASM_FINAL_POSTSCAN_INSN
+#define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
+
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST avr_register_move_cost
#undef TARGET_MEMORY_MOVE_COST
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 3158887fc01..579c8faa0b5 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -398,6 +398,10 @@ typedef struct avr_args
#define SUPPORTS_INIT_PRIORITY 0
+/* We pretend jump tables are in text section because otherwise,
+ final.c will switch to .rodata before jump tables and thereby
+ triggers __do_copy_data. As we implement ASM_OUTPUT_ADDR_VEC,
+ we still have full control over the jump tables themselves. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
#define ASM_COMMENT_START " ; "
@@ -447,8 +451,8 @@ typedef struct avr_args
fprintf (STREAM, "\tpop\tr%d", REGNO); \
}
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- avr_output_addr_vec_elt (STREAM, VALUE)
+#define ASM_OUTPUT_ADDR_VEC(TLABEL, TDATA) \
+ avr_output_addr_vec (TLABEL, TDATA)
#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
do { \
@@ -581,6 +585,26 @@ struct GTY(()) machine_function
/* 'true' if the above is_foo predicates are sanity-checked to avoid
multiple diagnose for the same function. */
int attributes_checked_p;
+
+ /* 'true' - if current function shall not use '__gcc_isr' pseudo
+ instructions as specified by the "no_gccisr" attribute. */
+ int is_no_gccisr;
+
+ /* Used for `__gcc_isr' pseudo instruction handling of
+ non-naked ISR prologue / epilogue(s). */
+ struct
+ {
+ /* 'true' if this function actually uses "*gasisr" insns. */
+ int yes;
+ /* 'true' if this function is allowed to use "*gasisr" insns. */
+ int maybe;
+ /* The register numer as printed by the Done chunk. */
+ int regno;
+ } gasisr;
+
+ /* 'true' if this function references .L__stack_usage like with
+ __builtin_return_address. */
+ int use_L__stack_usage;
};
/* AVR does not round pushes, but the existence of this macro is
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index a9be9a406c3..d17c0b13640 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -85,6 +85,7 @@
[UNSPECV_PROLOGUE_SAVES
UNSPECV_EPILOGUE_RESTORES
UNSPECV_WRITE_SP
+ UNSPECV_GASISR
UNSPECV_GOTO_RECEIVER
UNSPECV_ENABLE_IRQS
UNSPECV_MEMORY_BARRIER
@@ -94,6 +95,12 @@
UNSPECV_DELAY_CYCLES
])
+;; Chunk numbers for __gcc_isr are hard-coded in GAS.
+(define_constants
+ [(GASISR_Prologue 1)
+ (GASISR_Epilogue 2)
+ (GASISR_Done 0)
+ ])
(include "predicates.md")
(include "constraints.md")
@@ -5185,7 +5192,7 @@
(set_attr "cc" "none")])
;; table jump
-;; For entries in jump table see avr_output_addr_vec_elt.
+;; For entries in jump table see avr_output_addr_vec.
;; Table made from
;; "rjmp .L<n>" instructions for <= 8K devices
@@ -5800,6 +5807,38 @@
(set_attr "cc" "clobber")
(set_attr "isa" "rjmp,jmp")])
+
+;; $0 = Chunk: 1 = Prologue, 2 = Epilogue
+;; $1 = Register as printed by chunk 0 (Done) in final postscan.
+(define_expand "gasisr"
+ [(parallel [(unspec_volatile [(match_operand:QI 0 "const_int_operand")
+ (match_operand:QI 1 "const_int_operand")]
+ UNSPECV_GASISR)
+ (set (reg:HI REG_SP)
+ (unspec_volatile:HI [(reg:HI REG_SP)] UNSPECV_GASISR))
+ (set (match_dup 2)
+ (unspec_volatile:BLK [(match_dup 2)]
+ UNSPECV_MEMORY_BARRIER))])]
+ "TARGET_GASISR_PROLOGUES"
+ {
+ operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[2]) = 1;
+ })
+
+(define_insn "*gasisr"
+ [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "P,K")
+ (match_operand:QI 1 "const_int_operand" "n,n")]
+ UNSPECV_GASISR)
+ (set (reg:HI REG_SP)
+ (unspec_volatile:HI [(reg:HI REG_SP)] UNSPECV_GASISR))
+ (set (match_operand:BLK 2)
+ (unspec_volatile:BLK [(match_dup 2)] UNSPECV_MEMORY_BARRIER))]
+ "TARGET_GASISR_PROLOGUES"
+ "__gcc_isr %0"
+ [(set_attr "length" "6,5")
+ (set_attr "cc" "clobber")])
+
+
; return
(define_insn "return"
[(return)]
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 1efb1c063b6..81850e037f6 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -26,6 +26,10 @@ mmcu=
Target RejectNegative Joined Var(avr_mmcu) MissingArgError(missing device or architecture after %qs)
-mmcu=MCU Select the target MCU.
+mgas-isr-prologues
+Target Report Mask(GASISR_PROLOGUES)
+Allow usage of __gcc_isr pseudo instructions in ISR prologues and epilogues.
+
mn-flash=
Target RejectNegative Joined Var(avr_n_flash) UInteger Init(-1)
Set the number of 64 KiB flash segments.
diff --git a/gcc/config/avr/elf.h b/gcc/config/avr/elf.h
index f6b18d2e814..e11c04e9d6d 100644
--- a/gcc/config/avr/elf.h
+++ b/gcc/config/avr/elf.h
@@ -31,11 +31,6 @@
#undef STRING_LIMIT
#define STRING_LIMIT ((unsigned) 64)
-/* Output alignment 2**1 for jump tables. */
-#undef ASM_OUTPUT_BEFORE_CASE_LABEL
-#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \
- ASM_OUTPUT_ALIGN (FILE, 1);
-
/* Be conservative in crtstuff.c. */
#undef INIT_SECTION_ASM_OP
#undef FINI_SECTION_ASM_OP
diff --git a/gcc/config/avr/gen-avr-mmcu-specs.c b/gcc/config/avr/gen-avr-mmcu-specs.c
index db17eeb41d7..b923aa4ee3c 100644
--- a/gcc/config/avr/gen-avr-mmcu-specs.c
+++ b/gcc/config/avr/gen-avr-mmcu-specs.c
@@ -224,6 +224,11 @@ print_mcu (const avr_mcu_t *mcu)
: "\t%{mrmw}");
#endif // have avr-as -mrmw
+#ifdef HAVE_AS_AVR_MGCCISR_OPTION
+ fprintf (f, "*asm_gccisr:\n%s\n\n",
+ "\t%{!mno-gas-isr-prologues: -mgcc-isr}");
+#endif // have avr-as -mgcc-isr
+
fprintf (f, "*asm_errata_skip:\n%s\n\n", errata_skip
? "\t%{mno-skip-bug}"
: "\t%{!mskip-bug: -mno-skip-bug}");
diff --git a/gcc/config/avr/specs.h b/gcc/config/avr/specs.h
index da5df4039e9..4f046a11e1f 100644
--- a/gcc/config/avr/specs.h
+++ b/gcc/config/avr/specs.h
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
"%(asm_arch) " \
"%(asm_relax) " \
"%(asm_rmw) " \
+ "%(asm_gccisr) " \
"%(asm_errata_skip) "
#define LINK_ARCH_SPEC \
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 2073927af7c..9fe90fc37b4 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -2435,9 +2435,8 @@ cbranch_predicted_taken_p (rtx insn)
if (x)
{
- int pred_val = XINT (x, 0);
-
- return pred_val >= REG_BR_PROB_BASE / 2;
+ return profile_probability::from_reg_br_prob_note (XINT (x, 0))
+ >= profile_probability::even ();
}
return 0;
diff --git a/gcc/config/bfin/rtems.h b/gcc/config/bfin/rtems.h
index 440e886ffff..ac314f2911e 100644
--- a/gcc/config/bfin/rtems.h
+++ b/gcc/config/bfin/rtems.h
@@ -2,21 +2,26 @@
Copyright (C) 2006-2017 Free Software Foundation, Inc.
Contributed by Ralf Corsépius (ralf.corsepius@rtems.org).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS preprocessor built-ins. */
#define TARGET_OS_CPP_BUILTINS() \
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 8e6e25ab7f5..9a8cf31d400 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -3683,11 +3683,9 @@ default_function_sections:
void
darwin_function_switched_text_sections (FILE *fp, tree decl, bool new_is_cold)
{
- char buf[128];
- snprintf (buf, 128, "%s%s",new_is_cold?"__cold_sect_of_":"__hot_sect_of_",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
/* Make sure we pick up all the relevant quotes etc. */
- assemble_name_raw (fp, (const char *) buf);
+ 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);
}
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 0918b9835b9..c571d63f2c6 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -2621,7 +2621,6 @@ frv_print_operand_jump_hint (rtx_insn *insn)
rtx note;
rtx labelref;
int ret;
- int prob = -1;
enum { UNKNOWN, BACKWARD, FORWARD } jump_type = UNKNOWN;
gcc_assert (JUMP_P (insn));
@@ -2647,8 +2646,8 @@ frv_print_operand_jump_hint (rtx_insn *insn)
else
{
- prob = XINT (note, 0);
- ret = ((prob >= (REG_BR_PROB_BASE / 2))
+ ret = ((profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ >= profile_probability::even ())
? FRV_JUMP_LIKELY
: FRV_JUMP_NOT_LIKELY);
}
diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c
index d659959d77f..db0365e92c1 100644
--- a/gcc/config/ft32/ft32.c
+++ b/gcc/config/ft32/ft32.c
@@ -79,7 +79,7 @@ ft32_function_value (const_tree valtype,
We always return values in register $r0 for ft32. */
static rtx
-ft32_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+ft32_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
{
return gen_rtx_REG (mode, FT32_R0);
}
@@ -625,7 +625,7 @@ ft32_initial_elimination_offset (int from, int to)
static void
ft32_setup_incoming_varargs (cumulative_args_t cum_v,
- enum machine_mode mode,
+ machine_mode mode,
tree type ATTRIBUTE_UNUSED,
int *pretend_size, int no_rtl ATTRIBUTE_UNUSED)
{
@@ -653,7 +653,7 @@ ft32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
NULL_RTX if there's no more space. */
static rtx
-ft32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+ft32_function_arg (cumulative_args_t cum_v, machine_mode mode,
const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
@@ -670,7 +670,7 @@ ft32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
: (unsigned) int_size_in_bytes (TYPE))
static void
-ft32_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+ft32_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named ATTRIBUTE_UNUSED)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
@@ -684,7 +684,7 @@ ft32_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
static bool
ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
- enum machine_mode mode, const_tree type,
+ machine_mode mode, const_tree type,
bool named ATTRIBUTE_UNUSED)
{
unsigned HOST_WIDE_INT size;
@@ -707,7 +707,7 @@ ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
static int
ft32_arg_partial_bytes (cumulative_args_t cum_v,
- enum machine_mode mode, tree type, bool named)
+ machine_mode mode, tree type, bool named)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int bytes_left, size;
@@ -790,7 +790,7 @@ ft32_is_mem_pm (rtx o)
#undef TARGET_VALID_POINTER_MODE
#define TARGET_VALID_POINTER_MODE ft32_valid_pointer_mode
static bool
-ft32_valid_pointer_mode (enum machine_mode mode)
+ft32_valid_pointer_mode (machine_mode mode)
{
if (mode == SImode)
return 1;
@@ -799,7 +799,7 @@ ft32_valid_pointer_mode (enum machine_mode mode)
#undef TARGET_ADDR_SPACE_POINTER_MODE
#define TARGET_ADDR_SPACE_POINTER_MODE ft32_addr_space_pointer_mode
-static enum machine_mode
+static machine_mode
ft32_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
{
return Pmode;
@@ -807,7 +807,7 @@ ft32_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
#undef TARGET_ADDR_SPACE_ADDRESS_MODE
#define TARGET_ADDR_SPACE_ADDRESS_MODE ft32_addr_space_address_mode
-static enum machine_mode
+static machine_mode
ft32_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
{
return Pmode;
@@ -861,8 +861,7 @@ reg_ok_for_base_p (rtx r, bool strict)
}
static bool
-ft32_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
- bool strict,
+ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
addr_space_t as ATTRIBUTE_UNUSED)
{
if (mode != BLKmode)
diff --git a/gcc/config/i386/adxintrin.h b/gcc/config/i386/adxintrin.h
index 9c4152b9f36..7acdaf4ab6f 100644
--- a/gcc/config/i386/adxintrin.h
+++ b/gcc/config/i386/adxintrin.h
@@ -33,7 +33,7 @@ __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_subborrow_u32 (unsigned char __CF, unsigned int __X,
unsigned int __Y, unsigned int *__P)
{
- return __builtin_ia32_sbb_u32 (__CF, __Y, __X, __P);
+ return __builtin_ia32_sbb_u32 (__CF, __X, __Y, __P);
}
extern __inline unsigned char
@@ -58,7 +58,7 @@ __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_subborrow_u64 (unsigned char __CF, unsigned long long __X,
unsigned long long __Y, unsigned long long *__P)
{
- return __builtin_ia32_sbb_u64 (__CF, __Y, __X, __P);
+ return __builtin_ia32_sbb_u64 (__CF, __X, __Y, __P);
}
extern __inline unsigned char
diff --git a/gcc/config/i386/avx512fintrin.h b/gcc/config/i386/avx512fintrin.h
index e383983afc1..72f57f7b6c9 100644
--- a/gcc/config/i386/avx512fintrin.h
+++ b/gcc/config/i386/avx512fintrin.h
@@ -8417,6 +8417,29 @@ _mm_getexp_round_ss (__m128 __A, __m128 __B, const int __R)
__R);
}
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
+ __m128 __B, const int __R)
+{
+ return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_round_ss (__mmask8 __U, __m128 __A, __m128 __B,
+ const int __R)
+{
+ return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U, __R);
+}
+
extern __inline __m128d
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_getexp_round_sd (__m128d __A, __m128d __B, const int __R)
@@ -8426,6 +8449,29 @@ _mm_getexp_round_sd (__m128d __A, __m128d __B, const int __R)
__R);
}
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
+ __m128d __B, const int __R)
+{
+ return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U, __R);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_round_sd (__mmask8 __U, __m128d __A, __m128d __B,
+ const int __R)
+{
+ return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U, __R);
+}
+
extern __inline __m512
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm512_getexp_round_ps (__m512 __A, const int __R)
@@ -8570,6 +8616,33 @@ _mm_getmant_round_sd (__m128d __A, __m128d __B,
__R);
}
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
+ __m128d __B, _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__D << 2) | __C,
+ (__v2df) __W,
+ __U, __R);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_round_sd (__mmask8 __U, __m128d __A, __m128d __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__D << 2) | __C,
+ (__v2df)
+ _mm_setzero_pd(),
+ __U, __R);
+}
+
extern __inline __m128
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_getmant_round_ss (__m128 __A, __m128 __B,
@@ -8582,6 +8655,33 @@ _mm_getmant_round_ss (__m128 __A, __m128 __B,
__R);
}
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
+ __m128 __B, _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__D << 2) | __C,
+ (__v4sf) __W,
+ __U, __R);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_round_ss (__mmask8 __U, __m128 __A, __m128 __B,
+ _MM_MANTISSA_NORM_ENUM __C,
+ _MM_MANTISSA_SIGN_ENUM __D, const int __R)
+{
+ return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__D << 2) | __C,
+ (__v4sf)
+ _mm_setzero_ps(),
+ __U, __R);
+}
+
#else
#define _mm512_getmant_round_pd(X, B, C, R) \
((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \
@@ -8629,18 +8729,63 @@ _mm_getmant_round_ss (__m128 __A, __m128 __B,
(int)(((D)<<2) | (C)), \
(R)))
+#define _mm_mask_getmant_round_sd(W, U, X, Y, C, D, R) \
+ ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v2df)(__m128d)(W), \
+ (__mmask8)(U),\
+ (R)))
+
+#define _mm_maskz_getmant_round_sd(U, X, Y, C, D, R) \
+ ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v2df)(__m128d)_mm_setzero_pd(), \
+ (__mmask8)(U),\
+ (R)))
+
#define _mm_getmant_round_ss(X, Y, C, D, R) \
((__m128)__builtin_ia32_getmantss_round ((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), \
(int)(((D)<<2) | (C)), \
(R)))
+#define _mm_mask_getmant_round_ss(W, U, X, Y, C, D, R) \
+ ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v4sf)(__m128)(W), \
+ (__mmask8)(U),\
+ (R)))
+
+#define _mm_maskz_getmant_round_ss(U, X, Y, C, D, R) \
+ ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v4sf)(__m128)_mm_setzero_ps(), \
+ (__mmask8)(U),\
+ (R)))
+
#define _mm_getexp_round_ss(A, B, R) \
((__m128)__builtin_ia32_getexpss128_round((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), R))
+#define _mm_mask_getexp_round_ss(W, U, A, B, C) \
+ (__m128)__builtin_ia32_getexpss_mask_round(A, B, W, U, C)
+
+#define _mm_maskz_getexp_round_ss(U, A, B, C) \
+ (__m128)__builtin_ia32_getexpss_mask_round(A, B, (__v4sf)_mm_setzero_ps(), U, C)
+
#define _mm_getexp_round_sd(A, B, R) \
((__m128d)__builtin_ia32_getexpsd128_round((__v2df)(__m128d)(A), (__v2df)(__m128d)(B), R))
+#define _mm_mask_getexp_round_sd(W, U, A, B, C) \
+ (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, W, U, C)
+
+#define _mm_maskz_getexp_round_sd(U, A, B, C) \
+ (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, (__v2df)_mm_setzero_pd(), U, C)
+
+
#define _mm512_getexp_round_ps(A, R) \
((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_undefined_ps(), (__mmask16)-1, R))
@@ -13358,6 +13503,29 @@ _mm_getexp_ss (__m128 __A, __m128 __B)
_MM_FROUND_CUR_DIRECTION);
}
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
+{
+ return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B)
+{
+ return (__m128) __builtin_ia32_getexpss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
extern __inline __m128d
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_getexp_sd (__m128d __A, __m128d __B)
@@ -13367,6 +13535,29 @@ _mm_getexp_sd (__m128d __A, __m128d __B)
_MM_FROUND_CUR_DIRECTION);
}
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_getexpsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
extern __inline __m512d
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm512_getmant_pd (__m512d __A, _MM_MANTISSA_NORM_ENUM __B,
@@ -13450,6 +13641,33 @@ _mm_getmant_sd (__m128d __A, __m128d __B, _MM_MANTISSA_NORM_ENUM __C,
_MM_FROUND_CUR_DIRECTION);
}
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B,
+ _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__D << 2) | __C,
+ (__v2df) __W,
+ __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128d
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_sd (__mmask8 __U, __m128d __A, __m128d __B,
+ _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128d) __builtin_ia32_getmantsd_mask_round ((__v2df) __A,
+ (__v2df) __B,
+ (__D << 2) | __C,
+ (__v2df)
+ _mm_setzero_pd(),
+ __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
extern __inline __m128
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_getmant_ss (__m128 __A, __m128 __B, _MM_MANTISSA_NORM_ENUM __C,
@@ -13461,6 +13679,33 @@ _mm_getmant_ss (__m128 __A, __m128 __B, _MM_MANTISSA_NORM_ENUM __C,
_MM_FROUND_CUR_DIRECTION);
}
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_getmant_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B,
+ _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__D << 2) | __C,
+ (__v4sf) __W,
+ __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+extern __inline __m128
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_maskz_getmant_ss (__mmask8 __U, __m128 __A, __m128 __B,
+ _MM_MANTISSA_NORM_ENUM __C, _MM_MANTISSA_SIGN_ENUM __D)
+{
+ return (__m128) __builtin_ia32_getmantss_mask_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__D << 2) | __C,
+ (__v4sf)
+ _mm_setzero_ps(),
+ __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
#else
#define _mm512_getmant_pd(X, B, C) \
((__m512d)__builtin_ia32_getmantpd512_mask ((__v8df)(__m512d)(X), \
@@ -13508,20 +13753,68 @@ _mm_getmant_ss (__m128 __A, __m128 __B, _MM_MANTISSA_NORM_ENUM __C,
(int)(((D)<<2) | (C)), \
_MM_FROUND_CUR_DIRECTION))
+#define _mm_mask_getmant_sd(W, U, X, Y, C, D) \
+ ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v2df)(__m128d)(W), \
+ (__mmask8)(U),\
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_maskz_getmant_sd(U, X, Y, C, D) \
+ ((__m128d)__builtin_ia32_getmantsd_mask_round ((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v2df)_mm_setzero_pd(), \
+ (__mmask8)(U),\
+ _MM_FROUND_CUR_DIRECTION))
+
#define _mm_getmant_ss(X, Y, C, D) \
((__m128)__builtin_ia32_getmantss_round ((__v4sf)(__m128)(X), \
(__v4sf)(__m128)(Y), \
(int)(((D)<<2) | (C)), \
_MM_FROUND_CUR_DIRECTION))
+#define _mm_mask_getmant_ss(W, U, X, Y, C, D) \
+ ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v4sf)(__m128)(W), \
+ (__mmask8)(U),\
+ _MM_FROUND_CUR_DIRECTION))
+
+#define _mm_maskz_getmant_ss(U, X, Y, C, D) \
+ ((__m128)__builtin_ia32_getmantss_mask_round ((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), \
+ (int)(((D)<<2) | (C)), \
+ (__v4sf)_mm_setzero_ps(), \
+ (__mmask8)(U),\
+ _MM_FROUND_CUR_DIRECTION))
+
#define _mm_getexp_ss(A, B) \
- ((__m128)__builtin_ia32_getexpss128_mask((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), \
+ ((__m128)__builtin_ia32_getexpss128_round((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), \
_MM_FROUND_CUR_DIRECTION))
+#define _mm_mask_getexp_ss(W, U, A, B) \
+ (__m128)__builtin_ia32_getexpss_mask_round(A, B, W, U,\
+ _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_getexp_ss(U, A, B) \
+ (__m128)__builtin_ia32_getexpss_mask_round(A, B, (__v4sf)_mm_setzero_ps(), U,\
+ _MM_FROUND_CUR_DIRECTION)
+
#define _mm_getexp_sd(A, B) \
- ((__m128d)__builtin_ia32_getexpsd128_mask((__v2df)(__m128d)(A), (__v2df)(__m128d)(B),\
+ ((__m128d)__builtin_ia32_getexpsd128_round((__v2df)(__m128d)(A), (__v2df)(__m128d)(B),\
_MM_FROUND_CUR_DIRECTION))
+#define _mm_mask_getexp_sd(W, U, A, B) \
+ (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, W, U,\
+ _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_maskz_getexp_sd(U, A, B) \
+ (__m128d)__builtin_ia32_getexpsd_mask_round(A, B, (__v2df)_mm_setzero_pd(), U,\
+ _MM_FROUND_CUR_DIRECTION)
+
#define _mm512_getexp_ps(A) \
((__m512)__builtin_ia32_getexpps512_mask((__v16sf)(__m512)(A), \
(__v16sf)_mm512_undefined_ps(), (__mmask16)-1, _MM_FROUND_CUR_DIRECTION))
diff --git a/gcc/config/i386/avx512vlintrin.h b/gcc/config/i386/avx512vlintrin.h
index f62f641188e..05550516e44 100644
--- a/gcc/config/i386/avx512vlintrin.h
+++ b/gcc/config/i386/avx512vlintrin.h
@@ -9099,6 +9099,17 @@ _mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y)
extern __inline __m256i
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutexvar_epi64 (__m256i __X, __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_permvardi256_mask ((__v4di) __Y,
+ (__v4di) __X,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_mask_permutexvar_epi64 (__m256i __W, __mmask8 __M, __m256i __X,
__m256i __Y)
{
@@ -9163,6 +9174,17 @@ _mm_maskz_mul_epu32 (__mmask8 __M, __m128i __X, __m128i __Y)
extern __inline __m256i
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutexvar_epi32 (__m256i __X, __m256i __Y)
+{
+ return (__m256i) __builtin_ia32_permvarsi256_mask ((__v8si) __Y,
+ (__v8si) __X,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_mask_permutexvar_epi32 (__m256i __W, __mmask8 __M, __m256i __X,
__m256i __Y)
{
@@ -9751,6 +9773,17 @@ _mm_cmple_epi64_mask (__m128i __X, __m128i __Y)
#ifdef __OPTIMIZE__
extern __inline __m256i
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_permutex_epi64 (__m256i __X, const int __I)
+{
+ return (__m256i) __builtin_ia32_permdi256_mask ((__v4di) __X,
+ __I,
+ (__v4di)
+ _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+extern __inline __m256i
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm256_mask_permutex_epi64 (__m256i __W, __mmask8 __M,
__m256i __X, const int __I)
{
@@ -12367,6 +12400,13 @@ _mm256_permutex_pd (__m256d __X, const int __M)
_mm256_undefined_pd (), \
(__mmask8)-1))
+#define _mm256_permutex_epi64(X, I) \
+ ((__m256i) __builtin_ia32_permdi256_mask ((__v4di)(__m256i)(X), \
+ (int)(I), \
+ (__v4di)(__m256i) \
+ (_mm256_setzero_si256 ()),\
+ (__mmask8) -1))
+
#define _mm256_maskz_permutex_epi64(M, X, I) \
((__m256i) __builtin_ia32_permdi256_mask ((__v4di)(__m256i)(X), \
(int)(I), \
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index f94e274358b..98c05c9ebab 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -138,19 +138,19 @@
(define_register_constraint "Yd"
"TARGET_INTER_UNIT_MOVES_TO_VEC
- ? (TARGET_AVX512BW
+ ? (TARGET_AVX512DQ
? ALL_SSE_REGS
: (TARGET_SSE4_1 ? SSE_REGS : NO_REGS))
: NO_REGS"
- "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512BW target or any SSE register for SSE4_1 target, when inter-unit moves to vector registers are enabled.")
+ "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512DQ target or any SSE register for SSE4_1 target, when inter-unit moves to vector registers are enabled.")
(define_register_constraint "Ye"
"TARGET_INTER_UNIT_MOVES_FROM_VEC
- ? (TARGET_AVX512BW
+ ? (TARGET_AVX512DQ
? ALL_SSE_REGS
: (TARGET_SSE4_1 ? SSE_REGS : NO_REGS))
: NO_REGS"
- "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512BW target or any SSE register for SSE4_1 target, when inter-unit moves from vector registers are enabled.")
+ "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512DQ target or any SSE register for SSE4_1 target, when inter-unit moves from vector registers are enabled.")
(define_register_constraint "Ym"
"TARGET_MMX && TARGET_INTER_UNIT_MOVES_TO_VEC ? MMX_REGS : NO_REGS"
diff --git a/gcc/config/i386/gstabs.h b/gcc/config/i386/gstabs.h
deleted file mode 100644
index e9a621871e3..00000000000
--- a/gcc/config/i386/gstabs.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* We do not want to output SDB debugging information. */
-
-#undef SDB_DEBUGGING_INFO
-
-/* We want to output DBX debugging information. */
-
-#define DBX_DEBUGGING_INFO 1
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 19d876d73f2..8d584dbe940 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -454,6 +454,8 @@ DEF_FUNCTION_TYPE (V8SF, V8SF, V8SF, V8SI, INT, UQI)
DEF_FUNCTION_TYPE (V4SF, V4SF, V4SF, V4SI, INT, UQI)
DEF_FUNCTION_TYPE (V4SF, V4SF, V4SF, V4SI, INT, QI, INT)
DEF_FUNCTION_TYPE (V2DF, V2DF, V2DF, V2DI, INT, QI, INT)
+DEF_FUNCTION_TYPE (V2DF, V2DF, V2DF, INT, V2DF, UQI, INT)
+DEF_FUNCTION_TYPE (V4SF, V4SF, V4SF, INT, V4SF, UQI, INT)
DEF_FUNCTION_TYPE (V16SF, V16SF, V4SF, INT)
DEF_FUNCTION_TYPE (V16SF, V16SF, V4SF, INT, V16SF, UHI)
DEF_FUNCTION_TYPE (V16SF, V16SF, V8SF, INT, V16SF, UHI)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 23e88839048..e91468a1a2e 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -2449,11 +2449,15 @@ BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_sfixupimmv4sf_maskz_round, "__b
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_getexpv8df_mask_round, "__builtin_ia32_getexppd512_mask", IX86_BUILTIN_GETEXPPD512, UNKNOWN, (int) V8DF_FTYPE_V8DF_V8DF_QI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_getexpv16sf_mask_round, "__builtin_ia32_getexpps512_mask", IX86_BUILTIN_GETEXPPS512, UNKNOWN, (int) V16SF_FTYPE_V16SF_V16SF_HI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_sgetexpv2df_round, "__builtin_ia32_getexpsd128_round", IX86_BUILTIN_GETEXPSD128, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT)
+BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_sgetexpv2df_mask_round, "__builtin_ia32_getexpsd_mask_round", IX86_BUILTIN_GETEXPSD_MASK_ROUND, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_sgetexpv4sf_round, "__builtin_ia32_getexpss128_round", IX86_BUILTIN_GETEXPSS128, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT)
+BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_sgetexpv4sf_mask_round, "__builtin_ia32_getexpss_mask_round", IX86_BUILTIN_GETEXPSS_MASK_ROUND, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_getmantv8df_mask_round, "__builtin_ia32_getmantpd512_mask", IX86_BUILTIN_GETMANTPD512, UNKNOWN, (int) V8DF_FTYPE_V8DF_INT_V8DF_QI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_getmantv16sf_mask_round, "__builtin_ia32_getmantps512_mask", IX86_BUILTIN_GETMANTPS512, UNKNOWN, (int) V16SF_FTYPE_V16SF_INT_V16SF_HI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_vgetmantv2df_round, "__builtin_ia32_getmantsd_round", IX86_BUILTIN_GETMANTSD128, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT_INT)
+BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_vgetmantv2df_mask_round, "__builtin_ia32_getmantsd_mask_round", IX86_BUILTIN_GETMANTSD_MASK_ROUND, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_vgetmantv4sf_round, "__builtin_ia32_getmantss_round", IX86_BUILTIN_GETMANTSS128, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT_INT)
+BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_avx512f_vgetmantv4sf_mask_round, "__builtin_ia32_getmantss_mask_round", IX86_BUILTIN_GETMANTSS_MASK_ROUND, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_smaxv8df3_mask_round, "__builtin_ia32_maxpd512_mask", IX86_BUILTIN_MAXPD512, UNKNOWN, (int) V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_smaxv16sf3_mask_round, "__builtin_ia32_maxps512_mask", IX86_BUILTIN_MAXPS512, UNKNOWN, (int) V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT)
BDESC (OPTION_MASK_ISA_AVX512F, CODE_FOR_sse2_vmsmaxv2df3_round, "__builtin_ia32_maxsd_round", IX86_BUILTIN_MAXSD_ROUND, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT)
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 8bdd67eb608..bf8a0492592 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -316,7 +316,7 @@ extern enum attr_cpu ix86_schedule;
extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
- enum machine_mode mode);
+ machine_mode mode);
#ifdef RTX_CODE
/* Target data for multipass lookahead scheduling.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3caeeb0e377..9a35c995f26 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6284,6 +6284,12 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_isa_flags
|= OPTION_MASK_ISA_LZCNT & ~opts->x_ix86_isa_flags_explicit;
+ /* Disable BMI, BMI2 and TBM instructions for -m16. */
+ if (TARGET_16BIT_P(opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM)
+ & ~opts->x_ix86_isa_flags_explicit);
+
/* Validate -mpreferred-stack-boundary= value or default it to
PREFERRED_STACK_BOUNDARY_DEFAULT. */
ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT;
@@ -8742,6 +8748,15 @@ ix86_function_ms_hook_prologue (const_tree fn)
return false;
}
+static bool
+ix86_function_naked (const_tree fn)
+{
+ if (fn && lookup_attribute ("naked", DECL_ATTRIBUTES (fn)))
+ return true;
+
+ return false;
+}
+
/* Write the extra assembler code needed to declare a function properly. */
void
@@ -8771,16 +8786,15 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname,
if (TARGET_64BIT)
{
/* leaq [%rsp + 0], %rsp */
- asm_fprintf (asm_out_file, ASM_BYTE
- "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n");
+ fputs (ASM_BYTE "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n",
+ asm_out_file);
}
else
{
/* movl.s %edi, %edi
push %ebp
movl.s %esp, %ebp */
- asm_fprintf (asm_out_file, ASM_BYTE
- "0x8b, 0xff, 0x55, 0x8b, 0xec\n");
+ fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", asm_out_file);
}
}
}
@@ -10143,7 +10157,13 @@ ix86_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
/* For pointers passed in memory we expect bounds passed in Bounds
Table. */
if (!nregs)
- cum->bnds_in_bt = chkp_type_bounds_count (type);
+ {
+ /* Track if there are outgoing arguments on stack. */
+ if (cum->caller)
+ cfun->machine->outgoing_args_on_stack = true;
+
+ cum->bnds_in_bt = chkp_type_bounds_count (type);
+ }
}
/* Define where to put the arguments to a function.
@@ -10410,25 +10430,22 @@ ix86_function_arg (cumulative_args_t cum_v, machine_mode omode,
{
/* This is the pointer argument. */
gcc_assert (TYPE_MODE (type) == Pmode);
- if (cfun->machine->func_type == TYPE_INTERRUPT)
- /* -WORD(AP) in the current frame in interrupt handler. */
- arg = plus_constant (Pmode, arg_pointer_rtx,
- -UNITS_PER_WORD);
- else
- /* (AP) in the current frame in exception handler. */
- arg = arg_pointer_rtx;
+ /* It is at -WORD(AP) in the current frame in interrupt and
+ exception handlers. */
+ arg = plus_constant (Pmode, arg_pointer_rtx, -UNITS_PER_WORD);
}
else
{
gcc_assert (cfun->machine->func_type == TYPE_EXCEPTION
&& TREE_CODE (type) == INTEGER_TYPE
&& TYPE_MODE (type) == word_mode);
- /* The integer argument is the error code at -WORD(AP) in
- the current frame in exception handler. */
+ /* The error code is the word-mode integer argument at
+ -2 * WORD(AP) in the current frame of the exception
+ handler. */
arg = gen_rtx_MEM (word_mode,
plus_constant (Pmode,
arg_pointer_rtx,
- -UNITS_PER_WORD));
+ -2 * UNITS_PER_WORD));
}
return arg;
}
@@ -10473,6 +10490,10 @@ ix86_function_arg (cumulative_args_t cum_v, machine_mode omode,
else
arg = function_arg_32 (cum, mode, omode, type, bytes, words);
+ /* Track if there are outgoing arguments on stack. */
+ if (arg == NULL_RTX && cum->caller)
+ cfun->machine->outgoing_args_on_stack = true;
+
return arg;
}
@@ -11363,7 +11384,7 @@ ix86_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
static void
ix86_setup_incoming_vararg_bounds (cumulative_args_t cum_v,
- enum machine_mode mode,
+ machine_mode mode,
tree type,
int *pretend_size ATTRIBUTE_UNUSED,
int no_rtl)
@@ -12237,6 +12258,9 @@ ix86_can_use_return_insn_p (void)
{
struct ix86_frame frame;
+ if (ix86_function_naked (current_function_decl))
+ return false;
+
/* Don't use `ret' instruction in interrupt handler. */
if (! reload_completed
|| frame_pointer_needed
@@ -12899,8 +12923,8 @@ ix86_compute_frame_layout (void)
the registers need to be saved before allocating the frame. */
&& flag_stack_check != STATIC_BUILTIN_STACK_CHECK);
- /* Skip return address. */
- offset = UNITS_PER_WORD;
+ /* Skip return address and error code in exception handler. */
+ offset = INCOMING_FRAME_SP_OFFSET;
/* Skip pushed static chain. */
if (ix86_static_chain_on_stack)
@@ -13086,24 +13110,26 @@ choose_baseaddr_len (unsigned int regno, HOST_WIDE_INT offset)
return len;
}
-/* Determine if the stack pointer is valid for accessing the cfa_offset. */
+/* Determine if the stack pointer is valid for accessing the cfa_offset.
+ The register is saved at CFA - CFA_OFFSET. */
static inline bool
sp_valid_at (HOST_WIDE_INT cfa_offset)
{
const struct machine_frame_state &fs = cfun->machine->fs;
return fs.sp_valid && !(fs.sp_realigned
- && cfa_offset < fs.sp_realigned_offset);
+ && cfa_offset <= fs.sp_realigned_offset);
}
-/* Determine if the frame pointer is valid for accessing the cfa_offset. */
+/* Determine if the frame pointer is valid for accessing the cfa_offset.
+ The register is saved at CFA - CFA_OFFSET. */
static inline bool
fp_valid_at (HOST_WIDE_INT cfa_offset)
{
const struct machine_frame_state &fs = cfun->machine->fs;
return fs.fp_valid && !(fs.sp_valid && fs.sp_realigned
- && cfa_offset >= fs.sp_realigned_offset);
+ && cfa_offset > fs.sp_realigned_offset);
}
/* Choose a base register based upon alignment requested, speed and/or
@@ -13578,8 +13604,7 @@ ix86_minimum_incoming_stack_boundary (bool sibcall)
{
unsigned int incoming_stack_boundary;
- /* Stack of interrupt handler is aligned to 128 bits in 64bit
- mode. */
+ /* Stack of interrupt handler is aligned to 128 bits in 64bit mode. */
if (cfun->machine->func_type != TYPE_NORMAL)
incoming_stack_boundary = TARGET_64BIT ? 128 : MIN_STACK_BOUNDARY;
/* Prefer the one specified at command line. */
@@ -13646,7 +13671,11 @@ ix86_update_stack_boundary (void)
static rtx
ix86_get_drap_rtx (void)
{
- if (ix86_force_drap || !ACCUMULATE_OUTGOING_ARGS)
+ /* We must use DRAP if there are outgoing arguments on stack and
+ ACCUMULATE_OUTGOING_ARGS is false. */
+ if (ix86_force_drap
+ || (cfun->machine->outgoing_args_on_stack
+ && !ACCUMULATE_OUTGOING_ARGS))
crtl->need_drap = true;
if (stack_realign_drap)
@@ -14310,6 +14339,9 @@ ix86_expand_prologue (void)
bool sse_registers_saved;
rtx static_chain = NULL_RTX;
+ if (ix86_function_naked (current_function_decl))
+ return;
+
ix86_finalize_stack_realign_flags ();
/* DRAP should not coexist with stack_realign_fp */
@@ -15084,7 +15116,7 @@ ix86_emit_outlined_ms2sysv_restore (const struct ix86_frame &frame,
for (i = 0; i < ncregs; ++i)
{
const xlogue_layout::reginfo &r = xlogue.get_reginfo (i);
- enum machine_mode mode = SSE_REGNO_P (r.regno) ? V4SFmode : word_mode;
+ machine_mode mode = SSE_REGNO_P (r.regno) ? V4SFmode : word_mode;
rtx reg, frame_load;
reg = gen_rtx_REG (mode, r.regno);
@@ -15167,6 +15199,13 @@ ix86_expand_epilogue (int style)
bool using_drap;
bool restore_stub_is_tail = false;
+ if (ix86_function_naked (current_function_decl))
+ {
+ /* The program should not reach this point. */
+ emit_insn (gen_trap ());
+ return;
+ }
+
ix86_finalize_stack_realign_flags ();
frame = m->frame;
@@ -15200,8 +15239,9 @@ ix86_expand_epilogue (int style)
m->fs.red_zone_offset = 0;
if (ix86_using_red_zone () && crtl->args.pops_args < 65536)
{
- /* The red-zone begins below the return address. */
- m->fs.red_zone_offset = RED_ZONE_SIZE + UNITS_PER_WORD;
+ /* The red-zone begins below return address and error code in
+ exception handler. */
+ m->fs.red_zone_offset = RED_ZONE_SIZE + INCOMING_FRAME_SP_OFFSET;
/* When the register save area is in the aligned portion of
the stack, determine the maximum runtime displacement that
@@ -15496,18 +15536,7 @@ ix86_expand_epilogue (int style)
}
if (cfun->machine->func_type != TYPE_NORMAL)
- {
- /* Return with the "IRET" instruction from interrupt handler.
- Pop the 'ERROR_CODE' off the stack before the 'IRET'
- instruction in exception handler. */
- if (cfun->machine->func_type == TYPE_EXCEPTION)
- {
- rtx r = plus_constant (Pmode, stack_pointer_rtx,
- UNITS_PER_WORD);
- emit_insn (gen_rtx_SET (stack_pointer_rtx, r));
- }
- emit_jump_insn (gen_interrupt_return ());
- }
+ emit_jump_insn (gen_interrupt_return ());
else if (crtl->args.pops_args && crtl->args.size)
{
rtx popc = GEN_INT (crtl->args.pops_args);
@@ -15769,8 +15798,7 @@ ix86_expand_split_stack_prologue (void)
JUMP_LABEL (jump_insn) = label;
/* Mark the jump as very likely to be taken. */
- add_int_reg_note (jump_insn, REG_BR_PROB,
- REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100);
+ add_reg_br_prob_note (jump_insn, profile_probability::very_likely ());
if (split_stack_fn == NULL_RTX)
{
@@ -16168,9 +16196,9 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
/* Allow arg pointer and stack pointer as index if there is not scaling. */
if (base_reg && index_reg && scale == 1
- && (index_reg == arg_pointer_rtx
- || index_reg == frame_pointer_rtx
- || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
+ && (REGNO (index_reg) == ARG_POINTER_REGNUM
+ || REGNO (index_reg) == FRAME_POINTER_REGNUM
+ || REGNO (index_reg) == SP_REG))
{
std::swap (base, index);
std::swap (base_reg, index_reg);
@@ -16178,14 +16206,11 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
/* Special case: %ebp cannot be encoded as a base without a displacement.
Similarly %r13. */
- if (!disp
- && base_reg
- && (base_reg == hard_frame_pointer_rtx
- || base_reg == frame_pointer_rtx
- || base_reg == arg_pointer_rtx
- || (REG_P (base_reg)
- && (REGNO (base_reg) == HARD_FRAME_POINTER_REGNUM
- || REGNO (base_reg) == R13_REG))))
+ if (!disp && base_reg
+ && (REGNO (base_reg) == ARG_POINTER_REGNUM
+ || REGNO (base_reg) == FRAME_POINTER_REGNUM
+ || REGNO (base_reg) == BP_REG
+ || REGNO (base_reg) == R13_REG))
disp = const0_rtx;
/* Special case: on K6, [%esi] makes the instruction vector decoded.
@@ -16194,7 +16219,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
to test cfun for being non-NULL. */
if (TARGET_K6 && cfun && optimize_function_for_speed_p (cfun)
&& base_reg && !index_reg && !disp
- && REG_P (base_reg) && REGNO (base_reg) == SI_REG)
+ && REGNO (base_reg) == SI_REG)
disp = const0_rtx;
/* Special case: encode reg+reg instead of reg*2. */
@@ -19114,7 +19139,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
if (x)
{
- int pred_val = XINT (x, 0);
+ int pred_val = profile_probability::from_reg_br_prob_note
+ (XINT (x, 0)).to_reg_br_prob_base ();
if (pred_val < REG_BR_PROB_BASE * 45 / 100
|| pred_val > REG_BR_PROB_BASE * 55 / 100)
@@ -23851,8 +23877,8 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
(pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
condition, target1, target2)));
- if (split_branch_probability >= 0)
- add_int_reg_note (i, REG_BR_PROB, split_branch_probability);
+ if (split_branch_probability.initialized_p ())
+ add_reg_br_prob_note (i, split_branch_probability);
}
void
@@ -26897,7 +26923,7 @@ predict_jump (int prob)
{
rtx_insn *insn = get_last_insn ();
gcc_assert (JUMP_P (insn));
- add_int_reg_note (insn, REG_BR_PROB, prob);
+ add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
}
/* Helper function for the string operations below. Dest VARIABLE whether
@@ -30345,6 +30371,15 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
if (!any_condjump_p (condjmp))
return false;
+ unsigned int condreg1, condreg2;
+ rtx cc_reg_1;
+ ix86_fixed_condition_code_regs (&condreg1, &condreg2);
+ cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
+ if (!reg_referenced_p (cc_reg_1, PATTERN (condjmp))
+ || !condgen
+ || !modified_in_p (cc_reg_1, condgen))
+ return false;
+
if (get_attr_type (condgen) != TYPE_TEST
&& get_attr_type (condgen) != TYPE_ICMP
&& get_attr_type (condgen) != TYPE_INCDEC
@@ -31151,7 +31186,7 @@ ix86_constant_alignment (tree exp, int align)
static int
iamcu_alignment (tree type, int align)
{
- enum machine_mode mode;
+ machine_mode mode;
if (align < 32 || TYPE_USER_ALIGN (type))
return align;
@@ -31639,6 +31674,14 @@ ix86_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
#endif
}
+
+static bool
+ix86_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !ix86_function_naked (decl);
+}
/* The following file contains several enumerations and data structures
built from the definitions in i386-builtin-types.def. */
@@ -32564,134 +32607,134 @@ ix86_init_mmx_sse_builtins (void)
IX86_BUILTIN_RDRAND64_STEP);
/* AVX2 */
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv2df",
- V2DF_FTYPE_V2DF_PCDOUBLE_V4SI_V2DF_INT,
- IX86_BUILTIN_GATHERSIV2DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv2df",
+ V2DF_FTYPE_V2DF_PCDOUBLE_V4SI_V2DF_INT,
+ IX86_BUILTIN_GATHERSIV2DF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4df",
- V4DF_FTYPE_V4DF_PCDOUBLE_V4SI_V4DF_INT,
- IX86_BUILTIN_GATHERSIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4df",
+ V4DF_FTYPE_V4DF_PCDOUBLE_V4SI_V4DF_INT,
+ IX86_BUILTIN_GATHERSIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv2df",
- V2DF_FTYPE_V2DF_PCDOUBLE_V2DI_V2DF_INT,
- IX86_BUILTIN_GATHERDIV2DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv2df",
+ V2DF_FTYPE_V2DF_PCDOUBLE_V2DI_V2DF_INT,
+ IX86_BUILTIN_GATHERDIV2DF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4df",
- V4DF_FTYPE_V4DF_PCDOUBLE_V4DI_V4DF_INT,
- IX86_BUILTIN_GATHERDIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4df",
+ V4DF_FTYPE_V4DF_PCDOUBLE_V4DI_V4DF_INT,
+ IX86_BUILTIN_GATHERDIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4sf",
- V4SF_FTYPE_V4SF_PCFLOAT_V4SI_V4SF_INT,
- IX86_BUILTIN_GATHERSIV4SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4sf",
+ V4SF_FTYPE_V4SF_PCFLOAT_V4SI_V4SF_INT,
+ IX86_BUILTIN_GATHERSIV4SF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv8sf",
- V8SF_FTYPE_V8SF_PCFLOAT_V8SI_V8SF_INT,
- IX86_BUILTIN_GATHERSIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv8sf",
+ V8SF_FTYPE_V8SF_PCFLOAT_V8SI_V8SF_INT,
+ IX86_BUILTIN_GATHERSIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4sf",
- V4SF_FTYPE_V4SF_PCFLOAT_V2DI_V4SF_INT,
- IX86_BUILTIN_GATHERDIV4SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4sf",
+ V4SF_FTYPE_V4SF_PCFLOAT_V2DI_V4SF_INT,
+ IX86_BUILTIN_GATHERDIV4SF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4sf256",
- V4SF_FTYPE_V4SF_PCFLOAT_V4DI_V4SF_INT,
- IX86_BUILTIN_GATHERDIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4sf256",
+ V4SF_FTYPE_V4SF_PCFLOAT_V4DI_V4SF_INT,
+ IX86_BUILTIN_GATHERDIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv2di",
- V2DI_FTYPE_V2DI_PCINT64_V4SI_V2DI_INT,
- IX86_BUILTIN_GATHERSIV2DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv2di",
+ V2DI_FTYPE_V2DI_PCINT64_V4SI_V2DI_INT,
+ IX86_BUILTIN_GATHERSIV2DI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4di",
- V4DI_FTYPE_V4DI_PCINT64_V4SI_V4DI_INT,
- IX86_BUILTIN_GATHERSIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4di",
+ V4DI_FTYPE_V4DI_PCINT64_V4SI_V4DI_INT,
+ IX86_BUILTIN_GATHERSIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv2di",
- V2DI_FTYPE_V2DI_PCINT64_V2DI_V2DI_INT,
- IX86_BUILTIN_GATHERDIV2DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv2di",
+ V2DI_FTYPE_V2DI_PCINT64_V2DI_V2DI_INT,
+ IX86_BUILTIN_GATHERDIV2DI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4di",
- V4DI_FTYPE_V4DI_PCINT64_V4DI_V4DI_INT,
- IX86_BUILTIN_GATHERDIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4di",
+ V4DI_FTYPE_V4DI_PCINT64_V4DI_V4DI_INT,
+ IX86_BUILTIN_GATHERDIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4si",
- V4SI_FTYPE_V4SI_PCINT_V4SI_V4SI_INT,
- IX86_BUILTIN_GATHERSIV4SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv4si",
+ V4SI_FTYPE_V4SI_PCINT_V4SI_V4SI_INT,
+ IX86_BUILTIN_GATHERSIV4SI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv8si",
- V8SI_FTYPE_V8SI_PCINT_V8SI_V8SI_INT,
- IX86_BUILTIN_GATHERSIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gathersiv8si",
+ V8SI_FTYPE_V8SI_PCINT_V8SI_V8SI_INT,
+ IX86_BUILTIN_GATHERSIV8SI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4si",
- V4SI_FTYPE_V4SI_PCINT_V2DI_V4SI_INT,
- IX86_BUILTIN_GATHERDIV4SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4si",
+ V4SI_FTYPE_V4SI_PCINT_V2DI_V4SI_INT,
+ IX86_BUILTIN_GATHERDIV4SI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4si256",
- V4SI_FTYPE_V4SI_PCINT_V4DI_V4SI_INT,
- IX86_BUILTIN_GATHERDIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatherdiv4si256",
+ V4SI_FTYPE_V4SI_PCINT_V4DI_V4SI_INT,
+ IX86_BUILTIN_GATHERDIV8SI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltsiv4df ",
- V4DF_FTYPE_V4DF_PCDOUBLE_V8SI_V4DF_INT,
- IX86_BUILTIN_GATHERALTSIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltsiv4df ",
+ V4DF_FTYPE_V4DF_PCDOUBLE_V8SI_V4DF_INT,
+ IX86_BUILTIN_GATHERALTSIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltdiv4sf256 ",
- V8SF_FTYPE_V8SF_PCFLOAT_V4DI_V8SF_INT,
- IX86_BUILTIN_GATHERALTDIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltdiv4sf256 ",
+ V8SF_FTYPE_V8SF_PCFLOAT_V4DI_V8SF_INT,
+ IX86_BUILTIN_GATHERALTDIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltsiv4di ",
- V4DI_FTYPE_V4DI_PCINT64_V8SI_V4DI_INT,
- IX86_BUILTIN_GATHERALTSIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltsiv4di ",
+ V4DI_FTYPE_V4DI_PCINT64_V8SI_V4DI_INT,
+ IX86_BUILTIN_GATHERALTSIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltdiv4si256 ",
- V8SI_FTYPE_V8SI_PCINT_V4DI_V8SI_INT,
- IX86_BUILTIN_GATHERALTDIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX2, "__builtin_ia32_gatheraltdiv4si256 ",
+ V8SI_FTYPE_V8SI_PCINT_V4DI_V8SI_INT,
+ IX86_BUILTIN_GATHERALTDIV8SI);
/* AVX512F */
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv16sf",
- V16SF_FTYPE_V16SF_PCVOID_V16SI_HI_INT,
- IX86_BUILTIN_GATHER3SIV16SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv16sf",
+ V16SF_FTYPE_V16SF_PCVOID_V16SI_HI_INT,
+ IX86_BUILTIN_GATHER3SIV16SF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv8df",
- V8DF_FTYPE_V8DF_PCVOID_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV8DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv8df",
+ V8DF_FTYPE_V8DF_PCVOID_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV8DF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv16sf",
- V8SF_FTYPE_V8SF_PCVOID_V8DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV16SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv16sf",
+ V8SF_FTYPE_V8SF_PCVOID_V8DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV16SF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv8df",
- V8DF_FTYPE_V8DF_PCVOID_V8DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV8DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv8df",
+ V8DF_FTYPE_V8DF_PCVOID_V8DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV8DF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv16si",
- V16SI_FTYPE_V16SI_PCVOID_V16SI_HI_INT,
- IX86_BUILTIN_GATHER3SIV16SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv16si",
+ V16SI_FTYPE_V16SI_PCVOID_V16SI_HI_INT,
+ IX86_BUILTIN_GATHER3SIV16SI);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv8di",
- V8DI_FTYPE_V8DI_PCVOID_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV8DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gathersiv8di",
+ V8DI_FTYPE_V8DI_PCVOID_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV8DI);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv16si",
- V8SI_FTYPE_V8SI_PCVOID_V8DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV16SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv16si",
+ V8SI_FTYPE_V8SI_PCVOID_V8DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV16SI);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv8di",
- V8DI_FTYPE_V8DI_PCVOID_V8DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV8DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatherdiv8di",
+ V8DI_FTYPE_V8DI_PCVOID_V8DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV8DI);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltsiv8df ",
- V8DF_FTYPE_V8DF_PCDOUBLE_V16SI_QI_INT,
- IX86_BUILTIN_GATHER3ALTSIV8DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltsiv8df ",
+ V8DF_FTYPE_V8DF_PCDOUBLE_V16SI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTSIV8DF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltdiv8sf ",
- V16SF_FTYPE_V16SF_PCFLOAT_V8DI_HI_INT,
- IX86_BUILTIN_GATHER3ALTDIV16SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltdiv8sf ",
+ V16SF_FTYPE_V16SF_PCFLOAT_V8DI_HI_INT,
+ IX86_BUILTIN_GATHER3ALTDIV16SF);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltsiv8di ",
- V8DI_FTYPE_V8DI_PCINT64_V16SI_QI_INT,
- IX86_BUILTIN_GATHER3ALTSIV8DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltsiv8di ",
+ V8DI_FTYPE_V8DI_PCINT64_V16SI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTSIV8DI);
- def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltdiv8si ",
- V16SI_FTYPE_V16SI_PCINT_V8DI_HI_INT,
- IX86_BUILTIN_GATHER3ALTDIV16SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_gatheraltdiv8si ",
+ V16SI_FTYPE_V16SI_PCINT_V8DI_HI_INT,
+ IX86_BUILTIN_GATHER3ALTDIV16SI);
def_builtin (OPTION_MASK_ISA_AVX512F, "__builtin_ia32_scattersiv16sf",
VOID_FTYPE_PVOID_HI_V16SI_V16SF_INT,
@@ -32726,85 +32769,85 @@ ix86_init_mmx_sse_builtins (void)
IX86_BUILTIN_SCATTERDIV8DI);
/* AVX512VL */
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv2df",
- V2DF_FTYPE_V2DF_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV2DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv2df",
+ V2DF_FTYPE_V2DF_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV2DF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4df",
- V4DF_FTYPE_V4DF_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4df",
+ V4DF_FTYPE_V4DF_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div2df",
- V2DF_FTYPE_V2DF_PCVOID_V2DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV2DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div2df",
+ V2DF_FTYPE_V2DF_PCVOID_V2DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV2DF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4df",
- V4DF_FTYPE_V4DF_PCVOID_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4df",
+ V4DF_FTYPE_V4DF_PCVOID_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4sf",
- V4SF_FTYPE_V4SF_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV4SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4sf",
+ V4SF_FTYPE_V4SF_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV4SF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv8sf",
- V8SF_FTYPE_V8SF_PCVOID_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv8sf",
+ V8SF_FTYPE_V8SF_PCVOID_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4sf",
- V4SF_FTYPE_V4SF_PCVOID_V2DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV4SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4sf",
+ V4SF_FTYPE_V4SF_PCVOID_V2DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV4SF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div8sf",
- V4SF_FTYPE_V4SF_PCVOID_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div8sf",
+ V4SF_FTYPE_V4SF_PCVOID_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv2di",
- V2DI_FTYPE_V2DI_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV2DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv2di",
+ V2DI_FTYPE_V2DI_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV2DI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4di",
- V4DI_FTYPE_V4DI_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4di",
+ V4DI_FTYPE_V4DI_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div2di",
- V2DI_FTYPE_V2DI_PCVOID_V2DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV2DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div2di",
+ V2DI_FTYPE_V2DI_PCVOID_V2DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV2DI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4di",
- V4DI_FTYPE_V4DI_PCVOID_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4di",
+ V4DI_FTYPE_V4DI_PCVOID_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4si",
- V4SI_FTYPE_V4SI_PCVOID_V4SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV4SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv4si",
+ V4SI_FTYPE_V4SI_PCVOID_V4SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV4SI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv8si",
- V8SI_FTYPE_V8SI_PCVOID_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3SIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3siv8si",
+ V8SI_FTYPE_V8SI_PCVOID_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3SIV8SI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4si",
- V4SI_FTYPE_V4SI_PCVOID_V2DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV4SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div4si",
+ V4SI_FTYPE_V4SI_PCVOID_V2DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV4SI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div8si",
- V4SI_FTYPE_V4SI_PCVOID_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3DIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3div8si",
+ V4SI_FTYPE_V4SI_PCVOID_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3DIV8SI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altsiv4df ",
- V4DF_FTYPE_V4DF_PCDOUBLE_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3ALTSIV4DF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altsiv4df ",
+ V4DF_FTYPE_V4DF_PCDOUBLE_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTSIV4DF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altdiv8sf ",
- V8SF_FTYPE_V8SF_PCFLOAT_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3ALTDIV8SF);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altdiv8sf ",
+ V8SF_FTYPE_V8SF_PCFLOAT_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTDIV8SF);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altsiv4di ",
- V4DI_FTYPE_V4DI_PCINT64_V8SI_QI_INT,
- IX86_BUILTIN_GATHER3ALTSIV4DI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altsiv4di ",
+ V4DI_FTYPE_V4DI_PCINT64_V8SI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTSIV4DI);
- def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altdiv8si ",
- V8SI_FTYPE_V8SI_PCINT_V4DI_QI_INT,
- IX86_BUILTIN_GATHER3ALTDIV8SI);
+ def_builtin_pure (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_gather3altdiv8si ",
+ V8SI_FTYPE_V8SI_PCINT_V4DI_QI_INT,
+ IX86_BUILTIN_GATHER3ALTDIV8SI);
def_builtin (OPTION_MASK_ISA_AVX512VL, "__builtin_ia32_scattersiv8sf",
VOID_FTYPE_PVOID_QI_V8SI_V8SF_INT,
@@ -36473,21 +36516,11 @@ ix86_expand_args_builtin (const struct builtin_description *d,
}
/* Transform pattern of following layout:
- (parallel [
- set (A B)
- (unspec [C] UNSPEC_EMBEDDED_ROUNDING)])
- ])
- into:
- (set (A B))
-
- Or:
- (parallel [ A B
- ...
- (unspec [C] UNSPEC_EMBEDDED_ROUNDING)
- ...
- ])
+ (set A
+ (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
+ )
into:
- (parallel [ A B ... ]) */
+ (set (A B)) */
static rtx
ix86_erase_embedded_rounding (rtx pat)
@@ -36495,48 +36528,14 @@ ix86_erase_embedded_rounding (rtx pat)
if (GET_CODE (pat) == INSN)
pat = PATTERN (pat);
- if (GET_CODE (pat) == PARALLEL)
- {
- if (XVECLEN (pat, 0) == 2)
- {
- rtx p0 = XVECEXP (pat, 0, 0);
- rtx p1 = XVECEXP (pat, 0, 1);
- gcc_assert (GET_CODE (p0) == SET
- && GET_CODE (p1) == UNSPEC
- && XINT (p1, 1) == UNSPEC_EMBEDDED_ROUNDING);
- return p0;
- }
- else
- {
- rtx *res = XALLOCAVEC (rtx, XVECLEN (pat, 0));
- int i = 0;
- int j = 0;
-
- for (; i < XVECLEN (pat, 0); ++i)
- {
- rtx elem = XVECEXP (pat, 0, i);
- if (GET_CODE (elem) != UNSPEC
- || XINT (elem, 1) != UNSPEC_EMBEDDED_ROUNDING)
- res[j++] = elem;
- }
-
- /* No more than 1 occurence was removed. */
- gcc_assert (j >= XVECLEN (pat, 0) - 1);
-
- return gen_rtx_PARALLEL (GET_MODE (pat), gen_rtvec_v (j, res));
- }
- }
- else
- {
- gcc_assert (GET_CODE (pat) == SET);
- rtx src = SET_SRC (pat);
- gcc_assert (XVECLEN (src, 0) == 2);
- rtx p0 = XVECEXP (src, 0, 0);
- gcc_assert (GET_CODE (src) == UNSPEC
- && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
- rtx res = gen_rtx_SET (SET_DEST (pat), p0);
- return res;
- }
+ gcc_assert (GET_CODE (pat) == SET);
+ rtx src = SET_SRC (pat);
+ gcc_assert (XVECLEN (src, 0) == 2);
+ rtx p0 = XVECEXP (src, 0, 0);
+ gcc_assert (GET_CODE (src) == UNSPEC
+ && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
+ rtx res = gen_rtx_SET (SET_DEST (pat), p0);
+ return res;
}
/* Subroutine of ix86_expand_round_builtin to take care of comi insns
@@ -36736,6 +36735,8 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
+ case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
+ case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
nargs = 6;
nargs_constant = 4;
break;
@@ -36773,7 +36774,9 @@ ix86_expand_round_builtin (const struct builtin_description *d,
case CODE_FOR_avx512f_getmantv8df_mask_round:
case CODE_FOR_avx512f_getmantv16sf_mask_round:
case CODE_FOR_avx512f_vgetmantv2df_round:
+ case CODE_FOR_avx512f_vgetmantv2df_mask_round:
case CODE_FOR_avx512f_vgetmantv4sf_round:
+ case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
error ("the immediate argument must be a 4-bit immediate");
return const0_rtx;
case CODE_FOR_avx512f_cmpv8df3_mask_round:
@@ -44135,6 +44138,26 @@ ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
ix86_expand_vector_init_concat (mode, target, ops, n);
return;
+ case V2TImode:
+ for (i = 0; i < 2; i++)
+ ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
+ op0 = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
+ return;
+
+ case V4TImode:
+ for (i = 0; i < 4; i++)
+ ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
+ ops[4] = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
+ ops[5] = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
+ op0 = gen_reg_rtx (V8DImode);
+ ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
+ return;
+
case V32QImode:
half_mode = V16QImode;
goto half;
@@ -44676,6 +44699,8 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
case V2DFmode:
case V2DImode:
+ case V2TImode:
+ case V4TImode:
use_vec_extr = true;
break;
@@ -46491,6 +46516,8 @@ static const struct attribute_spec ix86_attribute_table[] =
ix86_handle_interrupt_attribute, false },
{ "no_caller_saved_registers", 0, 0, false, true, true,
ix86_handle_no_caller_saved_registers_attribute, false },
+ { "naked", 0, 0, true, false, false,
+ ix86_handle_fndecl_attribute, false },
/* End element. */
{ NULL, 0, 0, false, false, false, NULL, false }
@@ -47159,7 +47186,7 @@ canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
struct expand_vec_perm_d *nd)
{
int i;
- enum machine_mode mode = VOIDmode;
+ machine_mode mode = VOIDmode;
switch (d->vmode)
{
@@ -51409,7 +51436,7 @@ ix86_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info)
if (GET_CODE (SET_SRC (set)) != IF_THEN_ELSE)
continue;
rtx src = SET_SRC (set);
- enum machine_mode mode = GET_MODE (src);
+ machine_mode mode = GET_MODE (src);
if (GET_MODE_CLASS (mode) != MODE_INT
&& GET_MODE_CLASS (mode) != MODE_FLOAT)
continue;
@@ -51905,7 +51932,7 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
/* Return mode to be used for bounds or VOIDmode
if bounds are not supported. */
-static enum machine_mode
+static machine_mode
ix86_mpx_bound_mode ()
{
/* Do not support pointer checker if MPX
@@ -52025,7 +52052,7 @@ extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset)
bool
ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
- enum machine_mode mode)
+ machine_mode mode)
{
HOST_WIDE_INT offval_1, offval_2, msize;
rtx mem_1, mem_2, reg_1, reg_2, base_1, base_2, offset_1, offset_2;
@@ -52727,6 +52754,9 @@ ix86_run_selftests (void)
#undef TARGET_RETURN_POPS_ARGS
#define TARGET_RETURN_POPS_ARGS ix86_return_pops_args
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN ix86_warn_func_return
+
#undef TARGET_LEGITIMATE_COMBINED_INSN
#define TARGET_LEGITIMATE_COMBINED_INSN ix86_legitimate_combined_insn
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 08243c16498..bdea37b7313 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2165,7 +2165,7 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* Before the prologue, RA is at 0(%esp). */
#define INCOMING_RETURN_ADDR_RTX \
- gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM))
+ gen_rtx_MEM (Pmode, stack_pointer_rtx)
/* After the prologue, RA is at -4(AP) in the current frame. */
#define RETURN_ADDR_RTX(COUNT, FRAME) \
@@ -2177,8 +2177,11 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* PC is dbx register 8; let's use that column for RA. */
#define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8)
-/* Before the prologue, the top of the frame is at 4(%esp). */
-#define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
+/* Before the prologue, there are return address and error code for
+ exception handler on the top of the frame. */
+#define INCOMING_FRAME_SP_OFFSET \
+ (cfun->machine->func_type == TYPE_EXCEPTION \
+ ? 2 * UNITS_PER_WORD : UNITS_PER_WORD)
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) <= DX_REG ? (N) : INVALID_REGNUM)
@@ -2196,29 +2199,33 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
asm_preferred_eh_data_format ((CODE), (GLOBAL))
-/* This is how to output an insn to push a register on the stack.
- It need not be very fast code. */
+/* These are a couple of extensions to the formats accepted
+ by asm_fprintf:
+ %z prints out opcode suffix for word-mode instruction
+ %r prints out word-mode name for reg_names[arg] */
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
+ case 'z': \
+ fputc (TARGET_64BIT ? 'q' : 'l', (FILE)); \
+ break; \
+ \
+ case 'r': \
+ { \
+ unsigned int regno = va_arg ((ARGS), int); \
+ if (LEGACY_INT_REGNO_P (regno)) \
+ fputc (TARGET_64BIT ? 'r' : 'e', (FILE)); \
+ fputs (reg_names[regno], (FILE)); \
+ break; \
+ }
-#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
-do { \
- if (TARGET_64BIT) \
- asm_fprintf ((FILE), "\tpush{q}\t%%r%s\n", \
- reg_names[(REGNO)] + (REX_INT_REGNO_P (REGNO) != 0)); \
- else \
- asm_fprintf ((FILE), "\tpush{l}\t%%e%s\n", reg_names[(REGNO)]); \
-} while (0)
+/* This is how to output an insn to push a register on the stack. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
+ asm_fprintf ((FILE), "\tpush%z\t%%%r\n", (REGNO))
-/* This is how to output an insn to pop a register from the stack.
- It need not be very fast code. */
+/* This is how to output an insn to pop a register from the stack. */
#define ASM_OUTPUT_REG_POP(FILE, REGNO) \
-do { \
- if (TARGET_64BIT) \
- asm_fprintf ((FILE), "\tpop{q}\t%%r%s\n", \
- reg_names[(REGNO)] + (REX_INT_REGNO_P (REGNO) != 0)); \
- else \
- asm_fprintf ((FILE), "\tpop{l}\t%%e%s\n", reg_names[(REGNO)]); \
-} while (0)
+ asm_fprintf ((FILE), "\tpop%z\t%%%r\n", (REGNO))
/* This is how to output an element of a case-vector that is absolute. */
@@ -2657,6 +2664,9 @@ struct GTY(()) machine_function {
frame pointer.) */
unsigned int call_ms2sysv_extra_regs:3;
+ /* Nonzero if the function places outgoing arguments on stack. */
+ BOOL_BITFIELD outgoing_args_on_stack : 1;
+
/* During prologue/epilogue generation, the current frame state.
Otherwise, the frame state at the end of the prologue. */
struct machine_frame_state fs;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 40a20d0ec6e..5eff4e46fff 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5504,7 +5504,7 @@
(define_expand "floatunsdisf2"
[(use (match_operand:SF 0 "register_operand"))
(use (match_operand:DI 1 "nonimmediate_operand"))]
- "TARGET_64BIT && TARGET_SSE_MATH"
+ "TARGET_64BIT && TARGET_SSE && TARGET_SSE_MATH"
"x86_emit_floatuns (operands); DONE;")
(define_expand "floatunsdidf2"
@@ -7545,21 +7545,15 @@
(match_operand:XF 2 "register_operand")))]
"TARGET_80387")
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "register_operand")
- (div:DF (match_operand:DF 1 "register_operand")
- (match_operand:DF 2 "nonimmediate_operand")))]
- "(TARGET_80387 && X87_ENABLE_ARITH (DFmode))
- || (TARGET_SSE2 && TARGET_SSE_MATH)")
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "register_operand")
- (div:SF (match_operand:SF 1 "register_operand")
- (match_operand:SF 2 "nonimmediate_operand")))]
- "(TARGET_80387 && X87_ENABLE_ARITH (SFmode))
- || TARGET_SSE_MATH"
+(define_expand "div<mode>3"
+ [(set (match_operand:MODEF 0 "register_operand")
+ (div:MODEF (match_operand:MODEF 1 "register_operand")
+ (match_operand:MODEF 2 "nonimmediate_operand")))]
+ "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode))
+ || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
- if (TARGET_SSE_MATH
+ if (<MODE>mode == SFmode
+ && TARGET_SSE && TARGET_SSE_MATH
&& TARGET_RECIP_DIV
&& optimize_insn_for_speed_p ()
&& flag_finite_math_only && !flag_trapping_math
@@ -10738,10 +10732,15 @@
split_double_mode (<DWI>mode, &operands[0], 1, &operands[4], &operands[5]);
})
+(define_mode_attr rorx_immediate_operand
+ [(SI "const_0_to_31_operand")
+ (DI "const_0_to_63_operand")])
+
(define_insn "*bmi2_rorx<mode>3_1"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (rotatert:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")
- (match_operand:QI 2 "immediate_operand" "<S>")))]
+ (rotatert:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (match_operand:QI 2 "<rorx_immediate_operand>" "<S>")))]
"TARGET_BMI2"
"rorx\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "rotatex")
@@ -10784,7 +10783,7 @@
(define_split
[(set (match_operand:SWI48 0 "register_operand")
(rotate:SWI48 (match_operand:SWI48 1 "nonimmediate_operand")
- (match_operand:QI 2 "immediate_operand")))
+ (match_operand:QI 2 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2 && reload_completed"
[(set (match_dup 0)
@@ -10798,7 +10797,7 @@
(define_split
[(set (match_operand:SWI48 0 "register_operand")
(rotatert:SWI48 (match_operand:SWI48 1 "nonimmediate_operand")
- (match_operand:QI 2 "immediate_operand")))
+ (match_operand:QI 2 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2 && reload_completed"
[(set (match_dup 0)
@@ -10808,7 +10807,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "rm")
- (match_operand:QI 2 "immediate_operand" "I"))))]
+ (match_operand:QI 2 "const_0_to_31_operand" "I"))))]
"TARGET_64BIT && TARGET_BMI2"
"rorx\t{%2, %1, %k0|%k0, %1, %2}"
[(set_attr "type" "rotatex")
@@ -10852,7 +10851,7 @@
[(set (match_operand:DI 0 "register_operand")
(zero_extend:DI
(rotate:SI (match_operand:SI 1 "nonimmediate_operand")
- (match_operand:QI 2 "immediate_operand"))))
+ (match_operand:QI 2 "const_int_operand"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_BMI2 && reload_completed"
[(set (match_dup 0)
@@ -10867,7 +10866,7 @@
[(set (match_operand:DI 0 "register_operand")
(zero_extend:DI
(rotatert:SI (match_operand:SI 1 "nonimmediate_operand")
- (match_operand:QI 2 "immediate_operand"))))
+ (match_operand:QI 2 "const_int_operand"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_BMI2 && reload_completed"
[(set (match_dup 0)
@@ -11754,7 +11753,8 @@
(zero_extend (match_dup 1)))]
"(peep2_reg_dead_p (3, operands[1])
|| operands_match_p (operands[1], operands[3]))
- && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+ && ! reg_overlap_mentioned_p (operands[3], operands[0])
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(set (match_dup 4) (match_dup 0))
(set (strict_low_part (match_dup 5))
(match_dup 2))]
@@ -11775,7 +11775,8 @@
"(peep2_reg_dead_p (3, operands[1])
|| operands_match_p (operands[1], operands[3]))
&& ! reg_overlap_mentioned_p (operands[3], operands[0])
- && ! reg_set_p (operands[3], operands[4])"
+ && ! reg_set_p (operands[3], operands[4])
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 5) (match_dup 0))
(match_dup 4)])
(set (strict_low_part (match_dup 6))
@@ -11797,7 +11798,8 @@
(and:SI (match_dup 3) (const_int 255)))
(clobber (reg:CC FLAGS_REG))])]
"REGNO (operands[1]) == REGNO (operands[3])
- && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+ && ! reg_overlap_mentioned_p (operands[3], operands[0])
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(set (match_dup 4) (match_dup 0))
(set (strict_low_part (match_dup 5))
(match_dup 2))]
@@ -11819,7 +11821,8 @@
"(peep2_reg_dead_p (3, operands[1])
|| operands_match_p (operands[1], operands[3]))
&& ! reg_overlap_mentioned_p (operands[3], operands[0])
- && ! reg_set_p (operands[3], operands[4])"
+ && ! reg_set_p (operands[3], operands[4])
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 5) (match_dup 0))
(match_dup 4)])
(set (strict_low_part (match_dup 6))
@@ -14046,7 +14049,7 @@
[(set (match_operand:SF 0 "register_operand" "=x")
(unspec:SF [(match_operand:SF 1 "nonimmediate_operand" "xm")]
UNSPEC_RCP))]
- "TARGET_SSE_MATH"
+ "TARGET_SSE && TARGET_SSE_MATH"
"%vrcpss\t{%1, %d0|%d0, %1}"
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "rcp")
@@ -14348,7 +14351,7 @@
[(set (match_operand:SF 0 "register_operand" "=x")
(unspec:SF [(match_operand:SF 1 "nonimmediate_operand" "xm")]
UNSPEC_RSQRT))]
- "TARGET_SSE_MATH"
+ "TARGET_SSE && TARGET_SSE_MATH"
"%vrsqrtss\t{%1, %d0|%d0, %1}"
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "rcp")
@@ -14360,7 +14363,7 @@
[(set (match_operand:SF 0 "register_operand")
(unspec:SF [(match_operand:SF 1 "nonimmediate_operand")]
UNSPEC_RSQRT))]
- "TARGET_SSE_MATH"
+ "TARGET_SSE && TARGET_SSE_MATH"
{
ix86_emit_swsqrtsf (operands[0], operands[1], SFmode, 1);
DONE;
@@ -14389,7 +14392,7 @@
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
if (<MODE>mode == SFmode
- && TARGET_SSE_MATH
+ && TARGET_SSE && TARGET_SSE_MATH
&& TARGET_RECIP_SQRT
&& !optimize_function_for_size_p (cfun)
&& flag_finite_math_only && !flag_trapping_math
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 65b228544a5..adc75f36602 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -267,8 +267,8 @@ EnumValue
Enum(asm_dialect) String(att) Value(ASM_ATT)
mbranch-cost=
-Target RejectNegative Joined UInteger Var(ix86_branch_cost)
-Branches are this expensive (1-5, arbitrary units).
+Target RejectNegative Joined UInteger Var(ix86_branch_cost) IntegerRange(0, 5)
+Branches are this expensive (arbitrary units).
mlarge-data-threshold=
Target RejectNegative Joined UInteger Var(ix86_section_threshold) Init(DEFAULT_LARGE_SECTION_THRESHOLD)
diff --git a/gcc/config/i386/openbsd.h b/gcc/config/i386/openbsd.h
deleted file mode 100644
index 7d37c0de922..00000000000
--- a/gcc/config/i386/openbsd.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Configuration for an OpenBSD i386 target.
- Copyright (C) 1999-2017 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* This goes away when the math-emulator is fixed */
-#undef TARGET_SUBTARGET_DEFAULT
-#define TARGET_SUBTARGET_DEFAULT \
- (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__unix__"); \
- builtin_define ("__OpenBSD__"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=bsd"); \
- builtin_assert ("system=OpenBSD"); \
- } \
- while (0)
-
-/* Layout of source language data types. */
-
-/* This must agree with <machine/ansi.h> */
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-/* Assembler format: overall framework. */
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/* Stack & calling: aggregate returns. */
-
-/* Don't default to pcc-struct-return, because gcc is the only compiler, and
- we want to retain compatibility with older gcc versions. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-/* Assembler format: alignment output. */
-
-/* Kludgy test: when gas is upgraded, it will have p2align, and no problems
- with nops. */
-#ifndef HAVE_GAS_MAX_SKIP_P2ALIGN
-/* i386 OpenBSD still uses an older gas that doesn't insert nops by default
- when the .align directive demands to insert extra space in the text
- segment. */
-#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
-#endif
-
-/* Stack & calling: profiling. */
-
-/* OpenBSD's profiler recovers all information from the stack pointer.
- The icky part is not here, but in machine/profile.h. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fputs (flag_pic ? "\tcall mcount@PLT\n": "\tcall mcount\n", FILE);
-
-/* Assembler format: exception region output. */
-
-/* All configurations that don't use elf must be explicit about not using
- dwarf unwind information. */
-#define DWARF2_UNWIND_INFO 0
-
-#undef ASM_PREFERRED_EH_DATA_FORMAT
-
-#undef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-
-/* OpenBSD gas currently does not support quad, so do not use it. */
-#undef ASM_QUAD
-
-#define TARGET_HAVE_NAMED_SECTIONS false
diff --git a/gcc/config/i386/rtemself.h b/gcc/config/i386/rtemself.h
index e8eade28a5c..a68e8b30f62 100644
--- a/gcc/config/i386/rtemself.h
+++ b/gcc/config/i386/rtemself.h
@@ -2,21 +2,26 @@
Copyright (C) 1996-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index f61ae2bb927..56b7f436d5d 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -175,7 +175,7 @@
(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
- (V4TI "TARGET_AVX512BW") (V2TI "TARGET_AVX") V1TI
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX") V1TI
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
@@ -687,7 +687,8 @@
(V16SI "SI") (V8SI "SI") (V4SI "SI")
(V8DI "DI") (V4DI "DI") (V2DI "DI")
(V16SF "SF") (V8SF "SF") (V4SF "SF")
- (V8DF "DF") (V4DF "DF") (V2DF "DF")])
+ (V8DF "DF") (V4DF "DF") (V2DF "DF")
+ (V4TI "TI") (V2TI "TI")])
;; Mapping of vector modes to the 128bit modes
(define_mode_attr ssexmmmode
@@ -1568,21 +1569,21 @@
(set_attr "prefix" "<mask_prefix3>")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse>_vm<plusminus_insn><mode>3<mask_name><round_name>"
+(define_insn "<sse>_vm<plusminus_insn><mode>3<mask_scalar_name><round_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
(plusminus:VF_128
(match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "vector_operand" "xBm,<round_constraint>"))
+ (match_operand:VF_128 2 "vector_operand" "xBm,<round_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
"@
<plusminus_mnemonic><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
- v<plusminus_mnemonic><ssescalarmodesuffix>\t{<round_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %<iptr>2<round_mask_op3>}"
+ v<plusminus_mnemonic><ssescalarmodesuffix>\t{<round_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %1, %<iptr>2<round_scalar_mask_op3>}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sseadd")
- (set_attr "prefix" "<round_prefix>")
+ (set_attr "prefix" "<round_scalar_prefix>")
(set_attr "mode" "<ssescalarmode>")])
(define_expand "mul<mode>3<mask_name><round_name>"
@@ -1608,21 +1609,21 @@
(set_attr "btver2_decode" "direct,double")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse>_vm<multdiv_mnemonic><mode>3<mask_name><round_name>"
+(define_insn "<sse>_vm<multdiv_mnemonic><mode>3<mask_scalar_name><round_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
(multdiv:VF_128
(match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "vector_operand" "xBm,<round_constraint>"))
+ (match_operand:VF_128 2 "vector_operand" "xBm,<round_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
"@
<multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
- v<multdiv_mnemonic><ssescalarmodesuffix>\t{<round_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %<iptr>2<round_mask_op3>}"
+ v<multdiv_mnemonic><ssescalarmodesuffix>\t{<round_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %1, %<iptr>2<round_scalar_mask_op3>}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse<multdiv_mnemonic>")
- (set_attr "prefix" "<round_prefix>")
+ (set_attr "prefix" "<round_scalar_prefix>")
(set_attr "btver2_decode" "direct,double")
(set_attr "mode" "<ssescalarmode>")])
@@ -1944,22 +1945,22 @@
(set_attr "prefix" "<mask_prefix3>")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse>_vm<code><mode>3<mask_name><round_saeonly_name>"
+(define_insn "<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
(smaxmin:VF_128
(match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "vector_operand" "xBm,<round_saeonly_constraint>"))
+ (match_operand:VF_128 2 "vector_operand" "xBm,<round_saeonly_scalar_constraint>"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
"@
<maxmin_float><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
- v<maxmin_float><ssescalarmodesuffix>\t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %<iptr>2<round_saeonly_mask_op3>}"
+ v<maxmin_float><ssescalarmodesuffix>\t{<round_saeonly_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %1, %<iptr>2<round_saeonly_scalar_mask_op3>}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse")
(set_attr "btver2_sse_attr" "maxmin")
- (set_attr "prefix" "<round_saeonly_prefix>")
+ (set_attr "prefix" "<round_saeonly_scalar_prefix>")
(set_attr "mode" "<ssescalarmode>")])
(define_insn "avx_addsubv4df3"
@@ -6920,15 +6921,6 @@
(set_attr "prefix" "orig,maybe_evex,orig,maybe_evex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF")])
-(define_expand "vec_init<mode>"
- [(match_operand:V_128 0 "register_operand")
- (match_operand 1)]
- "TARGET_SSE"
-{
- ix86_expand_vector_init (false, operands[0], operands[1]);
- DONE;
-})
-
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
(define_insn "vec_set<mode>_0"
@@ -7359,13 +7351,13 @@
(define_insn "vec_extract_lo_<mode><mask_name>"
[(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=<store_mask_constraint>,v")
(vec_select:<ssehalfvecmode>
- (match_operand:V8FI 1 "nonimmediate_operand" "v,m")
+ (match_operand:V8FI 1 "<store_mask_predicate>" "v,<store_mask_constraint>")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)])))]
"TARGET_AVX512F
&& (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))"
{
- if (<mask_applied> || !TARGET_AVX512VL)
+ if (<mask_applied> || (!TARGET_AVX512VL && !MEM_P (operands[1])))
return "vextract<shuffletype>64x4\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}";
else
return "#";
@@ -7515,14 +7507,15 @@
(define_insn "vec_extract_lo_<mode><mask_name>"
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,m")
(vec_select:<ssehalfvecmode>
- (match_operand:V16FI 1 "nonimmediate_operand" "vm,v")
+ (match_operand:V16FI 1 "<store_mask_predicate>"
+ "<store_mask_constraint>,v")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)
(const_int 4) (const_int 5)
(const_int 6) (const_int 7)])))]
"TARGET_AVX512F
&& <mask_mode512bit_condition>
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))"
{
if (<mask_applied>)
return "vextract<shuffletype>32x8\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}";
@@ -7546,11 +7539,12 @@
(define_insn "vec_extract_lo_<mode><mask_name>"
[(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=v,m")
(vec_select:<ssehalfvecmode>
- (match_operand:VI8F_256 1 "nonimmediate_operand" "vm,v")
+ (match_operand:VI8F_256 1 "<store_mask_predicate>"
+ "<store_mask_constraint>,v")
(parallel [(const_int 0) (const_int 1)])))]
"TARGET_AVX
&& <mask_avx512vl_condition> && <mask_avx512dq_condition>
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))"
{
if (<mask_applied>)
return "vextract<shuffletype>64x2\t{$0x0, %1, %0%{%3%}|%0%{%3%}, %1, 0x0}";
@@ -7610,12 +7604,16 @@
"operands[1] = gen_lowpart (<ssehalfvecmode>mode, operands[1]);")
(define_insn "vec_extract_lo_<mode><mask_name>"
- [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=<store_mask_constraint>")
+ [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>"
+ "=<store_mask_constraint>,v")
(vec_select:<ssehalfvecmode>
- (match_operand:VI4F_256 1 "register_operand" "v")
+ (match_operand:VI4F_256 1 "<store_mask_predicate>"
+ "v,<store_mask_constraint>")
(parallel [(const_int 0) (const_int 1)
(const_int 2) (const_int 3)])))]
- "TARGET_AVX && <mask_avx512vl_condition> && <mask_avx512dq_condition>"
+ "TARGET_AVX
+ && <mask_avx512vl_condition> && <mask_avx512dq_condition>
+ && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))"
{
if (<mask_applied>)
return "vextract<shuffletype>32x4\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}";
@@ -7880,7 +7878,8 @@
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
- (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
(define_expand "vec_extract<mode>"
[(match_operand:<ssescalarmode> 0 "register_operand")
@@ -8288,17 +8287,17 @@
[(set_attr "prefix" "evex")
(set_attr "mode" "<MODE>")])
-(define_insn "avx512f_sgetexp<mode><round_saeonly_name>"
+(define_insn "avx512f_sgetexp<mode><mask_scalar_name><round_saeonly_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=v")
(vec_merge:VF_128
(unspec:VF_128
[(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")]
+ (match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")]
UNSPEC_GETEXP)
(match_dup 1)
(const_int 1)))]
"TARGET_AVX512F"
- "vgetexp<ssescalarmodesuffix>\t{<round_saeonly_op3>%2, %1, %0|%0, %1, %2<round_saeonly_op3>}";
+ "vgetexp<ssescalarmodesuffix>\t{<round_saeonly_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %1, %2<round_saeonly_scalar_mask_op3>}";
[(set_attr "prefix" "evex")
(set_attr "mode" "<ssescalarmode>")])
@@ -13728,6 +13727,50 @@
operands[1] = adjust_address (operands[1], <ssescalarmode>mode, offs);
})
+(define_insn "*vec_extractv2ti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=xm,vm")
+ (vec_select:TI
+ (match_operand:V2TI 1 "register_operand" "x,v")
+ (parallel
+ [(match_operand:SI 2 "const_0_to_1_operand")])))]
+ "TARGET_AVX"
+ "@
+ vextract%~128\t{%2, %1, %0|%0, %1, %2}
+ vextracti32x4\t{%2, %g1, %0|%0, %g1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex,evex")
+ (set_attr "mode" "OI")])
+
+(define_insn "*vec_extractv4ti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=vm")
+ (vec_select:TI
+ (match_operand:V4TI 1 "register_operand" "v")
+ (parallel
+ [(match_operand:SI 2 "const_0_to_3_operand")])))]
+ "TARGET_AVX512F"
+ "vextracti32x4\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_mode_iterator VEXTRACTI128_MODE
+ [(V4TI "TARGET_AVX512F") V2TI])
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand")
+ (vec_select:TI
+ (match_operand:VEXTRACTI128_MODE 1 "register_operand")
+ (parallel [(const_int 0)])))]
+ "TARGET_AVX
+ && reload_completed
+ && (TARGET_AVX512VL || !EXT_REX_SSE_REG_P (operands[1]))"
+ [(set (match_dup 0) (match_dup 1))]
+ "operands[1] = gen_lowpart (TImode, operands[1]);")
+
;; Turn SImode or DImode extraction from arbitrary SSE/AVX/AVX512F
;; vector modes into vec_extract*.
(define_split
@@ -18732,19 +18775,20 @@
<ssehalfvecmode>mode);
})
-(define_expand "vec_init<mode>"
- [(match_operand:V_256 0 "register_operand")
- (match_operand 1)]
- "TARGET_AVX"
-{
- ix86_expand_vector_init (false, operands[0], operands[1]);
- DONE;
-})
+;; Modes handled by vec_init patterns.
+(define_mode_iterator VEC_INIT_MODE
+ [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI
+ (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
(define_expand "vec_init<mode>"
- [(match_operand:VF48_I1248 0 "register_operand")
+ [(match_operand:VEC_INIT_MODE 0 "register_operand")
(match_operand 1)]
- "TARGET_AVX512F"
+ "TARGET_SSE"
{
ix86_expand_vector_init (false, operands[0], operands[1]);
DONE;
@@ -19495,18 +19539,18 @@
[(set_attr "prefix" "evex")
(set_attr "mode" "<MODE>")])
-(define_insn "avx512f_vgetmant<mode><round_saeonly_name>"
+(define_insn "avx512f_vgetmant<mode><mask_scalar_name><round_saeonly_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=v")
(vec_merge:VF_128
(unspec:VF_128
[(match_operand:VF_128 1 "register_operand" "v")
- (match_operand:VF_128 2 "<round_saeonly_nimm_predicate>" "<round_saeonly_constraint>")
+ (match_operand:VF_128 2 "<round_saeonly_scalar_nimm_predicate>" "<round_saeonly_scalar_constraint>")
(match_operand:SI 3 "const_0_to_15_operand")]
UNSPEC_GETMANT)
(match_dup 1)
(const_int 1)))]
"TARGET_AVX512F"
- "vgetmant<ssescalarmodesuffix>\t{%3, <round_saeonly_op4>%2, %1, %0|%0, %1, %2<round_saeonly_op4>, %3}";
+ "vgetmant<ssescalarmodesuffix>\t{%3, <round_saeonly_scalar_mask_op4>%2, %1, %0<mask_scalar_operand4>|%0<mask_scalar_operand4>, %1, %2<round_saeonly_scalar_mask_op4>, %3}";
[(set_attr "prefix" "evex")
(set_attr "mode" "<ssescalarmode>")])
diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md
index 4685db302b9..a318a8d4c80 100644
--- a/gcc/config/i386/subst.md
+++ b/gcc/config/i386/subst.md
@@ -236,3 +236,70 @@
(match_dup 3)
(match_operand:SUBST_V 4 "vector_move_operand")
(match_operand:<avx512fmaskmode> 5 "register_operand")])
+
+(define_subst_attr "mask_scalar_name" "mask_scalar" "" "_mask")
+(define_subst_attr "mask_scalar_operand3" "mask_scalar" "" "%{%4%}%N3")
+(define_subst_attr "mask_scalar_operand4" "mask_scalar" "" "%{%5%}%N4")
+
+(define_subst "mask_scalar"
+ [(set (match_operand:SUBST_V 0)
+ (vec_merge:SUBST_V
+ (match_operand:SUBST_V 1)
+ (match_operand:SUBST_V 2)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (vec_merge:SUBST_V
+ (vec_merge:SUBST_V
+ (match_dup 1)
+ (match_operand:SUBST_V 3 "vector_move_operand" "0C")
+ (match_operand:<avx512fmaskmode> 4 "register_operand" "Yk"))
+ (match_dup 2)
+ (const_int 1)))])
+
+(define_subst_attr "round_scalar_name" "round_scalar" "" "_round")
+(define_subst_attr "round_scalar_mask_operand3" "mask_scalar" "%R3" "%R5")
+(define_subst_attr "round_scalar_mask_op3" "round_scalar" "" "<round_scalar_mask_operand3>")
+(define_subst_attr "round_scalar_constraint" "round_scalar" "vm" "v")
+(define_subst_attr "round_scalar_prefix" "round_scalar" "vex" "evex")
+
+(define_subst "round_scalar"
+ [(set (match_operand:SUBST_V 0)
+ (vec_merge:SUBST_V
+ (match_operand:SUBST_V 1)
+ (match_operand:SUBST_V 2)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (unspec:SUBST_V [
+ (vec_merge:SUBST_V
+ (match_dup 1)
+ (match_dup 2)
+ (const_int 1))
+ (match_operand:SI 3 "const_4_or_8_to_11_operand")]
+ UNSPEC_EMBEDDED_ROUNDING))])
+
+(define_subst_attr "round_saeonly_scalar_name" "round_saeonly_scalar" "" "_round")
+(define_subst_attr "round_saeonly_scalar_mask_operand3" "mask_scalar" "%r3" "%r5")
+(define_subst_attr "round_saeonly_scalar_mask_operand4" "mask_scalar" "%r4" "%r6")
+(define_subst_attr "round_saeonly_scalar_mask_op3" "round_saeonly_scalar" "" "<round_saeonly_scalar_mask_operand3>")
+(define_subst_attr "round_saeonly_scalar_mask_op4" "round_saeonly_scalar" "" "<round_saeonly_scalar_mask_operand4>")
+(define_subst_attr "round_saeonly_scalar_constraint" "round_saeonly_scalar" "vm" "v")
+(define_subst_attr "round_saeonly_scalar_prefix" "round_saeonly_scalar" "vex" "evex")
+(define_subst_attr "round_saeonly_scalar_nimm_predicate" "round_saeonly_scalar" "vector_operand" "register_operand")
+
+(define_subst "round_saeonly_scalar"
+ [(set (match_operand:SUBST_V 0)
+ (vec_merge:SUBST_V
+ (match_operand:SUBST_V 1)
+ (match_operand:SUBST_V 2)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ [(set (match_dup 0)
+ (unspec:SUBST_V [
+ (vec_merge:SUBST_V
+ (match_dup 1)
+ (match_dup 2)
+ (const_int 1))
+ (match_operand:SI 3 "const48_operand")]
+ UNSPEC_EMBEDDED_ROUNDING))])
diff --git a/gcc/config/i386/t-openbsd b/gcc/config/i386/t-openbsd
deleted file mode 100644
index 4f8ff657a93..00000000000
--- a/gcc/config/i386/t-openbsd
+++ /dev/null
@@ -1,4 +0,0 @@
-# gdb gets confused if pic code is linked with non pic
-# We cope by building variants of libgcc.
-MULTILIB_OPTIONS = fpic
-MULTILIB_MATCHES=fpic=fPIC
diff --git a/gcc/config/i386/vxworks.h b/gcc/config/i386/vxworks.h
index f5d12afe111..6095f723850 100644
--- a/gcc/config/i386/vxworks.h
+++ b/gcc/config/i386/vxworks.h
@@ -18,9 +18,7 @@ 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 ASM_SPEC
-#define ASM_SPEC ""
-
+#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
@@ -34,7 +32,19 @@ along with GCC; see the file COPYING3. If not see
the SVR4 numbering. */
#undef DBX_REGISTER_NUMBER
-#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
+#define DBX_REGISTER_NUMBER(n) \
+ (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_LP64 ? "long int" : "int")
+
+#undef SIZE_TYPE
+#define SIZE_TYPE (TARGET_LP64 ? "long unsigned int" : "unsigned int")
+
+#if TARGET_64BIT_DEFAULT
+#undef VXWORKS_SYSCALL_LIBS_RTP
+#define VXWORKS_SYSCALL_LIBS_RTP "-lsyscall"
+#endif
#define TARGET_OS_CPP_BUILTINS() \
do \
@@ -59,7 +69,11 @@ along with GCC; see the file COPYING3. If not see
builtin_define ("CPU=PENTIUM4"); \
builtin_define ("CPU_VARIANT=PENTIUM4"); \
} \
- } \
+ else if (TARGET_64BIT) \
+ builtin_define ("CPU=X86_64"); \
+ else \
+ builtin_define ("CPU=I80386"); \
+ } \
while (0)
#undef CPP_SPEC
@@ -91,5 +105,10 @@ along with GCC; see the file COPYING3. If not see
#define STACK_CHECK_STATIC_BUILTIN 1
/* This platform supports the probing method of stack checking (RTP mode).
- 8K is reserved in the stack to propagate exceptions in case of overflow. */
+ 8K is reserved in the stack to propagate exceptions in case of overflow.
+ On 64-bit targets, we double that size. */
+#if TARGET_64BIT_DEFAULT
+#define STACK_CHECK_PROTECT 16384
+#else
#define STACK_CHECK_PROTECT 8192
+#endif
diff --git a/gcc/config/i386/winnt-cxx.c b/gcc/config/i386/winnt-cxx.c
index d6bf0afbab0..a3569fb1b56 100644
--- a/gcc/config/i386/winnt-cxx.c
+++ b/gcc/config/i386/winnt-cxx.c
@@ -114,14 +114,11 @@ i386_pe_adjust_class_at_definition (tree t)
decl_attributes (&ti_decl, na, 0);
}
- /* Check static VAR_DECL's. */
+ /* Check FUNCTION_DECL's and static VAR_DECL's. */
for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllexport (member);
-
- /* Check FUNCTION_DECL's. */
- for (member = TYPE_METHODS (t); member; member = DECL_CHAIN (member))
- if (TREE_CODE (member) == FUNCTION_DECL)
+ else if (TREE_CODE (member) == FUNCTION_DECL)
{
tree thunk;
maybe_add_dllexport (member);
@@ -130,9 +127,11 @@ i386_pe_adjust_class_at_definition (tree t)
for (thunk = DECL_THUNKS (member); thunk;
thunk = TREE_CHAIN (thunk))
maybe_add_dllexport (thunk);
- }
+ }
+
/* Check vtables */
- for (member = CLASSTYPE_VTABLES (t); member; member = DECL_CHAIN (member))
+ for (member = CLASSTYPE_VTABLES (t);
+ member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllexport (member);
}
@@ -147,14 +146,11 @@ i386_pe_adjust_class_at_definition (tree t)
That is just right since out-of class declarations can only be a
definition. */
- /* Check static VAR_DECL's. */
+ /* Check FUNCTION_DECL's and static VAR_DECL's. */
for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllimport (member);
-
- /* Check FUNCTION_DECL's. */
- for (member = TYPE_METHODS (t); member; member = DECL_CHAIN (member))
- if (TREE_CODE (member) == FUNCTION_DECL)
+ else if (TREE_CODE (member) == FUNCTION_DECL)
{
tree thunk;
maybe_add_dllimport (member);
@@ -163,10 +159,11 @@ i386_pe_adjust_class_at_definition (tree t)
for (thunk = DECL_THUNKS (member); thunk;
thunk = DECL_CHAIN (thunk))
maybe_add_dllimport (thunk);
- }
+ }
/* Check vtables */
- for (member = CLASSTYPE_VTABLES (t); member; member = DECL_CHAIN (member))
+ for (member = CLASSTYPE_VTABLES (t);
+ member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllimport (member);
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 617d188d4f2..c8e4c74bbdb 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -5502,7 +5502,8 @@ ia64_print_operand (FILE * file, rtx x, int code)
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
if (x)
{
- int pred_val = XINT (x, 0);
+ int pred_val = profile_probability::from_reg_br_prob_note
+ (XINT (x, 0)).to_reg_br_prob_base ();
/* Guess top and bottom 10% statically predicted. */
if (pred_val < REG_BR_PROB_BASE / 50
diff --git a/gcc/config/lm32/rtems.h b/gcc/config/lm32/rtems.h
index 67075ab47da..24d21e8b898 100644
--- a/gcc/config/lm32/rtems.h
+++ b/gcc/config/lm32/rtems.h
@@ -1,21 +1,26 @@
/* Definitions for rtems targeting a lm32 using ELF.
Copyright (C) 2009-2017 Free Software Foundation, Inc.
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS builtins. */
#undef TARGET_OS_CPP_BUILTINS
diff --git a/gcc/config/m32c/rtems.h b/gcc/config/m32c/rtems.h
index 733e04ba386..d70493ddc81 100644
--- a/gcc/config/m32c/rtems.h
+++ b/gcc/config/m32c/rtems.h
@@ -2,21 +2,26 @@
Copyright (C) 2008-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS builtins. */
#undef TARGET_OS_CPP_BUILTINS
diff --git a/gcc/config/m68k/rtemself.h b/gcc/config/m68k/rtemself.h
index ee9d7fdf777..f4a1eabda61 100644
--- a/gcc/config/m68k/rtemself.h
+++ b/gcc/config/m68k/rtemself.h
@@ -3,21 +3,26 @@
Copyright (C) 2007-2017 Free Software Foundation, Inc.
Contributed by Charles-Antoine Gauthier (charles.gauthier@nrc.ca).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS builtins. */
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index 9ba8f2d46f9..747ef359719 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -33,7 +33,7 @@ extern bool microblaze_expand_move (machine_mode, rtx *);
extern bool microblaze_expand_block_move (rtx, rtx, rtx, rtx);
extern void microblaze_expand_divide (rtx *);
extern void microblaze_expand_conditional_branch (machine_mode, rtx *);
-extern void microblaze_expand_conditional_branch_reg (enum machine_mode, rtx *);
+extern void microblaze_expand_conditional_branch_reg (machine_mode, rtx *);
extern void microblaze_expand_conditional_branch_sf (rtx *);
extern int microblaze_can_use_return_insn (void);
extern void print_operand (FILE *, rtx, int);
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index d0f86fd4607..15ceac0b346 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -3453,8 +3453,7 @@ microblaze_expand_conditional_branch (machine_mode mode, rtx operands[])
}
void
-microblaze_expand_conditional_branch_reg (enum machine_mode mode,
- rtx operands[])
+microblaze_expand_conditional_branch_reg (machine_mode mode, rtx operands[])
{
enum rtx_code code = GET_CODE (operands[0]);
rtx cmp_op0 = operands[1];
diff --git a/gcc/config/microblaze/rtems.h b/gcc/config/microblaze/rtems.h
index 980d8e72e1e..0ae8bbd8704 100644
--- a/gcc/config/microblaze/rtems.h
+++ b/gcc/config/microblaze/rtems.h
@@ -1,21 +1,26 @@
/* Definitions for rtems targeting a microblaze using ELF.
Copyright (C) 2012-2017 Free Software Foundation, Inc.
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/mips/rtems.h b/gcc/config/mips/rtems.h
index 2ce03de20e1..8699117b7bb 100644
--- a/gcc/config/mips/rtems.h
+++ b/gcc/config/mips/rtems.h
@@ -2,21 +2,26 @@
Copyright (C) 1996-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 32786881959..9849c19e076 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -1536,7 +1536,8 @@ mmix_print_operand (FILE *stream, rtx x, int code)
if (TARGET_BRANCH_PREDICT)
{
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
- if (x && XINT (x, 0) > REG_BR_PROB_BASE / 2)
+ if (x && profile_probability::from_reg_br_prob_note (XINT (x, 0))
+ > profile_probability::even ())
putc ('P', stream);
}
return;
diff --git a/gcc/config/moxie/rtems.h b/gcc/config/moxie/rtems.h
index d23061bb6c2..8c97238002a 100644
--- a/gcc/config/moxie/rtems.h
+++ b/gcc/config/moxie/rtems.h
@@ -2,21 +2,26 @@
Copyright (C) 2010-2017 Free Software Foundation, Inc.
Contributed by Anthony Green (green@moxielogic.com)
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS preprocessor built-ins. */
#define TARGET_OS_CPP_BUILTINS() \
diff --git a/gcc/config/netbsd.h b/gcc/config/netbsd.h
index 4001f240d58..f96ead05468 100644
--- a/gcc/config/netbsd.h
+++ b/gcc/config/netbsd.h
@@ -84,7 +84,6 @@ along with GCC; see the file COPYING3. If not see
FIXME: Could eliminate the duplication here if we were allowed to
use string concatenation. */
-#ifdef NETBSD_ENABLE_PTHREADS
#define NETBSD_LIB_SPEC \
"%{pthread: \
%{!p: \
@@ -96,26 +95,13 @@ along with GCC; see the file COPYING3. If not see
%{!pg:-lposix}} \
%{p:-lposix_p} \
%{pg:-lposix_p}} \
+ %{shared:-lc} \
%{!shared: \
%{!symbolic: \
%{!p: \
%{!pg:-lc}} \
%{p:-lc_p} \
%{pg:-lc_p}}}"
-#else
-#define NETBSD_LIB_SPEC \
- "%{posix: \
- %{!p: \
- %{!pg:-lposix}} \
- %{p:-lposix_p} \
- %{pg:-lposix_p}} \
- %{!shared: \
- %{!symbolic: \
- %{!p: \
- %{!pg:-lc}} \
- %{p:-lc_p} \
- %{pg:-lc_p}}}"
-#endif
#undef LIB_SPEC
#define LIB_SPEC NETBSD_LIB_SPEC
diff --git a/gcc/config/nios2/rtems.h b/gcc/config/nios2/rtems.h
index 4e772175721..344a1e91b07 100644
--- a/gcc/config/nios2/rtems.h
+++ b/gcc/config/nios2/rtems.h
@@ -3,21 +3,26 @@
Contributed by Chris Johns (chrisj@rtems.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/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
#define TARGET_OS_CPP_BUILTINS() \
diff --git a/gcc/config/nvptx/nvptx-modes.def b/gcc/config/nvptx/nvptx-modes.def
new file mode 100644
index 00000000000..ff61b363e62
--- /dev/null
+++ b/gcc/config/nvptx/nvptx-modes.def
@@ -0,0 +1,3 @@
+VECTOR_MODE (INT, SI, 2); /* V2SI */
+
+VECTOR_MODE (INT, DI, 2); /* V2DI */
diff --git a/gcc/config/nvptx/nvptx-protos.h b/gcc/config/nvptx/nvptx-protos.h
index 16b316f12b8..c3e3b84588b 100644
--- a/gcc/config/nvptx/nvptx-protos.h
+++ b/gcc/config/nvptx/nvptx-protos.h
@@ -41,6 +41,7 @@ extern void nvptx_function_end (FILE *);
extern void nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT);
extern void nvptx_output_ascii (FILE *, const char *, unsigned HOST_WIDE_INT);
extern void nvptx_register_pragmas (void);
+extern unsigned int nvptx_data_alignment (const_tree, unsigned int);
#ifdef RTX_CODE
extern void nvptx_expand_oacc_fork (unsigned);
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index daeec2733ea..208b11555f2 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -74,6 +74,8 @@
/* This file should be included last. */
#include "target-def.h"
+#define WORKAROUND_PTXJIT_BUG 1
+
/* The various PTX memory areas an object might reside in. */
enum nvptx_data_area
{
@@ -205,6 +207,17 @@ nvptx_option_override (void)
target_flags |= MASK_SOFT_STACK | MASK_UNIFORM_SIMT;
}
+/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
+
+static void
+nvptx_override_options_after_change (void)
+{
+ /* This is a workaround for PR81430 - nvptx acceleration compilation broken
+ because of running pass_partition_blocks. This should be dealt with in the
+ common code, not in the target. */
+ flag_reorder_blocks_and_partition = 0;
+}
+
/* Return a ptx type for MODE. If PROMOTE, then use .u32 for QImode to
deal with ptx ideosyncracies. */
@@ -234,6 +247,11 @@ nvptx_ptx_type_from_mode (machine_mode mode, bool promote)
case DFmode:
return ".f64";
+ case V2SImode:
+ return ".v2.u32";
+ case V2DImode:
+ return ".v2.u64";
+
default:
gcc_unreachable ();
}
@@ -2178,7 +2196,20 @@ nvptx_output_mov_insn (rtx dst, rtx src)
? "%.\tmov%t0\t%0, %1;" : "%.\tmov.b%T0\t%0, %1;");
if (GET_MODE_SIZE (dst_inner) == GET_MODE_SIZE (src_inner))
- return "%.\tmov.b%T0\t%0, %1;";
+ {
+ if (GET_MODE_BITSIZE (dst_mode) == 128
+ && GET_MODE_BITSIZE (GET_MODE (src)) == 128)
+ {
+ /* mov.b128 is not supported. */
+ if (dst_inner == V2DImode && src_inner == TImode)
+ return "%.\tmov.u64\t%0.x, %L1;\n\t%.\tmov.u64\t%0.y, %H1;";
+ else if (dst_inner == TImode && src_inner == V2DImode)
+ return "%.\tmov.u64\t%L0, %1.x;\n\t%.\tmov.u64\t%H0, %1.y;";
+
+ gcc_unreachable ();
+ }
+ return "%.\tmov.b%T0\t%0, %1;";
+ }
return "%.\tcvt%t0%t1\t%0, %1;";
}
@@ -2403,13 +2434,33 @@ nvptx_print_operand (FILE *file, rtx x, int code)
case 'u':
if (x_code == SUBREG)
{
- mode = GET_MODE (SUBREG_REG (x));
- if (split_mode_p (mode))
- mode = maybe_split_mode (mode);
+ machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+ if (VECTOR_MODE_P (inner_mode)
+ && (GET_MODE_SIZE (mode)
+ <= GET_MODE_SIZE (GET_MODE_INNER (inner_mode))))
+ mode = GET_MODE_INNER (inner_mode);
+ else if (split_mode_p (inner_mode))
+ mode = maybe_split_mode (inner_mode);
+ else
+ mode = inner_mode;
}
fprintf (file, "%s", nvptx_ptx_type_from_mode (mode, code == 't'));
break;
+ case 'H':
+ case 'L':
+ {
+ rtx inner_x = SUBREG_REG (x);
+ machine_mode inner_mode = GET_MODE (inner_x);
+ machine_mode split = maybe_split_mode (inner_mode);
+
+ output_reg (file, REGNO (inner_x), split,
+ (code == 'H'
+ ? GET_MODE_SIZE (inner_mode) / 2
+ : 0));
+ }
+ break;
+
case 'S':
{
nvptx_shuffle_kind kind = (nvptx_shuffle_kind) UINTVAL (x);
@@ -2506,7 +2557,14 @@ nvptx_print_operand (FILE *file, rtx x, int code)
machine_mode inner_mode = GET_MODE (inner_x);
machine_mode split = maybe_split_mode (inner_mode);
- if (split_mode_p (inner_mode)
+ if (VECTOR_MODE_P (inner_mode)
+ && (GET_MODE_SIZE (mode)
+ <= GET_MODE_SIZE (GET_MODE_INNER (inner_mode))))
+ {
+ output_reg (file, REGNO (inner_x), VOIDmode);
+ fprintf (file, ".%s", SUBREG_BYTE (x) == 0 ? "x" : "y");
+ }
+ else if (split_mode_p (inner_mode)
&& (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (mode)))
output_reg (file, REGNO (inner_x), split);
else
@@ -2548,6 +2606,22 @@ nvptx_print_operand (FILE *file, rtx x, int code)
fprintf (file, "0d%08lx%08lx", vals[1], vals[0]);
break;
+ case CONST_VECTOR:
+ {
+ unsigned n = CONST_VECTOR_NUNITS (x);
+ fprintf (file, "{ ");
+ for (unsigned i = 0; i < n; ++i)
+ {
+ if (i != 0)
+ fprintf (file, ", ");
+
+ rtx elem = CONST_VECTOR_ELT (x, i);
+ output_addr_const (file, elem);
+ }
+ fprintf (file, " }");
+ }
+ break;
+
default:
output_addr_const (file, x);
}
@@ -3844,6 +3918,24 @@ nvptx_wsync (bool after)
return gen_nvptx_barsync (GEN_INT (after));
}
+#if WORKAROUND_PTXJIT_BUG
+/* Return first real insn in BB, or return NULL_RTX if BB does not contain
+ real insns. */
+
+static rtx_insn *
+bb_first_real_insn (basic_block bb)
+{
+ rtx_insn *insn;
+
+ /* Find first insn of from block. */
+ FOR_BB_INSNS (bb, insn)
+ if (INSN_P (insn))
+ return insn;
+
+ return 0;
+}
+#endif
+
/* Single neutering according to MASK. FROM is the incoming block and
TO is the outgoing block. These may be the same block. Insert at
start of FROM:
@@ -3866,9 +3958,25 @@ nvptx_single (unsigned mask, basic_block from, basic_block to)
rtx_insn *tail = BB_END (to);
unsigned skip_mask = mask;
- /* Find first insn of from block */
- while (head != BB_END (from) && !INSN_P (head))
- head = NEXT_INSN (head);
+ while (true)
+ {
+ /* Find first insn of from block. */
+ while (head != BB_END (from) && !INSN_P (head))
+ head = NEXT_INSN (head);
+
+ if (from == to)
+ break;
+
+ if (!(JUMP_P (head) && single_succ_p (from)))
+ break;
+
+ basic_block jump_target = single_succ (from);
+ if (!single_pred_p (jump_target))
+ break;
+
+ from = jump_target;
+ head = BB_HEAD (from);
+ }
/* Find last insn of to block */
rtx_insn *limit = from == to ? head : BB_HEAD (to);
@@ -3958,6 +4066,39 @@ nvptx_single (unsigned mask, basic_block from, basic_block to)
if (GOMP_DIM_MASK (GOMP_DIM_VECTOR) == mask)
{
/* Vector mode only, do a shuffle. */
+#if WORKAROUND_PTXJIT_BUG
+ /* The branch condition %rcond is propagated like this:
+
+ {
+ .reg .u32 %x;
+ mov.u32 %x,%tid.x;
+ setp.ne.u32 %rnotvzero,%x,0;
+ }
+
+ @%rnotvzero bra Lskip;
+ setp.<op>.<type> %rcond,op1,op2;
+ Lskip:
+ selp.u32 %rcondu32,1,0,%rcond;
+ shfl.idx.b32 %rcondu32,%rcondu32,0,31;
+ setp.ne.u32 %rcond,%rcondu32,0;
+
+ There seems to be a bug in the ptx JIT compiler (observed at driver
+ version 381.22, at -O1 and higher for sm_61), that drops the shfl
+ unless %rcond is initialized to something before 'bra Lskip'. The
+ bug is not observed with ptxas from cuda 8.0.61.
+
+ It is true that the code is non-trivial: at Lskip, %rcond is
+ uninitialized in threads 1-31, and after the selp the same holds
+ for %rcondu32. But shfl propagates the defined value in thread 0
+ to threads 1-31, so after the shfl %rcondu32 is defined in threads
+ 0-31, and after the setp.ne %rcond is defined in threads 0-31.
+
+ There is nothing in the PTX spec to suggest that this is wrong, or
+ to explain why the extra initialization is needed. So, we classify
+ it as a JIT bug, and the extra initialization as workaround. */
+ emit_insn_before (gen_movbi (pvar, const0_rtx),
+ bb_first_real_insn (from));
+#endif
emit_insn_before (nvptx_gen_vcast (pvar), tail);
}
else
@@ -5143,6 +5284,7 @@ nvptx_goacc_reduction_init (gcall *call)
/* Fixup flags from call_bb to init_bb. */
init_edge->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
+ init_edge->probability = profile_probability::even ();
/* Set the initialization stmts. */
gimple_seq init_seq = NULL;
@@ -5158,6 +5300,7 @@ nvptx_goacc_reduction_init (gcall *call)
/* Create false edge from call_bb to dst_bb. */
edge nop_edge = make_edge (call_bb, dst_bb, EDGE_FALSE_VALUE);
+ nop_edge->probability = profile_probability::even ();
/* Create phi node in dst block. */
gphi *phi = create_phi_node (lhs, dst_bb);
@@ -5335,9 +5478,49 @@ nvptx_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
return true;
}
+static bool
+nvptx_vector_mode_supported (machine_mode mode)
+{
+ return (mode == V2SImode
+ || mode == V2DImode);
+}
+
+/* Return the preferred mode for vectorizing scalar MODE. */
+
+static machine_mode
+nvptx_preferred_simd_mode (machine_mode mode)
+{
+ switch (mode)
+ {
+ case DImode:
+ return V2DImode;
+ case SImode:
+ return V2SImode;
+
+ default:
+ return default_preferred_simd_mode (mode);
+ }
+}
+
+unsigned int
+nvptx_data_alignment (const_tree type, unsigned int basic_align)
+{
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ {
+ unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ if (size == GET_MODE_SIZE (TImode))
+ return GET_MODE_BITSIZE (maybe_split_mode (TImode));
+ }
+
+ return basic_align;
+}
+
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE nvptx_option_override
+#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
+#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE nvptx_override_options_after_change
+
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE nvptx_attribute_table
@@ -5452,6 +5635,13 @@ nvptx_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM nvptx_cannot_force_const_mem
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P nvptx_vector_mode_supported
+
+#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
+#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE \
+ nvptx_preferred_simd_mode
+
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 0a000a73df5..4224acf26e2 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -52,13 +52,15 @@
/* Alignments in bits. */
#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 64
+#define STACK_BOUNDARY 128
#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT 128
#define STRICT_ALIGNMENT 1
#define MAX_STACK_ALIGNMENT (1024 * 8)
+#define DATA_ALIGNMENT nvptx_data_alignment
+
/* Copied from elf.h and other places. We'd otherwise use
BIGGEST_ALIGNMENT and fail a number of testcases. */
#define MAX_OFILE_ALIGNMENT (32768 * 8)
diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
index f2b090594e3..41a24b31edd 100644
--- a/gcc/config/nvptx/nvptx.md
+++ b/gcc/config/nvptx/nvptx.md
@@ -184,6 +184,7 @@
(define_mode_iterator SDCM [SC DC])
(define_mode_iterator BITS [SI SF])
(define_mode_iterator BITD [DI DF])
+(define_mode_iterator VECIM [V2SI V2DI])
;; This mode iterator allows :P to be used for patterns that operate on
;; pointer-sized quantities. Exactly one of the two alternatives will match.
@@ -201,6 +202,20 @@
%.\\tsetp.eq.u32\\t%0, 1, 1;")
(define_insn "*mov<mode>_insn"
+ [(set (match_operand:VECIM 0 "nonimmediate_operand" "=R,R,m")
+ (match_operand:VECIM 1 "general_operand" "Ri,m,R"))]
+ "!MEM_P (operands[0]) || REG_P (operands[1])"
+{
+ if (which_alternative == 1)
+ return "%.\\tld%A1%u1\\t%0, %1;";
+ if (which_alternative == 2)
+ return "%.\\tst%A0%u0\\t%0, %1;";
+
+ return nvptx_output_mov_insn (operands[0], operands[1]);
+}
+ [(set_attr "subregs_ok" "true")])
+
+(define_insn "*mov<mode>_insn"
[(set (match_operand:QHSDIM 0 "nonimmediate_operand" "=R,R,m")
(match_operand:QHSDIM 1 "general_operand" "Ri,m,R"))]
"!MEM_P (operands[0]) || REG_P (operands[1])"
@@ -242,6 +257,20 @@
""
"%.\\tmov%t0\\t%0, %%ar%1;")
+ (define_expand "mov<mode>"
+ [(set (match_operand:VECIM 0 "nonimmediate_operand" "")
+ (match_operand:VECIM 1 "general_operand" ""))]
+ ""
+{
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ {
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ emit_move_insn (tmp, operands[1]);
+ emit_move_insn (operands[0], tmp);
+ DONE;
+ }
+})
+
(define_expand "mov<mode>"
[(set (match_operand:QHSDISDFM 0 "nonimmediate_operand" "")
(match_operand:QHSDISDFM 1 "general_operand" ""))]
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 3e65ba1db59..2a78018650c 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -10723,7 +10723,8 @@ pa_expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
/* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
- GET_MODE (success), 1, label, 0);
+ GET_MODE (success), 1, label,
+ profile_probability::guessed_never ());
return true;
}
diff --git a/gcc/config/powerpcspe/powerpcspe.c b/gcc/config/powerpcspe/powerpcspe.c
index 73d608fd805..b94afd5ca2e 100644
--- a/gcc/config/powerpcspe/powerpcspe.c
+++ b/gcc/config/powerpcspe/powerpcspe.c
@@ -3608,12 +3608,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
CODE_FOR_fusion_gpr_di_df_store },
};
- enum machine_mode cur_pmode = Pmode;
+ machine_mode cur_pmode = Pmode;
size_t i;
for (i = 0; i < ARRAY_SIZE (addis_insns); i++)
{
- enum machine_mode xmode = addis_insns[i].mode;
+ machine_mode xmode = addis_insns[i].mode;
enum rs6000_reload_reg_type rtype = addis_insns[i].rtype;
if (addis_insns[i].pmode != cur_pmode)
@@ -10399,7 +10399,7 @@ rs6000_offsettable_memref_p (rtx op, machine_mode reg_mode)
static int
rs6000_reassociation_width (unsigned int opc ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ machine_mode mode)
{
switch (rs6000_cpu)
{
@@ -24860,8 +24860,8 @@ rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED,
const_tree type1,
const_tree type2)
{
- enum machine_mode mode1 = TYPE_MODE (type1);
- enum machine_mode mode2 = TYPE_MODE (type2);
+ machine_mode mode1 = TYPE_MODE (type1);
+ machine_mode mode2 = TYPE_MODE (type2);
/* For complex modes, use the inner type. */
if (COMPLEX_MODE_P (mode1))
@@ -25333,7 +25333,8 @@ output_cbranch (rtx op, const char *label, int reversed, rtx_insn *insn)
if (note != NULL_RTX)
{
/* PROB is the difference from 50%. */
- int prob = XINT (note, 0) - REG_BR_PROB_BASE / 2;
+ int prob = profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ .to_reg_br_prob_base () - REG_BR_PROB_BASE / 2;
/* Only hint for highly probable/improbable branches on newer cpus when
we have real profile data, as static prediction overrides processor
@@ -26123,10 +26124,9 @@ rs6000_split_signbit (rtx dest, rtx src)
static void
emit_unlikely_jump (rtx cond, rtx label)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
rtx_insn *insn = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
- add_int_reg_note (insn, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (insn, profile_probability::very_unlikely ());
}
/* A subroutine of the atomic operation splitters. Emit a load-locked
@@ -32192,8 +32192,7 @@ rs6000_expand_split_stack_prologue (void)
insn = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
JUMP_LABEL (insn) = ok_label;
/* Mark the jump as very likely to be taken. */
- add_int_reg_note (insn, REG_BR_PROB,
- REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100);
+ add_reg_br_prob_note (insn, profile_probability::very_likely ());
lr = gen_rtx_REG (Pmode, LR_REGNO);
insn = emit_move_insn (r0, lr);
@@ -41284,7 +41283,7 @@ fusion_p9_p (rtx addis_reg, /* register set via addis. */
rtx src) /* source (register or memory). */
{
rtx addr, mem, offset;
- enum machine_mode mode = GET_MODE (src);
+ machine_mode mode = GET_MODE (src);
/* Validate arguments. */
if (!base_reg_operand (addis_reg, GET_MODE (addis_reg)))
@@ -41458,7 +41457,7 @@ expand_fusion_p9_store (rtx *operands)
const char *
emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
{
- enum machine_mode mode = GET_MODE (reg);
+ machine_mode mode = GET_MODE (reg);
rtx hi;
rtx lo;
rtx addr;
@@ -41551,7 +41550,7 @@ emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
const char *
emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
{
- enum machine_mode mode = GET_MODE (reg);
+ machine_mode mode = GET_MODE (reg);
rtx hi;
rtx lo;
rtx addr;
diff --git a/gcc/config/powerpcspe/rtems.h b/gcc/config/powerpcspe/rtems.h
index 54a36de6eb4..1ab4e313fdb 100644
--- a/gcc/config/powerpcspe/rtems.h
+++ b/gcc/config/powerpcspe/rtems.h
@@ -14,8 +14,13 @@
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
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/riscv/riscv-builtins.c b/gcc/config/riscv/riscv-builtins.c
index 626a6a33f99..1311fee6f70 100644
--- a/gcc/config/riscv/riscv-builtins.c
+++ b/gcc/config/riscv/riscv-builtins.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "memmodel.h"
#include "expmed.h"
+#include "profile-count.h"
#include "optabs.h"
#include "recog.h"
#include "diagnostic-core.h"
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index de7023f88c5..aa57d1a7152 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -38,18 +38,18 @@ enum riscv_symbol_type {
/* Routines implemented in riscv.c. */
extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
-extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool);
-extern bool riscv_hard_regno_mode_ok_p (unsigned int, enum machine_mode);
-extern int riscv_address_insns (rtx, enum machine_mode, bool);
+extern int riscv_regno_mode_ok_for_base_p (int, machine_mode, bool);
+extern bool riscv_hard_regno_mode_ok_p (unsigned int, machine_mode);
+extern int riscv_address_insns (rtx, machine_mode, bool);
extern int riscv_const_insns (rtx);
extern int riscv_split_const_insns (rtx);
extern int riscv_load_store_insns (rtx, rtx_insn *);
extern rtx riscv_emit_move (rtx, rtx);
-extern bool riscv_split_symbol (rtx, rtx, enum machine_mode, rtx *);
+extern bool riscv_split_symbol (rtx, rtx, machine_mode, rtx *);
extern bool riscv_split_symbol_type (enum riscv_symbol_type);
extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT);
-extern bool riscv_legitimize_move (enum machine_mode, rtx, rtx);
+extern bool riscv_legitimize_move (machine_mode, rtx, rtx);
extern rtx riscv_subword (rtx, bool);
extern bool riscv_split_64bit_move_p (rtx, rtx);
extern void riscv_split_doubleword_move (rtx, rtx);
@@ -68,15 +68,15 @@ extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
extern void riscv_expand_prologue (void);
extern void riscv_expand_epilogue (bool);
extern bool riscv_can_use_return_insn (void);
-extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
-extern unsigned int riscv_hard_regno_nregs (int, enum machine_mode);
+extern rtx riscv_function_value (const_tree, const_tree, machine_mode);
+extern unsigned int riscv_hard_regno_nregs (int, machine_mode);
/* Routines implemented in riscv-c.c. */
void riscv_cpu_cpp_builtins (cpp_reader *);
/* Routines implemented in riscv-builtins.c. */
extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *);
-extern rtx riscv_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+extern rtx riscv_expand_builtin (tree, rtx, rtx, machine_mode, int);
extern tree riscv_builtin_decl (unsigned int, bool);
extern void riscv_init_builtins (void);
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 111701ec059..57b2edbcb43 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -25,86 +25,30 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "rtl.h"
#include "regs.h"
-#include "hard-reg-set.h"
#include "insn-config.h"
-#include "conditions.h"
#include "insn-attr.h"
#include "recog.h"
#include "output.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
#include "tree.h"
-#include "fold-const.h"
#include "varasm.h"
-#include "stringpool.h"
#include "stor-layout.h"
#include "calls.h"
#include "function.h"
-#include "hashtab.h"
-#include "flags.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
-#include "expmed.h"
-#include "dojump.h"
#include "explow.h"
#include "memmodel.h"
#include "emit-rtl.h"
-#include "stmt.h"
-#include "expr.h"
-#include "insn-codes.h"
-#include "optabs.h"
-#include "libfuncs.h"
#include "reload.h"
#include "tm_p.h"
-#include "ggc.h"
-#include "gstab.h"
-#include "hash-table.h"
-#include "debug.h"
#include "target.h"
#include "target-def.h"
-#include "common/common-target.h"
-#include "langhooks.h"
-#include "dominance.h"
-#include "profile-count.h"
-#include "cfg.h"
-#include "cfgrtl.h"
-#include "cfganal.h"
-#include "lcm.h"
-#include "cfgbuild.h"
-#include "cfgcleanup.h"
-#include "predict.h"
#include "basic-block.h"
+#include "expr.h"
+#include "optabs.h"
#include "bitmap.h"
-#include "regset.h"
#include "df.h"
-#include "sched-int.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 "gimplify.h"
#include "diagnostic.h"
-#include "target-globals.h"
-#include "opts.h"
-#include "tree-pass.h"
-#include "context.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
#include "builtins.h"
-#include "rtl-iter.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
@@ -347,7 +291,7 @@ riscv_parse_cpu (const char *cpu_string)
static int
riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
- HOST_WIDE_INT value, enum machine_mode mode)
+ HOST_WIDE_INT value, machine_mode mode)
{
HOST_WIDE_INT low_part = CONST_LOW_PART (value);
int cost = RISCV_MAX_INTEGER_OPS + 1, alt_cost;
@@ -421,7 +365,7 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
static int
riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value,
- enum machine_mode mode)
+ machine_mode mode)
{
int cost = riscv_build_integer_1 (codes, value, mode);
@@ -489,7 +433,7 @@ riscv_integer_cost (HOST_WIDE_INT val)
/* Try to split a 64b integer into 32b parts, then reassemble. */
static rtx
-riscv_split_integer (HOST_WIDE_INT val, enum machine_mode mode)
+riscv_split_integer (HOST_WIDE_INT val, machine_mode mode)
{
unsigned HOST_WIDE_INT loval = sext_hwi (val, 32);
unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32);
@@ -608,7 +552,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
static bool
-riscv_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+riscv_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
return riscv_const_insns (x) > 0;
}
@@ -616,7 +560,7 @@ riscv_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
static bool
-riscv_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
enum riscv_symbol_type type;
rtx base, offset;
@@ -651,7 +595,7 @@ riscv_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
int
riscv_regno_mode_ok_for_base_p (int regno,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
bool strict_p)
{
if (!HARD_REGISTER_NUM_P (regno))
@@ -674,7 +618,7 @@ riscv_regno_mode_ok_for_base_p (int regno,
STRICT_P is true if REG_OK_STRICT is in effect. */
static bool
-riscv_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p)
+riscv_valid_base_register_p (rtx x, machine_mode mode, bool strict_p)
{
if (!strict_p && GET_CODE (x) == SUBREG)
x = SUBREG_REG (x);
@@ -687,7 +631,7 @@ riscv_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p)
can address a value of mode MODE. */
static bool
-riscv_valid_offset_p (rtx x, enum machine_mode mode)
+riscv_valid_offset_p (rtx x, machine_mode mode)
{
/* Check that X is a signed 12-bit number. */
if (!const_arith_operand (x, Pmode))
@@ -720,7 +664,7 @@ riscv_split_symbol_type (enum riscv_symbol_type symbol_type)
LO_SUM symbol has type SYM_TYPE. */
static bool
-riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, enum machine_mode mode)
+riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode)
{
/* Check that symbols of type SYMBOL_TYPE can be used to access values
of mode MODE. */
@@ -747,7 +691,7 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, enum machine_mode mode)
static bool
riscv_classify_address (struct riscv_address_info *info, rtx x,
- enum machine_mode mode, bool strict_p)
+ machine_mode mode, bool strict_p)
{
switch (GET_CODE (x))
{
@@ -797,7 +741,7 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
static bool
-riscv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p)
+riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
{
struct riscv_address_info addr;
@@ -811,7 +755,7 @@ riscv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p)
enough. */
int
-riscv_address_insns (rtx x, enum machine_mode mode, bool might_split_p)
+riscv_address_insns (rtx x, machine_mode mode, bool might_split_p)
{
struct riscv_address_info addr;
int n = 1;
@@ -906,7 +850,7 @@ riscv_split_const_insns (rtx x)
int
riscv_load_store_insns (rtx mem, rtx_insn *insn)
{
- enum machine_mode mode;
+ machine_mode mode;
bool might_split_p;
rtx set;
@@ -962,7 +906,7 @@ riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y)
of mode MODE. Return that new register. */
static rtx
-riscv_force_binary (enum machine_mode mode, enum rtx_code code, rtx x, rtx y)
+riscv_force_binary (machine_mode mode, enum rtx_code code, rtx x, rtx y)
{
return riscv_emit_binary (code, gen_reg_rtx (mode), x, y);
}
@@ -1080,7 +1024,7 @@ static rtx riscv_tls_add_tp_le (rtx dest, rtx base, rtx sym)
is guaranteed to be a legitimate address for mode MODE. */
bool
-riscv_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *low_out)
+riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
{
enum riscv_symbol_type symbol_type;
@@ -1238,7 +1182,7 @@ riscv_legitimize_tls_address (rtx loc)
/* If X is not a valid address for mode MODE, force it into a register. */
static rtx
-riscv_force_address (rtx x, enum machine_mode mode)
+riscv_force_address (rtx x, machine_mode mode)
{
if (!riscv_legitimate_address_p (mode, x, false))
x = force_reg (Pmode, x);
@@ -1252,7 +1196,7 @@ riscv_force_address (rtx x, enum machine_mode mode)
static rtx
riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ machine_mode mode)
{
rtx addr;
@@ -1285,7 +1229,7 @@ void
riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
{
struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
- enum machine_mode mode;
+ machine_mode mode;
int i, num_ops;
rtx x;
@@ -1319,7 +1263,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
move_operand. */
static void
-riscv_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
+riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
{
rtx base, offset;
@@ -1369,7 +1313,7 @@ riscv_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
sequence that is valid. */
bool
-riscv_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
+riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
{
if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
{
@@ -1675,7 +1619,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
/* Implement TARGET_ADDRESS_COST. */
static int
-riscv_address_cost (rtx addr, enum machine_mode mode,
+riscv_address_cost (rtx addr, machine_mode mode,
addr_space_t as ATTRIBUTE_UNUSED,
bool speed ATTRIBUTE_UNUSED)
{
@@ -1689,7 +1633,7 @@ rtx
riscv_subword (rtx op, bool high_p)
{
unsigned int byte = high_p ? UNITS_PER_WORD : 0;
- enum machine_mode mode = GET_MODE (op);
+ machine_mode mode = GET_MODE (op);
if (mode == VOIDmode)
mode = TARGET_64BIT ? TImode : DImode;
@@ -1754,7 +1698,7 @@ const char *
riscv_output_move (rtx dest, rtx src)
{
enum rtx_code dest_code, src_code;
- enum machine_mode mode;
+ machine_mode mode;
bool dbl_p;
dest_code = GET_CODE (dest);
@@ -1877,7 +1821,7 @@ riscv_int_order_operand_ok_p (enum rtx_code code, rtx cmp1)
static bool
riscv_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1,
- enum machine_mode mode)
+ machine_mode mode)
{
HOST_WIDE_INT plus_one;
@@ -1922,7 +1866,7 @@ static void
riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
rtx target, rtx cmp0, rtx cmp1)
{
- enum machine_mode mode;
+ machine_mode mode;
/* First see if there is a RISCV instruction that can do this operation.
If not, try doing the same for the inverse operation. If that also
@@ -2176,7 +2120,7 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1)
to STACK_BOUNDARY bits if the type requires it. */
static unsigned int
-riscv_function_arg_boundary (enum machine_mode mode, const_tree type)
+riscv_function_arg_boundary (machine_mode mode, const_tree type)
{
unsigned int alignment;
@@ -2193,7 +2137,7 @@ riscv_function_arg_boundary (enum machine_mode mode, const_tree type)
floating-point registers, return the number of registers, else 0. */
static unsigned
-riscv_pass_mode_in_fpr_p (enum machine_mode mode)
+riscv_pass_mode_in_fpr_p (machine_mode mode)
{
if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG)
{
@@ -2376,8 +2320,8 @@ riscv_pass_aggregate_in_fpr_and_gpr_p (const_tree type,
has mode BLKmode. */
static rtx
-riscv_pass_fpr_single (enum machine_mode type_mode, unsigned regno,
- enum machine_mode value_mode)
+riscv_pass_fpr_single (machine_mode type_mode, unsigned regno,
+ machine_mode value_mode)
{
rtx x = gen_rtx_REG (value_mode, regno);
@@ -2395,9 +2339,9 @@ riscv_pass_fpr_single (enum machine_mode type_mode, unsigned regno,
second value. */
static rtx
-riscv_pass_fpr_pair (enum machine_mode mode, unsigned regno1,
- enum machine_mode mode1, HOST_WIDE_INT offset1,
- unsigned regno2, enum machine_mode mode2,
+riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
+ machine_mode mode1, HOST_WIDE_INT offset1,
+ unsigned regno2, machine_mode mode2,
HOST_WIDE_INT offset2)
{
return gen_rtx_PARALLEL
@@ -2420,7 +2364,7 @@ riscv_pass_fpr_pair (enum machine_mode mode, unsigned regno1,
static rtx
riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
- enum machine_mode mode, const_tree type, bool named,
+ machine_mode mode, const_tree type, bool named,
bool return_p)
{
unsigned num_bytes, num_words;
@@ -2516,7 +2460,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
/* Implement TARGET_FUNCTION_ARG. */
static rtx
-riscv_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+riscv_function_arg (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
@@ -2531,7 +2475,7 @@ riscv_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
/* Implement TARGET_FUNCTION_ARG_ADVANCE. */
static void
-riscv_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+riscv_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
@@ -2551,7 +2495,7 @@ riscv_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
static int
riscv_arg_partial_bytes (cumulative_args_t cum,
- enum machine_mode mode, tree type, bool named)
+ machine_mode mode, tree type, bool named)
{
struct riscv_arg_info arg;
@@ -2564,7 +2508,7 @@ riscv_arg_partial_bytes (cumulative_args_t cum,
VALTYPE is null and MODE is the mode of the return value. */
rtx
-riscv_function_value (const_tree type, const_tree func, enum machine_mode mode)
+riscv_function_value (const_tree type, const_tree func, machine_mode mode)
{
struct riscv_arg_info info;
CUMULATIVE_ARGS args;
@@ -2587,7 +2531,7 @@ riscv_function_value (const_tree type, const_tree func, enum machine_mode mode)
/* Implement TARGET_PASS_BY_REFERENCE. */
static bool
-riscv_pass_by_reference (cumulative_args_t cum_v, enum machine_mode mode,
+riscv_pass_by_reference (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named)
{
HOST_WIDE_INT size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
@@ -2626,7 +2570,7 @@ riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
/* Implement TARGET_SETUP_INCOMING_VARARGS. */
static void
-riscv_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
+riscv_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
tree type, int *pretend_size ATTRIBUTE_UNUSED,
int no_rtl)
{
@@ -2776,7 +2720,7 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
static void
riscv_print_operand (FILE *file, rtx op, int letter)
{
- enum machine_mode mode = GET_MODE (op);
+ machine_mode mode = GET_MODE (op);
enum rtx_code code = GET_CODE (op);
switch (letter)
@@ -2892,7 +2836,7 @@ riscv_in_small_data_p (const_tree x)
/* Return a section for X, handling small data. */
static section *
-riscv_elf_select_rtx_section (enum machine_mode mode, rtx x,
+riscv_elf_select_rtx_section (machine_mode mode, rtx x,
unsigned HOST_WIDE_INT align)
{
section *s = default_elf_select_rtx_section (mode, x, align);
@@ -3163,7 +3107,7 @@ typedef void (*riscv_save_restore_fn) (rtx, rtx);
stack pointer. */
static void
-riscv_save_restore_reg (enum machine_mode mode, int regno,
+riscv_save_restore_reg (machine_mode mode, int regno,
HOST_WIDE_INT offset, riscv_save_restore_fn fn)
{
rtx mem;
@@ -3196,7 +3140,7 @@ riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn)
for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
{
- enum machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
+ machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
riscv_save_restore_reg (mode, regno, offset, fn);
offset -= GET_MODE_SIZE (mode);
@@ -3567,7 +3511,7 @@ riscv_can_use_return_insn (void)
/* Implement TARGET_REGISTER_MOVE_COST. */
static int
-riscv_register_move_cost (enum machine_mode mode,
+riscv_register_move_cost (machine_mode mode,
reg_class_t from, reg_class_t to)
{
return SECONDARY_MEMORY_NEEDED (from, to, mode) ? 8 : 2;
@@ -3576,7 +3520,7 @@ riscv_register_move_cost (enum machine_mode mode,
/* Return true if register REGNO can store a value of mode MODE. */
bool
-riscv_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
+riscv_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
{
unsigned int nregs = riscv_hard_regno_nregs (regno, mode);
@@ -3615,7 +3559,7 @@ riscv_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
/* Implement HARD_REGNO_NREGS. */
unsigned int
-riscv_hard_regno_nregs (int regno, enum machine_mode mode)
+riscv_hard_regno_nregs (int regno, machine_mode mode)
{
if (FP_REG_P (regno))
return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
@@ -3627,7 +3571,7 @@ riscv_hard_regno_nregs (int regno, enum machine_mode mode)
/* Implement CLASS_MAX_NREGS. */
static unsigned char
-riscv_class_max_nregs (reg_class_t rclass, enum machine_mode mode)
+riscv_class_max_nregs (reg_class_t rclass, machine_mode mode)
{
if (reg_class_subset_p (FP_REGS, rclass))
return riscv_hard_regno_nregs (FP_REG_FIRST, mode);
@@ -3641,7 +3585,7 @@ riscv_class_max_nregs (reg_class_t rclass, enum machine_mode mode)
/* Implement TARGET_MEMORY_MOVE_COST. */
static int
-riscv_memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in)
+riscv_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
{
return (tune_info->memory_cost
+ memory_move_secondary_cost (mode, rclass, in));
diff --git a/gcc/config/riscv/rtems.h b/gcc/config/riscv/rtems.h
new file mode 100644
index 00000000000..221e2f69815
--- /dev/null
+++ b/gcc/config/riscv/rtems.h
@@ -0,0 +1,31 @@
+/* Definitions for RISC-V RTEMS systems with ELF format.
+ Copyright (C) 2017 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.
+
+ 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/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+ } while (0)
diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
index ed67a5d3134..25619841717 100644
--- a/gcc/config/rl78/rl78-protos.h
+++ b/gcc/config/rl78/rl78-protos.h
@@ -22,7 +22,7 @@ const char * rl78_addsi3_internal (rtx *, unsigned int);
void rl78_emit_eh_epilogue (rtx);
void rl78_expand_compare (rtx *);
void rl78_expand_movsi (rtx *);
-void rl78_split_movsi (rtx *, enum machine_mode);
+void rl78_split_movsi (rtx *, machine_mode);
int rl78_force_nonfar_2 (rtx *, rtx (*gen)(rtx,rtx));
int rl78_force_nonfar_3 (rtx *, rtx (*gen)(rtx,rtx,rtx));
void rl78_expand_eh_epilogue (rtx);
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 894ac2b95f6..460775cb995 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -539,7 +539,7 @@ rl78_expand_movsi (rtx *operands)
/* Generate code to move an SImode value. */
void
-rl78_split_movsi (rtx *operands, enum machine_mode omode)
+rl78_split_movsi (rtx *operands, machine_mode omode)
{
rtx op00, op02, op10, op12;
@@ -997,7 +997,7 @@ rl78_hl_b_c_addr_p (rtx op)
#undef TARGET_ADDR_SPACE_ADDRESS_MODE
#define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
-static enum machine_mode
+static machine_mode
rl78_addr_space_address_mode (addr_space_t addrspace)
{
switch (addrspace)
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index d542315b99d..4d34a97c9ae 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -142,6 +142,7 @@
#define vec_madd __builtin_vec_madd
#define vec_madds __builtin_vec_madds
#define vec_mtvscr __builtin_vec_mtvscr
+#define vec_reve __builtin_vec_vreve
#define vec_vmaxfp __builtin_vec_vmaxfp
#define vec_vmaxsw __builtin_vec_vmaxsw
#define vec_vmaxsh __builtin_vec_vmaxsh
@@ -181,8 +182,18 @@
#define vec_rlnm(a,b,c) (__builtin_vec_rlnm((a),((b)<<8)|(c)))
#define vec_rsqrt __builtin_vec_rsqrt
#define vec_rsqrte __builtin_vec_rsqrte
+#define vec_signed __builtin_vec_vsigned
+#define vec_signed2 __builtin_vec_vsigned2
+#define vec_signede __builtin_vec_vsignede
+#define vec_signedo __builtin_vec_vsignedo
+#define vec_unsigned __builtin_vec_vunsigned
+#define vec_unsigned2 __builtin_vec_vunsigned2
+#define vec_unsignede __builtin_vec_vunsignede
+#define vec_unsignedo __builtin_vec_vunsignedo
#define vec_vsubfp __builtin_vec_vsubfp
#define vec_subc __builtin_vec_subc
+#define vec_sube __builtin_vec_sube
+#define vec_subec __builtin_vec_subec
#define vec_vsubsws __builtin_vec_vsubsws
#define vec_vsubshs __builtin_vec_vsubshs
#define vec_vsubsbs __builtin_vec_vsubsbs
@@ -407,6 +418,8 @@
#ifdef __POWER9_VECTOR__
/* Vector additions added in ISA 3.0. */
+#define vec_pack_to_short_fp32 __builtin_vec_convert_4f32_8i16
+#define vec_parity_lsbb __builtin_vec_vparity_lsbb
#define vec_vctz __builtin_vec_vctz
#define vec_cnttz __builtin_vec_vctz
#define vec_vctzb __builtin_vec_vctzb
@@ -436,6 +449,9 @@
#define vec_insert_exp __builtin_vec_insert_exp
#define vec_test_data_class __builtin_vec_test_data_class
+#define vec_extract_fp_from_shorth __builtin_vec_vextract_fp_from_shorth
+#define vec_extract_fp_from_shortl __builtin_vec_vextract_fp_from_shortl
+
#define scalar_extract_exp __builtin_vec_scalar_extract_exp
#define scalar_extract_sig __builtin_vec_scalar_extract_sig
#define scalar_insert_exp __builtin_vec_scalar_insert_exp
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 0e3d96528b9..c14cb92f0f3 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -50,6 +50,7 @@
UNSPEC_VPACK_UNS_UNS_SAT
UNSPEC_VPACK_UNS_UNS_MOD
UNSPEC_VPACK_UNS_UNS_MOD_DIRECT
+ UNSPEC_VREVEV
UNSPEC_VSLV4SI
UNSPEC_VSLO
UNSPEC_VSR
@@ -78,6 +79,7 @@
UNSPEC_VUNPACK_LO_SIGN_DIRECT
UNSPEC_VUPKHPX
UNSPEC_VUPKLPX
+ UNSPEC_CONVERT_4F32_8I16
UNSPEC_DARN
UNSPEC_DARN_32
UNSPEC_DARN_RAW
@@ -1416,32 +1418,6 @@
DONE;
})
-(define_expand "vec_widen_umult_even_v4si"
- [(use (match_operand:V2DI 0 "register_operand" ""))
- (use (match_operand:V4SI 1 "register_operand" ""))
- (use (match_operand:V4SI 2 "register_operand" ""))]
- "TARGET_ALTIVEC"
-{
- if (VECTOR_ELT_ORDER_BIG)
- emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "vec_widen_smult_even_v4si"
- [(use (match_operand:V2DI 0 "register_operand" ""))
- (use (match_operand:V4SI 1 "register_operand" ""))
- (use (match_operand:V4SI 2 "register_operand" ""))]
- "TARGET_ALTIVEC"
-{
- if (VECTOR_ELT_ORDER_BIG)
- emit_insn (gen_altivec_vmulesw (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_altivec_vmulosw (operands[0], operands[1], operands[2]));
- DONE;
-})
-
(define_expand "vec_widen_umult_odd_v16qi"
[(use (match_operand:V8HI 0 "register_operand" ""))
(use (match_operand:V16QI 1 "register_operand" ""))
@@ -1494,34 +1470,6 @@
DONE;
})
-(define_expand "vec_widen_umult_odd_v4si"
- [(use (match_operand:V2DI 0 "register_operand" ""))
- (use (match_operand:V4SI 1 "register_operand" ""))
- (use (match_operand:V4SI 2 "register_operand" ""))]
- "TARGET_ALTIVEC"
-{
- if (VECTOR_ELT_ORDER_BIG)
- emit_insn (gen_altivec_vmulouw (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_altivec_vmuleuw (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "vec_widen_smult_odd_v4si"
- [(use (match_operand:V2DI 0 "register_operand" ""))
- (use (match_operand:V4SI 1 "register_operand" ""))
- (use (match_operand:V4SI 2 "register_operand" ""))]
- "TARGET_ALTIVEC"
-{
- if (VECTOR_ELT_ORDER_BIG)
- emit_insn (gen_altivec_vmulosw (operands[0], operands[1],
- operands[2]));
- else
- emit_insn (gen_altivec_vmulesw (operands[0], operands[1],
- operands[2]));
- DONE;
-})
-
(define_insn "altivec_vmuleub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
@@ -1596,37 +1544,37 @@
(define_insn "altivec_vmuleuw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
- (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VMULEUW))]
- "TARGET_ALTIVEC"
+ (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMULEUW))]
+ "TARGET_P8_VECTOR"
"vmuleuw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulouw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
- (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VMULOUW))]
- "TARGET_ALTIVEC"
+ (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMULOUW))]
+ "TARGET_P8_VECTOR"
"vmulouw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulesw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
- (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VMULESW))]
- "TARGET_ALTIVEC"
+ (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMULESW))]
+ "TARGET_P8_VECTOR"
"vmulesw %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmulosw"
[(set (match_operand:V2DI 0 "register_operand" "=v")
- (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")]
- UNSPEC_VMULOSW))]
- "TARGET_ALTIVEC"
+ (unspec:V2DI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMULOSW))]
+ "TARGET_P8_VECTOR"
"vmulosw %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -3169,6 +3117,23 @@
}
[(set_attr "type" "veccomplex")])
+;; Generate two vector F32 converted to packed vector I16 vector
+(define_expand "convert_4f32_8i16"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_CONVERT_4F32_8I16))]
+ "TARGET_P9_VECTOR"
+{
+ rtx rtx_tmp_hi = gen_reg_rtx (V4SImode);
+ rtx rtx_tmp_lo = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_altivec_vctuxs (rtx_tmp_hi, operands[1], const0_rtx));
+ emit_insn (gen_altivec_vctuxs (rtx_tmp_lo, operands[2], const0_rtx));
+ emit_insn (gen_altivec_vpkswss (operands[0], rtx_tmp_hi, rtx_tmp_lo));
+ DONE;
+})
+
;; Generate
;; xxlxor/vxor SCRATCH0,SCRATCH0,SCRATCH0
;; vsubu?m SCRATCH2,SCRATCH1,%1
@@ -3820,6 +3785,31 @@
DONE;
}")
+;; Vector reverse elements
+(define_expand "altivec_vreve<mode>2"
+ [(set (match_operand:VEC_A 0 "register_operand" "=v")
+ (unspec:VEC_A [(match_operand:VEC_A 1 "register_operand" "v")]
+ UNSPEC_VREVEV))]
+ "TARGET_ALTIVEC"
+{
+ int i, j, size, num_elements;
+ rtvec v = rtvec_alloc (16);
+ rtx mask = gen_reg_rtx (V16QImode);
+
+ size = GET_MODE_UNIT_SIZE (<MODE>mode);
+ num_elements = GET_MODE_NUNITS (<MODE>mode);
+
+ for (j = 0; j < num_elements; j++)
+ for (i = 0; i < size; i++)
+ RTVEC_ELT (v, i + j * size)
+ = GEN_INT (i + (num_elements - 1 - j) * size);
+
+ emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
+ emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
+ operands[1], mask));
+ DONE;
+})
+
;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL,
;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell.
(define_insn "altivec_lvlx"
diff --git a/gcc/config/rs6000/mmintrin.h b/gcc/config/rs6000/mmintrin.h
new file mode 100644
index 00000000000..00b9a1507b8
--- /dev/null
+++ b/gcc/config/rs6000/mmintrin.h
@@ -0,0 +1,1456 @@
+/* Copyright (C) 2002-2017 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.
+
+ 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/>. */
+
+/* Implemented from the specification included in the Intel C++ Compiler
+ User Guide and Reference, version 9.0. */
+
+#ifndef NO_WARN_X86_INTRINSICS
+/* This header is distributed to simplify porting x86_64 code that
+ makes explicit use of Intel intrinsics to powerpc64le.
+ It is the user's responsibility to determine if the results are
+ acceptable and make additional changes as necessary.
+ Note that much code that uses Intel intrinsics can be rewritten in
+ standard C or GNU C extensions, which are more portable and better
+ optimized across multiple targets.
+
+ In the specific case of X86 MMX (__m64) intrinsics, the PowerPC
+ target does not support a native __vector_size__ (8) type. Instead
+ we typedef __m64 to a 64-bit unsigned long long, which is natively
+ supported in 64-bit mode. This works well for the _si64 and some
+ _pi32 operations, but starts to generate long sequences for _pi16
+ and _pi8 operations. For those cases it better (faster and
+ smaller code) to transfer __m64 data to the PowerPC vector 128-bit
+ unit, perform the operation, and then transfer the result back to
+ the __m64 type. This implies that the direct register move
+ instructions, introduced with power8, are available for efficient
+ implementation of these transfers.
+
+ Most MMX intrinsic operations can be performed efficiently as
+ C language 64-bit scalar operation or optimized to use the newer
+ 128-bit SSE/Altivec operations. We recomend this for new
+ applications. */
+#warning "Please read comment above. Use -DNO_WARN_X86_INTRINSICS to disable this warning."
+#endif
+
+#ifndef _MMINTRIN_H_INCLUDED
+#define _MMINTRIN_H_INCLUDED
+
+#include <altivec.h>
+/* The Intel API is flexible enough that we must allow aliasing with other
+ vector types, and their scalar components. */
+typedef __attribute__ ((__aligned__ (8))) unsigned long long __m64;
+
+typedef __attribute__ ((__aligned__ (8)))
+union
+ {
+ __m64 as_m64;
+ char as_char[8];
+ signed char as_signed_char [8];
+ short as_short[4];
+ int as_int[2];
+ long long as_long_long;
+ float as_float[2];
+ double as_double;
+ } __m64_union;
+
+/* Empty the multimedia state. */
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_empty (void)
+{
+ /* nothing to do on PowerPC. */
+}
+
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_empty (void)
+{
+ /* nothing to do on PowerPC. */
+}
+
+/* Convert I to a __m64 object. The integer is zero-extended to 64-bits. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi32_si64 (int __i)
+{
+ return (__m64) (unsigned int) __i;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_from_int (int __i)
+{
+ return _mm_cvtsi32_si64 (__i);
+}
+
+/* Convert the lower 32 bits of the __m64 object into an integer. */
+extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi64_si32 (__m64 __i)
+{
+ return ((int) __i);
+}
+
+extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_to_int (__m64 __i)
+{
+ return _mm_cvtsi64_si32 (__i);
+}
+
+#ifdef __powerpc64__
+/* Convert I to a __m64 object. */
+
+/* Intel intrinsic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_from_int64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi64_m64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+/* Microsoft intrinsic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi64x_si64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_pi64x (long long __i)
+{
+ return (__m64) __i;
+}
+
+/* Convert the __m64 object to a 64bit integer. */
+
+/* Intel intrinsic. */
+extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_to_int64 (__m64 __i)
+{
+ return (long long)__i;
+}
+
+extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtm64_si64 (__m64 __i)
+{
+ return (long long) __i;
+}
+
+/* Microsoft intrinsic. */
+extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtsi64_si64x (__m64 __i)
+{
+ return (long long) __i;
+}
+
+#ifdef _ARCH_PWR8
+/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
+ the result, and the four 16-bit values from M2 into the upper four 8-bit
+ values of the result, all with signed saturation. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_packs_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short vm1;
+ __vector signed char vresult;
+
+ vm1 = (__vector signed short)__builtin_pack_vector_int128 (__m2, __m1);
+ vresult = vec_vpkshss (vm1, vm1);
+ return (__m64) __builtin_unpack_vector_int128 ((__vector __int128)vresult, 0);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_packsswb (__m64 __m1, __m64 __m2)
+{
+ return _mm_packs_pi16 (__m1, __m2);
+}
+
+/* Pack the two 32-bit values from M1 in to the lower two 16-bit values of
+ the result, and the two 32-bit values from M2 into the upper two 16-bit
+ values of the result, all with signed saturation. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_packs_pi32 (__m64 __m1, __m64 __m2)
+{
+ __vector signed int vm1;
+ __vector signed short vresult;
+
+ vm1 = (__vector signed int)__builtin_pack_vector_int128 (__m2, __m1);
+ vresult = vec_vpkswss (vm1, vm1);
+ return ((__m64) __builtin_unpack_vector_int128 ((__vector __int128)vresult, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_packssdw (__m64 __m1, __m64 __m2)
+{
+ return _mm_packs_pi32 (__m1, __m2);
+}
+
+/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
+ the result, and the four 16-bit values from M2 into the upper four 8-bit
+ values of the result, all with unsigned saturation. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_packs_pu16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short vm1;
+ __vector unsigned char vresult;
+
+ vm1 = (__vector signed short)__builtin_pack_vector_int128 (__m2, __m1);
+ vresult = vec_vpkshus (vm1, vm1);
+ return ((__m64) __builtin_unpack_vector_int128 ((__vector __int128)vresult, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_packuswb (__m64 __m1, __m64 __m2)
+{
+ return _mm_packs_pu16 (__m1, __m2);
+}
+#endif /* end ARCH_PWR8 */
+
+/* Interleave the four 8-bit values from the high half of M1 with the four
+ 8-bit values from the high half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector unsigned char a, b, c;
+
+ a = (__vector unsigned char)vec_splats (__m1);
+ b = (__vector unsigned char)vec_splats (__m2);
+ c = vec_mergel (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = m1.as_char[4];
+ res.as_char[1] = m2.as_char[4];
+ res.as_char[2] = m1.as_char[5];
+ res.as_char[3] = m2.as_char[5];
+ res.as_char[4] = m1.as_char[6];
+ res.as_char[5] = m2.as_char[6];
+ res.as_char[6] = m1.as_char[7];
+ res.as_char[7] = m2.as_char[7];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpckhbw (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpackhi_pi8 (__m1, __m2);
+}
+
+/* Interleave the two 16-bit values from the high half of M1 with the two
+ 16-bit values from the high half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2)
+{
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = m1.as_short[2];
+ res.as_short[1] = m2.as_short[2];
+ res.as_short[2] = m1.as_short[3];
+ res.as_short[3] = m2.as_short[3];
+
+ return (__m64) res.as_m64;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpckhwd (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpackhi_pi16 (__m1, __m2);
+}
+/* Interleave the 32-bit value from the high half of M1 with the 32-bit
+ value from the high half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpackhi_pi32 (__m64 __m1, __m64 __m2)
+{
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = m1.as_int[1];
+ res.as_int[1] = m2.as_int[1];
+
+ return (__m64) res.as_m64;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpckhdq (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpackhi_pi32 (__m1, __m2);
+}
+/* Interleave the four 8-bit values from the low half of M1 with the four
+ 8-bit values from the low half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector unsigned char a, b, c;
+
+ a = (__vector unsigned char)vec_splats (__m1);
+ b = (__vector unsigned char)vec_splats (__m2);
+ c = vec_mergel (a, b);
+ return (__builtin_unpack_vector_int128 ((vector __int128_t)c, 1));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = m1.as_char[0];
+ res.as_char[1] = m2.as_char[0];
+ res.as_char[2] = m1.as_char[1];
+ res.as_char[3] = m2.as_char[1];
+ res.as_char[4] = m1.as_char[2];
+ res.as_char[5] = m2.as_char[2];
+ res.as_char[6] = m1.as_char[3];
+ res.as_char[7] = m2.as_char[3];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpcklbw (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpacklo_pi8 (__m1, __m2);
+}
+/* Interleave the two 16-bit values from the low half of M1 with the two
+ 16-bit values from the low half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2)
+{
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = m1.as_short[0];
+ res.as_short[1] = m2.as_short[0];
+ res.as_short[2] = m1.as_short[1];
+ res.as_short[3] = m2.as_short[1];
+
+ return (__m64) res.as_m64;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpcklwd (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpacklo_pi16 (__m1, __m2);
+}
+
+/* Interleave the 32-bit value from the low half of M1 with the 32-bit
+ value from the low half of M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_unpacklo_pi32 (__m64 __m1, __m64 __m2)
+{
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = m1.as_int[0];
+ res.as_int[1] = m2.as_int[0];
+
+ return (__m64) res.as_m64;
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_punpckldq (__m64 __m1, __m64 __m2)
+{
+ return _mm_unpacklo_pi32 (__m1, __m2);
+}
+
+/* Add the 8-bit values in M1 to the 8-bit values in M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_pi8 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed char a, b, c;
+
+ a = (__vector signed char)vec_splats (__m1);
+ b = (__vector signed char)vec_splats (__m2);
+ c = vec_add (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = m1.as_char[0] + m2.as_char[0];
+ res.as_char[1] = m1.as_char[1] + m2.as_char[1];
+ res.as_char[2] = m1.as_char[2] + m2.as_char[2];
+ res.as_char[3] = m1.as_char[3] + m2.as_char[3];
+ res.as_char[4] = m1.as_char[4] + m2.as_char[4];
+ res.as_char[5] = m1.as_char[5] + m2.as_char[5];
+ res.as_char[6] = m1.as_char[6] + m2.as_char[6];
+ res.as_char[7] = m1.as_char[7] + m2.as_char[7];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddb (__m64 __m1, __m64 __m2)
+{
+ return _mm_add_pi8 (__m1, __m2);
+}
+
+/* Add the 16-bit values in M1 to the 16-bit values in M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_pi16 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = vec_add (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = m1.as_short[0] + m2.as_short[0];
+ res.as_short[1] = m1.as_short[1] + m2.as_short[1];
+ res.as_short[2] = m1.as_short[2] + m2.as_short[2];
+ res.as_short[3] = m1.as_short[3] + m2.as_short[3];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddw (__m64 __m1, __m64 __m2)
+{
+ return _mm_add_pi16 (__m1, __m2);
+}
+
+/* Add the 32-bit values in M1 to the 32-bit values in M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_pi32 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR9
+ __vector signed int a, b, c;
+
+ a = (__vector signed int)vec_splats (__m1, __m1);
+ b = (__vector signed int)vec_splats (__m2, __m2);
+ c = vec_add (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = m1.as_int[0] + m2.as_int[0];
+ res.as_int[1] = m1.as_int[1] + m2.as_int[1];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddd (__m64 __m1, __m64 __m2)
+{
+ return _mm_add_pi32 (__m1, __m2);
+}
+
+/* Subtract the 8-bit values in M2 from the 8-bit values in M1. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_pi8 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed char a, b, c;
+
+ a = (__vector signed char)vec_splats (__m1);
+ b = (__vector signed char)vec_splats (__m2);
+ c = vec_sub (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = m1.as_char[0] - m2.as_char[0];
+ res.as_char[1] = m1.as_char[1] - m2.as_char[1];
+ res.as_char[2] = m1.as_char[2] - m2.as_char[2];
+ res.as_char[3] = m1.as_char[3] - m2.as_char[3];
+ res.as_char[4] = m1.as_char[4] - m2.as_char[4];
+ res.as_char[5] = m1.as_char[5] - m2.as_char[5];
+ res.as_char[6] = m1.as_char[6] - m2.as_char[6];
+ res.as_char[7] = m1.as_char[7] - m2.as_char[7];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubb (__m64 __m1, __m64 __m2)
+{
+ return _mm_sub_pi8 (__m1, __m2);
+}
+
+/* Subtract the 16-bit values in M2 from the 16-bit values in M1. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_pi16 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = vec_sub (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = m1.as_short[0] - m2.as_short[0];
+ res.as_short[1] = m1.as_short[1] - m2.as_short[1];
+ res.as_short[2] = m1.as_short[2] - m2.as_short[2];
+ res.as_short[3] = m1.as_short[3] - m2.as_short[3];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubw (__m64 __m1, __m64 __m2)
+{
+ return _mm_sub_pi16 (__m1, __m2);
+}
+
+/* Subtract the 32-bit values in M2 from the 32-bit values in M1. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_pi32 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR9
+ __vector signed int a, b, c;
+
+ a = (__vector signed int)vec_splats (__m1);
+ b = (__vector signed int)vec_splats (__m2);
+ c = vec_sub (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = m1.as_int[0] - m2.as_int[0];
+ res.as_int[1] = m1.as_int[1] - m2.as_int[1];
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubd (__m64 __m1, __m64 __m2)
+{
+ return _mm_add_pi32 (__m1, __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_add_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m1 + __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sub_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m1 - __m2);
+}
+
+/* Shift the 64-bit value in M left by COUNT. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sll_si64 (__m64 __m, __m64 __count)
+{
+ return (__m << __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psllq (__m64 __m, __m64 __count)
+{
+ return _mm_sll_si64 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_slli_si64 (__m64 __m, const int __count)
+{
+ return (__m << __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psllqi (__m64 __m, const int __count)
+{
+ return _mm_slli_si64 (__m, __count);
+}
+
+/* Shift the 64-bit value in M left by COUNT; shift in zeros. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srl_si64 (__m64 __m, __m64 __count)
+{
+ return (__m >> __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrlq (__m64 __m, __m64 __count)
+{
+ return _mm_srl_si64 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srli_si64 (__m64 __m, const int __count)
+{
+ return (__m >> __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrlqi (__m64 __m, const int __count)
+{
+ return _mm_srli_si64 (__m, __count);
+}
+
+/* Bit-wise AND the 64-bit values in M1 and M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_and_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m1 & __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pand (__m64 __m1, __m64 __m2)
+{
+ return _mm_and_si64 (__m1, __m2);
+}
+
+/* Bit-wise complement the 64-bit value in M1 and bit-wise AND it with the
+ 64-bit value in M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_andnot_si64 (__m64 __m1, __m64 __m2)
+{
+ return (~__m1 & __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pandn (__m64 __m1, __m64 __m2)
+{
+ return _mm_andnot_si64 (__m1, __m2);
+}
+
+/* Bit-wise inclusive OR the 64-bit values in M1 and M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_or_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m1 | __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_por (__m64 __m1, __m64 __m2)
+{
+ return _mm_or_si64 (__m1, __m2);
+}
+
+/* Bit-wise exclusive OR the 64-bit values in M1 and M2. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_xor_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m1 ^ __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pxor (__m64 __m1, __m64 __m2)
+{
+ return _mm_xor_si64 (__m1, __m2);
+}
+
+/* Creates a 64-bit zero. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setzero_si64 (void)
+{
+ return (__m64) 0;
+}
+
+/* Compare eight 8-bit values. The result of the comparison is 0xFF if the
+ test is true and zero if false. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpeq_pi8 (__m64 __m1, __m64 __m2)
+{
+#ifdef _ARCH_PWR6
+ __m64 res;
+ __asm__(
+ "cmpb %0,%1,%2;\n"
+ : "=r" (res)
+ : "r" (__m1),
+ "r" (__m2)
+ : );
+ return (res);
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = (m1.as_char[0] == m2.as_char[0])? -1: 0;
+ res.as_char[1] = (m1.as_char[1] == m2.as_char[1])? -1: 0;
+ res.as_char[2] = (m1.as_char[2] == m2.as_char[2])? -1: 0;
+ res.as_char[3] = (m1.as_char[3] == m2.as_char[3])? -1: 0;
+ res.as_char[4] = (m1.as_char[4] == m2.as_char[4])? -1: 0;
+ res.as_char[5] = (m1.as_char[5] == m2.as_char[5])? -1: 0;
+ res.as_char[6] = (m1.as_char[6] == m2.as_char[6])? -1: 0;
+ res.as_char[7] = (m1.as_char[7] == m2.as_char[7])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpeqb (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpeq_pi8 (__m1, __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpgt_pi8 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed char a, b, c;
+
+ a = (__vector signed char)vec_splats (__m1);
+ b = (__vector signed char)vec_splats (__m2);
+ c = (__vector signed char)vec_cmpgt (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_char[0] = (m1.as_char[0] > m2.as_char[0])? -1: 0;
+ res.as_char[1] = (m1.as_char[1] > m2.as_char[1])? -1: 0;
+ res.as_char[2] = (m1.as_char[2] > m2.as_char[2])? -1: 0;
+ res.as_char[3] = (m1.as_char[3] > m2.as_char[3])? -1: 0;
+ res.as_char[4] = (m1.as_char[4] > m2.as_char[4])? -1: 0;
+ res.as_char[5] = (m1.as_char[5] > m2.as_char[5])? -1: 0;
+ res.as_char[6] = (m1.as_char[6] > m2.as_char[6])? -1: 0;
+ res.as_char[7] = (m1.as_char[7] > m2.as_char[7])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpgtb (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpgt_pi8 (__m1, __m2);
+}
+
+/* Compare four 16-bit values. The result of the comparison is 0xFFFF if
+ the test is true and zero if false. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpeq_pi16 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = (__vector signed short)vec_cmpeq (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = (m1.as_short[0] == m2.as_short[0])? -1: 0;
+ res.as_short[1] = (m1.as_short[1] == m2.as_short[1])? -1: 0;
+ res.as_short[2] = (m1.as_short[2] == m2.as_short[2])? -1: 0;
+ res.as_short[3] = (m1.as_short[3] == m2.as_short[3])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpeqw (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpeq_pi16 (__m1, __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpgt_pi16 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR8
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = (__vector signed short)vec_cmpgt (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_short[0] = (m1.as_short[0] > m2.as_short[0])? -1: 0;
+ res.as_short[1] = (m1.as_short[1] > m2.as_short[1])? -1: 0;
+ res.as_short[2] = (m1.as_short[2] > m2.as_short[2])? -1: 0;
+ res.as_short[3] = (m1.as_short[3] > m2.as_short[3])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpgtw (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpgt_pi16 (__m1, __m2);
+}
+
+/* Compare two 32-bit values. The result of the comparison is 0xFFFFFFFF if
+ the test is true and zero if false. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR9
+ __vector signed int a, b, c;
+
+ a = (__vector signed int)vec_splats (__m1);
+ b = (__vector signed int)vec_splats (__m2);
+ c = (__vector signed short)vec_cmpeq (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = (m1.as_int[0] == m2.as_int[0])? -1: 0;
+ res.as_int[1] = (m1.as_int[1] == m2.as_int[1])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpeqd (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpeq_pi32 (__m1, __m2);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cmpgt_pi32 (__m64 __m1, __m64 __m2)
+{
+#if _ARCH_PWR9
+ __vector signed int a, b, c;
+
+ a = (__vector signed int)vec_splats (__m1);
+ b = (__vector signed int)vec_splats (__m2);
+ c = (__vector signed short)vec_cmpgt (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+#else
+ __m64_union m1, m2, res;
+
+ m1.as_m64 = __m1;
+ m2.as_m64 = __m2;
+
+ res.as_int[0] = (m1.as_int[0] > m2.as_int[0])? -1: 0;
+ res.as_int[1] = (m1.as_int[1] > m2.as_int[1])? -1: 0;
+
+ return (__m64) res.as_m64;
+#endif
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pcmpgtd (__m64 __m1, __m64 __m2)
+{
+ return _mm_cmpgt_pi32 (__m1, __m2);
+}
+
+#if _ARCH_PWR8
+/* Add the 8-bit values in M1 to the 8-bit values in M2 using signed
+ saturated arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_adds_pi8 (__m64 __m1, __m64 __m2)
+{
+ __vector signed char a, b, c;
+
+ a = (__vector signed char)vec_splats (__m1);
+ b = (__vector signed char)vec_splats (__m2);
+ c = vec_adds (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddsb (__m64 __m1, __m64 __m2)
+{
+ return _mm_adds_pi8 (__m1, __m2);
+}
+/* Add the 16-bit values in M1 to the 16-bit values in M2 using signed
+ saturated arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_adds_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = vec_adds (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddsw (__m64 __m1, __m64 __m2)
+{
+ return _mm_adds_pi16 (__m1, __m2);
+}
+/* Add the 8-bit values in M1 to the 8-bit values in M2 using unsigned
+ saturated arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_adds_pu8 (__m64 __m1, __m64 __m2)
+{
+ __vector unsigned char a, b, c;
+
+ a = (__vector unsigned char)vec_splats (__m1);
+ b = (__vector unsigned char)vec_splats (__m2);
+ c = vec_adds (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddusb (__m64 __m1, __m64 __m2)
+{
+ return _mm_adds_pu8 (__m1, __m2);
+}
+
+/* Add the 16-bit values in M1 to the 16-bit values in M2 using unsigned
+ saturated arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_adds_pu16 (__m64 __m1, __m64 __m2)
+{
+ __vector unsigned short a, b, c;
+
+ a = (__vector unsigned short)vec_splats (__m1);
+ b = (__vector unsigned short)vec_splats (__m2);
+ c = vec_adds (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_paddusw (__m64 __m1, __m64 __m2)
+{
+ return _mm_adds_pu16 (__m1, __m2);
+}
+
+/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using signed
+ saturating arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_subs_pi8 (__m64 __m1, __m64 __m2)
+{
+ __vector signed char a, b, c;
+
+ a = (__vector signed char)vec_splats (__m1);
+ b = (__vector signed char)vec_splats (__m2);
+ c = vec_subs (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubsb (__m64 __m1, __m64 __m2)
+{
+ return _mm_subs_pi8 (__m1, __m2);
+}
+
+/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
+ signed saturating arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_subs_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = vec_subs (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubsw (__m64 __m1, __m64 __m2)
+{
+ return _mm_subs_pi16 (__m1, __m2);
+}
+
+/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using
+ unsigned saturating arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_subs_pu8 (__m64 __m1, __m64 __m2)
+{
+ __vector unsigned char a, b, c;
+
+ a = (__vector unsigned char)vec_splats (__m1);
+ b = (__vector unsigned char)vec_splats (__m2);
+ c = vec_subs (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubusb (__m64 __m1, __m64 __m2)
+{
+ return _mm_subs_pu8 (__m1, __m2);
+}
+
+/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
+ unsigned saturating arithmetic. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_subs_pu16 (__m64 __m1, __m64 __m2)
+{
+ __vector unsigned short a, b, c;
+
+ a = (__vector unsigned short)vec_splats (__m1);
+ b = (__vector unsigned short)vec_splats (__m2);
+ c = vec_subs (a, b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psubusw (__m64 __m1, __m64 __m2)
+{
+ return _mm_subs_pu16 (__m1, __m2);
+}
+
+/* Multiply four 16-bit values in M1 by four 16-bit values in M2 producing
+ four 32-bit intermediate results, which are then summed by pairs to
+ produce two 32-bit results. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_madd_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short a, b;
+ __vector signed int c;
+ __vector signed int zero = {0, 0, 0, 0};
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = vec_vmsumshm (a, b, zero);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pmaddwd (__m64 __m1, __m64 __m2)
+{
+ return _mm_madd_pi16 (__m1, __m2);
+}
+/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in
+ M2 and produce the high 16 bits of the 32-bit results. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mulhi_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short a, b;
+ __vector signed short c;
+ __vector signed int w0, w1;
+ __vector unsigned char xform1 = {
+ 0x02, 0x03, 0x12, 0x13, 0x06, 0x07, 0x16, 0x17,
+ 0x0A, 0x0B, 0x1A, 0x1B, 0x0E, 0x0F, 0x1E, 0x1F
+ };
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+
+ w0 = vec_vmulesh (a, b);
+ w1 = vec_vmulosh (a, b);
+ c = (__vector signed short)vec_perm (w0, w1, xform1);
+
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pmulhw (__m64 __m1, __m64 __m2)
+{
+ return _mm_mulhi_pi16 (__m1, __m2);
+}
+
+/* Multiply four 16-bit values in M1 by four 16-bit values in M2 and produce
+ the low 16 bits of the results. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mullo_pi16 (__m64 __m1, __m64 __m2)
+{
+ __vector signed short a, b, c;
+
+ a = (__vector signed short)vec_splats (__m1);
+ b = (__vector signed short)vec_splats (__m2);
+ c = a * b;
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)c, 0));
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pmullw (__m64 __m1, __m64 __m2)
+{
+ return _mm_mullo_pi16 (__m1, __m2);
+}
+
+/* Shift four 16-bit values in M left by COUNT. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sll_pi16 (__m64 __m, __m64 __count)
+{
+ __vector signed short m, r;
+ __vector unsigned short c;
+
+ if (__count <= 15)
+ {
+ m = (__vector signed short)vec_splats (__m);
+ c = (__vector unsigned short)vec_splats ((unsigned short)__count);
+ r = vec_sl (m, (__vector unsigned short)c);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)r, 0));
+ }
+ else
+ return (0);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psllw (__m64 __m, __m64 __count)
+{
+ return _mm_sll_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_slli_pi16 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_sll_pi16. */
+ return _mm_sll_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psllwi (__m64 __m, int __count)
+{
+ return _mm_slli_pi16 (__m, __count);
+}
+
+/* Shift two 32-bit values in M left by COUNT. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sll_pi32 (__m64 __m, __m64 __count)
+{
+ __m64_union m, res;
+
+ m.as_m64 = __m;
+
+ res.as_int[0] = m.as_int[0] << __count;
+ res.as_int[1] = m.as_int[1] << __count;
+ return (res.as_m64);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pslld (__m64 __m, __m64 __count)
+{
+ return _mm_sll_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_slli_pi32 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_sll_pi32. */
+ return _mm_sll_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_pslldi (__m64 __m, int __count)
+{
+ return _mm_slli_pi32 (__m, __count);
+}
+
+/* Shift four 16-bit values in M right by COUNT; shift in the sign bit. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sra_pi16 (__m64 __m, __m64 __count)
+{
+ __vector signed short m, r;
+ __vector unsigned short c;
+
+ if (__count <= 15)
+ {
+ m = (__vector signed short)vec_splats (__m);
+ c = (__vector unsigned short)vec_splats ((unsigned short)__count);
+ r = vec_sra (m, (__vector unsigned short)c);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)r, 0));
+ }
+ else
+ return (0);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psraw (__m64 __m, __m64 __count)
+{
+ return _mm_sra_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srai_pi16 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_sra_pi32. */
+ return _mm_sra_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrawi (__m64 __m, int __count)
+{
+ return _mm_srai_pi16 (__m, __count);
+}
+
+/* Shift two 32-bit values in M right by COUNT; shift in the sign bit. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_sra_pi32 (__m64 __m, __m64 __count)
+{
+ __m64_union m, res;
+
+ m.as_m64 = __m;
+
+ res.as_int[0] = m.as_int[0] >> __count;
+ res.as_int[1] = m.as_int[1] >> __count;
+ return (res.as_m64);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrad (__m64 __m, __m64 __count)
+{
+ return _mm_sra_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srai_pi32 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_sra_pi32. */
+ return _mm_sra_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psradi (__m64 __m, int __count)
+{
+ return _mm_srai_pi32 (__m, __count);
+}
+
+/* Shift four 16-bit values in M right by COUNT; shift in zeros. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srl_pi16 (__m64 __m, __m64 __count)
+{
+ __vector unsigned short m, r;
+ __vector unsigned short c;
+
+ if (__count <= 15)
+ {
+ m = (__vector unsigned short)vec_splats (__m);
+ c = (__vector unsigned short)vec_splats ((unsigned short)__count);
+ r = vec_sr (m, (__vector unsigned short)c);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)r, 0));
+ }
+ else
+ return (0);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrlw (__m64 __m, __m64 __count)
+{
+ return _mm_srl_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srli_pi16 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_sra_pi32. */
+ return _mm_srl_pi16 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrlwi (__m64 __m, int __count)
+{
+ return _mm_srli_pi16 (__m, __count);
+}
+
+/* Shift two 32-bit values in M right by COUNT; shift in zeros. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srl_pi32 (__m64 __m, __m64 __count)
+{
+ __m64_union m, res;
+
+ m.as_m64 = __m;
+
+ res.as_int[0] = (unsigned int)m.as_int[0] >> __count;
+ res.as_int[1] = (unsigned int)m.as_int[1] >> __count;
+ return (res.as_m64);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrld (__m64 __m, __m64 __count)
+{
+ return _mm_srl_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_srli_pi32 (__m64 __m, int __count)
+{
+ /* Promote int to long then invoke mm_srl_pi32. */
+ return _mm_srl_pi32 (__m, __count);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_psrldi (__m64 __m, int __count)
+{
+ return _mm_srli_pi32 (__m, __count);
+}
+#endif /* _ARCH_PWR8 */
+
+/* Creates a vector of two 32-bit values; I0 is least significant. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_pi32 (int __i1, int __i0)
+{
+ __m64_union res;
+
+ res.as_int[0] = __i0;
+ res.as_int[1] = __i1;
+ return (res.as_m64);
+}
+
+/* Creates a vector of four 16-bit values; W0 is least significant. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_pi16 (short __w3, short __w2, short __w1, short __w0)
+{
+ __m64_union res;
+
+ res.as_short[0] = __w0;
+ res.as_short[1] = __w1;
+ res.as_short[2] = __w2;
+ res.as_short[3] = __w3;
+ return (res.as_m64);
+}
+
+/* Creates a vector of eight 8-bit values; B0 is least significant. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set_pi8 (char __b7, char __b6, char __b5, char __b4,
+ char __b3, char __b2, char __b1, char __b0)
+{
+ __m64_union res;
+
+ res.as_char[0] = __b0;
+ res.as_char[1] = __b1;
+ res.as_char[2] = __b2;
+ res.as_char[3] = __b3;
+ res.as_char[4] = __b4;
+ res.as_char[5] = __b5;
+ res.as_char[6] = __b6;
+ res.as_char[7] = __b7;
+ return (res.as_m64);
+}
+
+/* Similar, but with the arguments in reverse order. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setr_pi32 (int __i0, int __i1)
+{
+ __m64_union res;
+
+ res.as_int[0] = __i0;
+ res.as_int[1] = __i1;
+ return (res.as_m64);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setr_pi16 (short __w0, short __w1, short __w2, short __w3)
+{
+ return _mm_set_pi16 (__w3, __w2, __w1, __w0);
+}
+
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_setr_pi8 (char __b0, char __b1, char __b2, char __b3,
+ char __b4, char __b5, char __b6, char __b7)
+{
+ return _mm_set_pi8 (__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0);
+}
+
+/* Creates a vector of two 32-bit values, both elements containing I. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set1_pi32 (int __i)
+{
+ __m64_union res;
+
+ res.as_int[0] = __i;
+ res.as_int[1] = __i;
+ return (res.as_m64);
+}
+
+/* Creates a vector of four 16-bit values, all elements containing W. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set1_pi16 (short __w)
+{
+#if _ARCH_PWR9
+ __vector signed short w;
+
+ w = (__vector signed short)vec_splats (__w);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)w, 0));
+#else
+ __m64_union res;
+
+ res.as_short[0] = __w;
+ res.as_short[1] = __w;
+ res.as_short[2] = __w;
+ res.as_short[3] = __w;
+ return (res.as_m64);
+#endif
+}
+
+/* Creates a vector of eight 8-bit values, all elements containing B. */
+extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_set1_pi8 (signed char __b)
+{
+#if _ARCH_PWR8
+ __vector signed char b;
+
+ b = (__vector signed char)vec_splats (__b);
+ return (__builtin_unpack_vector_int128 ((__vector __int128_t)b, 0));
+#else
+ __m64_union res;
+
+ res.as_char[0] = __b;
+ res.as_char[1] = __b;
+ res.as_char[2] = __b;
+ res.as_char[3] = __b;
+ res.as_char[4] = __b;
+ res.as_char[5] = __b;
+ res.as_char[6] = __b;
+ res.as_char[7] = __b;
+ return (res.as_m64);
+#endif
+}
+#endif /* __powerpc64__ */
+#endif /* _MMINTRIN_H_INCLUDED */
diff --git a/gcc/config/rs6000/ppc-auxv.h b/gcc/config/rs6000/ppc-auxv.h
index c7e2e0bfbf2..dcee28a8152 100644
--- a/gcc/config/rs6000/ppc-auxv.h
+++ b/gcc/config/rs6000/ppc-auxv.h
@@ -89,6 +89,8 @@
#define PPC_FEATURE2_HTM_NOSC 0x01000000
#define PPC_FEATURE2_ARCH_3_00 0x00800000
#define PPC_FEATURE2_HAS_IEEE128 0x00400000
+#define PPC_FEATURE2_DARN 0x00200000
+#define PPC_FEATURE2_SCV 0x00100000
/* Thread Control Block (TCB) offsets of the AT_PLATFORM, AT_HWCAP and
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index aa1c01b93dd..466f9131aa0 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -783,10 +783,8 @@
(and (and (match_code "mem")
(match_test "MEM_VOLATILE_P (op)"))
(if_then_else (match_test "reload_completed")
- (match_operand 0 "memory_operand")
- (if_then_else (match_test "reload_in_progress")
- (match_test "strict_memory_address_p (mode, XEXP (op, 0))")
- (match_test "memory_address_p (mode, XEXP (op, 0))")))))
+ (match_operand 0 "memory_operand")
+ (match_test "memory_address_p (mode, XEXP (op, 0))"))))
;; Return 1 if the operand is an offsettable memory operand.
(define_predicate "offsettable_mem_operand"
@@ -1142,7 +1140,7 @@
if (! volatile_ok && MEM_VOLATILE_P (op))
return 0;
- if (reload_in_progress || lra_in_progress || reload_completed)
+ if (lra_in_progress || reload_completed)
return indexed_or_indirect_address (addr, vmode);
else
return memory_address_addr_space_p (vmode, addr, MEM_ADDR_SPACE (op));
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 963b9a892fa..a043e70f93b 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1031,14 +1031,14 @@ BU_ALTIVEC_2 (VMULEUB, "vmuleub", CONST, vec_widen_umult_even_v16qi)
BU_ALTIVEC_2 (VMULESB, "vmulesb", CONST, vec_widen_smult_even_v16qi)
BU_ALTIVEC_2 (VMULEUH, "vmuleuh", CONST, vec_widen_umult_even_v8hi)
BU_ALTIVEC_2 (VMULESH, "vmulesh", CONST, vec_widen_smult_even_v8hi)
-BU_ALTIVEC_2 (VMULEUW, "vmuleuw", CONST, vec_widen_umult_even_v4si)
-BU_ALTIVEC_2 (VMULESW, "vmulesw", CONST, vec_widen_smult_even_v4si)
+BU_ALTIVEC_2 (VMULEUW, "vmuleuw", CONST, altivec_vmuleuw)
+BU_ALTIVEC_2 (VMULESW, "vmulesw", CONST, altivec_vmulesw)
BU_ALTIVEC_2 (VMULOUB, "vmuloub", CONST, vec_widen_umult_odd_v16qi)
BU_ALTIVEC_2 (VMULOSB, "vmulosb", CONST, vec_widen_smult_odd_v16qi)
BU_ALTIVEC_2 (VMULOUH, "vmulouh", CONST, vec_widen_umult_odd_v8hi)
BU_ALTIVEC_2 (VMULOSH, "vmulosh", CONST, vec_widen_smult_odd_v8hi)
-BU_ALTIVEC_2 (VMULOUW, "vmulouw", CONST, vec_widen_umult_odd_v4si)
-BU_ALTIVEC_2 (VMULOSW, "vmulosw", CONST, vec_widen_smult_odd_v4si)
+BU_ALTIVEC_2 (VMULOUW, "vmulouw", CONST, altivec_vmulouw)
+BU_ALTIVEC_2 (VMULOSW, "vmulosw", CONST, altivec_vmulosw)
BU_ALTIVEC_2 (VNOR, "vnor", CONST, norv4si3)
BU_ALTIVEC_2 (VOR, "vor", CONST, iorv4si3)
BU_ALTIVEC_2 (VPKUHUM, "vpkuhum", CONST, altivec_vpkuhum)
@@ -1134,6 +1134,13 @@ BU_ALTIVEC_1 (VUPKLSB, "vupklsb", CONST, altivec_vupklsb)
BU_ALTIVEC_1 (VUPKLPX, "vupklpx", CONST, altivec_vupklpx)
BU_ALTIVEC_1 (VUPKLSH, "vupklsh", CONST, altivec_vupklsh)
+BU_ALTIVEC_1 (VREVE_V2DI, "vreve_v2di", CONST, altivec_vrevev2di2)
+BU_ALTIVEC_1 (VREVE_V4SI, "vreve_v4si", CONST, altivec_vrevev4si2)
+BU_ALTIVEC_1 (VREVE_V8HI, "vreve_v8hi", CONST, altivec_vrevev8hi2)
+BU_ALTIVEC_1 (VREVE_V16QI, "vreve_v16qi", CONST, altivec_vrevev16qi2)
+BU_ALTIVEC_1 (VREVE_V2DF, "vreve_v2df", CONST, altivec_vrevev2df2)
+BU_ALTIVEC_1 (VREVE_V4SF, "vreve_v4sf", CONST, altivec_vrevev4sf2)
+
BU_ALTIVEC_1 (FLOAT_V4SI_V4SF, "float_sisf", FP, floatv4siv4sf2)
BU_ALTIVEC_1 (UNSFLOAT_V4SI_V4SF, "uns_float_sisf", FP, floatunsv4siv4sf2)
BU_ALTIVEC_1 (FIX_V4SF_V4SI, "fix_sfsi", FP, fix_truncv4sfv4si2)
@@ -1422,6 +1429,8 @@ BU_ALTIVEC_OVERLOAD_1 (VUPKLPX, "vupklpx")
BU_ALTIVEC_OVERLOAD_1 (VUPKLSB, "vupklsb")
BU_ALTIVEC_OVERLOAD_1 (VUPKLSH, "vupklsh")
+BU_ALTIVEC_OVERLOAD_1 (VREVE, "vreve")
+
/* Overloaded altivec predicates. */
BU_ALTIVEC_OVERLOAD_P (VCMPEQ_P, "vcmpeq_p")
BU_ALTIVEC_OVERLOAD_P (VCMPGT_P, "vcmpgt_p")
@@ -1465,6 +1474,8 @@ BU_ALTIVEC_OVERLOAD_X (STVLX, "stvlx")
BU_ALTIVEC_OVERLOAD_X (STVLXL, "stvlxl")
BU_ALTIVEC_OVERLOAD_X (STVRX, "stvrx")
BU_ALTIVEC_OVERLOAD_X (STVRXL, "stvrxl")
+BU_ALTIVEC_OVERLOAD_X (SUBE, "sube")
+BU_ALTIVEC_OVERLOAD_X (SUBEC, "subec")
BU_ALTIVEC_OVERLOAD_X (VCFSX, "vcfsx")
BU_ALTIVEC_OVERLOAD_X (VCFUX, "vcfux")
BU_ALTIVEC_OVERLOAD_X (VSPLTB, "vspltb")
@@ -1602,6 +1613,9 @@ BU_VSX_2 (CMPLE_U2DI, "cmple_u2di", CONST, vector_ngtuv2di)
BU_VSX_2 (FLOAT2_V2DI, "float2_v2di", CONST, float2_v2di)
BU_VSX_2 (UNS_FLOAT2_V2DI, "uns_float2_v2di", CONST, uns_float2_v2di)
+BU_VSX_2 (VEC_VSIGNED2_V2DF, "vsigned2_v2df", CONST, vsigned2_v2df)
+BU_VSX_2 (VEC_VUNSIGNED2_V2DF, "vunsigned2_v2df", CONST, vunsigned2_v2df)
+
/* VSX abs builtin functions. */
BU_VSX_A (XVABSDP, "xvabsdp", CONST, absv2df2)
BU_VSX_A (XVNABSDP, "xvnabsdp", CONST, vsx_nabsv2df2)
@@ -1693,6 +1707,16 @@ BU_VSX_1 (DOUBLEL_V4SI, "doublel_v4si", CONST, doublelv4si2)
BU_VSX_1 (DOUBLEL_V4SF, "doublel_v4sf", CONST, doublelv4sf2)
BU_VSX_1 (UNS_DOUBLEL_V4SI, "uns_doublel_v4si", CONST, unsdoublelv4si2)
+BU_VSX_1 (VEC_VSIGNED_V4SF, "vsigned_v4sf", CONST, vsx_xvcvspsxws)
+BU_VSX_1 (VEC_VSIGNED_V2DF, "vsigned_v2df", CONST, vsx_xvcvdpsxds)
+BU_VSX_1 (VEC_VSIGNEDE_V2DF, "vsignede_v2df", CONST, vsignede_v2df)
+BU_VSX_1 (VEC_VSIGNEDO_V2DF, "vsignedo_v2df", CONST, vsignedo_v2df)
+
+BU_VSX_1 (VEC_VUNSIGNED_V4SF, "vunsigned_v4sf", CONST, vsx_xvcvspsxws)
+BU_VSX_1 (VEC_VUNSIGNED_V2DF, "vunsigned_v2df", CONST, vsx_xvcvdpsxds)
+BU_VSX_1 (VEC_VUNSIGNEDE_V2DF, "vunsignede_v2df", CONST, vunsignede_v2df)
+BU_VSX_1 (VEC_VUNSIGNEDO_V2DF, "vunsignedo_v2df", CONST, vunsignedo_v2df)
+
/* VSX predicate functions. */
BU_VSX_P (XVCMPEQSP_P, "xvcmpeqsp_p", CONST, vector_eq_v4sf_p)
BU_VSX_P (XVCMPGESP_P, "xvcmpgesp_p", CONST, vector_ge_v4sf_p)
@@ -1782,6 +1806,8 @@ BU_VSX_OVERLOAD_2 (XXSPLTD, "xxspltd")
BU_VSX_OVERLOAD_2 (XXSPLTW, "xxspltw")
BU_VSX_OVERLOAD_2 (FLOAT2, "float2")
BU_VSX_OVERLOAD_2 (UNS_FLOAT2, "uns_float2")
+BU_VSX_OVERLOAD_2 (VSIGNED2, "vsigned2")
+BU_VSX_OVERLOAD_2 (VUNSIGNED2, "vunsigned2")
/* 1 argument VSX overloaded builtin functions. */
BU_VSX_OVERLOAD_1 (DOUBLE, "double")
@@ -1797,6 +1823,14 @@ BU_VSX_OVERLOAD_1 (FLOAT, "float")
BU_VSX_OVERLOAD_1 (FLOATE, "floate")
BU_VSX_OVERLOAD_1 (FLOATO, "floato")
+BU_VSX_OVERLOAD_1 (VSIGNED, "vsigned")
+BU_VSX_OVERLOAD_1 (VSIGNEDE, "vsignede")
+BU_VSX_OVERLOAD_1 (VSIGNEDO, "vsignedo")
+
+BU_VSX_OVERLOAD_1 (VUNSIGNED, "vunsigned")
+BU_VSX_OVERLOAD_1 (VUNSIGNEDE, "vunsignede")
+BU_VSX_OVERLOAD_1 (VUNSIGNEDO, "vunsignedo")
+
/* VSX builtins that are handled as special cases. */
BU_VSX_OVERLOAD_X (LD, "ld")
BU_VSX_OVERLOAD_X (ST, "st")
@@ -1956,10 +1990,12 @@ BU_P8V_OVERLOAD_3 (VSUBEUQM, "vsubeuqm")
/* ISA 3.0 vector overloaded 2-argument functions. */
BU_P9V_AV_2 (VSLV, "vslv", CONST, vslv)
BU_P9V_AV_2 (VSRV, "vsrv", CONST, vsrv)
+BU_P9V_AV_2 (CONVERT_4F32_8I16, "convert_4f32_8i16", CONST, convert_4f32_8i16)
/* ISA 3.0 vector overloaded 2-argument functions. */
BU_P9V_OVERLOAD_2 (VSLV, "vslv")
BU_P9V_OVERLOAD_2 (VSRV, "vsrv")
+BU_P9V_OVERLOAD_2 (CONVERT_4F32_8I16, "convert_4f32_8i16")
/* 2 argument vector functions added in ISA 3.0 (power9). */
BU_P9V_AV_2 (VADUB, "vadub", CONST, vaduv16qi3)
@@ -1988,6 +2024,10 @@ BU_P9V_OVERLOAD_3 (RLMI, "rlmi")
BU_P9V_64BIT_VSX_1 (VSEEDP, "scalar_extract_exp", CONST, xsxexpdp)
BU_P9V_64BIT_VSX_1 (VSESDP, "scalar_extract_sig", CONST, xsxsigdp)
+BU_P9V_64BIT_VSX_1 (VSEEQP, "scalar_extract_expq", CONST, xsxexpqp)
+BU_P9V_64BIT_VSX_1 (VSESQP, "scalar_extract_sigq", CONST, xsxsigqp)
+
+BU_P9V_VSX_1 (VSTDCNQP, "scalar_test_neg_qp", CONST, xststdcnegqp)
BU_P9V_VSX_1 (VSTDCNDP, "scalar_test_neg_dp", CONST, xststdcnegdp)
BU_P9V_VSX_1 (VSTDCNSP, "scalar_test_neg_sp", CONST, xststdcnegsp)
@@ -2003,11 +2043,15 @@ BU_P9V_VSX_1 (XXBRH_V8HI, "xxbrh_v8hi", CONST, p9_xxbrh_v8hi)
BU_P9V_64BIT_VSX_2 (VSIEDP, "scalar_insert_exp", CONST, xsiexpdp)
BU_P9V_64BIT_VSX_2 (VSIEDPF, "scalar_insert_exp_dp", CONST, xsiexpdpf)
+BU_P9V_64BIT_VSX_2 (VSIEQP, "scalar_insert_exp_q", CONST, xsiexpqp)
+BU_P9V_64BIT_VSX_2 (VSIEQPF, "scalar_insert_exp_qp", CONST, xsiexpqpf)
+
BU_P9V_VSX_2 (VSCEDPGT, "scalar_cmp_exp_dp_gt", CONST, xscmpexpdp_gt)
BU_P9V_VSX_2 (VSCEDPLT, "scalar_cmp_exp_dp_lt", CONST, xscmpexpdp_lt)
BU_P9V_VSX_2 (VSCEDPEQ, "scalar_cmp_exp_dp_eq", CONST, xscmpexpdp_eq)
BU_P9V_VSX_2 (VSCEDPUO, "scalar_cmp_exp_dp_unordered", CONST, xscmpexpdp_unordered)
+BU_P9V_VSX_2 (VSTDCQP, "scalar_test_data_class_qp", CONST, xststdcqp)
BU_P9V_VSX_2 (VSTDCDP, "scalar_test_data_class_dp", CONST, xststdcdp)
BU_P9V_VSX_2 (VSTDCSP, "scalar_test_data_class_sp", CONST, xststdcsp)
@@ -2016,15 +2060,20 @@ BU_P9V_OVERLOAD_1 (VSEEDP, "scalar_extract_exp")
BU_P9V_OVERLOAD_1 (VSESDP, "scalar_extract_sig")
BU_P9V_OVERLOAD_1 (VSTDCN, "scalar_test_neg")
+BU_P9V_OVERLOAD_1 (VSTDCNQP, "scalar_test_neg_qp")
BU_P9V_OVERLOAD_1 (VSTDCNDP, "scalar_test_neg_dp")
BU_P9V_OVERLOAD_1 (VSTDCNSP, "scalar_test_neg_sp")
BU_P9V_OVERLOAD_1 (REVB, "revb")
+BU_P9V_OVERLOAD_1 (VEXTRACT_FP_FROM_SHORTH, "vextract_fp_from_shorth")
+BU_P9V_OVERLOAD_1 (VEXTRACT_FP_FROM_SHORTL, "vextract_fp_from_shortl")
+
/* ISA 3.0 vector scalar overloaded 2 argument functions. */
BU_P9V_OVERLOAD_2 (VSIEDP, "scalar_insert_exp")
BU_P9V_OVERLOAD_2 (VSTDC, "scalar_test_data_class")
+BU_P9V_OVERLOAD_2 (VSTDCQP, "scalar_test_data_class_qp")
BU_P9V_OVERLOAD_2 (VSTDCDP, "scalar_test_data_class_dp")
BU_P9V_OVERLOAD_2 (VSTDCSP, "scalar_test_data_class_sp")
@@ -2038,6 +2087,8 @@ BU_P9V_VSX_1 (VEEDP, "extract_exp_dp", CONST, xvxexpdp)
BU_P9V_VSX_1 (VEESP, "extract_exp_sp", CONST, xvxexpsp)
BU_P9V_VSX_1 (VESDP, "extract_sig_dp", CONST, xvxsigdp)
BU_P9V_VSX_1 (VESSP, "extract_sig_sp", CONST, xvxsigsp)
+BU_P9V_VSX_1 (VEXTRACT_FP_FROM_SHORTH, "vextract_fp_from_shorth", CONST, vextract_fp_from_shorth)
+BU_P9V_VSX_1 (VEXTRACT_FP_FROM_SHORTL, "vextract_fp_from_shortl", CONST, vextract_fp_from_shortl)
/* 2 argument vsx vector functions added in ISA 3.0 (power9). */
BU_P9V_VSX_2 (VIEDP, "insert_exp_dp", CONST, xviexpdp)
@@ -2251,6 +2302,7 @@ BU_P9V_OVERLOAD_1 (VPRTYB, "vprtyb")
BU_P9V_OVERLOAD_1 (VPRTYBD, "vprtybd")
BU_P9V_OVERLOAD_1 (VPRTYBQ, "vprtybq")
BU_P9V_OVERLOAD_1 (VPRTYBW, "vprtybw")
+BU_P9V_OVERLOAD_1 (VPARITY_LSBB, "vparity_lsbb")
/* 2 argument functions added in ISA 3.0 (power9). */
BU_P9_2 (CMPRB, "byte_in_range", CONST, cmprb)
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index cfd74abdf7e..1359099366d 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -575,40 +575,6 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
2. If TARGET_ALTIVEC is turned off. */
if ((flags & OPTION_MASK_CRYPTO) != 0)
rs6000_define_or_undefine_macro (define_p, "__CRYPTO__");
- /* Note that the OPTION_MASK_UPPER_REGS_DF flag is automatically
- turned on in the following conditions:
- 1. If TARGET_UPPER_REGS is explicitly turned on and
- TARGET_VSX is turned on and OPTION_MASK_UPPER_REGS_DF is not
- explicitly turned off. Hereafter, the
- OPTION_MASK_UPPER_REGS_DF flag is considered to have been
- explicitly set.
- Note that the OPTION_MASK_UPPER_REGS_DF flag is automatically
- turned off in the following conditions:
- 1. If TARGET_UPPER_REGS is explicitly turned off and TARGET_VSX
- is turned on and OPTION_MASK_UPPER_REGS_DF is not explicitly
- turned on. Hereafter, the OPTION_MASK_UPPER_REGS_DF flag is
- considered to have been explicitly cleared.
- 2. If TARGET_UPPER_REGS_DF is turned on but TARGET_VSX is turned
- off. */
- if ((flags & OPTION_MASK_UPPER_REGS_DF) != 0)
- rs6000_define_or_undefine_macro (define_p, "__UPPER_REGS_DF__");
- /* Note that the OPTION_MASK_UPPER_REGS_SF flag is automatically
- turned on in the following conditions:
- 1. If TARGET_UPPER_REGS is explicitly turned on and
- TARGET_P8_VECTOR is on and OPTION_MASK_UPPER_REGS_SF is not
- turned off explicitly. Hereafter, the
- OPTION_MASK_UPPER_REGS_SF flag is considered to have been
- explicitly set.
- Note that the OPTION_MASK_UPPER_REGS_SF flag is automatically
- turned off in the following conditions:
- 1. If TARGET_UPPER_REGS is explicitly turned off and
- TARGET_P8_VECTOR is on and OPTION_MASK_UPPER_REGS_SF is not
- turned off explicitly. Hereafter, the
- OPTION_MASK_UPPER_REGS_SF flag is considered to have been
- explicitly cleared.
- 2. If TARGET_P8_VECTOR is off. */
- if ((flags & OPTION_MASK_UPPER_REGS_SF) != 0)
- rs6000_define_or_undefine_macro (define_p, "__UPPER_REGS_SF__");
/* options from the builtin masks. */
/* Note that RS6000_BTM_PAIRED is enabled only if
@@ -644,6 +610,9 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
builtin_define ("__FLOAT128_HARDWARE__");
if (TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (TFmode))
builtin_define ("__ibm128=long double");
+#ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
+ builtin_define ("__BUILTIN_CPU_SUPPORTS__");
+#endif
/* We needed to create a keyword if -mfloat128-type was used but not -mfloat,
so we used __ieee128. If -mfloat128 was used, create a #define back to
@@ -2417,6 +2386,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V2DI, RS6000_BTI_bool_V2DI, 0 },
{ ALTIVEC_BUILTIN_VEC_PACK, P8V_BUILTIN_VPKUDUM,
RS6000_BTI_V4SF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+
+ { P9V_BUILTIN_VEC_CONVERT_4F32_8I16, P9V_BUILTIN_CONVERT_4F32_8I16,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+
{ ALTIVEC_BUILTIN_VEC_VPKUWUM, ALTIVEC_BUILTIN_VPKUWUM,
RS6000_BTI_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_VPKUWUM, ALTIVEC_BUILTIN_VPKUWUM,
@@ -2950,8 +2923,17 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+
+ { ALTIVEC_BUILTIN_VEC_SUBC, ALTIVEC_BUILTIN_VSUBCUW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_SUBC, ALTIVEC_BUILTIN_VSUBCUW,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBC, P8V_BUILTIN_VSUBCUQ,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
+ RS6000_BTI_unsigned_V1TI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBC, P8V_BUILTIN_VSUBCUQ,
+ RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, 0 },
+
{ ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUBS,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
{ ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUBS,
@@ -4733,33 +4715,50 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_bool_int, RS6000_BTI_float, RS6000_BTI_INTSI, 0 },
{ P9V_BUILTIN_VEC_VSTDC, P9V_BUILTIN_VSTDCDP,
RS6000_BTI_bool_int, RS6000_BTI_double, RS6000_BTI_INTSI, 0 },
+ { P9V_BUILTIN_VEC_VSTDC, P9V_BUILTIN_VSTDCQP,
+ RS6000_BTI_bool_int, RS6000_BTI_ieee128_float, RS6000_BTI_INTSI, 0 },
{ P9V_BUILTIN_VEC_VSTDCSP, P9V_BUILTIN_VSTDCSP,
RS6000_BTI_bool_int, RS6000_BTI_float, RS6000_BTI_INTSI, 0 },
{ P9V_BUILTIN_VEC_VSTDCDP, P9V_BUILTIN_VSTDCDP,
RS6000_BTI_bool_int, RS6000_BTI_double, RS6000_BTI_INTSI, 0 },
+ { P9V_BUILTIN_VEC_VSTDCQP, P9V_BUILTIN_VSTDCQP,
+ RS6000_BTI_bool_int, RS6000_BTI_ieee128_float, RS6000_BTI_INTSI, 0 },
{ P9V_BUILTIN_VEC_VSTDCN, P9V_BUILTIN_VSTDCNSP,
RS6000_BTI_bool_int, RS6000_BTI_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSTDCN, P9V_BUILTIN_VSTDCNDP,
RS6000_BTI_bool_int, RS6000_BTI_double, 0, 0 },
+ { P9V_BUILTIN_VEC_VSTDCN, P9V_BUILTIN_VSTDCNQP,
+ RS6000_BTI_bool_int, RS6000_BTI_ieee128_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSTDCNSP, P9V_BUILTIN_VSTDCNSP,
RS6000_BTI_bool_int, RS6000_BTI_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSTDCNDP, P9V_BUILTIN_VSTDCNDP,
RS6000_BTI_bool_int, RS6000_BTI_double, 0, 0 },
+ { P9V_BUILTIN_VEC_VSTDCNQP, P9V_BUILTIN_VSTDCNQP,
+ RS6000_BTI_bool_int, RS6000_BTI_ieee128_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSEEDP, P9V_BUILTIN_VSEEDP,
RS6000_BTI_UINTSI, RS6000_BTI_double, 0, 0 },
+ { P9V_BUILTIN_VEC_VSEEDP, P9V_BUILTIN_VSEEQP,
+ RS6000_BTI_UINTDI, RS6000_BTI_ieee128_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSESDP, P9V_BUILTIN_VSESDP,
RS6000_BTI_UINTDI, RS6000_BTI_double, 0, 0 },
+ { P9V_BUILTIN_VEC_VSESDP, P9V_BUILTIN_VSESQP,
+ RS6000_BTI_UINTTI, RS6000_BTI_ieee128_float, 0, 0 },
{ P9V_BUILTIN_VEC_VSIEDP, P9V_BUILTIN_VSIEDP,
RS6000_BTI_double, RS6000_BTI_UINTDI, RS6000_BTI_UINTDI, 0 },
{ P9V_BUILTIN_VEC_VSIEDP, P9V_BUILTIN_VSIEDPF,
RS6000_BTI_double, RS6000_BTI_double, RS6000_BTI_UINTDI, 0 },
+ { P9V_BUILTIN_VEC_VSIEDP, P9V_BUILTIN_VSIEQP,
+ RS6000_BTI_ieee128_float, RS6000_BTI_UINTTI, RS6000_BTI_UINTDI, 0 },
+ { P9V_BUILTIN_VEC_VSIEDP, P9V_BUILTIN_VSIEQPF,
+ RS6000_BTI_ieee128_float, RS6000_BTI_ieee128_float, RS6000_BTI_UINTDI, 0 },
+
{ P9V_BUILTIN_VEC_VSCEDPGT, P9V_BUILTIN_VSCEDPGT,
RS6000_BTI_INTSI, RS6000_BTI_double, RS6000_BTI_double, 0 },
{ P9V_BUILTIN_VEC_VSCEDPLT, P9V_BUILTIN_VSCEDPLT,
@@ -5151,6 +5150,11 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P9V_BUILTIN_VEC_VEXTRACT4B, P9V_BUILTIN_VEXTRACT4B,
RS6000_BTI_INTDI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_UINTSI, 0 },
+ { P9V_BUILTIN_VEC_VEXTRACT_FP_FROM_SHORTH, P9V_BUILTIN_VEXTRACT_FP_FROM_SHORTH,
+ RS6000_BTI_V4SF, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { P9V_BUILTIN_VEC_VEXTRACT_FP_FROM_SHORTL, P9V_BUILTIN_VEXTRACT_FP_FROM_SHORTL,
+ RS6000_BTI_V4SF, RS6000_BTI_unsigned_V8HI, 0, 0 },
+
{ P9V_BUILTIN_VEC_VEXTULX, P9V_BUILTIN_VEXTUBLX,
RS6000_BTI_INTQI, RS6000_BTI_UINTSI,
RS6000_BTI_V16QI, 0 },
@@ -5406,6 +5410,19 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
RS6000_BTI_UINTTI, RS6000_BTI_UINTTI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_V1TI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPARITY_LSBB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI, 0, 0 },
+
{ P9_BUILTIN_CMPRB, P9_BUILTIN_SCALAR_CMPRB,
RS6000_BTI_INTSI, RS6000_BTI_UINTQI, RS6000_BTI_UINTSI, 0 },
{ P9_BUILTIN_CMPRB2, P9_BUILTIN_SCALAR_CMPRB2,
@@ -5499,6 +5516,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRQ_V16QI,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRQ_V16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0, 0 },
+ { P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRQ_V16QI,
RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRQ_V1TI,
RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI, 0, 0 },
@@ -5511,16 +5530,72 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRD_V2DF,
RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRW_V4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRW_V4SI,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRW_V4SI,
RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRW_V4SF,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRH_V8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRH_V8HI,
RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0, 0 },
{ P9V_BUILTIN_VEC_REVB, P9V_BUILTIN_XXBRH_V8HI,
RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V2DI,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V2DI,
+ RS6000_BTI_bool_V2DI, RS6000_BTI_bool_V2DI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V2DF,
+ RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V2DI,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VREVE, ALTIVEC_BUILTIN_VREVE_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+ { VSX_BUILTIN_VEC_VSIGNED, VSX_BUILTIN_VEC_VSIGNED_V4SF,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNED, VSX_BUILTIN_VEC_VSIGNED_V2DF,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNEDE, VSX_BUILTIN_VEC_VSIGNEDE_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNEDO, VSX_BUILTIN_VEC_VSIGNEDO_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VSIGNED2, VSX_BUILTIN_VEC_VSIGNED2_V2DF,
+ RS6000_BTI_V4SI, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+
+ { VSX_BUILTIN_VEC_VUNSIGNED, VSX_BUILTIN_VEC_VUNSIGNED_V4SF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNED, VSX_BUILTIN_VEC_VUNSIGNED_V2DF,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNEDE, VSX_BUILTIN_VEC_VUNSIGNEDE_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNEDO, VSX_BUILTIN_VEC_VUNSIGNEDO_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF, 0, 0 },
+ { VSX_BUILTIN_VEC_VUNSIGNED2, VSX_BUILTIN_VEC_VUNSIGNED2_V2DF,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DF,
+ RS6000_BTI_V2DF, 0 },
+
/* Crypto builtins. */
{ CRYPTO_BUILTIN_VPERMXOR, CRYPTO_BUILTIN_VPERMXOR_V16QI,
RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
@@ -5832,13 +5907,16 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
/* else, fall through and process the Power9 alternative below */
}
- if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDE
+ || fcode == ALTIVEC_BUILTIN_VEC_SUBE)
{
/* vec_adde needs to be special cased because there is no instruction
for the {un}signed int version. */
if (nargs != 3)
{
- error ("vec_adde only accepts 3 arguments");
+ const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDE ?
+ "vec_adde": "vec_sube";
+ error ("%s only accepts 3 arguments", name);
return error_mark_node;
}
@@ -5861,14 +5939,24 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
{
/* For {un}signed ints,
vec_adde (va, vb, carryv) == vec_add (vec_add (va, vb),
- vec_and (carryv, 0x1)). */
+ vec_and (carryv, 1)).
+ vec_sube (va, vb, carryv) == vec_sub (vec_sub (va, vb),
+ vec_and (carryv, 1)). */
case SImode:
{
+ tree add_sub_builtin;
+
vec<tree, va_gc> *params = make_tree_vector ();
vec_safe_push (params, arg0);
vec_safe_push (params, arg1);
- tree add_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
- tree call = altivec_resolve_overloaded_builtin (loc, add_builtin,
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
+ add_sub_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
+ else
+ add_sub_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUB];
+
+ tree call = altivec_resolve_overloaded_builtin (loc,
+ add_sub_builtin,
params);
tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
tree ones_vector = build_vector_from_val (arg0_type, const1);
@@ -5877,16 +5965,22 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
params = make_tree_vector ();
vec_safe_push (params, call);
vec_safe_push (params, and_expr);
- return altivec_resolve_overloaded_builtin (loc, add_builtin,
+ return altivec_resolve_overloaded_builtin (loc, add_sub_builtin,
params);
}
/* For {un}signed __int128s use the vaddeuqm instruction
directly. */
case TImode:
{
- tree adde_bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDEUQM];
- return altivec_resolve_overloaded_builtin (loc, adde_bii,
- arglist);
+ tree bii;
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
+ bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDEUQM];
+
+ else
+ bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VSUBEUQM];
+
+ return altivec_resolve_overloaded_builtin (loc, bii, arglist);
}
/* Types other than {un}signed int and {un}signed __int128
@@ -5896,13 +5990,16 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
}
}
- if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC
+ || fcode == ALTIVEC_BUILTIN_VEC_SUBEC)
{
- /* vec_addec needs to be special cased because there is no instruction
- for the {un}signed int version. */
+ /* vec_addec and vec_subec needs to be special cased because there is
+ no instruction for the {un}signed int version. */
if (nargs != 3)
{
- error ("vec_addec only accepts 3 arguments");
+ const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDEC ?
+ "vec_addec": "vec_subec";
+ error ("%s only accepts 3 arguments", name);
return error_mark_node;
}
@@ -5933,19 +6030,33 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
/* Use save_expr to ensure that operands used more than once
that may have side effects (like calls) are only evaluated
once. */
+ tree as_builtin;
+ tree as_c_builtin;
+
arg0 = save_expr (arg0);
arg1 = save_expr (arg1);
vec<tree, va_gc> *params = make_tree_vector ();
vec_safe_push (params, arg0);
vec_safe_push (params, arg1);
- tree addc_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADDC];
- tree call1 = altivec_resolve_overloaded_builtin (loc, addc_builtin,
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
+ as_c_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADDC];
+ else
+ as_c_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUBC];
+
+ tree call1 = altivec_resolve_overloaded_builtin (loc, as_c_builtin,
params);
params = make_tree_vector ();
vec_safe_push (params, arg0);
vec_safe_push (params, arg1);
- tree add_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
- tree call2 = altivec_resolve_overloaded_builtin (loc, add_builtin,
+
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
+ as_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD];
+ else
+ as_builtin = rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_SUB];
+
+ tree call2 = altivec_resolve_overloaded_builtin (loc, as_builtin,
params);
tree const1 = build_int_cstu (TREE_TYPE (arg0_type), 1);
tree ones_vector = build_vector_from_val (arg0_type, const1);
@@ -5954,7 +6065,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
params = make_tree_vector ();
vec_safe_push (params, call2);
vec_safe_push (params, and_expr);
- call2 = altivec_resolve_overloaded_builtin (loc, addc_builtin,
+ call2 = altivec_resolve_overloaded_builtin (loc, as_c_builtin,
params);
params = make_tree_vector ();
vec_safe_push (params, call1);
@@ -5963,12 +6074,19 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return altivec_resolve_overloaded_builtin (loc, or_builtin,
params);
}
- /* For {un}signed __int128s use the vaddecuq instruction. */
+ /* For {un}signed __int128s use the vaddecuq/vsubbecuq
+ instructions. */
case TImode:
{
- tree VADDECUQ_bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDECUQ];
- return altivec_resolve_overloaded_builtin (loc, VADDECUQ_bii,
- arglist);
+ tree bii;
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDEC)
+ bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDECUQ];
+
+ else
+ bii = rs6000_builtin_decls[P8V_BUILTIN_VEC_VSUBECUQ];
+
+ return altivec_resolve_overloaded_builtin (loc, bii, arglist);
}
/* Types other than {un}signed int and {un}signed __int128
are errors. */
@@ -6551,8 +6669,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
if (fcode == P6_OV_BUILTIN_CMPB)
{
int overloaded_code;
- int arg1_mode = TYPE_MODE (types[0]);
- int arg2_mode = TYPE_MODE (types[1]);
+ machine_mode arg1_mode = TYPE_MODE (types[0]);
+ machine_mode arg2_mode = TYPE_MODE (types[1]);
if (nargs != 2)
{
@@ -6590,6 +6708,52 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
unsupported_builtin = true;
}
}
+ else if (fcode == P9V_BUILTIN_VEC_VSIEDP)
+ {
+ int overloaded_code;
+ int arg1_mode = TYPE_MODE (types[0]);
+
+ if (nargs != 2)
+ {
+ error ("scalar_insert_exp only accepts 2 arguments");
+ return error_mark_node;
+ }
+
+ /* If supplied first argument is wider than 64 bits, resolve to
+ 128-bit variant of built-in function. */
+ if (GET_MODE_PRECISION (arg1_mode) > 64)
+ {
+ /* If first argument is of float variety, choose variant
+ that expects __ieee128 argument. Otherwise, expect
+ __int128 argument. */
+ if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
+ overloaded_code = P9V_BUILTIN_VSIEQPF;
+ else
+ overloaded_code = P9V_BUILTIN_VSIEQP;
+ }
+ else
+ {
+ /* If first argument is of float variety, choose variant
+ that expects double argument. Otherwise, expect
+ long long int argument. */
+ if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT)
+ overloaded_code = P9V_BUILTIN_VSIEDPF;
+ else
+ overloaded_code = P9V_BUILTIN_VSIEDP;
+ }
+ while (desc->code && desc->code == fcode &&
+ desc->overloaded_code != overloaded_code)
+ desc++;
+ if (desc->code && (desc->code == fcode)
+ && rs6000_builtin_type_compatible (types[0], desc->op1)
+ && rs6000_builtin_type_compatible (types[1], desc->op2))
+ {
+ if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
+ return altivec_build_resolved_builtin (args, n, desc);
+ else
+ unsupported_builtin = true;
+ }
+ }
else
{
/* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index cd5c70688d8..190f9123fa0 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -44,9 +44,7 @@
#define ISA_2_6_MASKS_SERVER (ISA_2_5_MASKS_SERVER \
| OPTION_MASK_POPCNTD \
| OPTION_MASK_ALTIVEC \
- | OPTION_MASK_VSX \
- | OPTION_MASK_UPPER_REGS_DI \
- | OPTION_MASK_UPPER_REGS_DF)
+ | OPTION_MASK_VSX)
/* For now, don't provide an embedded version of ISA 2.07. */
#define ISA_2_7_MASKS_SERVER (ISA_2_6_MASKS_SERVER \
@@ -57,9 +55,7 @@
| OPTION_MASK_EFFICIENT_UNALIGNED_VSX \
| OPTION_MASK_HTM \
| OPTION_MASK_QUAD_MEMORY \
- | OPTION_MASK_QUAD_MEMORY_ATOMIC \
- | OPTION_MASK_UPPER_REGS_SF \
- | OPTION_MASK_VSX_SMALL_INTEGER)
+ | OPTION_MASK_QUAD_MEMORY_ATOMIC)
/* Add ISEL back into ISA 3.0, since it is supposed to be a win. Do not add
FLOAT128_HW here until we are ready to make -mfloat128 on by default. */
@@ -78,11 +74,7 @@
#define ISA_3_0_MASKS_IEEE (OPTION_MASK_VSX \
| OPTION_MASK_P8_VECTOR \
| OPTION_MASK_P9_VECTOR \
- | OPTION_MASK_DIRECT_MOVE \
- | OPTION_MASK_UPPER_REGS_DI \
- | OPTION_MASK_UPPER_REGS_DF \
- | OPTION_MASK_UPPER_REGS_SF \
- | OPTION_MASK_VSX_SMALL_INTEGER)
+ | OPTION_MASK_DIRECT_MOVE)
/* Flags that need to be turned off if -mno-power9-vector. */
#define OTHER_P9_VECTOR_MASKS (OPTION_MASK_FLOAT128_HW \
@@ -94,8 +86,7 @@
#define OTHER_P8_VECTOR_MASKS (OTHER_P9_VECTOR_MASKS \
| OPTION_MASK_P9_VECTOR \
| OPTION_MASK_DIRECT_MOVE \
- | OPTION_MASK_CRYPTO \
- | OPTION_MASK_UPPER_REGS_SF) \
+ | OPTION_MASK_CRYPTO)
/* Flags that need to be turned off if -mno-vsx. */
#define OTHER_VSX_VECTOR_MASKS (OTHER_P8_VECTOR_MASKS \
@@ -103,9 +94,6 @@
| OPTION_MASK_FLOAT128_KEYWORD \
| OPTION_MASK_FLOAT128_TYPE \
| OPTION_MASK_P8_VECTOR \
- | OPTION_MASK_UPPER_REGS_DI \
- | OPTION_MASK_UPPER_REGS_DF \
- | OPTION_MASK_VSX_SMALL_INTEGER \
| OPTION_MASK_VSX_TIMODE)
#define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
@@ -135,7 +123,6 @@
| OPTION_MASK_FPRND \
| OPTION_MASK_HTM \
| OPTION_MASK_ISEL \
- | OPTION_MASK_LRA \
| OPTION_MASK_MFCRF \
| OPTION_MASK_MFPGPR \
| OPTION_MASK_MODULO \
@@ -160,11 +147,7 @@
| OPTION_MASK_SOFT_FLOAT \
| OPTION_MASK_STRICT_ALIGN_OPTIONAL \
| OPTION_MASK_TOC_FUSION \
- | OPTION_MASK_UPPER_REGS_DI \
- | OPTION_MASK_UPPER_REGS_DF \
- | OPTION_MASK_UPPER_REGS_SF \
| OPTION_MASK_VSX \
- | OPTION_MASK_VSX_SMALL_INTEGER \
| OPTION_MASK_VSX_TIMODE)
#endif
@@ -251,11 +234,7 @@ RS6000_CPU ("power6", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
| MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
| MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION)
-RS6000_CPU ("power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
- POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
- | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
- | MASK_VSX | MASK_RECIP_PRECISION | OPTION_MASK_UPPER_REGS_DF
- | OPTION_MASK_UPPER_REGS_DI)
+RS6000_CPU ("power7", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_6_MASKS_SERVER)
RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER)
RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
diff --git a/gcc/config/rs6000/rs6000-p8swap.c b/gcc/config/rs6000/rs6000-p8swap.c
new file mode 100644
index 00000000000..1557f7f587e
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-p8swap.c
@@ -0,0 +1,1892 @@
+/* Subroutines used to remove unnecessary doubleword swaps
+ for p8 little-endian VSX code.
+ Copyright (C) 1991-2017 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 "backend.h"
+#include "rtl.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "df.h"
+#include "tm_p.h"
+#include "ira.h"
+#include "print-tree.h"
+#include "varasm.h"
+#include "explow.h"
+#include "expr.h"
+#include "output.h"
+#include "tree-pass.h"
+
+/* Analyze vector computations and remove unnecessary doubleword
+ swaps (xxswapdi instructions). This pass is performed only
+ for little-endian VSX code generation.
+
+ For this specific case, loads and stores of 4x32 and 2x64 vectors
+ are inefficient. These are implemented using the lvx2dx and
+ stvx2dx instructions, which invert the order of doublewords in
+ a vector register. Thus the code generation inserts an xxswapdi
+ after each such load, and prior to each such store. (For spill
+ code after register assignment, an additional xxswapdi is inserted
+ following each store in order to return a hard register to its
+ unpermuted value.)
+
+ The extra xxswapdi instructions reduce performance. This can be
+ particularly bad for vectorized code. The purpose of this pass
+ is to reduce the number of xxswapdi instructions required for
+ correctness.
+
+ The primary insight is that much code that operates on vectors
+ does not care about the relative order of elements in a register,
+ so long as the correct memory order is preserved. If we have
+ a computation where all input values are provided by lvxd2x/xxswapdi
+ sequences, all outputs are stored using xxswapdi/stvxd2x sequences,
+ and all intermediate computations are pure SIMD (independent of
+ element order), then all the xxswapdi's associated with the loads
+ and stores may be removed.
+
+ This pass uses some of the infrastructure and logical ideas from
+ the "web" pass in web.c. We create maximal webs of computations
+ fitting the description above using union-find. Each such web is
+ then optimized by removing its unnecessary xxswapdi instructions.
+
+ The pass is placed prior to global optimization so that we can
+ perform the optimization in the safest and simplest way possible;
+ that is, by replacing each xxswapdi insn with a register copy insn.
+ Subsequent forward propagation will remove copies where possible.
+
+ There are some operations sensitive to element order for which we
+ can still allow the operation, provided we modify those operations.
+ These include CONST_VECTORs, for which we must swap the first and
+ second halves of the constant vector; and SUBREGs, for which we
+ must adjust the byte offset to account for the swapped doublewords.
+ A remaining opportunity would be non-immediate-form splats, for
+ which we should adjust the selected lane of the input. We should
+ also make code generation adjustments for sum-across operations,
+ since this is a common vectorizer reduction.
+
+ Because we run prior to the first split, we can see loads and stores
+ here that match *vsx_le_perm_{load,store}_<mode>. These are vanilla
+ vector loads and stores that have not yet been split into a permuting
+ load/store and a swap. (One way this can happen is with a builtin
+ call to vec_vsx_{ld,st}.) We can handle these as well, but rather
+ than deleting a swap, we convert the load/store into a permuting
+ load/store (which effectively removes the swap). */
+
+/* Notes on Permutes
+
+ We do not currently handle computations that contain permutes. There
+ is a general transformation that can be performed correctly, but it
+ may introduce more expensive code than it replaces. To handle these
+ would require a cost model to determine when to perform the optimization.
+ This commentary records how this could be done if desired.
+
+ The most general permute is something like this (example for V16QI):
+
+ (vec_select:V16QI (vec_concat:V32QI (op1:V16QI) (op2:V16QI))
+ (parallel [(const_int a0) (const_int a1)
+ ...
+ (const_int a14) (const_int a15)]))
+
+ where a0,...,a15 are in [0,31] and select elements from op1 and op2
+ to produce in the result.
+
+ Regardless of mode, we can convert the PARALLEL to a mask of 16
+ byte-element selectors. Let's call this M, with M[i] representing
+ the ith byte-element selector value. Then if we swap doublewords
+ throughout the computation, we can get correct behavior by replacing
+ M with M' as follows:
+
+ M'[i] = { (M[i]+8)%16 : M[i] in [0,15]
+ { ((M[i]+8)%16)+16 : M[i] in [16,31]
+
+ This seems promising at first, since we are just replacing one mask
+ with another. But certain masks are preferable to others. If M
+ is a mask that matches a vmrghh pattern, for example, M' certainly
+ will not. Instead of a single vmrghh, we would generate a load of
+ M' and a vperm. So we would need to know how many xxswapd's we can
+ remove as a result of this transformation to determine if it's
+ profitable; and preferably the logic would need to be aware of all
+ the special preferable masks.
+
+ Another form of permute is an UNSPEC_VPERM, in which the mask is
+ already in a register. In some cases, this mask may be a constant
+ that we can discover with ud-chains, in which case the above
+ transformation is ok. However, the common usage here is for the
+ mask to be produced by an UNSPEC_LVSL, in which case the mask
+ cannot be known at compile time. In such a case we would have to
+ generate several instructions to compute M' as above at run time,
+ and a cost model is needed again.
+
+ However, when the mask M for an UNSPEC_VPERM is loaded from the
+ constant pool, we can replace M with M' as above at no cost
+ beyond adding a constant pool entry. */
+
+/* This is based on the union-find logic in web.c. web_entry_base is
+ defined in df.h. */
+class swap_web_entry : public web_entry_base
+{
+ public:
+ /* Pointer to the insn. */
+ rtx_insn *insn;
+ /* Set if insn contains a mention of a vector register. All other
+ fields are undefined if this field is unset. */
+ unsigned int is_relevant : 1;
+ /* Set if insn is a load. */
+ unsigned int is_load : 1;
+ /* Set if insn is a store. */
+ unsigned int is_store : 1;
+ /* Set if insn is a doubleword swap. This can either be a register swap
+ or a permuting load or store (test is_load and is_store for this). */
+ unsigned int is_swap : 1;
+ /* Set if the insn has a live-in use of a parameter register. */
+ unsigned int is_live_in : 1;
+ /* Set if the insn has a live-out def of a return register. */
+ unsigned int is_live_out : 1;
+ /* Set if the insn contains a subreg reference of a vector register. */
+ unsigned int contains_subreg : 1;
+ /* Set if the insn contains a 128-bit integer operand. */
+ unsigned int is_128_int : 1;
+ /* Set if this is a call-insn. */
+ unsigned int is_call : 1;
+ /* Set if this insn does not perform a vector operation for which
+ element order matters, or if we know how to fix it up if it does.
+ Undefined if is_swap is set. */
+ unsigned int is_swappable : 1;
+ /* A nonzero value indicates what kind of special handling for this
+ insn is required if doublewords are swapped. Undefined if
+ is_swappable is not set. */
+ unsigned int special_handling : 4;
+ /* Set if the web represented by this entry cannot be optimized. */
+ unsigned int web_not_optimizable : 1;
+ /* Set if this insn should be deleted. */
+ unsigned int will_delete : 1;
+};
+
+enum special_handling_values {
+ SH_NONE = 0,
+ SH_CONST_VECTOR,
+ SH_SUBREG,
+ SH_NOSWAP_LD,
+ SH_NOSWAP_ST,
+ SH_EXTRACT,
+ SH_SPLAT,
+ SH_XXPERMDI,
+ SH_CONCAT,
+ SH_VPERM
+};
+
+/* Union INSN with all insns containing definitions that reach USE.
+ Detect whether USE is live-in to the current function. */
+static void
+union_defs (swap_web_entry *insn_entry, rtx insn, df_ref use)
+{
+ struct df_link *link = DF_REF_CHAIN (use);
+
+ if (!link)
+ insn_entry[INSN_UID (insn)].is_live_in = 1;
+
+ while (link)
+ {
+ if (DF_REF_IS_ARTIFICIAL (link->ref))
+ insn_entry[INSN_UID (insn)].is_live_in = 1;
+
+ if (DF_REF_INSN_INFO (link->ref))
+ {
+ rtx def_insn = DF_REF_INSN (link->ref);
+ (void)unionfind_union (insn_entry + INSN_UID (insn),
+ insn_entry + INSN_UID (def_insn));
+ }
+
+ link = link->next;
+ }
+}
+
+/* Union INSN with all insns containing uses reached from DEF.
+ Detect whether DEF is live-out from the current function. */
+static void
+union_uses (swap_web_entry *insn_entry, rtx insn, df_ref def)
+{
+ struct df_link *link = DF_REF_CHAIN (def);
+
+ if (!link)
+ insn_entry[INSN_UID (insn)].is_live_out = 1;
+
+ while (link)
+ {
+ /* This could be an eh use or some other artificial use;
+ we treat these all the same (killing the optimization). */
+ if (DF_REF_IS_ARTIFICIAL (link->ref))
+ insn_entry[INSN_UID (insn)].is_live_out = 1;
+
+ if (DF_REF_INSN_INFO (link->ref))
+ {
+ rtx use_insn = DF_REF_INSN (link->ref);
+ (void)unionfind_union (insn_entry + INSN_UID (insn),
+ insn_entry + INSN_UID (use_insn));
+ }
+
+ link = link->next;
+ }
+}
+
+/* Return 1 iff INSN is a load insn, including permuting loads that
+ represent an lvxd2x instruction; else return 0. */
+static unsigned int
+insn_is_load_p (rtx insn)
+{
+ rtx body = PATTERN (insn);
+
+ if (GET_CODE (body) == SET)
+ {
+ if (GET_CODE (SET_SRC (body)) == MEM)
+ return 1;
+
+ if (GET_CODE (SET_SRC (body)) == VEC_SELECT
+ && GET_CODE (XEXP (SET_SRC (body), 0)) == MEM)
+ return 1;
+
+ return 0;
+ }
+
+ if (GET_CODE (body) != PARALLEL)
+ return 0;
+
+ rtx set = XVECEXP (body, 0, 0);
+
+ if (GET_CODE (set) == SET && GET_CODE (SET_SRC (set)) == MEM)
+ return 1;
+
+ return 0;
+}
+
+/* Return 1 iff INSN is a store insn, including permuting stores that
+ represent an stvxd2x instruction; else return 0. */
+static unsigned int
+insn_is_store_p (rtx insn)
+{
+ rtx body = PATTERN (insn);
+ if (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == MEM)
+ return 1;
+ if (GET_CODE (body) != PARALLEL)
+ return 0;
+ rtx set = XVECEXP (body, 0, 0);
+ if (GET_CODE (set) == SET && GET_CODE (SET_DEST (set)) == MEM)
+ return 1;
+ return 0;
+}
+
+/* Return 1 iff INSN swaps doublewords. This may be a reg-reg swap,
+ a permuting load, or a permuting store. */
+static unsigned int
+insn_is_swap_p (rtx insn)
+{
+ rtx body = PATTERN (insn);
+ if (GET_CODE (body) != SET)
+ return 0;
+ rtx rhs = SET_SRC (body);
+ if (GET_CODE (rhs) != VEC_SELECT)
+ return 0;
+ rtx parallel = XEXP (rhs, 1);
+ if (GET_CODE (parallel) != PARALLEL)
+ return 0;
+ unsigned int len = XVECLEN (parallel, 0);
+ if (len != 2 && len != 4 && len != 8 && len != 16)
+ return 0;
+ for (unsigned int i = 0; i < len / 2; ++i)
+ {
+ rtx op = XVECEXP (parallel, 0, i);
+ if (GET_CODE (op) != CONST_INT || INTVAL (op) != len / 2 + i)
+ return 0;
+ }
+ for (unsigned int i = len / 2; i < len; ++i)
+ {
+ rtx op = XVECEXP (parallel, 0, i);
+ if (GET_CODE (op) != CONST_INT || INTVAL (op) != i - len / 2)
+ return 0;
+ }
+ return 1;
+}
+
+/* Return TRUE if insn is a swap fed by a load from the constant pool. */
+static bool
+const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
+{
+ unsigned uid = INSN_UID (insn);
+ if (!insn_entry[uid].is_swap || insn_entry[uid].is_load)
+ return false;
+
+ const_rtx tocrel_base;
+
+ /* Find the unique use in the swap and locate its def. If the def
+ isn't unique, punt. */
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref use;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ if (!def_link || def_link->next)
+ return false;
+
+ rtx def_insn = DF_REF_INSN (def_link->ref);
+ unsigned uid2 = INSN_UID (def_insn);
+ if (!insn_entry[uid2].is_load || !insn_entry[uid2].is_swap)
+ return false;
+
+ rtx body = PATTERN (def_insn);
+ if (GET_CODE (body) != SET
+ || GET_CODE (SET_SRC (body)) != VEC_SELECT
+ || GET_CODE (XEXP (SET_SRC (body), 0)) != MEM)
+ return false;
+
+ rtx mem = XEXP (SET_SRC (body), 0);
+ rtx base_reg = XEXP (mem, 0);
+
+ df_ref base_use;
+ insn_info = DF_INSN_INFO_GET (def_insn);
+ FOR_EACH_INSN_INFO_USE (base_use, insn_info)
+ {
+ if (!rtx_equal_p (DF_REF_REG (base_use), base_reg))
+ continue;
+
+ struct df_link *base_def_link = DF_REF_CHAIN (base_use);
+ if (!base_def_link || base_def_link->next)
+ return false;
+
+ rtx tocrel_insn = DF_REF_INSN (base_def_link->ref);
+ rtx tocrel_body = PATTERN (tocrel_insn);
+ rtx base, offset;
+ if (GET_CODE (tocrel_body) != SET)
+ return false;
+ /* There is an extra level of indirection for small/large
+ code models. */
+ rtx tocrel_expr = SET_SRC (tocrel_body);
+ if (GET_CODE (tocrel_expr) == MEM)
+ tocrel_expr = XEXP (tocrel_expr, 0);
+ if (!toc_relative_expr_p (tocrel_expr, false, &tocrel_base, NULL))
+ return false;
+ split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
+ if (GET_CODE (base) != SYMBOL_REF || !CONSTANT_POOL_ADDRESS_P (base))
+ return false;
+ }
+ }
+ return true;
+}
+
+/* Return TRUE iff OP matches a V2DF reduction pattern. See the
+ definition of vsx_reduc_<VEC_reduc_name>_v2df in vsx.md. */
+static bool
+v2df_reduction_p (rtx op)
+{
+ if (GET_MODE (op) != V2DFmode)
+ return false;
+
+ enum rtx_code code = GET_CODE (op);
+ if (code != PLUS && code != SMIN && code != SMAX)
+ return false;
+
+ rtx concat = XEXP (op, 0);
+ if (GET_CODE (concat) != VEC_CONCAT)
+ return false;
+
+ rtx select0 = XEXP (concat, 0);
+ rtx select1 = XEXP (concat, 1);
+ if (GET_CODE (select0) != VEC_SELECT || GET_CODE (select1) != VEC_SELECT)
+ return false;
+
+ rtx reg0 = XEXP (select0, 0);
+ rtx reg1 = XEXP (select1, 0);
+ if (!rtx_equal_p (reg0, reg1) || !REG_P (reg0))
+ return false;
+
+ rtx parallel0 = XEXP (select0, 1);
+ rtx parallel1 = XEXP (select1, 1);
+ if (GET_CODE (parallel0) != PARALLEL || GET_CODE (parallel1) != PARALLEL)
+ return false;
+
+ if (!rtx_equal_p (XVECEXP (parallel0, 0, 0), const1_rtx)
+ || !rtx_equal_p (XVECEXP (parallel1, 0, 0), const0_rtx))
+ return false;
+
+ return true;
+}
+
+/* Return 1 iff OP is an operand that will not be affected by having
+ vector doublewords swapped in memory. */
+static unsigned int
+rtx_is_swappable_p (rtx op, unsigned int *special)
+{
+ enum rtx_code code = GET_CODE (op);
+ int i, j;
+ rtx parallel;
+
+ switch (code)
+ {
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CLOBBER:
+ case REG:
+ return 1;
+
+ case VEC_CONCAT:
+ case ASM_INPUT:
+ case ASM_OPERANDS:
+ return 0;
+
+ case CONST_VECTOR:
+ {
+ *special = SH_CONST_VECTOR;
+ return 1;
+ }
+
+ case VEC_DUPLICATE:
+ /* Opportunity: If XEXP (op, 0) has the same mode as the result,
+ and XEXP (op, 1) is a PARALLEL with a single QImode const int,
+ it represents a vector splat for which we can do special
+ handling. */
+ if (GET_CODE (XEXP (op, 0)) == CONST_INT)
+ return 1;
+ else if (REG_P (XEXP (op, 0))
+ && GET_MODE_INNER (GET_MODE (op)) == GET_MODE (XEXP (op, 0)))
+ /* This catches V2DF and V2DI splat, at a minimum. */
+ return 1;
+ else if (GET_CODE (XEXP (op, 0)) == TRUNCATE
+ && REG_P (XEXP (XEXP (op, 0), 0))
+ && GET_MODE_INNER (GET_MODE (op)) == GET_MODE (XEXP (op, 0)))
+ /* This catches splat of a truncated value. */
+ return 1;
+ else if (GET_CODE (XEXP (op, 0)) == VEC_SELECT)
+ /* If the duplicated item is from a select, defer to the select
+ processing to see if we can change the lane for the splat. */
+ return rtx_is_swappable_p (XEXP (op, 0), special);
+ else
+ return 0;
+
+ case VEC_SELECT:
+ /* A vec_extract operation is ok if we change the lane. */
+ if (GET_CODE (XEXP (op, 0)) == REG
+ && GET_MODE_INNER (GET_MODE (XEXP (op, 0))) == GET_MODE (op)
+ && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
+ && XVECLEN (parallel, 0) == 1
+ && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT)
+ {
+ *special = SH_EXTRACT;
+ return 1;
+ }
+ /* An XXPERMDI is ok if we adjust the lanes. Note that if the
+ XXPERMDI is a swap operation, it will be identified by
+ insn_is_swap_p and therefore we won't get here. */
+ else if (GET_CODE (XEXP (op, 0)) == VEC_CONCAT
+ && (GET_MODE (XEXP (op, 0)) == V4DFmode
+ || GET_MODE (XEXP (op, 0)) == V4DImode)
+ && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
+ && XVECLEN (parallel, 0) == 2
+ && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT
+ && GET_CODE (XVECEXP (parallel, 0, 1)) == CONST_INT)
+ {
+ *special = SH_XXPERMDI;
+ return 1;
+ }
+ else if (v2df_reduction_p (op))
+ return 1;
+ else
+ return 0;
+
+ case UNSPEC:
+ {
+ /* Various operations are unsafe for this optimization, at least
+ without significant additional work. Permutes are obviously
+ problematic, as both the permute control vector and the ordering
+ of the target values are invalidated by doubleword swapping.
+ Vector pack and unpack modify the number of vector lanes.
+ Merge-high/low will not operate correctly on swapped operands.
+ Vector shifts across element boundaries are clearly uncool,
+ as are vector select and concatenate operations. Vector
+ sum-across instructions define one operand with a specific
+ order-dependent element, so additional fixup code would be
+ needed to make those work. Vector set and non-immediate-form
+ vector splat are element-order sensitive. A few of these
+ cases might be workable with special handling if required.
+ Adding cost modeling would be appropriate in some cases. */
+ int val = XINT (op, 1);
+ switch (val)
+ {
+ default:
+ break;
+ case UNSPEC_VMRGH_DIRECT:
+ case UNSPEC_VMRGL_DIRECT:
+ case UNSPEC_VPACK_SIGN_SIGN_SAT:
+ case UNSPEC_VPACK_SIGN_UNS_SAT:
+ case UNSPEC_VPACK_UNS_UNS_MOD:
+ case UNSPEC_VPACK_UNS_UNS_MOD_DIRECT:
+ case UNSPEC_VPACK_UNS_UNS_SAT:
+ case UNSPEC_VPERM:
+ case UNSPEC_VPERM_UNS:
+ case UNSPEC_VPERMHI:
+ case UNSPEC_VPERMSI:
+ case UNSPEC_VPKPX:
+ case UNSPEC_VSLDOI:
+ case UNSPEC_VSLO:
+ case UNSPEC_VSRO:
+ case UNSPEC_VSUM2SWS:
+ case UNSPEC_VSUM4S:
+ case UNSPEC_VSUM4UBS:
+ case UNSPEC_VSUMSWS:
+ case UNSPEC_VSUMSWS_DIRECT:
+ case UNSPEC_VSX_CONCAT:
+ case UNSPEC_VSX_SET:
+ case UNSPEC_VSX_SLDWI:
+ case UNSPEC_VUNPACK_HI_SIGN:
+ case UNSPEC_VUNPACK_HI_SIGN_DIRECT:
+ case UNSPEC_VUNPACK_LO_SIGN:
+ case UNSPEC_VUNPACK_LO_SIGN_DIRECT:
+ case UNSPEC_VUPKHPX:
+ case UNSPEC_VUPKHS_V4SF:
+ case UNSPEC_VUPKHU_V4SF:
+ case UNSPEC_VUPKLPX:
+ case UNSPEC_VUPKLS_V4SF:
+ case UNSPEC_VUPKLU_V4SF:
+ case UNSPEC_VSX_CVDPSPN:
+ case UNSPEC_VSX_CVSPDP:
+ case UNSPEC_VSX_CVSPDPN:
+ case UNSPEC_VSX_EXTRACT:
+ case UNSPEC_VSX_VSLO:
+ case UNSPEC_VSX_VEC_INIT:
+ return 0;
+ case UNSPEC_VSPLT_DIRECT:
+ case UNSPEC_VSX_XXSPLTD:
+ *special = SH_SPLAT;
+ return 1;
+ case UNSPEC_REDUC_PLUS:
+ case UNSPEC_REDUC:
+ return 1;
+ }
+ }
+
+ default:
+ break;
+ }
+
+ const char *fmt = GET_RTX_FORMAT (code);
+ int ok = 1;
+
+ for (i = 0; i < GET_RTX_LENGTH (code); ++i)
+ if (fmt[i] == 'e' || fmt[i] == 'u')
+ {
+ unsigned int special_op = SH_NONE;
+ ok &= rtx_is_swappable_p (XEXP (op, i), &special_op);
+ if (special_op == SH_NONE)
+ continue;
+ /* Ensure we never have two kinds of special handling
+ for the same insn. */
+ if (*special != SH_NONE && *special != special_op)
+ return 0;
+ *special = special_op;
+ }
+ else if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (op, i); ++j)
+ {
+ unsigned int special_op = SH_NONE;
+ ok &= rtx_is_swappable_p (XVECEXP (op, i, j), &special_op);
+ if (special_op == SH_NONE)
+ continue;
+ /* Ensure we never have two kinds of special handling
+ for the same insn. */
+ if (*special != SH_NONE && *special != special_op)
+ return 0;
+ *special = special_op;
+ }
+
+ return ok;
+}
+
+/* Return 1 iff INSN is an operand that will not be affected by
+ having vector doublewords swapped in memory (in which case
+ *SPECIAL is unchanged), or that can be modified to be correct
+ if vector doublewords are swapped in memory (in which case
+ *SPECIAL is changed to a value indicating how). */
+static unsigned int
+insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn,
+ unsigned int *special)
+{
+ /* Calls are always bad. */
+ if (GET_CODE (insn) == CALL_INSN)
+ return 0;
+
+ /* Loads and stores seen here are not permuting, but we can still
+ fix them up by converting them to permuting ones. Exceptions:
+ UNSPEC_LVE, UNSPEC_LVX, and UNSPEC_STVX, which have a PARALLEL
+ body instead of a SET; and UNSPEC_STVE, which has an UNSPEC
+ for the SET source. Also we must now make an exception for lvx
+ and stvx when they are not in the UNSPEC_LVX/STVX form (with the
+ explicit "& -16") since this leads to unrecognizable insns. */
+ rtx body = PATTERN (insn);
+ int i = INSN_UID (insn);
+
+ if (insn_entry[i].is_load)
+ {
+ if (GET_CODE (body) == SET)
+ {
+ rtx rhs = SET_SRC (body);
+ /* Even without a swap, the RHS might be a vec_select for, say,
+ a byte-reversing load. */
+ if (GET_CODE (rhs) != MEM)
+ return 0;
+ if (GET_CODE (XEXP (rhs, 0)) == AND)
+ return 0;
+
+ *special = SH_NOSWAP_LD;
+ return 1;
+ }
+ else
+ return 0;
+ }
+
+ if (insn_entry[i].is_store)
+ {
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_SRC (body)) != UNSPEC)
+ {
+ rtx lhs = SET_DEST (body);
+ /* Even without a swap, the LHS might be a vec_select for, say,
+ a byte-reversing store. */
+ if (GET_CODE (lhs) != MEM)
+ return 0;
+ if (GET_CODE (XEXP (lhs, 0)) == AND)
+ return 0;
+
+ *special = SH_NOSWAP_ST;
+ return 1;
+ }
+ else
+ return 0;
+ }
+
+ /* A convert to single precision can be left as is provided that
+ all of its uses are in xxspltw instructions that splat BE element
+ zero. */
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_SRC (body)) == UNSPEC
+ && XINT (SET_SRC (body), 1) == UNSPEC_VSX_CVDPSPN)
+ {
+ df_ref def;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ struct df_link *link = DF_REF_CHAIN (def);
+ if (!link)
+ return 0;
+
+ for (; link; link = link->next) {
+ rtx use_insn = DF_REF_INSN (link->ref);
+ rtx use_body = PATTERN (use_insn);
+ if (GET_CODE (use_body) != SET
+ || GET_CODE (SET_SRC (use_body)) != UNSPEC
+ || XINT (SET_SRC (use_body), 1) != UNSPEC_VSX_XXSPLTW
+ || XVECEXP (SET_SRC (use_body), 0, 1) != const0_rtx)
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+
+ /* A concatenation of two doublewords is ok if we reverse the
+ order of the inputs. */
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_SRC (body)) == VEC_CONCAT
+ && (GET_MODE (SET_SRC (body)) == V2DFmode
+ || GET_MODE (SET_SRC (body)) == V2DImode))
+ {
+ *special = SH_CONCAT;
+ return 1;
+ }
+
+ /* V2DF reductions are always swappable. */
+ if (GET_CODE (body) == PARALLEL)
+ {
+ rtx expr = XVECEXP (body, 0, 0);
+ if (GET_CODE (expr) == SET
+ && v2df_reduction_p (SET_SRC (expr)))
+ return 1;
+ }
+
+ /* An UNSPEC_VPERM is ok if the mask operand is loaded from the
+ constant pool. */
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_SRC (body)) == UNSPEC
+ && XINT (SET_SRC (body), 1) == UNSPEC_VPERM
+ && XVECLEN (SET_SRC (body), 0) == 3
+ && GET_CODE (XVECEXP (SET_SRC (body), 0, 2)) == REG)
+ {
+ rtx mask_reg = XVECEXP (SET_SRC (body), 0, 2);
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref use;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ if (rtx_equal_p (DF_REF_REG (use), mask_reg))
+ {
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ /* Punt if multiple definitions for this reg. */
+ if (def_link && !def_link->next &&
+ const_load_sequence_p (insn_entry,
+ DF_REF_INSN (def_link->ref)))
+ {
+ *special = SH_VPERM;
+ return 1;
+ }
+ }
+ }
+
+ /* Otherwise check the operands for vector lane violations. */
+ return rtx_is_swappable_p (body, special);
+}
+
+enum chain_purpose { FOR_LOADS, FOR_STORES };
+
+/* Return true if the UD or DU chain headed by LINK is non-empty,
+ and every entry on the chain references an insn that is a
+ register swap. Furthermore, if PURPOSE is FOR_LOADS, each such
+ register swap must have only permuting loads as reaching defs.
+ If PURPOSE is FOR_STORES, each such register swap must have only
+ register swaps or permuting stores as reached uses. */
+static bool
+chain_contains_only_swaps (swap_web_entry *insn_entry, struct df_link *link,
+ enum chain_purpose purpose)
+{
+ if (!link)
+ return false;
+
+ for (; link; link = link->next)
+ {
+ if (!ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (DF_REF_REG (link->ref))))
+ continue;
+
+ if (DF_REF_IS_ARTIFICIAL (link->ref))
+ return false;
+
+ rtx reached_insn = DF_REF_INSN (link->ref);
+ unsigned uid = INSN_UID (reached_insn);
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (reached_insn);
+
+ if (!insn_entry[uid].is_swap || insn_entry[uid].is_load
+ || insn_entry[uid].is_store)
+ return false;
+
+ if (purpose == FOR_LOADS)
+ {
+ df_ref use;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ struct df_link *swap_link = DF_REF_CHAIN (use);
+
+ while (swap_link)
+ {
+ if (DF_REF_IS_ARTIFICIAL (link->ref))
+ return false;
+
+ rtx swap_def_insn = DF_REF_INSN (swap_link->ref);
+ unsigned uid2 = INSN_UID (swap_def_insn);
+
+ /* Only permuting loads are allowed. */
+ if (!insn_entry[uid2].is_swap || !insn_entry[uid2].is_load)
+ return false;
+
+ swap_link = swap_link->next;
+ }
+ }
+ }
+ else if (purpose == FOR_STORES)
+ {
+ df_ref def;
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ struct df_link *swap_link = DF_REF_CHAIN (def);
+
+ while (swap_link)
+ {
+ if (DF_REF_IS_ARTIFICIAL (link->ref))
+ return false;
+
+ rtx swap_use_insn = DF_REF_INSN (swap_link->ref);
+ unsigned uid2 = INSN_UID (swap_use_insn);
+
+ /* Permuting stores or register swaps are allowed. */
+ if (!insn_entry[uid2].is_swap || insn_entry[uid2].is_load)
+ return false;
+
+ swap_link = swap_link->next;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Mark the xxswapdi instructions associated with permuting loads and
+ stores for removal. Note that we only flag them for deletion here,
+ as there is a possibility of a swap being reached from multiple
+ loads, etc. */
+static void
+mark_swaps_for_removal (swap_web_entry *insn_entry, unsigned int i)
+{
+ rtx insn = insn_entry[i].insn;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+
+ if (insn_entry[i].is_load)
+ {
+ df_ref def;
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ struct df_link *link = DF_REF_CHAIN (def);
+
+ /* We know by now that these are swaps, so we can delete
+ them confidently. */
+ while (link)
+ {
+ rtx use_insn = DF_REF_INSN (link->ref);
+ insn_entry[INSN_UID (use_insn)].will_delete = 1;
+ link = link->next;
+ }
+ }
+ }
+ else if (insn_entry[i].is_store)
+ {
+ df_ref use;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ /* Ignore uses for addressability. */
+ machine_mode mode = GET_MODE (DF_REF_REG (use));
+ if (!ALTIVEC_OR_VSX_VECTOR_MODE (mode))
+ continue;
+
+ struct df_link *link = DF_REF_CHAIN (use);
+
+ /* We know by now that these are swaps, so we can delete
+ them confidently. */
+ while (link)
+ {
+ rtx def_insn = DF_REF_INSN (link->ref);
+ insn_entry[INSN_UID (def_insn)].will_delete = 1;
+ link = link->next;
+ }
+ }
+ }
+}
+
+/* OP is either a CONST_VECTOR or an expression containing one.
+ Swap the first half of the vector with the second in the first
+ case. Recurse to find it in the second. */
+static void
+swap_const_vector_halves (rtx op)
+{
+ int i;
+ enum rtx_code code = GET_CODE (op);
+ if (GET_CODE (op) == CONST_VECTOR)
+ {
+ int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
+ for (i = 0; i < half_units; ++i)
+ {
+ rtx temp = CONST_VECTOR_ELT (op, i);
+ CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
+ CONST_VECTOR_ELT (op, i + half_units) = temp;
+ }
+ }
+ else
+ {
+ int j;
+ const char *fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); ++i)
+ if (fmt[i] == 'e' || fmt[i] == 'u')
+ swap_const_vector_halves (XEXP (op, i));
+ else if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (op, i); ++j)
+ swap_const_vector_halves (XVECEXP (op, i, j));
+ }
+}
+
+/* Find all subregs of a vector expression that perform a narrowing,
+ and adjust the subreg index to account for doubleword swapping. */
+static void
+adjust_subreg_index (rtx op)
+{
+ enum rtx_code code = GET_CODE (op);
+ if (code == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (op))
+ < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))))
+ {
+ unsigned int index = SUBREG_BYTE (op);
+ if (index < 8)
+ index += 8;
+ else
+ index -= 8;
+ SUBREG_BYTE (op) = index;
+ }
+
+ const char *fmt = GET_RTX_FORMAT (code);
+ int i,j;
+ for (i = 0; i < GET_RTX_LENGTH (code); ++i)
+ if (fmt[i] == 'e' || fmt[i] == 'u')
+ adjust_subreg_index (XEXP (op, i));
+ else if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (op, i); ++j)
+ adjust_subreg_index (XVECEXP (op, i, j));
+}
+
+/* Convert the non-permuting load INSN to a permuting one. */
+static void
+permute_load (rtx_insn *insn)
+{
+ rtx body = PATTERN (insn);
+ rtx mem_op = SET_SRC (body);
+ rtx tgt_reg = SET_DEST (body);
+ machine_mode mode = GET_MODE (tgt_reg);
+ int n_elts = GET_MODE_NUNITS (mode);
+ int half_elts = n_elts / 2;
+ rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
+ int i, j;
+ for (i = 0, j = half_elts; i < half_elts; ++i, ++j)
+ XVECEXP (par, 0, i) = GEN_INT (j);
+ for (i = half_elts, j = 0; j < half_elts; ++i, ++j)
+ XVECEXP (par, 0, i) = GEN_INT (j);
+ rtx sel = gen_rtx_VEC_SELECT (mode, mem_op, par);
+ SET_SRC (body) = sel;
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Replacing load %d with permuted load\n",
+ INSN_UID (insn));
+}
+
+/* Convert the non-permuting store INSN to a permuting one. */
+static void
+permute_store (rtx_insn *insn)
+{
+ rtx body = PATTERN (insn);
+ rtx src_reg = SET_SRC (body);
+ machine_mode mode = GET_MODE (src_reg);
+ int n_elts = GET_MODE_NUNITS (mode);
+ int half_elts = n_elts / 2;
+ rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
+ int i, j;
+ for (i = 0, j = half_elts; i < half_elts; ++i, ++j)
+ XVECEXP (par, 0, i) = GEN_INT (j);
+ for (i = half_elts, j = 0; j < half_elts; ++i, ++j)
+ XVECEXP (par, 0, i) = GEN_INT (j);
+ rtx sel = gen_rtx_VEC_SELECT (mode, src_reg, par);
+ SET_SRC (body) = sel;
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Replacing store %d with permuted store\n",
+ INSN_UID (insn));
+}
+
+/* Given OP that contains a vector extract operation, adjust the index
+ of the extracted lane to account for the doubleword swap. */
+static void
+adjust_extract (rtx_insn *insn)
+{
+ rtx pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == PARALLEL)
+ pattern = XVECEXP (pattern, 0, 0);
+ rtx src = SET_SRC (pattern);
+ /* The vec_select may be wrapped in a vec_duplicate for a splat, so
+ account for that. */
+ rtx sel = GET_CODE (src) == VEC_DUPLICATE ? XEXP (src, 0) : src;
+ rtx par = XEXP (sel, 1);
+ int half_elts = GET_MODE_NUNITS (GET_MODE (XEXP (sel, 0))) >> 1;
+ int lane = INTVAL (XVECEXP (par, 0, 0));
+ lane = lane >= half_elts ? lane - half_elts : lane + half_elts;
+ XVECEXP (par, 0, 0) = GEN_INT (lane);
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Changing lane for extract %d\n", INSN_UID (insn));
+}
+
+/* Given OP that contains a vector direct-splat operation, adjust the index
+ of the source lane to account for the doubleword swap. */
+static void
+adjust_splat (rtx_insn *insn)
+{
+ rtx body = PATTERN (insn);
+ rtx unspec = XEXP (body, 1);
+ int half_elts = GET_MODE_NUNITS (GET_MODE (unspec)) >> 1;
+ int lane = INTVAL (XVECEXP (unspec, 0, 1));
+ lane = lane >= half_elts ? lane - half_elts : lane + half_elts;
+ XVECEXP (unspec, 0, 1) = GEN_INT (lane);
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn));
+}
+
+/* Given OP that contains an XXPERMDI operation (that is not a doubleword
+ swap), reverse the order of the source operands and adjust the indices
+ of the source lanes to account for doubleword reversal. */
+static void
+adjust_xxpermdi (rtx_insn *insn)
+{
+ rtx set = PATTERN (insn);
+ rtx select = XEXP (set, 1);
+ rtx concat = XEXP (select, 0);
+ rtx src0 = XEXP (concat, 0);
+ XEXP (concat, 0) = XEXP (concat, 1);
+ XEXP (concat, 1) = src0;
+ rtx parallel = XEXP (select, 1);
+ int lane0 = INTVAL (XVECEXP (parallel, 0, 0));
+ int lane1 = INTVAL (XVECEXP (parallel, 0, 1));
+ int new_lane0 = 3 - lane1;
+ int new_lane1 = 3 - lane0;
+ XVECEXP (parallel, 0, 0) = GEN_INT (new_lane0);
+ XVECEXP (parallel, 0, 1) = GEN_INT (new_lane1);
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Changing lanes for xxpermdi %d\n", INSN_UID (insn));
+}
+
+/* Given OP that contains a VEC_CONCAT operation of two doublewords,
+ reverse the order of those inputs. */
+static void
+adjust_concat (rtx_insn *insn)
+{
+ rtx set = PATTERN (insn);
+ rtx concat = XEXP (set, 1);
+ rtx src0 = XEXP (concat, 0);
+ XEXP (concat, 0) = XEXP (concat, 1);
+ XEXP (concat, 1) = src0;
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Reversing inputs for concat %d\n", INSN_UID (insn));
+}
+
+/* Given an UNSPEC_VPERM insn, modify the mask loaded from the
+ constant pool to reflect swapped doublewords. */
+static void
+adjust_vperm (rtx_insn *insn)
+{
+ /* We previously determined that the UNSPEC_VPERM was fed by a
+ swap of a swapping load of a TOC-relative constant pool symbol.
+ Find the MEM in the swapping load and replace it with a MEM for
+ the adjusted mask constant. */
+ rtx set = PATTERN (insn);
+ rtx mask_reg = XVECEXP (SET_SRC (set), 0, 2);
+
+ /* Find the swap. */
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref use;
+ rtx_insn *swap_insn = 0;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ if (rtx_equal_p (DF_REF_REG (use), mask_reg))
+ {
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ gcc_assert (def_link && !def_link->next);
+ swap_insn = DF_REF_INSN (def_link->ref);
+ break;
+ }
+ gcc_assert (swap_insn);
+
+ /* Find the load. */
+ insn_info = DF_INSN_INFO_GET (swap_insn);
+ rtx_insn *load_insn = 0;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ gcc_assert (def_link && !def_link->next);
+ load_insn = DF_REF_INSN (def_link->ref);
+ break;
+ }
+ gcc_assert (load_insn);
+
+ /* Find the TOC-relative symbol access. */
+ insn_info = DF_INSN_INFO_GET (load_insn);
+ rtx_insn *tocrel_insn = 0;
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ gcc_assert (def_link && !def_link->next);
+ tocrel_insn = DF_REF_INSN (def_link->ref);
+ break;
+ }
+ gcc_assert (tocrel_insn);
+
+ /* Find the embedded CONST_VECTOR. We have to call toc_relative_expr_p
+ to set tocrel_base; otherwise it would be unnecessary as we've
+ already established it will return true. */
+ rtx base, offset;
+ const_rtx tocrel_base;
+ rtx tocrel_expr = SET_SRC (PATTERN (tocrel_insn));
+ /* There is an extra level of indirection for small/large code models. */
+ if (GET_CODE (tocrel_expr) == MEM)
+ tocrel_expr = XEXP (tocrel_expr, 0);
+ if (!toc_relative_expr_p (tocrel_expr, false, &tocrel_base, NULL))
+ gcc_unreachable ();
+ split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
+ rtx const_vector = get_pool_constant (base);
+ /* With the extra indirection, get_pool_constant will produce the
+ real constant from the reg_equal expression, so get the real
+ constant. */
+ if (GET_CODE (const_vector) == SYMBOL_REF)
+ const_vector = get_pool_constant (const_vector);
+ gcc_assert (GET_CODE (const_vector) == CONST_VECTOR);
+
+ /* Create an adjusted mask from the initial mask. */
+ unsigned int new_mask[16], i, val;
+ for (i = 0; i < 16; ++i) {
+ val = INTVAL (XVECEXP (const_vector, 0, i));
+ if (val < 16)
+ new_mask[i] = (val + 8) % 16;
+ else
+ new_mask[i] = ((val + 8) % 16) + 16;
+ }
+
+ /* Create a new CONST_VECTOR and a MEM that references it. */
+ rtx vals = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
+ for (i = 0; i < 16; ++i)
+ XVECEXP (vals, 0, i) = GEN_INT (new_mask[i]);
+ rtx new_const_vector = gen_rtx_CONST_VECTOR (V16QImode, XVEC (vals, 0));
+ rtx new_mem = force_const_mem (V16QImode, new_const_vector);
+ /* This gives us a MEM whose base operand is a SYMBOL_REF, which we
+ can't recognize. Force the SYMBOL_REF into a register. */
+ if (!REG_P (XEXP (new_mem, 0))) {
+ rtx base_reg = force_reg (Pmode, XEXP (new_mem, 0));
+ XEXP (new_mem, 0) = base_reg;
+ /* Move the newly created insn ahead of the load insn. */
+ rtx_insn *force_insn = get_last_insn ();
+ remove_insn (force_insn);
+ rtx_insn *before_load_insn = PREV_INSN (load_insn);
+ add_insn_after (force_insn, before_load_insn, BLOCK_FOR_INSN (load_insn));
+ df_insn_rescan (before_load_insn);
+ df_insn_rescan (force_insn);
+ }
+
+ /* Replace the MEM in the load instruction and rescan it. */
+ XEXP (SET_SRC (PATTERN (load_insn)), 0) = new_mem;
+ INSN_CODE (load_insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (load_insn);
+
+ if (dump_file)
+ fprintf (dump_file, "Adjusting mask for vperm %d\n", INSN_UID (insn));
+}
+
+/* The insn described by INSN_ENTRY[I] can be swapped, but only
+ with special handling. Take care of that here. */
+static void
+handle_special_swappables (swap_web_entry *insn_entry, unsigned i)
+{
+ rtx_insn *insn = insn_entry[i].insn;
+ rtx body = PATTERN (insn);
+
+ switch (insn_entry[i].special_handling)
+ {
+ default:
+ gcc_unreachable ();
+ case SH_CONST_VECTOR:
+ {
+ /* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
+ gcc_assert (GET_CODE (body) == SET);
+ rtx rhs = SET_SRC (body);
+ swap_const_vector_halves (rhs);
+ if (dump_file)
+ fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
+ break;
+ }
+ case SH_SUBREG:
+ /* A subreg of the same size is already safe. For subregs that
+ select a smaller portion of a reg, adjust the index for
+ swapped doublewords. */
+ adjust_subreg_index (body);
+ if (dump_file)
+ fprintf (dump_file, "Adjusting subreg in insn %d\n", i);
+ break;
+ case SH_NOSWAP_LD:
+ /* Convert a non-permuting load to a permuting one. */
+ permute_load (insn);
+ break;
+ case SH_NOSWAP_ST:
+ /* Convert a non-permuting store to a permuting one. */
+ permute_store (insn);
+ break;
+ case SH_EXTRACT:
+ /* Change the lane on an extract operation. */
+ adjust_extract (insn);
+ break;
+ case SH_SPLAT:
+ /* Change the lane on a direct-splat operation. */
+ adjust_splat (insn);
+ break;
+ case SH_XXPERMDI:
+ /* Change the lanes on an XXPERMDI operation. */
+ adjust_xxpermdi (insn);
+ break;
+ case SH_CONCAT:
+ /* Reverse the order of a concatenation operation. */
+ adjust_concat (insn);
+ break;
+ case SH_VPERM:
+ /* Change the mask loaded from the constant pool for a VPERM. */
+ adjust_vperm (insn);
+ break;
+ }
+}
+
+/* Find the insn from the Ith table entry, which is known to be a
+ register swap Y = SWAP(X). Replace it with a copy Y = X. */
+static void
+replace_swap_with_copy (swap_web_entry *insn_entry, unsigned i)
+{
+ rtx_insn *insn = insn_entry[i].insn;
+ rtx body = PATTERN (insn);
+ rtx src_reg = XEXP (SET_SRC (body), 0);
+ rtx copy = gen_rtx_SET (SET_DEST (body), src_reg);
+ rtx_insn *new_insn = emit_insn_before (copy, insn);
+ set_block_for_insn (new_insn, BLOCK_FOR_INSN (insn));
+ df_insn_rescan (new_insn);
+
+ if (dump_file)
+ {
+ unsigned int new_uid = INSN_UID (new_insn);
+ fprintf (dump_file, "Replacing swap %d with copy %d\n", i, new_uid);
+ }
+
+ df_insn_delete (insn);
+ remove_insn (insn);
+ insn->set_deleted ();
+}
+
+/* Dump the swap table to DUMP_FILE. */
+static void
+dump_swap_insn_table (swap_web_entry *insn_entry)
+{
+ int e = get_max_uid ();
+ fprintf (dump_file, "\nRelevant insns with their flag settings\n\n");
+
+ for (int i = 0; i < e; ++i)
+ if (insn_entry[i].is_relevant)
+ {
+ swap_web_entry *pred_entry = (swap_web_entry *)insn_entry[i].pred ();
+ fprintf (dump_file, "%6d %6d ", i,
+ pred_entry && pred_entry->insn
+ ? INSN_UID (pred_entry->insn) : 0);
+ if (insn_entry[i].is_load)
+ fputs ("load ", dump_file);
+ if (insn_entry[i].is_store)
+ fputs ("store ", dump_file);
+ if (insn_entry[i].is_swap)
+ fputs ("swap ", dump_file);
+ if (insn_entry[i].is_live_in)
+ fputs ("live-in ", dump_file);
+ if (insn_entry[i].is_live_out)
+ fputs ("live-out ", dump_file);
+ if (insn_entry[i].contains_subreg)
+ fputs ("subreg ", dump_file);
+ if (insn_entry[i].is_128_int)
+ fputs ("int128 ", dump_file);
+ if (insn_entry[i].is_call)
+ fputs ("call ", dump_file);
+ if (insn_entry[i].is_swappable)
+ {
+ fputs ("swappable ", dump_file);
+ if (insn_entry[i].special_handling == SH_CONST_VECTOR)
+ fputs ("special:constvec ", dump_file);
+ else if (insn_entry[i].special_handling == SH_SUBREG)
+ fputs ("special:subreg ", dump_file);
+ else if (insn_entry[i].special_handling == SH_NOSWAP_LD)
+ fputs ("special:load ", dump_file);
+ else if (insn_entry[i].special_handling == SH_NOSWAP_ST)
+ fputs ("special:store ", dump_file);
+ else if (insn_entry[i].special_handling == SH_EXTRACT)
+ fputs ("special:extract ", dump_file);
+ else if (insn_entry[i].special_handling == SH_SPLAT)
+ fputs ("special:splat ", dump_file);
+ else if (insn_entry[i].special_handling == SH_XXPERMDI)
+ fputs ("special:xxpermdi ", dump_file);
+ else if (insn_entry[i].special_handling == SH_CONCAT)
+ fputs ("special:concat ", dump_file);
+ else if (insn_entry[i].special_handling == SH_VPERM)
+ fputs ("special:vperm ", dump_file);
+ }
+ if (insn_entry[i].web_not_optimizable)
+ fputs ("unoptimizable ", dump_file);
+ if (insn_entry[i].will_delete)
+ fputs ("delete ", dump_file);
+ fputs ("\n", dump_file);
+ }
+ fputs ("\n", dump_file);
+}
+
+/* Return RTX with its address canonicalized to (reg) or (+ reg reg).
+ Here RTX is an (& addr (const_int -16)). Always return a new copy
+ to avoid problems with combine. */
+static rtx
+alignment_with_canonical_addr (rtx align)
+{
+ rtx canon;
+ rtx addr = XEXP (align, 0);
+
+ if (REG_P (addr))
+ canon = addr;
+
+ else if (GET_CODE (addr) == PLUS)
+ {
+ rtx addrop0 = XEXP (addr, 0);
+ rtx addrop1 = XEXP (addr, 1);
+
+ if (!REG_P (addrop0))
+ addrop0 = force_reg (GET_MODE (addrop0), addrop0);
+
+ if (!REG_P (addrop1))
+ addrop1 = force_reg (GET_MODE (addrop1), addrop1);
+
+ canon = gen_rtx_PLUS (GET_MODE (addr), addrop0, addrop1);
+ }
+
+ else
+ canon = force_reg (GET_MODE (addr), addr);
+
+ return gen_rtx_AND (GET_MODE (align), canon, GEN_INT (-16));
+}
+
+/* Check whether an rtx is an alignment mask, and if so, return
+ a fully-expanded rtx for the masking operation. */
+static rtx
+alignment_mask (rtx_insn *insn)
+{
+ rtx body = PATTERN (insn);
+
+ if (GET_CODE (body) != SET
+ || GET_CODE (SET_SRC (body)) != AND
+ || !REG_P (XEXP (SET_SRC (body), 0)))
+ return 0;
+
+ rtx mask = XEXP (SET_SRC (body), 1);
+
+ if (GET_CODE (mask) == CONST_INT)
+ {
+ if (INTVAL (mask) == -16)
+ return alignment_with_canonical_addr (SET_SRC (body));
+ else
+ return 0;
+ }
+
+ if (!REG_P (mask))
+ return 0;
+
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref use;
+ rtx real_mask = 0;
+
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ if (!rtx_equal_p (DF_REF_REG (use), mask))
+ continue;
+
+ struct df_link *def_link = DF_REF_CHAIN (use);
+ if (!def_link || def_link->next)
+ return 0;
+
+ rtx_insn *const_insn = DF_REF_INSN (def_link->ref);
+ rtx const_body = PATTERN (const_insn);
+ if (GET_CODE (const_body) != SET)
+ return 0;
+
+ real_mask = SET_SRC (const_body);
+
+ if (GET_CODE (real_mask) != CONST_INT
+ || INTVAL (real_mask) != -16)
+ return 0;
+ }
+
+ if (real_mask == 0)
+ return 0;
+
+ return alignment_with_canonical_addr (SET_SRC (body));
+}
+
+/* Given INSN that's a load or store based at BASE_REG, look for a
+ feeding computation that aligns its address on a 16-byte boundary. */
+static rtx
+find_alignment_op (rtx_insn *insn, rtx base_reg)
+{
+ df_ref base_use;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ rtx and_operation = 0;
+
+ FOR_EACH_INSN_INFO_USE (base_use, insn_info)
+ {
+ if (!rtx_equal_p (DF_REF_REG (base_use), base_reg))
+ continue;
+
+ struct df_link *base_def_link = DF_REF_CHAIN (base_use);
+ if (!base_def_link || base_def_link->next)
+ break;
+
+ /* With stack-protector code enabled, and possibly in other
+ circumstances, there may not be an associated insn for
+ the def. */
+ if (DF_REF_IS_ARTIFICIAL (base_def_link->ref))
+ break;
+
+ rtx_insn *and_insn = DF_REF_INSN (base_def_link->ref);
+ and_operation = alignment_mask (and_insn);
+ if (and_operation != 0)
+ break;
+ }
+
+ return and_operation;
+}
+
+struct del_info { bool replace; rtx_insn *replace_insn; };
+
+/* If INSN is the load for an lvx pattern, put it in canonical form. */
+static void
+recombine_lvx_pattern (rtx_insn *insn, del_info *to_delete)
+{
+ rtx body = PATTERN (insn);
+ gcc_assert (GET_CODE (body) == SET
+ && GET_CODE (SET_SRC (body)) == VEC_SELECT
+ && GET_CODE (XEXP (SET_SRC (body), 0)) == MEM);
+
+ rtx mem = XEXP (SET_SRC (body), 0);
+ rtx base_reg = XEXP (mem, 0);
+
+ rtx and_operation = find_alignment_op (insn, base_reg);
+
+ if (and_operation != 0)
+ {
+ df_ref def;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ struct df_link *link = DF_REF_CHAIN (def);
+ if (!link || link->next)
+ break;
+
+ rtx_insn *swap_insn = DF_REF_INSN (link->ref);
+ if (!insn_is_swap_p (swap_insn)
+ || insn_is_load_p (swap_insn)
+ || insn_is_store_p (swap_insn))
+ break;
+
+ /* Expected lvx pattern found. Change the swap to
+ a copy, and propagate the AND operation into the
+ load. */
+ to_delete[INSN_UID (swap_insn)].replace = true;
+ to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn;
+
+ XEXP (mem, 0) = and_operation;
+ SET_SRC (body) = mem;
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "lvx opportunity found at %d\n",
+ INSN_UID (insn));
+ }
+ }
+}
+
+/* If INSN is the store for an stvx pattern, put it in canonical form. */
+static void
+recombine_stvx_pattern (rtx_insn *insn, del_info *to_delete)
+{
+ rtx body = PATTERN (insn);
+ gcc_assert (GET_CODE (body) == SET
+ && GET_CODE (SET_DEST (body)) == MEM
+ && GET_CODE (SET_SRC (body)) == VEC_SELECT);
+ rtx mem = SET_DEST (body);
+ rtx base_reg = XEXP (mem, 0);
+
+ rtx and_operation = find_alignment_op (insn, base_reg);
+
+ if (and_operation != 0)
+ {
+ rtx src_reg = XEXP (SET_SRC (body), 0);
+ df_ref src_use;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ FOR_EACH_INSN_INFO_USE (src_use, insn_info)
+ {
+ if (!rtx_equal_p (DF_REF_REG (src_use), src_reg))
+ continue;
+
+ struct df_link *link = DF_REF_CHAIN (src_use);
+ if (!link || link->next)
+ break;
+
+ rtx_insn *swap_insn = DF_REF_INSN (link->ref);
+ if (!insn_is_swap_p (swap_insn)
+ || insn_is_load_p (swap_insn)
+ || insn_is_store_p (swap_insn))
+ break;
+
+ /* Expected stvx pattern found. Change the swap to
+ a copy, and propagate the AND operation into the
+ store. */
+ to_delete[INSN_UID (swap_insn)].replace = true;
+ to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn;
+
+ XEXP (mem, 0) = and_operation;
+ SET_SRC (body) = src_reg;
+ INSN_CODE (insn) = -1; /* Force re-recognition. */
+ df_insn_rescan (insn);
+
+ if (dump_file)
+ fprintf (dump_file, "stvx opportunity found at %d\n",
+ INSN_UID (insn));
+ }
+ }
+}
+
+/* Look for patterns created from builtin lvx and stvx calls, and
+ canonicalize them to be properly recognized as such. */
+static void
+recombine_lvx_stvx_patterns (function *fun)
+{
+ int i;
+ basic_block bb;
+ rtx_insn *insn;
+
+ int num_insns = get_max_uid ();
+ del_info *to_delete = XCNEWVEC (del_info, num_insns);
+
+ FOR_ALL_BB_FN (bb, fun)
+ FOR_BB_INSNS (bb, insn)
+ {
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ if (insn_is_load_p (insn) && insn_is_swap_p (insn))
+ recombine_lvx_pattern (insn, to_delete);
+ else if (insn_is_store_p (insn) && insn_is_swap_p (insn))
+ recombine_stvx_pattern (insn, to_delete);
+ }
+
+ /* Turning swaps into copies is delayed until now, to avoid problems
+ with deleting instructions during the insn walk. */
+ for (i = 0; i < num_insns; i++)
+ if (to_delete[i].replace)
+ {
+ rtx swap_body = PATTERN (to_delete[i].replace_insn);
+ rtx src_reg = XEXP (SET_SRC (swap_body), 0);
+ rtx copy = gen_rtx_SET (SET_DEST (swap_body), src_reg);
+ rtx_insn *new_insn = emit_insn_before (copy,
+ to_delete[i].replace_insn);
+ set_block_for_insn (new_insn,
+ BLOCK_FOR_INSN (to_delete[i].replace_insn));
+ df_insn_rescan (new_insn);
+ df_insn_delete (to_delete[i].replace_insn);
+ remove_insn (to_delete[i].replace_insn);
+ to_delete[i].replace_insn->set_deleted ();
+ }
+
+ free (to_delete);
+}
+
+/* Main entry point for this pass. */
+unsigned int
+rs6000_analyze_swaps (function *fun)
+{
+ swap_web_entry *insn_entry;
+ basic_block bb;
+ rtx_insn *insn, *curr_insn = 0;
+
+ /* Dataflow analysis for use-def chains. */
+ df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
+ df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+
+ /* Pre-pass to recombine lvx and stvx patterns so we don't lose info. */
+ recombine_lvx_stvx_patterns (fun);
+
+ /* Allocate structure to represent webs of insns. */
+ insn_entry = XCNEWVEC (swap_web_entry, get_max_uid ());
+
+ /* Walk the insns to gather basic data. */
+ FOR_ALL_BB_FN (bb, fun)
+ FOR_BB_INSNS_SAFE (bb, insn, curr_insn)
+ {
+ unsigned int uid = INSN_UID (insn);
+ if (NONDEBUG_INSN_P (insn))
+ {
+ insn_entry[uid].insn = insn;
+
+ if (GET_CODE (insn) == CALL_INSN)
+ insn_entry[uid].is_call = 1;
+
+ /* Walk the uses and defs to see if we mention vector regs.
+ Record any constraints on optimization of such mentions. */
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref mention;
+ FOR_EACH_INSN_INFO_USE (mention, insn_info)
+ {
+ /* We use DF_REF_REAL_REG here to get inside any subregs. */
+ machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention));
+
+ /* If a use gets its value from a call insn, it will be
+ a hard register and will look like (reg:V4SI 3 3).
+ The df analysis creates two mentions for GPR3 and GPR4,
+ both DImode. We must recognize this and treat it as a
+ vector mention to ensure the call is unioned with this
+ use. */
+ if (mode == DImode && DF_REF_INSN_INFO (mention))
+ {
+ rtx feeder = DF_REF_INSN (mention);
+ /* FIXME: It is pretty hard to get from the df mention
+ to the mode of the use in the insn. We arbitrarily
+ pick a vector mode here, even though the use might
+ be a real DImode. We can be too conservative
+ (create a web larger than necessary) because of
+ this, so consider eventually fixing this. */
+ if (GET_CODE (feeder) == CALL_INSN)
+ mode = V4SImode;
+ }
+
+ if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
+ {
+ insn_entry[uid].is_relevant = 1;
+ if (mode == TImode || mode == V1TImode
+ || FLOAT128_VECTOR_P (mode))
+ insn_entry[uid].is_128_int = 1;
+ if (DF_REF_INSN_INFO (mention))
+ insn_entry[uid].contains_subreg
+ = !rtx_equal_p (DF_REF_REG (mention),
+ DF_REF_REAL_REG (mention));
+ union_defs (insn_entry, insn, mention);
+ }
+ }
+ FOR_EACH_INSN_INFO_DEF (mention, insn_info)
+ {
+ /* We use DF_REF_REAL_REG here to get inside any subregs. */
+ machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention));
+
+ /* If we're loading up a hard vector register for a call,
+ it looks like (set (reg:V4SI 9 9) (...)). The df
+ analysis creates two mentions for GPR9 and GPR10, both
+ DImode. So relying on the mode from the mentions
+ isn't sufficient to ensure we union the call into the
+ web with the parameter setup code. */
+ if (mode == DImode && GET_CODE (insn) == SET
+ && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
+ mode = GET_MODE (SET_DEST (insn));
+
+ if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
+ {
+ insn_entry[uid].is_relevant = 1;
+ if (mode == TImode || mode == V1TImode
+ || FLOAT128_VECTOR_P (mode))
+ insn_entry[uid].is_128_int = 1;
+ if (DF_REF_INSN_INFO (mention))
+ insn_entry[uid].contains_subreg
+ = !rtx_equal_p (DF_REF_REG (mention),
+ DF_REF_REAL_REG (mention));
+ /* REG_FUNCTION_VALUE_P is not valid for subregs. */
+ else if (REG_FUNCTION_VALUE_P (DF_REF_REG (mention)))
+ insn_entry[uid].is_live_out = 1;
+ union_uses (insn_entry, insn, mention);
+ }
+ }
+
+ if (insn_entry[uid].is_relevant)
+ {
+ /* Determine if this is a load or store. */
+ insn_entry[uid].is_load = insn_is_load_p (insn);
+ insn_entry[uid].is_store = insn_is_store_p (insn);
+
+ /* Determine if this is a doubleword swap. If not,
+ determine whether it can legally be swapped. */
+ if (insn_is_swap_p (insn))
+ insn_entry[uid].is_swap = 1;
+ else
+ {
+ unsigned int special = SH_NONE;
+ insn_entry[uid].is_swappable
+ = insn_is_swappable_p (insn_entry, insn, &special);
+ if (special != SH_NONE && insn_entry[uid].contains_subreg)
+ insn_entry[uid].is_swappable = 0;
+ else if (special != SH_NONE)
+ insn_entry[uid].special_handling = special;
+ else if (insn_entry[uid].contains_subreg)
+ insn_entry[uid].special_handling = SH_SUBREG;
+ }
+ }
+ }
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nSwap insn entry table when first built\n");
+ dump_swap_insn_table (insn_entry);
+ }
+
+ /* Record unoptimizable webs. */
+ unsigned e = get_max_uid (), i;
+ for (i = 0; i < e; ++i)
+ {
+ if (!insn_entry[i].is_relevant)
+ continue;
+
+ swap_web_entry *root
+ = (swap_web_entry*)(&insn_entry[i])->unionfind_root ();
+
+ if (insn_entry[i].is_live_in || insn_entry[i].is_live_out
+ || (insn_entry[i].contains_subreg
+ && insn_entry[i].special_handling != SH_SUBREG)
+ || insn_entry[i].is_128_int || insn_entry[i].is_call
+ || !(insn_entry[i].is_swappable || insn_entry[i].is_swap))
+ root->web_not_optimizable = 1;
+
+ /* If we have loads or stores that aren't permuting then the
+ optimization isn't appropriate. */
+ else if ((insn_entry[i].is_load || insn_entry[i].is_store)
+ && !insn_entry[i].is_swap && !insn_entry[i].is_swappable)
+ root->web_not_optimizable = 1;
+
+ /* If we have permuting loads or stores that are not accompanied
+ by a register swap, the optimization isn't appropriate. */
+ else if (insn_entry[i].is_load && insn_entry[i].is_swap)
+ {
+ rtx insn = insn_entry[i].insn;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref def;
+
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ struct df_link *link = DF_REF_CHAIN (def);
+
+ if (!chain_contains_only_swaps (insn_entry, link, FOR_LOADS))
+ {
+ root->web_not_optimizable = 1;
+ break;
+ }
+ }
+ }
+ else if (insn_entry[i].is_store && insn_entry[i].is_swap)
+ {
+ rtx insn = insn_entry[i].insn;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref use;
+
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ struct df_link *link = DF_REF_CHAIN (use);
+
+ if (!chain_contains_only_swaps (insn_entry, link, FOR_STORES))
+ {
+ root->web_not_optimizable = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nSwap insn entry table after web analysis\n");
+ dump_swap_insn_table (insn_entry);
+ }
+
+ /* For each load and store in an optimizable web (which implies
+ the loads and stores are permuting), find the associated
+ register swaps and mark them for removal. Due to various
+ optimizations we may mark the same swap more than once. Also
+ perform special handling for swappable insns that require it. */
+ for (i = 0; i < e; ++i)
+ if ((insn_entry[i].is_load || insn_entry[i].is_store)
+ && insn_entry[i].is_swap)
+ {
+ swap_web_entry* root_entry
+ = (swap_web_entry*)((&insn_entry[i])->unionfind_root ());
+ if (!root_entry->web_not_optimizable)
+ mark_swaps_for_removal (insn_entry, i);
+ }
+ else if (insn_entry[i].is_swappable && insn_entry[i].special_handling)
+ {
+ swap_web_entry* root_entry
+ = (swap_web_entry*)((&insn_entry[i])->unionfind_root ());
+ if (!root_entry->web_not_optimizable)
+ handle_special_swappables (insn_entry, i);
+ }
+
+ /* Now delete the swaps marked for removal. */
+ for (i = 0; i < e; ++i)
+ if (insn_entry[i].will_delete)
+ replace_swap_with_copy (insn_entry, i);
+
+ /* Clean up. */
+ free (insn_entry);
+ return 0;
+}
+
+const pass_data pass_data_analyze_swaps =
+{
+ RTL_PASS, /* type */
+ "swaps", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_analyze_swaps : public rtl_opt_pass
+{
+public:
+ pass_analyze_swaps(gcc::context *ctxt)
+ : rtl_opt_pass(pass_data_analyze_swaps, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return (optimize > 0 && !BYTES_BIG_ENDIAN && TARGET_VSX
+ && !TARGET_P9_VECTOR && rs6000_optimize_swaps);
+ }
+
+ virtual unsigned int execute (function *fun)
+ {
+ return rs6000_analyze_swaps (fun);
+ }
+
+ opt_pass *clone ()
+ {
+ return new pass_analyze_swaps (m_ctxt);
+ }
+
+}; // class pass_analyze_swaps
+
+rtl_opt_pass *
+make_pass_analyze_swaps (gcc::context *ctxt)
+{
+ return new pass_analyze_swaps (ctxt);
+}
+
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index e3132049270..144bdb26fa4 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -40,7 +40,7 @@ extern int num_insns_constant_wide (HOST_WIDE_INT);
extern int small_data_operand (rtx, machine_mode);
extern bool mem_operand_gpr (rtx, machine_mode);
extern bool mem_operand_ds_form (rtx, machine_mode);
-extern bool toc_relative_expr_p (const_rtx, bool);
+extern bool toc_relative_expr_p (const_rtx, bool, const_rtx *, const_rtx *);
extern void validate_condition_mode (enum rtx_code, machine_mode);
extern bool legitimate_constant_pool_address_p (const_rtx, machine_mode,
bool);
@@ -73,6 +73,7 @@ extern void rs6000_expand_extract_even (rtx, rtx, rtx);
extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
extern void rs6000_scale_v2df (rtx, rtx, int);
extern void rs6000_generate_float2_code (bool, rtx, rtx, rtx);
+extern void rs6000_generate_vsigned2_code (bool, rtx, rtx, rtx);
extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
extern bool expand_block_compare (rtx[]);
@@ -150,10 +151,10 @@ extern rtx rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx, rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
+extern void rs6000_emit_le_vsx_permute (rtx, rtx, machine_mode);
extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
extern bool valid_sf_si_move (rtx, rtx, machine_mode);
extern void rs6000_emit_move (rtx, rtx, machine_mode);
-extern rtx rs6000_secondary_memory_needed_rtx (machine_mode);
extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
int, int, int, int *);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 79dccba1dce..386a5cebc2f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -143,10 +143,6 @@ typedef struct GTY(()) machine_function
/* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
varargs save area. */
HOST_WIDE_INT varargs_save_offset;
- /* Temporary stack slot to use for SDmode copies. This slot is
- 64-bits wide and is allocated early enough so that the offset
- does not overflow the 16-bit load/store offset field. */
- rtx sdmode_stack_slot;
/* Alternative internal arg pointer for -fsplit-stack. */
rtx split_stack_arg_pointer;
bool split_stack_argp_used;
@@ -379,7 +375,9 @@ static const struct
{ "tar", PPC_FEATURE2_HAS_TAR, 1 },
{ "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 },
{ "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 },
- { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 }
+ { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 },
+ { "darn", PPC_FEATURE2_DARN, 1 },
+ { "scv", PPC_FEATURE2_SCV, 1 }
};
/* On PowerPC, we have a limited number of target clones that we care about
@@ -1872,12 +1870,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal
-#undef TARGET_EXPAND_TO_RTL_HOOK
-#define TARGET_EXPAND_TO_RTL_HOOK rs6000_alloc_sdmode_stack_slot
-
-#undef TARGET_INSTANTIATE_DECLS
-#define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
-
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
@@ -1887,9 +1879,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P rs6000_mode_dependent_address_p
-#undef TARGET_LRA_P
-#define TARGET_LRA_P rs6000_lra_p
-
#undef TARGET_COMPUTE_PRESSURE_CLASSES
#define TARGET_COMPUTE_PRESSURE_CLASSES rs6000_compute_pressure_classes
@@ -2104,14 +2093,11 @@ rs6000_hard_regno_mode_ok (int regno, machine_mode mode)
if(GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
return 1;
- if (TARGET_VSX_SMALL_INTEGER)
- {
- if (mode == SImode)
- return 1;
+ if (TARGET_P8_VECTOR && (mode == SImode))
+ return 1;
- if (TARGET_P9_VECTOR && (mode == HImode || mode == QImode))
- return 1;
- }
+ if (TARGET_P9_VECTOR && (mode == QImode || mode == HImode))
+ return 1;
}
if (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
@@ -2793,8 +2779,6 @@ rs6000_debug_reg_global (void)
if (TARGET_LINK_STACK)
fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
- fprintf (stderr, DEBUG_FMT_S, "lra", TARGET_LRA ? "true" : "false");
-
if (TARGET_P8_FUSION)
{
char options[80];
@@ -2907,9 +2891,7 @@ rs6000_setup_reg_addr_masks (void)
&& !VECTOR_MODE_P (m2)
&& !FLOAT128_VECTOR_P (m2)
&& !complex_p
- && !small_int_vsx_p
- && (m2 != DFmode || !TARGET_UPPER_REGS_DF)
- && (m2 != SFmode || !TARGET_UPPER_REGS_SF))
+ && !small_int_vsx_p)
{
addr_mask |= RELOAD_REG_PRE_INCDEC;
@@ -3218,22 +3200,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS; /* V2DFmode */
rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS; /* V4SFmode */
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS; /* DFmode */
+ rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS; /* DFmode */
+ rs6000_constraints[RS6000_CONSTRAINT_wi] = VSX_REGS; /* DImode */
if (TARGET_VSX_TIMODE)
rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS; /* TImode */
-
- if (TARGET_UPPER_REGS_DF) /* DFmode */
- {
- rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
- }
- else
- rs6000_constraints[RS6000_CONSTRAINT_ws] = FLOAT_REGS;
-
- if (TARGET_UPPER_REGS_DI) /* DImode */
- rs6000_constraints[RS6000_CONSTRAINT_wi] = VSX_REGS;
- else
- rs6000_constraints[RS6000_CONSTRAINT_wi] = FLOAT_REGS;
}
/* Add conditional constraints based on various options, to allow us to
@@ -3263,7 +3235,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
rs6000_constraints[RS6000_CONSTRAINT_wA] = BASE_REGS;
}
- if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF) /* SFmode */
+ if (TARGET_P8_VECTOR) /* SFmode */
{
rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
@@ -3303,7 +3275,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
rs6000_constraints[RS6000_CONSTRAINT_we] = VSX_REGS;
/* Support small integers in VSX registers. */
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
{
rs6000_constraints[RS6000_CONSTRAINT_wH] = ALTIVEC_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wI] = FLOAT_REGS;
@@ -3458,18 +3430,14 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
}
}
- if (TARGET_UPPER_REGS_DF)
- reg_addr[DFmode].scalar_in_vmx_p = true;
-
- if (TARGET_UPPER_REGS_DI)
- reg_addr[DImode].scalar_in_vmx_p = true;
+ reg_addr[DFmode].scalar_in_vmx_p = true;
+ reg_addr[DImode].scalar_in_vmx_p = true;
- if (TARGET_UPPER_REGS_SF)
- reg_addr[SFmode].scalar_in_vmx_p = true;
-
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
{
+ reg_addr[SFmode].scalar_in_vmx_p = true;
reg_addr[SImode].scalar_in_vmx_p = true;
+
if (TARGET_P9_VECTOR)
{
reg_addr[HImode].scalar_in_vmx_p = true;
@@ -3564,12 +3532,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
CODE_FOR_fusion_gpr_di_df_store },
};
- enum machine_mode cur_pmode = Pmode;
+ machine_mode cur_pmode = Pmode;
size_t i;
for (i = 0; i < ARRAY_SIZE (addis_insns); i++)
{
- enum machine_mode xmode = addis_insns[i].mode;
+ machine_mode xmode = addis_insns[i].mode;
enum rs6000_reload_reg_type rtype = addis_insns[i].rtype;
if (addis_insns[i].pmode != cur_pmode)
@@ -4277,18 +4245,10 @@ rs6000_option_override_internal (bool global_init_p)
{
if (cpu_index == PROCESSOR_POWER9)
{
- /* legacy behavior: allow -mcpu-power9 with certain
+ /* legacy behavior: allow -mcpu=power9 with certain
capabilities explicitly disabled. */
rs6000_isa_flags |= (ISA_3_0_MASKS_SERVER & ~ignore_masks);
- /* However, reject this automatic fix if certain
- capabilities required for TARGET_P9_MINMAX support
- have been explicitly disabled. */
- if (((OPTION_MASK_VSX | OPTION_MASK_UPPER_REGS_SF
- | OPTION_MASK_UPPER_REGS_DF) & rs6000_isa_flags)
- != (OPTION_MASK_VSX | OPTION_MASK_UPPER_REGS_SF
- | OPTION_MASK_UPPER_REGS_DF))
- error ("-mpower9-minmax incompatible with explicitly disabled options");
- }
+ }
else
error ("Power9 target option is incompatible with -mcpu=<xxx> for "
"<xxx> less than power9");
@@ -4374,73 +4334,6 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_isa_flags &= ~OPTION_MASK_DFP;
}
- /* Allow an explicit -mupper-regs to set -mupper-regs-df, -mupper-regs-di,
- and -mupper-regs-sf, depending on the cpu, unless the user explicitly also
- set the individual option. */
- if (TARGET_UPPER_REGS > 0)
- {
- if (TARGET_VSX
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DF))
- {
- rs6000_isa_flags |= OPTION_MASK_UPPER_REGS_DF;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_DF;
- }
- if (TARGET_VSX
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DI))
- {
- rs6000_isa_flags |= OPTION_MASK_UPPER_REGS_DI;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_DI;
- }
- if (TARGET_P8_VECTOR
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_SF))
- {
- rs6000_isa_flags |= OPTION_MASK_UPPER_REGS_SF;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_SF;
- }
- }
- else if (TARGET_UPPER_REGS == 0)
- {
- if (TARGET_VSX
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DF))
- {
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_DF;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_DF;
- }
- if (TARGET_VSX
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DI))
- {
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_DI;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_DI;
- }
- if (TARGET_P8_VECTOR
- && !(rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_SF))
- {
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_SF;
- rs6000_isa_flags_explicit |= OPTION_MASK_UPPER_REGS_SF;
- }
- }
-
- if (TARGET_UPPER_REGS_DF && !TARGET_VSX)
- {
- if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DF)
- error ("-mupper-regs-df requires -mvsx");
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_DF;
- }
-
- if (TARGET_UPPER_REGS_DI && !TARGET_VSX)
- {
- if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DI)
- error ("-mupper-regs-di requires -mvsx");
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_DI;
- }
-
- if (TARGET_UPPER_REGS_SF && !TARGET_P8_VECTOR)
- {
- if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_SF)
- error ("-mupper-regs-sf requires -mpower8-vector");
- rs6000_isa_flags &= ~OPTION_MASK_UPPER_REGS_SF;
- }
-
/* The quad memory instructions only works in 64-bit mode. In 32-bit mode,
silently turn off quad memory mode. */
if ((TARGET_QUAD_MEMORY || TARGET_QUAD_MEMORY_ATOMIC) && !TARGET_POWERPC64)
@@ -4649,53 +4542,10 @@ rs6000_option_override_internal (bool global_init_p)
}
}
- if (TARGET_P9_DFORM_SCALAR && !TARGET_UPPER_REGS_DF)
- {
- /* We prefer to not mention undocumented options in
- error messages. However, if users have managed to select
- power9-dform without selecting upper-regs-df, they
- already know about undocumented flags. */
- if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DF)
- error ("-mpower9-dform requires -mupper-regs-df");
- rs6000_isa_flags &= ~OPTION_MASK_P9_DFORM_SCALAR;
- }
-
- if (TARGET_P9_DFORM_SCALAR && !TARGET_UPPER_REGS_SF)
- {
- if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_SF)
- error ("-mpower9-dform requires -mupper-regs-sf");
- rs6000_isa_flags &= ~OPTION_MASK_P9_DFORM_SCALAR;
- }
-
- /* Enable LRA by default. */
- if ((rs6000_isa_flags_explicit & OPTION_MASK_LRA) == 0)
- rs6000_isa_flags |= OPTION_MASK_LRA;
-
- /* There have been bugs with -mvsx-timode that don't show up with -mlra,
- but do show up with -mno-lra. Given -mlra will become the default once
- PR 69847 is fixed, turn off the options with problems by default if
- -mno-lra was used, and warn if the user explicitly asked for the option.
-
- Enable -mpower9-dform-vector by default if LRA and other power9 options.
- Enable -mvsx-timode by default if LRA and VSX. */
- if (!TARGET_LRA)
- {
- if (TARGET_VSX_TIMODE)
- {
- if ((rs6000_isa_flags_explicit & OPTION_MASK_VSX_TIMODE) != 0)
- warning (0, "-mvsx-timode might need -mlra");
-
- else
- rs6000_isa_flags &= ~OPTION_MASK_VSX_TIMODE;
- }
- }
-
- else
- {
- if (TARGET_VSX && !TARGET_VSX_TIMODE
- && (rs6000_isa_flags_explicit & OPTION_MASK_VSX_TIMODE) == 0)
- rs6000_isa_flags |= OPTION_MASK_VSX_TIMODE;
- }
+ /* Enable -mvsx-timode by default if VSX. */
+ if (TARGET_VSX && !TARGET_VSX_TIMODE
+ && (rs6000_isa_flags_explicit & OPTION_MASK_VSX_TIMODE) == 0)
+ rs6000_isa_flags |= OPTION_MASK_VSX_TIMODE;
/* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07
support. If we only have ISA 2.06 support, and the user did not specify
@@ -4737,20 +4587,6 @@ rs6000_option_override_internal (bool global_init_p)
}
}
- /* Check whether we should allow small integers into VSX registers. We
- require direct move to prevent the register allocator from having to move
- variables through memory to do moves. SImode can be used on ISA 2.07,
- while HImode and QImode require ISA 3.0. */
- if (TARGET_VSX_SMALL_INTEGER
- && (!TARGET_DIRECT_MOVE || !TARGET_P8_VECTOR || !TARGET_UPPER_REGS_DI))
- {
- if (rs6000_isa_flags_explicit & OPTION_MASK_VSX_SMALL_INTEGER)
- error ("-mvsx-small-integer requires -mpower8-vector, "
- "-mupper-regs-di, and -mdirect-move");
-
- rs6000_isa_flags &= ~OPTION_MASK_VSX_SMALL_INTEGER;
- }
-
/* Set long double size before the IEEE 128-bit tests. */
if (!global_options_set.x_rs6000_long_double_type_size)
{
@@ -5757,7 +5593,7 @@ rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
if (TARGET_P9_VECTOR)
return TYPE_VECTOR_SUBPARTS (vectype) - 1 + 2;
else
- return TYPE_VECTOR_SUBPARTS (vectype) - 1 + 11;
+ return TYPE_VECTOR_SUBPARTS (vectype) - 1 + 5;
}
else
/* V2DFmode doesn't need a direct move. */
@@ -7443,8 +7279,7 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
else if (mode == V2DImode)
insn = gen_vsx_set_v2di (target, target, val, elt_rtx);
- else if (TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64)
+ else if (TARGET_P9_VECTOR && TARGET_POWERPC64)
{
if (mode == V4SImode)
insn = gen_vsx_set_v4si_p9 (target, target, val, elt_rtx);
@@ -8628,14 +8463,20 @@ constant_pool_expr_p (rtx op)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode));
}
-static const_rtx tocrel_base, tocrel_offset;
+/* These are only used to pass through from print_operand/print_operand_address
+ to rs6000_output_addr_const_extra over the intervening function
+ output_addr_const which is not target code. */
+static const_rtx tocrel_base_oac, tocrel_offset_oac;
/* Return true if OP is a toc pointer relative address (the output
of create_TOC_reference). If STRICT, do not match non-split
- -mcmodel=large/medium toc pointer relative addresses. */
+ -mcmodel=large/medium toc pointer relative addresses. If the pointers
+ are non-NULL, place base and offset pieces in TOCREL_BASE_RET and
+ TOCREL_OFFSET_RET respectively. */
bool
-toc_relative_expr_p (const_rtx op, bool strict)
+toc_relative_expr_p (const_rtx op, bool strict, const_rtx *tocrel_base_ret,
+ const_rtx *tocrel_offset_ret)
{
if (!TARGET_TOC)
return false;
@@ -8655,14 +8496,20 @@ toc_relative_expr_p (const_rtx op, bool strict)
op = XEXP (op, 1);
}
- tocrel_base = op;
- tocrel_offset = const0_rtx;
+ const_rtx tocrel_base = op;
+ const_rtx tocrel_offset = const0_rtx;
+
if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), GET_MODE (op)))
{
tocrel_base = XEXP (op, 0);
tocrel_offset = XEXP (op, 1);
}
+ if (tocrel_base_ret)
+ *tocrel_base_ret = tocrel_base;
+ if (tocrel_offset_ret)
+ *tocrel_offset_ret = tocrel_offset;
+
return (GET_CODE (tocrel_base) == UNSPEC
&& XINT (tocrel_base, 1) == UNSPEC_TOCREL);
}
@@ -8674,7 +8521,8 @@ bool
legitimate_constant_pool_address_p (const_rtx x, machine_mode mode,
bool strict)
{
- return (toc_relative_expr_p (x, strict)
+ const_rtx tocrel_base, tocrel_offset;
+ return (toc_relative_expr_p (x, strict, &tocrel_base, &tocrel_offset)
&& (TARGET_CMODEL != CMODEL_MEDIUM
|| constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0))
|| mode == QImode
@@ -8772,14 +8620,6 @@ legitimate_indexed_address_p (rtx x, int strict)
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
- /* Recognize the rtl generated by reload which we know will later be
- replaced with proper base and index regs. */
- if (!strict
- && reload_in_progress
- && (REG_P (op0) || GET_CODE (op0) == PLUS)
- && REG_P (op1))
- return true;
-
return (REG_P (op0) && REG_P (op1)
&& ((INT_REG_OK_FOR_BASE_P (op0, strict)
&& INT_REG_OK_FOR_INDEX_P (op1, strict))
@@ -10023,9 +9863,7 @@ rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
ret ? "true" : "false",
GET_MODE_NAME (mode),
reg_ok_strict,
- (reload_completed
- ? "after"
- : (reload_in_progress ? "progress" : "before")),
+ (reload_completed ? "after" : "before"),
GET_RTX_NAME (GET_CODE (x)));
debug_rtx (x);
@@ -10178,7 +10016,7 @@ rs6000_offsettable_memref_p (rtx op, machine_mode reg_mode)
static int
rs6000_reassociation_width (unsigned int opc ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ machine_mode mode)
{
switch (rs6000_cpu)
{
@@ -10427,9 +10265,6 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
static void
rs6000_eliminate_indexed_memrefs (rtx operands[2])
{
- if (reload_in_progress)
- return;
-
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) != REG
&& ! legitimate_constant_pool_address_p (XEXP (operands[0], 0),
@@ -10488,19 +10323,30 @@ rs6000_const_vec (machine_mode mode)
return v;
}
-/* Generate a permute rtx that represents an lxvd2x, stxvd2x, or xxpermdi
- for a VSX load or store operation. */
-rtx
-rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
+/* Emit an lxvd2x, stxvd2x, or xxpermdi instruction for a VSX load or
+ store operation. */
+void
+rs6000_emit_le_vsx_permute (rtx dest, rtx source, machine_mode mode)
{
- /* Use ROTATE instead of VEC_SELECT on IEEE 128-bit floating point, and
- 128-bit integers if they are allowed in VSX registers. */
- if (FLOAT128_VECTOR_P (mode) || mode == TImode || mode == V1TImode)
- return gen_rtx_ROTATE (mode, source, GEN_INT (64));
+ /* Scalar permutations are easier to express in integer modes rather than
+ floating-point modes, so cast them here. We use V1TImode instead
+ of TImode to ensure that the values don't go through GPRs. */
+ if (FLOAT128_VECTOR_P (mode))
+ {
+ dest = gen_lowpart (V1TImode, dest);
+ source = gen_lowpart (V1TImode, source);
+ mode = V1TImode;
+ }
+
+ /* Use ROTATE instead of VEC_SELECT if the mode contains only a single
+ scalar. */
+ if (mode == TImode || mode == V1TImode)
+ emit_insn (gen_rtx_SET (dest, gen_rtx_ROTATE (mode, source,
+ GEN_INT (64))));
else
{
rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
- return gen_rtx_VEC_SELECT (mode, source, par);
+ emit_insn (gen_rtx_SET (dest, gen_rtx_VEC_SELECT (mode, source, par)));
}
}
@@ -10510,8 +10356,6 @@ rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
void
rs6000_emit_le_vsx_load (rtx dest, rtx source, machine_mode mode)
{
- rtx tmp, permute_mem, permute_reg;
-
/* Use V2DImode to do swaps of types with 128-bit scalare parts (TImode,
V1TImode). */
if (mode == TImode || mode == V1TImode)
@@ -10521,11 +10365,9 @@ rs6000_emit_le_vsx_load (rtx dest, rtx source, machine_mode mode)
source = adjust_address (source, V2DImode, 0);
}
- tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (dest) : dest;
- permute_mem = rs6000_gen_le_vsx_permute (source, mode);
- permute_reg = rs6000_gen_le_vsx_permute (tmp, mode);
- emit_insn (gen_rtx_SET (tmp, permute_mem));
- emit_insn (gen_rtx_SET (dest, permute_reg));
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (dest) : dest;
+ rs6000_emit_le_vsx_permute (tmp, source, mode);
+ rs6000_emit_le_vsx_permute (dest, tmp, mode);
}
/* Emit a little-endian store to vector memory location DEST from VSX
@@ -10534,12 +10376,10 @@ rs6000_emit_le_vsx_load (rtx dest, rtx source, machine_mode mode)
void
rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode)
{
- rtx tmp, permute_src, permute_tmp;
-
- /* This should never be called during or after reload, because it does
+ /* This should never be called during or after LRA, because it does
not re-permute the source register. It is intended only for use
during expand. */
- gcc_assert (!reload_in_progress && !lra_in_progress && !reload_completed);
+ gcc_assert (!lra_in_progress && !reload_completed);
/* Use V2DImode to do swaps of types with 128-bit scalar parts (TImode,
V1TImode). */
@@ -10550,11 +10390,9 @@ rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode)
source = gen_lowpart (V2DImode, source);
}
- tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (source) : source;
- permute_src = rs6000_gen_le_vsx_permute (source, mode);
- permute_tmp = rs6000_gen_le_vsx_permute (tmp, mode);
- emit_insn (gen_rtx_SET (tmp, permute_src));
- emit_insn (gen_rtx_SET (dest, permute_tmp));
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (source) : source;
+ rs6000_emit_le_vsx_permute (tmp, source, mode);
+ rs6000_emit_le_vsx_permute (dest, tmp, mode);
}
/* Emit a sequence representing a little-endian VSX load or store,
@@ -10633,8 +10471,7 @@ valid_sf_si_move (rtx dest, rtx src, machine_mode mode)
static bool
rs6000_emit_move_si_sf_subreg (rtx dest, rtx source, machine_mode mode)
{
- if (TARGET_DIRECT_MOVE_64BIT && !reload_in_progress && !reload_completed
- && !lra_in_progress
+ if (TARGET_DIRECT_MOVE_64BIT && !lra_in_progress && !reload_completed
&& (!SUBREG_P (dest) || !sf_subreg_operand (dest, mode))
&& SUBREG_P (source) && sf_subreg_operand (source, mode))
{
@@ -10668,10 +10505,10 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr,
- "\nrs6000_emit_move: mode = %s, reload_in_progress = %d, "
+ "\nrs6000_emit_move: mode = %s, lra_in_progress = %d, "
"reload_completed = %d, can_create_pseudos = %d.\ndest:\n",
GET_MODE_NAME (mode),
- reload_in_progress,
+ lra_in_progress,
reload_completed,
can_create_pseudo_p ());
debug_rtx (dest);
@@ -10745,12 +10582,6 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
operands[1] = tmp;
}
- /* Handle the case where reload calls us with an invalid address. */
- if (reload_in_progress && mode == Pmode
- && (! general_operand (operands[1], mode)
- || ! nonimmediate_operand (operands[0], mode)))
- goto emit_set;
-
/* 128-bit constant floating-point values on Darwin should really be loaded
as two parts. However, this premature splitting is a problem when DFmode
values can go into Altivec registers. */
@@ -10768,11 +10599,6 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
return;
}
- if (reload_in_progress && cfun->machine->sdmode_stack_slot != NULL_RTX)
- cfun->machine->sdmode_stack_slot =
- eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
-
-
/* Transform (p0:DD, (SUBREG:DD p1:SD)) to ((SUBREG:SD p0:DD),
p1:SD) if p1 is not of floating point class and p0 is spilled as
we can have no analogous movsd_store for this. */
@@ -10882,57 +10708,6 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
return;
}
- if (reload_in_progress
- && mode == SDmode
- && cfun->machine->sdmode_stack_slot != NULL_RTX
- && MEM_P (operands[0])
- && rtx_equal_p (operands[0], cfun->machine->sdmode_stack_slot)
- && REG_P (operands[1]))
- {
- if (FP_REGNO_P (REGNO (operands[1])))
- {
- rtx mem = adjust_address_nv (operands[0], DDmode, 0);
- mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
- emit_insn (gen_movsd_store (mem, operands[1]));
- }
- else if (INT_REGNO_P (REGNO (operands[1])))
- {
- rtx mem = operands[0];
- if (BYTES_BIG_ENDIAN)
- mem = adjust_address_nv (mem, mode, 4);
- mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
- emit_insn (gen_movsd_hardfloat (mem, operands[1]));
- }
- else
- gcc_unreachable();
- return;
- }
- if (reload_in_progress
- && mode == SDmode
- && REG_P (operands[0])
- && MEM_P (operands[1])
- && cfun->machine->sdmode_stack_slot != NULL_RTX
- && rtx_equal_p (operands[1], cfun->machine->sdmode_stack_slot))
- {
- if (FP_REGNO_P (REGNO (operands[0])))
- {
- rtx mem = adjust_address_nv (operands[1], DDmode, 0);
- mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
- emit_insn (gen_movsd_load (operands[0], mem));
- }
- else if (INT_REGNO_P (REGNO (operands[0])))
- {
- rtx mem = operands[1];
- if (BYTES_BIG_ENDIAN)
- mem = adjust_address_nv (mem, mode, 4);
- mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
- emit_insn (gen_movsd_hardfloat (operands[0], mem));
- }
- else
- gcc_unreachable();
- return;
- }
-
/* FIXME: In the long term, this switch statement should go away
and be replaced by a sequence of tests based on things like
mode == Pmode. */
@@ -11069,7 +10844,7 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
> (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
|| (GET_CODE (operands[0]) == REG
&& FP_REGNO_P (REGNO (operands[0]))))
- && !toc_relative_expr_p (operands[1], false)
+ && !toc_relative_expr_p (operands[1], false, NULL, NULL)
&& (TARGET_CMODEL == CMODEL_SMALL
|| can_create_pseudo_p ()
|| (REG_P (operands[0])
@@ -11091,10 +10866,9 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
/* If we are to limit the number of things we put in the TOC and
this is a symbol plus a constant we can add in one insn,
- just put the symbol in the TOC and add the constant. Don't do
- this if reload is in progress. */
+ just put the symbol in the TOC and add the constant. */
if (GET_CODE (operands[1]) == CONST
- && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
+ && TARGET_NO_SUM_IN_TOC
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
&& (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
@@ -11140,10 +10914,9 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
/* Above, we may have called force_const_mem which may have returned
an invalid address. If we can, fix this up; otherwise, reload will
have to deal with it. */
- if (GET_CODE (operands[1]) == MEM && ! reload_in_progress)
+ if (GET_CODE (operands[1]) == MEM)
operands[1] = validize_mem (operands[1]);
- emit_set:
emit_insn (gen_rtx_SET (operands[0], operands[1]));
}
@@ -14341,7 +14114,8 @@ rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
return CONST0_RTX (tmode);
}
}
- else if (icode == CODE_FOR_xststdcdp
+ else if (icode == CODE_FOR_xststdcqp
+ || icode == CODE_FOR_xststdcdp
|| icode == CODE_FOR_xststdcsp
|| icode == CODE_FOR_xvtstdcdp
|| icode == CODE_FOR_xvtstdcsp)
@@ -15163,6 +14937,8 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED,
emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx));
emit_insn (gen_rtx_SET (target, gen_rtx_XOR (SImode, scratch2, const1_rtx)));
}
+ else
+ gcc_unreachable ();
/* Record that we have expanded a CPU builtin, so that we can later
emit a reference to the special symbol exported by LIBC to ensure we
@@ -15170,6 +14946,9 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED,
cpu_builtin_p = true;
#else
+ warning (0, "%s needs GLIBC (2.23 and newer) that exports hardware "
+ "capability bits", rs6000_builtin_info[(size_t) fcode].name);
+
/* For old LIBCs, always return FALSE. */
emit_move_insn (target, GEN_INT (0));
#endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */
@@ -16284,6 +16063,10 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
= (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
tree arg0, arg1, lhs;
+ /* Generic solution to prevent gimple folding of code without a LHS. */
+ if (!gimple_call_lhs (stmt))
+ return false;
+
switch (fn_code)
{
/* Flavors of vec_add. We deliberately don't expand
@@ -16335,11 +16118,9 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
/* Even element flavors of vec_mul (signed). */
case ALTIVEC_BUILTIN_VMULESB:
case ALTIVEC_BUILTIN_VMULESH:
- case ALTIVEC_BUILTIN_VMULESW:
/* Even element flavors of vec_mul (unsigned). */
case ALTIVEC_BUILTIN_VMULEUB:
case ALTIVEC_BUILTIN_VMULEUH:
- case ALTIVEC_BUILTIN_VMULEUW:
{
arg0 = gimple_call_arg (stmt, 0);
arg1 = gimple_call_arg (stmt, 1);
@@ -16352,11 +16133,9 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
/* Odd element flavors of vec_mul (signed). */
case ALTIVEC_BUILTIN_VMULOSB:
case ALTIVEC_BUILTIN_VMULOSH:
- case ALTIVEC_BUILTIN_VMULOSW:
/* Odd element flavors of vec_mul (unsigned). */
case ALTIVEC_BUILTIN_VMULOUB:
case ALTIVEC_BUILTIN_VMULOUH:
- case ALTIVEC_BUILTIN_VMULOUW:
{
arg0 = gimple_call_arg (stmt, 0);
arg1 = gimple_call_arg (stmt, 1);
@@ -17581,6 +17360,10 @@ altivec_init_builtins (void)
ALTIVEC_BUILTIN_VEC_CMPNE);
def_builtin ("__builtin_vec_mul", opaque_ftype_opaque_opaque,
ALTIVEC_BUILTIN_VEC_MUL);
+ def_builtin ("__builtin_vec_sube", opaque_ftype_opaque_opaque_opaque,
+ ALTIVEC_BUILTIN_VEC_SUBE);
+ def_builtin ("__builtin_vec_subec", opaque_ftype_opaque_opaque_opaque,
+ ALTIVEC_BUILTIN_VEC_SUBEC);
/* Cell builtins. */
def_builtin ("__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX);
@@ -19326,42 +19109,6 @@ mems_ok_for_quad_peep (rtx mem1, rtx mem2)
return 1;
}
-
-rtx
-rs6000_secondary_memory_needed_rtx (machine_mode mode)
-{
- static bool eliminated = false;
- rtx ret;
-
- if (mode != SDmode || TARGET_NO_SDMODE_STACK)
- ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
- else
- {
- rtx mem = cfun->machine->sdmode_stack_slot;
- gcc_assert (mem != NULL_RTX);
-
- if (!eliminated)
- {
- mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
- cfun->machine->sdmode_stack_slot = mem;
- eliminated = true;
- }
- ret = mem;
- }
-
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr, "\nrs6000_secondary_memory_needed_rtx, mode %s, rtx:\n",
- GET_MODE_NAME (mode));
- if (!ret)
- fprintf (stderr, "\tNULL_RTX\n");
- else
- debug_rtx (ret);
- }
-
- return ret;
-}
-
/* Return the mode to be used for memory when a secondary memory
location is needed. For SDmode values we need to use DDmode, in
all other cases we can use the same mode. */
@@ -19373,36 +19120,6 @@ rs6000_secondary_memory_needed_mode (machine_mode mode)
return mode;
}
-static tree
-rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
-{
- /* Don't walk into types. */
- if (*tp == NULL_TREE || *tp == error_mark_node || TYPE_P (*tp))
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
-
- switch (TREE_CODE (*tp))
- {
- case VAR_DECL:
- case PARM_DECL:
- case FIELD_DECL:
- case RESULT_DECL:
- case SSA_NAME:
- case REAL_CST:
- case MEM_REF:
- case VIEW_CONVERT_EXPR:
- if (TYPE_MODE (TREE_TYPE (*tp)) == SDmode)
- return *tp;
- break;
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
/* Classify a register type. Because the FMRGOW/FMRGEW instructions only work
on traditional floating point registers, and the VMRGOW/VMRGEW instructions
only work on the traditional altivec registers, note if an altivec register
@@ -19423,7 +19140,7 @@ register_to_reg_type (rtx reg, bool *is_altivec)
regno = REGNO (reg);
if (regno >= FIRST_PSEUDO_REGISTER)
{
- if (!lra_in_progress && !reload_in_progress && !reload_completed)
+ if (!lra_in_progress && !reload_completed)
return PSEUDO_REG_TYPE;
regno = true_regnum (reg);
@@ -19796,7 +19513,7 @@ rs6000_secondary_reload_simple_move (enum rs6000_reg_type to_type,
}
/* ISA 2.07: MTVSRWZ or MFVSRWZ. */
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
{
if (mode == SImode)
return true;
@@ -20500,64 +20217,6 @@ rs6000_secondary_reload_gpr (rtx reg, rtx mem, rtx scratch, bool store_p)
return;
}
-/* Allocate a 64-bit stack slot to be used for copying SDmode values through if
- this function has any SDmode references. If we are on a power7 or later, we
- don't need the 64-bit stack slot since the LFIWZX and STIFWX instructions
- can load/store the value. */
-
-static void
-rs6000_alloc_sdmode_stack_slot (void)
-{
- tree t;
- basic_block bb;
- gimple_stmt_iterator gsi;
-
- gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
- /* We use a different approach for dealing with the secondary
- memory in LRA. */
- if (ira_use_lra_p)
- return;
-
- if (TARGET_NO_SDMODE_STACK)
- return;
-
- FOR_EACH_BB_FN (bb, cfun)
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- tree ret = walk_gimple_op (gsi_stmt (gsi), rs6000_check_sdmode, NULL);
- if (ret)
- {
- rtx stack = assign_stack_local (DDmode, GET_MODE_SIZE (DDmode), 0);
- cfun->machine->sdmode_stack_slot = adjust_address_nv (stack,
- SDmode, 0);
- return;
- }
- }
-
- /* Check for any SDmode parameters of the function. */
- for (t = DECL_ARGUMENTS (cfun->decl); t; t = DECL_CHAIN (t))
- {
- if (TREE_TYPE (t) == error_mark_node)
- continue;
-
- if (TYPE_MODE (TREE_TYPE (t)) == SDmode
- || TYPE_MODE (DECL_ARG_TYPE (t)) == SDmode)
- {
- rtx stack = assign_stack_local (DDmode, GET_MODE_SIZE (DDmode), 0);
- cfun->machine->sdmode_stack_slot = adjust_address_nv (stack,
- SDmode, 0);
- return;
- }
- }
-}
-
-static void
-rs6000_instantiate_decls (void)
-{
- if (cfun->machine->sdmode_stack_slot != NULL_RTX)
- instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
-}
-
/* 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; but on some machines
@@ -20630,7 +20289,6 @@ rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
/* ISA 3.0 can load -128..127 using the XXSPLTIB instruction and
a sign extend in the Altivec registers. */
if (IN_RANGE (value, -128, 127) && TARGET_P9_VECTOR
- && TARGET_VSX_SMALL_INTEGER
&& (rclass == ALTIVEC_REGS || rclass == VSX_REGS))
return ALTIVEC_REGS;
}
@@ -21812,14 +21470,14 @@ print_operand (FILE *file, rtx x, int code)
}
else
{
- if (toc_relative_expr_p (x, false))
+ if (toc_relative_expr_p (x, false, &tocrel_base_oac, &tocrel_offset_oac))
/* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends
where the assembler expects to find them. eg.
(plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4)
without this hack would be output as "x@toc+4". We
want "x+4@toc". */
- output_addr_const (file, CONST_CAST_RTX (tocrel_base));
+ output_addr_const (file, CONST_CAST_RTX (tocrel_base_oac));
else
output_addr_const (file, x);
}
@@ -21886,7 +21544,7 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
}
#endif
- else if (toc_relative_expr_p (x, false))
+ else if (toc_relative_expr_p (x, false, &tocrel_base_oac, &tocrel_offset_oac))
{
/* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends
@@ -21895,17 +21553,17 @@ print_operand_address (FILE *file, rtx x)
. (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 8))
without this hack would be output as "x@toc+8@l(9)". We
want "x+8@toc@l(9)". */
- output_addr_const (file, CONST_CAST_RTX (tocrel_base));
+ output_addr_const (file, CONST_CAST_RTX (tocrel_base_oac));
if (GET_CODE (x) == LO_SUM)
fprintf (file, "@l(%s)", reg_names[REGNO (XEXP (x, 0))]);
else
- fprintf (file, "(%s)", reg_names[REGNO (XVECEXP (tocrel_base, 0, 1))]);
+ fprintf (file, "(%s)", reg_names[REGNO (XVECEXP (tocrel_base_oac, 0, 1))]);
}
else
gcc_unreachable ();
}
-/* Implement TARGET_OUTPUT_ADDR_CONST_EXTRA. */
+/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
static bool
rs6000_output_addr_const_extra (FILE *file, rtx x)
@@ -21918,11 +21576,11 @@ rs6000_output_addr_const_extra (FILE *file, rtx x)
&& REG_P (XVECEXP (x, 0, 1))
&& REGNO (XVECEXP (x, 0, 1)) == TOC_REGISTER);
output_addr_const (file, XVECEXP (x, 0, 0));
- if (x == tocrel_base && tocrel_offset != const0_rtx)
+ if (x == tocrel_base_oac && tocrel_offset_oac != const0_rtx)
{
- if (INTVAL (tocrel_offset) >= 0)
+ if (INTVAL (tocrel_offset_oac) >= 0)
fprintf (file, "+");
- output_addr_const (file, CONST_CAST_RTX (tocrel_offset));
+ output_addr_const (file, CONST_CAST_RTX (tocrel_offset_oac));
}
if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC))
{
@@ -22296,8 +21954,8 @@ rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED,
const_tree type1,
const_tree type2)
{
- enum machine_mode mode1 = TYPE_MODE (type1);
- enum machine_mode mode2 = TYPE_MODE (type2);
+ machine_mode mode1 = TYPE_MODE (type1);
+ machine_mode mode2 = TYPE_MODE (type2);
/* For complex modes, use the inner type. */
if (COMPLEX_MODE_P (mode1))
@@ -22732,7 +22390,8 @@ output_cbranch (rtx op, const char *label, int reversed, rtx_insn *insn)
if (note != NULL_RTX)
{
/* PROB is the difference from 50%. */
- int prob = XINT (note, 0) - REG_BR_PROB_BASE / 2;
+ int prob = profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ .to_reg_br_prob_base () - REG_BR_PROB_BASE / 2;
/* Only hint for highly probable/improbable branches on newer cpus when
we have real profile data, as static prediction overrides processor
@@ -23501,10 +23160,9 @@ rs6000_split_signbit (rtx dest, rtx src)
static void
emit_unlikely_jump (rtx cond, rtx label)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
rtx_insn *insn = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
- add_int_reg_note (insn, REG_BR_PROB, very_unlikely);
+ add_reg_br_prob_note (insn, profile_probability::very_unlikely ());
}
/* A subroutine of the atomic operation splitters. Emit a load-locked
@@ -23586,10 +23244,9 @@ static rtx
rs6000_pre_atomic_barrier (rtx mem, enum memmodel model)
{
rtx addr = XEXP (mem, 0);
- int strict_p = (reload_in_progress || reload_completed);
- if (!legitimate_indirect_address_p (addr, strict_p)
- && !legitimate_indexed_address_p (addr, strict_p))
+ if (!legitimate_indirect_address_p (addr, reload_completed)
+ && !legitimate_indexed_address_p (addr, reload_completed))
{
addr = force_reg (Pmode, addr);
mem = replace_equiv_address_nv (mem, addr);
@@ -29257,8 +28914,7 @@ rs6000_expand_split_stack_prologue (void)
insn = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
JUMP_LABEL (insn) = ok_label;
/* Mark the jump as very likely to be taken. */
- add_int_reg_note (insn, REG_BR_PROB,
- REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100);
+ add_reg_br_prob_note (insn, profile_probability::very_likely ());
lr = gen_rtx_REG (Pmode, LR_REGNO);
insn = emit_move_insn (r0, lr);
@@ -33317,7 +32973,7 @@ rs6000_machopic_legitimize_pic_address (rtx orig, machine_mode mode,
{
rtx base, offset;
- if (reg == NULL && ! reload_in_progress && ! reload_completed)
+ if (reg == NULL && !reload_completed)
reg = gen_reg_rtx (Pmode);
if (GET_CODE (orig) == CONST)
@@ -33343,7 +32999,7 @@ rs6000_machopic_legitimize_pic_address (rtx orig, machine_mode mode,
{
if (SMALL_INT (offset))
return plus_constant (Pmode, base, INTVAL (offset));
- else if (! reload_in_progress && ! reload_completed)
+ else if (!reload_completed)
offset = force_reg (Pmode, offset);
else
{
@@ -35979,14 +35635,6 @@ rs6000_libcall_value (machine_mode mode)
return gen_rtx_REG (mode, regno);
}
-
-/* Return true if we use LRA instead of reload pass. */
-static bool
-rs6000_lra_p (void)
-{
- return TARGET_LRA;
-}
-
/* Compute register pressure classes. We implement the target hook to avoid
IRA picking something like NON_SPECIAL_REGS as a pressure class, which can
lead to incorrect estimates of number of available registers and therefor
@@ -36338,11 +35986,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "string", OPTION_MASK_STRING, false, true },
{ "toc-fusion", OPTION_MASK_TOC_FUSION, false, true },
{ "update", OPTION_MASK_NO_UPDATE, true , true },
- { "upper-regs-di", OPTION_MASK_UPPER_REGS_DI, false, true },
- { "upper-regs-df", OPTION_MASK_UPPER_REGS_DF, false, true },
- { "upper-regs-sf", OPTION_MASK_UPPER_REGS_SF, false, true },
{ "vsx", OPTION_MASK_VSX, false, true },
- { "vsx-small-integer", OPTION_MASK_VSX_SMALL_INTEGER, false, true },
{ "vsx-timode", OPTION_MASK_VSX_TIMODE, false, true },
#ifdef OPTION_MASK_64BIT
#if TARGET_AIX_OS
@@ -37266,6 +36910,12 @@ rs6000_get_function_versions_dispatcher (void *decl)
default_node = default_version_info->this_node;
+#ifndef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
+ error_at (DECL_SOURCE_LOCATION (default_node->decl),
+ "target_clones attribute needs GLIBC (2.23 and newer) that "
+ "exports hardware capability bits");
+#else
+
if (targetm.has_ifunc_p ())
{
struct cgraph_function_version_info *it_v = NULL;
@@ -37297,6 +36947,7 @@ rs6000_get_function_versions_dispatcher (void *decl)
"multiversioning needs ifunc which is not supported "
"on this target");
}
+#endif
return dispatch_decl;
}
@@ -37311,29 +36962,19 @@ make_resolver_func (const tree default_decl,
const tree dispatch_decl,
basic_block *empty_bb)
{
- /* IFUNC's have to be globally visible. So, if the default_decl is
- not, then the name of the IFUNC should be made unique. */
- bool is_uniq = (TREE_PUBLIC (default_decl) == 0);
-
- /* Append the filename to the resolver function if the versions are
- not externally visible. This is because the resolver function has
- to be externally visible for the loader to find it. So, appending
- the filename will prevent conflicts with a resolver function from
- another module which is based on the same version name. */
- char *resolver_name = make_unique_name (default_decl, "resolver", is_uniq);
-
- /* The resolver function should return a (void *). */
+ /* Make the resolver function static. The resolver function returns
+ void *. */
+ tree decl_name = clone_function_name (default_decl, "resolver");
+ const char *resolver_name = IDENTIFIER_POINTER (decl_name);
tree type = build_function_type_list (ptr_type_node, NULL_TREE);
tree decl = build_fn_decl (resolver_name, type);
- tree decl_name = get_identifier (resolver_name);
SET_DECL_ASSEMBLER_NAME (decl, decl_name);
DECL_NAME (decl) = decl_name;
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 0;
- /* IFUNC resolvers have to be externally visible. */
- TREE_PUBLIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
DECL_UNINLINABLE (decl) = 1;
/* Resolver is not external, body is generated. */
@@ -37344,15 +36985,6 @@ make_resolver_func (const tree default_decl,
DECL_INITIAL (decl) = make_node (BLOCK);
DECL_STATIC_CONSTRUCTOR (decl) = 0;
- if (DECL_COMDAT_GROUP (default_decl) || TREE_PUBLIC (default_decl))
- {
- /* In this case, each translation unit with a call to this
- versioned function will put out a resolver. Ensure it
- is comdat to keep just one copy. */
- DECL_COMDAT (decl) = 1;
- make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
- }
-
/* Build result decl and add to function_decl. */
tree t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
DECL_ARTIFICIAL (t) = 1;
@@ -37374,7 +37006,7 @@ make_resolver_func (const tree default_decl,
= make_attribute ("ifunc", resolver_name, DECL_ATTRIBUTES (dispatch_decl));
cgraph_node::create_same_body_alias (dispatch_decl, decl);
- XDELETEVEC (resolver_name);
+
return decl;
}
@@ -37616,7 +37248,7 @@ rs6000_allocate_stack_temp (machine_mode mode,
{
rtx stack = assign_stack_temp (mode, GET_MODE_SIZE (mode));
rtx addr = XEXP (stack, 0);
- int strict_p = (reload_in_progress || reload_completed);
+ int strict_p = reload_completed;
if (!legitimate_indirect_address_p (addr, strict_p))
{
@@ -37638,13 +37270,12 @@ rs6000_allocate_stack_temp (machine_mode mode,
rtx
rs6000_address_for_fpconvert (rtx x)
{
- int strict_p = (reload_in_progress || reload_completed);
rtx addr;
gcc_assert (MEM_P (x));
addr = XEXP (x, 0);
- if (! legitimate_indirect_address_p (addr, strict_p)
- && ! legitimate_indexed_address_p (addr, strict_p))
+ if (! legitimate_indirect_address_p (addr, reload_completed)
+ && ! legitimate_indexed_address_p (addr, reload_completed))
{
if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
{
@@ -37682,10 +37313,9 @@ rs6000_address_for_altivec (rtx x)
if (!altivec_indexed_or_indirect_operand (x, GET_MODE (x)))
{
rtx addr = XEXP (x, 0);
- int strict_p = (reload_in_progress || reload_completed);
- if (!legitimate_indexed_address_p (addr, strict_p)
- && !legitimate_indirect_address_p (addr, strict_p))
+ if (!legitimate_indexed_address_p (addr, reload_completed)
+ && !legitimate_indirect_address_p (addr, reload_completed))
addr = copy_to_mode_reg (Pmode, addr);
addr = gen_rtx_AND (Pmode, addr, GEN_INT (-16));
@@ -38669,7 +38299,7 @@ fusion_p9_p (rtx addis_reg, /* register set via addis. */
rtx src) /* source (register or memory). */
{
rtx addr, mem, offset;
- enum machine_mode mode = GET_MODE (src);
+ machine_mode mode = GET_MODE (src);
/* Validate arguments. */
if (!base_reg_operand (addis_reg, GET_MODE (addis_reg)))
@@ -38843,7 +38473,7 @@ expand_fusion_p9_store (rtx *operands)
const char *
emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
{
- enum machine_mode mode = GET_MODE (reg);
+ machine_mode mode = GET_MODE (reg);
rtx hi;
rtx lo;
rtx addr;
@@ -38936,7 +38566,7 @@ emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
const char *
emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
{
- enum machine_mode mode = GET_MODE (reg);
+ machine_mode mode = GET_MODE (reg);
rtx hi;
rtx lo;
rtx addr;
@@ -39013,1859 +38643,6 @@ emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
return "";
}
-
-/* Analyze vector computations and remove unnecessary doubleword
- swaps (xxswapdi instructions). This pass is performed only
- for little-endian VSX code generation.
-
- For this specific case, loads and stores of 4x32 and 2x64 vectors
- are inefficient. These are implemented using the lvx2dx and
- stvx2dx instructions, which invert the order of doublewords in
- a vector register. Thus the code generation inserts an xxswapdi
- after each such load, and prior to each such store. (For spill
- code after register assignment, an additional xxswapdi is inserted
- following each store in order to return a hard register to its
- unpermuted value.)
-
- The extra xxswapdi instructions reduce performance. This can be
- particularly bad for vectorized code. The purpose of this pass
- is to reduce the number of xxswapdi instructions required for
- correctness.
-
- The primary insight is that much code that operates on vectors
- does not care about the relative order of elements in a register,
- so long as the correct memory order is preserved. If we have
- a computation where all input values are provided by lvxd2x/xxswapdi
- sequences, all outputs are stored using xxswapdi/stvxd2x sequences,
- and all intermediate computations are pure SIMD (independent of
- element order), then all the xxswapdi's associated with the loads
- and stores may be removed.
-
- This pass uses some of the infrastructure and logical ideas from
- the "web" pass in web.c. We create maximal webs of computations
- fitting the description above using union-find. Each such web is
- then optimized by removing its unnecessary xxswapdi instructions.
-
- The pass is placed prior to global optimization so that we can
- perform the optimization in the safest and simplest way possible;
- that is, by replacing each xxswapdi insn with a register copy insn.
- Subsequent forward propagation will remove copies where possible.
-
- There are some operations sensitive to element order for which we
- can still allow the operation, provided we modify those operations.
- These include CONST_VECTORs, for which we must swap the first and
- second halves of the constant vector; and SUBREGs, for which we
- must adjust the byte offset to account for the swapped doublewords.
- A remaining opportunity would be non-immediate-form splats, for
- which we should adjust the selected lane of the input. We should
- also make code generation adjustments for sum-across operations,
- since this is a common vectorizer reduction.
-
- Because we run prior to the first split, we can see loads and stores
- here that match *vsx_le_perm_{load,store}_<mode>. These are vanilla
- vector loads and stores that have not yet been split into a permuting
- load/store and a swap. (One way this can happen is with a builtin
- call to vec_vsx_{ld,st}.) We can handle these as well, but rather
- than deleting a swap, we convert the load/store into a permuting
- load/store (which effectively removes the swap). */
-
-/* Notes on Permutes
-
- We do not currently handle computations that contain permutes. There
- is a general transformation that can be performed correctly, but it
- may introduce more expensive code than it replaces. To handle these
- would require a cost model to determine when to perform the optimization.
- This commentary records how this could be done if desired.
-
- The most general permute is something like this (example for V16QI):
-
- (vec_select:V16QI (vec_concat:V32QI (op1:V16QI) (op2:V16QI))
- (parallel [(const_int a0) (const_int a1)
- ...
- (const_int a14) (const_int a15)]))
-
- where a0,...,a15 are in [0,31] and select elements from op1 and op2
- to produce in the result.
-
- Regardless of mode, we can convert the PARALLEL to a mask of 16
- byte-element selectors. Let's call this M, with M[i] representing
- the ith byte-element selector value. Then if we swap doublewords
- throughout the computation, we can get correct behavior by replacing
- M with M' as follows:
-
- M'[i] = { (M[i]+8)%16 : M[i] in [0,15]
- { ((M[i]+8)%16)+16 : M[i] in [16,31]
-
- This seems promising at first, since we are just replacing one mask
- with another. But certain masks are preferable to others. If M
- is a mask that matches a vmrghh pattern, for example, M' certainly
- will not. Instead of a single vmrghh, we would generate a load of
- M' and a vperm. So we would need to know how many xxswapd's we can
- remove as a result of this transformation to determine if it's
- profitable; and preferably the logic would need to be aware of all
- the special preferable masks.
-
- Another form of permute is an UNSPEC_VPERM, in which the mask is
- already in a register. In some cases, this mask may be a constant
- that we can discover with ud-chains, in which case the above
- transformation is ok. However, the common usage here is for the
- mask to be produced by an UNSPEC_LVSL, in which case the mask
- cannot be known at compile time. In such a case we would have to
- generate several instructions to compute M' as above at run time,
- and a cost model is needed again.
-
- However, when the mask M for an UNSPEC_VPERM is loaded from the
- constant pool, we can replace M with M' as above at no cost
- beyond adding a constant pool entry. */
-
-/* This is based on the union-find logic in web.c. web_entry_base is
- defined in df.h. */
-class swap_web_entry : public web_entry_base
-{
- public:
- /* Pointer to the insn. */
- rtx_insn *insn;
- /* Set if insn contains a mention of a vector register. All other
- fields are undefined if this field is unset. */
- unsigned int is_relevant : 1;
- /* Set if insn is a load. */
- unsigned int is_load : 1;
- /* Set if insn is a store. */
- unsigned int is_store : 1;
- /* Set if insn is a doubleword swap. This can either be a register swap
- or a permuting load or store (test is_load and is_store for this). */
- unsigned int is_swap : 1;
- /* Set if the insn has a live-in use of a parameter register. */
- unsigned int is_live_in : 1;
- /* Set if the insn has a live-out def of a return register. */
- unsigned int is_live_out : 1;
- /* Set if the insn contains a subreg reference of a vector register. */
- unsigned int contains_subreg : 1;
- /* Set if the insn contains a 128-bit integer operand. */
- unsigned int is_128_int : 1;
- /* Set if this is a call-insn. */
- unsigned int is_call : 1;
- /* Set if this insn does not perform a vector operation for which
- element order matters, or if we know how to fix it up if it does.
- Undefined if is_swap is set. */
- unsigned int is_swappable : 1;
- /* A nonzero value indicates what kind of special handling for this
- insn is required if doublewords are swapped. Undefined if
- is_swappable is not set. */
- unsigned int special_handling : 4;
- /* Set if the web represented by this entry cannot be optimized. */
- unsigned int web_not_optimizable : 1;
- /* Set if this insn should be deleted. */
- unsigned int will_delete : 1;
-};
-
-enum special_handling_values {
- SH_NONE = 0,
- SH_CONST_VECTOR,
- SH_SUBREG,
- SH_NOSWAP_LD,
- SH_NOSWAP_ST,
- SH_EXTRACT,
- SH_SPLAT,
- SH_XXPERMDI,
- SH_CONCAT,
- SH_VPERM
-};
-
-/* Union INSN with all insns containing definitions that reach USE.
- Detect whether USE is live-in to the current function. */
-static void
-union_defs (swap_web_entry *insn_entry, rtx insn, df_ref use)
-{
- struct df_link *link = DF_REF_CHAIN (use);
-
- if (!link)
- insn_entry[INSN_UID (insn)].is_live_in = 1;
-
- while (link)
- {
- if (DF_REF_IS_ARTIFICIAL (link->ref))
- insn_entry[INSN_UID (insn)].is_live_in = 1;
-
- if (DF_REF_INSN_INFO (link->ref))
- {
- rtx def_insn = DF_REF_INSN (link->ref);
- (void)unionfind_union (insn_entry + INSN_UID (insn),
- insn_entry + INSN_UID (def_insn));
- }
-
- link = link->next;
- }
-}
-
-/* Union INSN with all insns containing uses reached from DEF.
- Detect whether DEF is live-out from the current function. */
-static void
-union_uses (swap_web_entry *insn_entry, rtx insn, df_ref def)
-{
- struct df_link *link = DF_REF_CHAIN (def);
-
- if (!link)
- insn_entry[INSN_UID (insn)].is_live_out = 1;
-
- while (link)
- {
- /* This could be an eh use or some other artificial use;
- we treat these all the same (killing the optimization). */
- if (DF_REF_IS_ARTIFICIAL (link->ref))
- insn_entry[INSN_UID (insn)].is_live_out = 1;
-
- if (DF_REF_INSN_INFO (link->ref))
- {
- rtx use_insn = DF_REF_INSN (link->ref);
- (void)unionfind_union (insn_entry + INSN_UID (insn),
- insn_entry + INSN_UID (use_insn));
- }
-
- link = link->next;
- }
-}
-
-/* Return 1 iff INSN is a load insn, including permuting loads that
- represent an lvxd2x instruction; else return 0. */
-static unsigned int
-insn_is_load_p (rtx insn)
-{
- rtx body = PATTERN (insn);
-
- if (GET_CODE (body) == SET)
- {
- if (GET_CODE (SET_SRC (body)) == MEM)
- return 1;
-
- if (GET_CODE (SET_SRC (body)) == VEC_SELECT
- && GET_CODE (XEXP (SET_SRC (body), 0)) == MEM)
- return 1;
-
- return 0;
- }
-
- if (GET_CODE (body) != PARALLEL)
- return 0;
-
- rtx set = XVECEXP (body, 0, 0);
-
- if (GET_CODE (set) == SET && GET_CODE (SET_SRC (set)) == MEM)
- return 1;
-
- return 0;
-}
-
-/* Return 1 iff INSN is a store insn, including permuting stores that
- represent an stvxd2x instruction; else return 0. */
-static unsigned int
-insn_is_store_p (rtx insn)
-{
- rtx body = PATTERN (insn);
- if (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == MEM)
- return 1;
- if (GET_CODE (body) != PARALLEL)
- return 0;
- rtx set = XVECEXP (body, 0, 0);
- if (GET_CODE (set) == SET && GET_CODE (SET_DEST (set)) == MEM)
- return 1;
- return 0;
-}
-
-/* Return 1 iff INSN swaps doublewords. This may be a reg-reg swap,
- a permuting load, or a permuting store. */
-static unsigned int
-insn_is_swap_p (rtx insn)
-{
- rtx body = PATTERN (insn);
- if (GET_CODE (body) != SET)
- return 0;
- rtx rhs = SET_SRC (body);
- if (GET_CODE (rhs) != VEC_SELECT)
- return 0;
- rtx parallel = XEXP (rhs, 1);
- if (GET_CODE (parallel) != PARALLEL)
- return 0;
- unsigned int len = XVECLEN (parallel, 0);
- if (len != 2 && len != 4 && len != 8 && len != 16)
- return 0;
- for (unsigned int i = 0; i < len / 2; ++i)
- {
- rtx op = XVECEXP (parallel, 0, i);
- if (GET_CODE (op) != CONST_INT || INTVAL (op) != len / 2 + i)
- return 0;
- }
- for (unsigned int i = len / 2; i < len; ++i)
- {
- rtx op = XVECEXP (parallel, 0, i);
- if (GET_CODE (op) != CONST_INT || INTVAL (op) != i - len / 2)
- return 0;
- }
- return 1;
-}
-
-/* Return TRUE if insn is a swap fed by a load from the constant pool. */
-static bool
-const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
-{
- unsigned uid = INSN_UID (insn);
- if (!insn_entry[uid].is_swap || insn_entry[uid].is_load)
- return false;
-
- /* Find the unique use in the swap and locate its def. If the def
- isn't unique, punt. */
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref use;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- struct df_link *def_link = DF_REF_CHAIN (use);
- if (!def_link || def_link->next)
- return false;
-
- rtx def_insn = DF_REF_INSN (def_link->ref);
- unsigned uid2 = INSN_UID (def_insn);
- if (!insn_entry[uid2].is_load || !insn_entry[uid2].is_swap)
- return false;
-
- rtx body = PATTERN (def_insn);
- if (GET_CODE (body) != SET
- || GET_CODE (SET_SRC (body)) != VEC_SELECT
- || GET_CODE (XEXP (SET_SRC (body), 0)) != MEM)
- return false;
-
- rtx mem = XEXP (SET_SRC (body), 0);
- rtx base_reg = XEXP (mem, 0);
-
- df_ref base_use;
- insn_info = DF_INSN_INFO_GET (def_insn);
- FOR_EACH_INSN_INFO_USE (base_use, insn_info)
- {
- if (!rtx_equal_p (DF_REF_REG (base_use), base_reg))
- continue;
-
- struct df_link *base_def_link = DF_REF_CHAIN (base_use);
- if (!base_def_link || base_def_link->next)
- return false;
-
- rtx tocrel_insn = DF_REF_INSN (base_def_link->ref);
- rtx tocrel_body = PATTERN (tocrel_insn);
- rtx base, offset;
- if (GET_CODE (tocrel_body) != SET)
- return false;
- /* There is an extra level of indirection for small/large
- code models. */
- rtx tocrel_expr = SET_SRC (tocrel_body);
- if (GET_CODE (tocrel_expr) == MEM)
- tocrel_expr = XEXP (tocrel_expr, 0);
- if (!toc_relative_expr_p (tocrel_expr, false))
- return false;
- split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
- if (GET_CODE (base) != SYMBOL_REF || !CONSTANT_POOL_ADDRESS_P (base))
- return false;
- }
- }
- return true;
-}
-
-/* Return TRUE iff OP matches a V2DF reduction pattern. See the
- definition of vsx_reduc_<VEC_reduc_name>_v2df in vsx.md. */
-static bool
-v2df_reduction_p (rtx op)
-{
- if (GET_MODE (op) != V2DFmode)
- return false;
-
- enum rtx_code code = GET_CODE (op);
- if (code != PLUS && code != SMIN && code != SMAX)
- return false;
-
- rtx concat = XEXP (op, 0);
- if (GET_CODE (concat) != VEC_CONCAT)
- return false;
-
- rtx select0 = XEXP (concat, 0);
- rtx select1 = XEXP (concat, 1);
- if (GET_CODE (select0) != VEC_SELECT || GET_CODE (select1) != VEC_SELECT)
- return false;
-
- rtx reg0 = XEXP (select0, 0);
- rtx reg1 = XEXP (select1, 0);
- if (!rtx_equal_p (reg0, reg1) || !REG_P (reg0))
- return false;
-
- rtx parallel0 = XEXP (select0, 1);
- rtx parallel1 = XEXP (select1, 1);
- if (GET_CODE (parallel0) != PARALLEL || GET_CODE (parallel1) != PARALLEL)
- return false;
-
- if (!rtx_equal_p (XVECEXP (parallel0, 0, 0), const1_rtx)
- || !rtx_equal_p (XVECEXP (parallel1, 0, 0), const0_rtx))
- return false;
-
- return true;
-}
-
-/* Return 1 iff OP is an operand that will not be affected by having
- vector doublewords swapped in memory. */
-static unsigned int
-rtx_is_swappable_p (rtx op, unsigned int *special)
-{
- enum rtx_code code = GET_CODE (op);
- int i, j;
- rtx parallel;
-
- switch (code)
- {
- case LABEL_REF:
- case SYMBOL_REF:
- case CLOBBER:
- case REG:
- return 1;
-
- case VEC_CONCAT:
- case ASM_INPUT:
- case ASM_OPERANDS:
- return 0;
-
- case CONST_VECTOR:
- {
- *special = SH_CONST_VECTOR;
- return 1;
- }
-
- case VEC_DUPLICATE:
- /* Opportunity: If XEXP (op, 0) has the same mode as the result,
- and XEXP (op, 1) is a PARALLEL with a single QImode const int,
- it represents a vector splat for which we can do special
- handling. */
- if (GET_CODE (XEXP (op, 0)) == CONST_INT)
- return 1;
- else if (REG_P (XEXP (op, 0))
- && GET_MODE_INNER (GET_MODE (op)) == GET_MODE (XEXP (op, 0)))
- /* This catches V2DF and V2DI splat, at a minimum. */
- return 1;
- else if (GET_CODE (XEXP (op, 0)) == TRUNCATE
- && REG_P (XEXP (XEXP (op, 0), 0))
- && GET_MODE_INNER (GET_MODE (op)) == GET_MODE (XEXP (op, 0)))
- /* This catches splat of a truncated value. */
- return 1;
- else if (GET_CODE (XEXP (op, 0)) == VEC_SELECT)
- /* If the duplicated item is from a select, defer to the select
- processing to see if we can change the lane for the splat. */
- return rtx_is_swappable_p (XEXP (op, 0), special);
- else
- return 0;
-
- case VEC_SELECT:
- /* A vec_extract operation is ok if we change the lane. */
- if (GET_CODE (XEXP (op, 0)) == REG
- && GET_MODE_INNER (GET_MODE (XEXP (op, 0))) == GET_MODE (op)
- && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
- && XVECLEN (parallel, 0) == 1
- && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT)
- {
- *special = SH_EXTRACT;
- return 1;
- }
- /* An XXPERMDI is ok if we adjust the lanes. Note that if the
- XXPERMDI is a swap operation, it will be identified by
- insn_is_swap_p and therefore we won't get here. */
- else if (GET_CODE (XEXP (op, 0)) == VEC_CONCAT
- && (GET_MODE (XEXP (op, 0)) == V4DFmode
- || GET_MODE (XEXP (op, 0)) == V4DImode)
- && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
- && XVECLEN (parallel, 0) == 2
- && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT
- && GET_CODE (XVECEXP (parallel, 0, 1)) == CONST_INT)
- {
- *special = SH_XXPERMDI;
- return 1;
- }
- else if (v2df_reduction_p (op))
- return 1;
- else
- return 0;
-
- case UNSPEC:
- {
- /* Various operations are unsafe for this optimization, at least
- without significant additional work. Permutes are obviously
- problematic, as both the permute control vector and the ordering
- of the target values are invalidated by doubleword swapping.
- Vector pack and unpack modify the number of vector lanes.
- Merge-high/low will not operate correctly on swapped operands.
- Vector shifts across element boundaries are clearly uncool,
- as are vector select and concatenate operations. Vector
- sum-across instructions define one operand with a specific
- order-dependent element, so additional fixup code would be
- needed to make those work. Vector set and non-immediate-form
- vector splat are element-order sensitive. A few of these
- cases might be workable with special handling if required.
- Adding cost modeling would be appropriate in some cases. */
- int val = XINT (op, 1);
- switch (val)
- {
- default:
- break;
- case UNSPEC_VMRGH_DIRECT:
- case UNSPEC_VMRGL_DIRECT:
- case UNSPEC_VPACK_SIGN_SIGN_SAT:
- case UNSPEC_VPACK_SIGN_UNS_SAT:
- case UNSPEC_VPACK_UNS_UNS_MOD:
- case UNSPEC_VPACK_UNS_UNS_MOD_DIRECT:
- case UNSPEC_VPACK_UNS_UNS_SAT:
- case UNSPEC_VPERM:
- case UNSPEC_VPERM_UNS:
- case UNSPEC_VPERMHI:
- case UNSPEC_VPERMSI:
- case UNSPEC_VPKPX:
- case UNSPEC_VSLDOI:
- case UNSPEC_VSLO:
- case UNSPEC_VSRO:
- case UNSPEC_VSUM2SWS:
- case UNSPEC_VSUM4S:
- case UNSPEC_VSUM4UBS:
- case UNSPEC_VSUMSWS:
- case UNSPEC_VSUMSWS_DIRECT:
- case UNSPEC_VSX_CONCAT:
- case UNSPEC_VSX_SET:
- case UNSPEC_VSX_SLDWI:
- case UNSPEC_VUNPACK_HI_SIGN:
- case UNSPEC_VUNPACK_HI_SIGN_DIRECT:
- case UNSPEC_VUNPACK_LO_SIGN:
- case UNSPEC_VUNPACK_LO_SIGN_DIRECT:
- case UNSPEC_VUPKHPX:
- case UNSPEC_VUPKHS_V4SF:
- case UNSPEC_VUPKHU_V4SF:
- case UNSPEC_VUPKLPX:
- case UNSPEC_VUPKLS_V4SF:
- case UNSPEC_VUPKLU_V4SF:
- case UNSPEC_VSX_CVDPSPN:
- case UNSPEC_VSX_CVSPDP:
- case UNSPEC_VSX_CVSPDPN:
- case UNSPEC_VSX_EXTRACT:
- case UNSPEC_VSX_VSLO:
- case UNSPEC_VSX_VEC_INIT:
- return 0;
- case UNSPEC_VSPLT_DIRECT:
- case UNSPEC_VSX_XXSPLTD:
- *special = SH_SPLAT;
- return 1;
- case UNSPEC_REDUC_PLUS:
- case UNSPEC_REDUC:
- return 1;
- }
- }
-
- default:
- break;
- }
-
- const char *fmt = GET_RTX_FORMAT (code);
- int ok = 1;
-
- for (i = 0; i < GET_RTX_LENGTH (code); ++i)
- if (fmt[i] == 'e' || fmt[i] == 'u')
- {
- unsigned int special_op = SH_NONE;
- ok &= rtx_is_swappable_p (XEXP (op, i), &special_op);
- if (special_op == SH_NONE)
- continue;
- /* Ensure we never have two kinds of special handling
- for the same insn. */
- if (*special != SH_NONE && *special != special_op)
- return 0;
- *special = special_op;
- }
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (op, i); ++j)
- {
- unsigned int special_op = SH_NONE;
- ok &= rtx_is_swappable_p (XVECEXP (op, i, j), &special_op);
- if (special_op == SH_NONE)
- continue;
- /* Ensure we never have two kinds of special handling
- for the same insn. */
- if (*special != SH_NONE && *special != special_op)
- return 0;
- *special = special_op;
- }
-
- return ok;
-}
-
-/* Return 1 iff INSN is an operand that will not be affected by
- having vector doublewords swapped in memory (in which case
- *SPECIAL is unchanged), or that can be modified to be correct
- if vector doublewords are swapped in memory (in which case
- *SPECIAL is changed to a value indicating how). */
-static unsigned int
-insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn,
- unsigned int *special)
-{
- /* Calls are always bad. */
- if (GET_CODE (insn) == CALL_INSN)
- return 0;
-
- /* Loads and stores seen here are not permuting, but we can still
- fix them up by converting them to permuting ones. Exceptions:
- UNSPEC_LVE, UNSPEC_LVX, and UNSPEC_STVX, which have a PARALLEL
- body instead of a SET; and UNSPEC_STVE, which has an UNSPEC
- for the SET source. Also we must now make an exception for lvx
- and stvx when they are not in the UNSPEC_LVX/STVX form (with the
- explicit "& -16") since this leads to unrecognizable insns. */
- rtx body = PATTERN (insn);
- int i = INSN_UID (insn);
-
- if (insn_entry[i].is_load)
- {
- if (GET_CODE (body) == SET)
- {
- rtx rhs = SET_SRC (body);
- /* Even without a swap, the RHS might be a vec_select for, say,
- a byte-reversing load. */
- if (GET_CODE (rhs) != MEM)
- return 0;
- if (GET_CODE (XEXP (rhs, 0)) == AND)
- return 0;
-
- *special = SH_NOSWAP_LD;
- return 1;
- }
- else
- return 0;
- }
-
- if (insn_entry[i].is_store)
- {
- if (GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) != UNSPEC)
- {
- rtx lhs = SET_DEST (body);
- /* Even without a swap, the LHS might be a vec_select for, say,
- a byte-reversing store. */
- if (GET_CODE (lhs) != MEM)
- return 0;
- if (GET_CODE (XEXP (lhs, 0)) == AND)
- return 0;
-
- *special = SH_NOSWAP_ST;
- return 1;
- }
- else
- return 0;
- }
-
- /* A convert to single precision can be left as is provided that
- all of its uses are in xxspltw instructions that splat BE element
- zero. */
- if (GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) == UNSPEC
- && XINT (SET_SRC (body), 1) == UNSPEC_VSX_CVDPSPN)
- {
- df_ref def;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-
- FOR_EACH_INSN_INFO_DEF (def, insn_info)
- {
- struct df_link *link = DF_REF_CHAIN (def);
- if (!link)
- return 0;
-
- for (; link; link = link->next) {
- rtx use_insn = DF_REF_INSN (link->ref);
- rtx use_body = PATTERN (use_insn);
- if (GET_CODE (use_body) != SET
- || GET_CODE (SET_SRC (use_body)) != UNSPEC
- || XINT (SET_SRC (use_body), 1) != UNSPEC_VSX_XXSPLTW
- || XVECEXP (SET_SRC (use_body), 0, 1) != const0_rtx)
- return 0;
- }
- }
-
- return 1;
- }
-
- /* A concatenation of two doublewords is ok if we reverse the
- order of the inputs. */
- if (GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) == VEC_CONCAT
- && (GET_MODE (SET_SRC (body)) == V2DFmode
- || GET_MODE (SET_SRC (body)) == V2DImode))
- {
- *special = SH_CONCAT;
- return 1;
- }
-
- /* V2DF reductions are always swappable. */
- if (GET_CODE (body) == PARALLEL)
- {
- rtx expr = XVECEXP (body, 0, 0);
- if (GET_CODE (expr) == SET
- && v2df_reduction_p (SET_SRC (expr)))
- return 1;
- }
-
- /* An UNSPEC_VPERM is ok if the mask operand is loaded from the
- constant pool. */
- if (GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) == UNSPEC
- && XINT (SET_SRC (body), 1) == UNSPEC_VPERM
- && XVECLEN (SET_SRC (body), 0) == 3
- && GET_CODE (XVECEXP (SET_SRC (body), 0, 2)) == REG)
- {
- rtx mask_reg = XVECEXP (SET_SRC (body), 0, 2);
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref use;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- if (rtx_equal_p (DF_REF_REG (use), mask_reg))
- {
- struct df_link *def_link = DF_REF_CHAIN (use);
- /* Punt if multiple definitions for this reg. */
- if (def_link && !def_link->next &&
- const_load_sequence_p (insn_entry,
- DF_REF_INSN (def_link->ref)))
- {
- *special = SH_VPERM;
- return 1;
- }
- }
- }
-
- /* Otherwise check the operands for vector lane violations. */
- return rtx_is_swappable_p (body, special);
-}
-
-enum chain_purpose { FOR_LOADS, FOR_STORES };
-
-/* Return true if the UD or DU chain headed by LINK is non-empty,
- and every entry on the chain references an insn that is a
- register swap. Furthermore, if PURPOSE is FOR_LOADS, each such
- register swap must have only permuting loads as reaching defs.
- If PURPOSE is FOR_STORES, each such register swap must have only
- register swaps or permuting stores as reached uses. */
-static bool
-chain_contains_only_swaps (swap_web_entry *insn_entry, struct df_link *link,
- enum chain_purpose purpose)
-{
- if (!link)
- return false;
-
- for (; link; link = link->next)
- {
- if (!ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (DF_REF_REG (link->ref))))
- continue;
-
- if (DF_REF_IS_ARTIFICIAL (link->ref))
- return false;
-
- rtx reached_insn = DF_REF_INSN (link->ref);
- unsigned uid = INSN_UID (reached_insn);
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (reached_insn);
-
- if (!insn_entry[uid].is_swap || insn_entry[uid].is_load
- || insn_entry[uid].is_store)
- return false;
-
- if (purpose == FOR_LOADS)
- {
- df_ref use;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- struct df_link *swap_link = DF_REF_CHAIN (use);
-
- while (swap_link)
- {
- if (DF_REF_IS_ARTIFICIAL (link->ref))
- return false;
-
- rtx swap_def_insn = DF_REF_INSN (swap_link->ref);
- unsigned uid2 = INSN_UID (swap_def_insn);
-
- /* Only permuting loads are allowed. */
- if (!insn_entry[uid2].is_swap || !insn_entry[uid2].is_load)
- return false;
-
- swap_link = swap_link->next;
- }
- }
- }
- else if (purpose == FOR_STORES)
- {
- df_ref def;
- FOR_EACH_INSN_INFO_DEF (def, insn_info)
- {
- struct df_link *swap_link = DF_REF_CHAIN (def);
-
- while (swap_link)
- {
- if (DF_REF_IS_ARTIFICIAL (link->ref))
- return false;
-
- rtx swap_use_insn = DF_REF_INSN (swap_link->ref);
- unsigned uid2 = INSN_UID (swap_use_insn);
-
- /* Permuting stores or register swaps are allowed. */
- if (!insn_entry[uid2].is_swap || insn_entry[uid2].is_load)
- return false;
-
- swap_link = swap_link->next;
- }
- }
- }
- }
-
- return true;
-}
-
-/* Mark the xxswapdi instructions associated with permuting loads and
- stores for removal. Note that we only flag them for deletion here,
- as there is a possibility of a swap being reached from multiple
- loads, etc. */
-static void
-mark_swaps_for_removal (swap_web_entry *insn_entry, unsigned int i)
-{
- rtx insn = insn_entry[i].insn;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-
- if (insn_entry[i].is_load)
- {
- df_ref def;
- FOR_EACH_INSN_INFO_DEF (def, insn_info)
- {
- struct df_link *link = DF_REF_CHAIN (def);
-
- /* We know by now that these are swaps, so we can delete
- them confidently. */
- while (link)
- {
- rtx use_insn = DF_REF_INSN (link->ref);
- insn_entry[INSN_UID (use_insn)].will_delete = 1;
- link = link->next;
- }
- }
- }
- else if (insn_entry[i].is_store)
- {
- df_ref use;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- /* Ignore uses for addressability. */
- machine_mode mode = GET_MODE (DF_REF_REG (use));
- if (!ALTIVEC_OR_VSX_VECTOR_MODE (mode))
- continue;
-
- struct df_link *link = DF_REF_CHAIN (use);
-
- /* We know by now that these are swaps, so we can delete
- them confidently. */
- while (link)
- {
- rtx def_insn = DF_REF_INSN (link->ref);
- insn_entry[INSN_UID (def_insn)].will_delete = 1;
- link = link->next;
- }
- }
- }
-}
-
-/* OP is either a CONST_VECTOR or an expression containing one.
- Swap the first half of the vector with the second in the first
- case. Recurse to find it in the second. */
-static void
-swap_const_vector_halves (rtx op)
-{
- int i;
- enum rtx_code code = GET_CODE (op);
- if (GET_CODE (op) == CONST_VECTOR)
- {
- int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
- for (i = 0; i < half_units; ++i)
- {
- rtx temp = CONST_VECTOR_ELT (op, i);
- CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
- CONST_VECTOR_ELT (op, i + half_units) = temp;
- }
- }
- else
- {
- int j;
- const char *fmt = GET_RTX_FORMAT (code);
- for (i = 0; i < GET_RTX_LENGTH (code); ++i)
- if (fmt[i] == 'e' || fmt[i] == 'u')
- swap_const_vector_halves (XEXP (op, i));
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (op, i); ++j)
- swap_const_vector_halves (XVECEXP (op, i, j));
- }
-}
-
-/* Find all subregs of a vector expression that perform a narrowing,
- and adjust the subreg index to account for doubleword swapping. */
-static void
-adjust_subreg_index (rtx op)
-{
- enum rtx_code code = GET_CODE (op);
- if (code == SUBREG
- && (GET_MODE_SIZE (GET_MODE (op))
- < GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))))
- {
- unsigned int index = SUBREG_BYTE (op);
- if (index < 8)
- index += 8;
- else
- index -= 8;
- SUBREG_BYTE (op) = index;
- }
-
- const char *fmt = GET_RTX_FORMAT (code);
- int i,j;
- for (i = 0; i < GET_RTX_LENGTH (code); ++i)
- if (fmt[i] == 'e' || fmt[i] == 'u')
- adjust_subreg_index (XEXP (op, i));
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (op, i); ++j)
- adjust_subreg_index (XVECEXP (op, i, j));
-}
-
-/* Convert the non-permuting load INSN to a permuting one. */
-static void
-permute_load (rtx_insn *insn)
-{
- rtx body = PATTERN (insn);
- rtx mem_op = SET_SRC (body);
- rtx tgt_reg = SET_DEST (body);
- machine_mode mode = GET_MODE (tgt_reg);
- int n_elts = GET_MODE_NUNITS (mode);
- int half_elts = n_elts / 2;
- rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
- int i, j;
- for (i = 0, j = half_elts; i < half_elts; ++i, ++j)
- XVECEXP (par, 0, i) = GEN_INT (j);
- for (i = half_elts, j = 0; j < half_elts; ++i, ++j)
- XVECEXP (par, 0, i) = GEN_INT (j);
- rtx sel = gen_rtx_VEC_SELECT (mode, mem_op, par);
- SET_SRC (body) = sel;
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Replacing load %d with permuted load\n",
- INSN_UID (insn));
-}
-
-/* Convert the non-permuting store INSN to a permuting one. */
-static void
-permute_store (rtx_insn *insn)
-{
- rtx body = PATTERN (insn);
- rtx src_reg = SET_SRC (body);
- machine_mode mode = GET_MODE (src_reg);
- int n_elts = GET_MODE_NUNITS (mode);
- int half_elts = n_elts / 2;
- rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
- int i, j;
- for (i = 0, j = half_elts; i < half_elts; ++i, ++j)
- XVECEXP (par, 0, i) = GEN_INT (j);
- for (i = half_elts, j = 0; j < half_elts; ++i, ++j)
- XVECEXP (par, 0, i) = GEN_INT (j);
- rtx sel = gen_rtx_VEC_SELECT (mode, src_reg, par);
- SET_SRC (body) = sel;
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Replacing store %d with permuted store\n",
- INSN_UID (insn));
-}
-
-/* Given OP that contains a vector extract operation, adjust the index
- of the extracted lane to account for the doubleword swap. */
-static void
-adjust_extract (rtx_insn *insn)
-{
- rtx pattern = PATTERN (insn);
- if (GET_CODE (pattern) == PARALLEL)
- pattern = XVECEXP (pattern, 0, 0);
- rtx src = SET_SRC (pattern);
- /* The vec_select may be wrapped in a vec_duplicate for a splat, so
- account for that. */
- rtx sel = GET_CODE (src) == VEC_DUPLICATE ? XEXP (src, 0) : src;
- rtx par = XEXP (sel, 1);
- int half_elts = GET_MODE_NUNITS (GET_MODE (XEXP (sel, 0))) >> 1;
- int lane = INTVAL (XVECEXP (par, 0, 0));
- lane = lane >= half_elts ? lane - half_elts : lane + half_elts;
- XVECEXP (par, 0, 0) = GEN_INT (lane);
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Changing lane for extract %d\n", INSN_UID (insn));
-}
-
-/* Given OP that contains a vector direct-splat operation, adjust the index
- of the source lane to account for the doubleword swap. */
-static void
-adjust_splat (rtx_insn *insn)
-{
- rtx body = PATTERN (insn);
- rtx unspec = XEXP (body, 1);
- int half_elts = GET_MODE_NUNITS (GET_MODE (unspec)) >> 1;
- int lane = INTVAL (XVECEXP (unspec, 0, 1));
- lane = lane >= half_elts ? lane - half_elts : lane + half_elts;
- XVECEXP (unspec, 0, 1) = GEN_INT (lane);
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn));
-}
-
-/* Given OP that contains an XXPERMDI operation (that is not a doubleword
- swap), reverse the order of the source operands and adjust the indices
- of the source lanes to account for doubleword reversal. */
-static void
-adjust_xxpermdi (rtx_insn *insn)
-{
- rtx set = PATTERN (insn);
- rtx select = XEXP (set, 1);
- rtx concat = XEXP (select, 0);
- rtx src0 = XEXP (concat, 0);
- XEXP (concat, 0) = XEXP (concat, 1);
- XEXP (concat, 1) = src0;
- rtx parallel = XEXP (select, 1);
- int lane0 = INTVAL (XVECEXP (parallel, 0, 0));
- int lane1 = INTVAL (XVECEXP (parallel, 0, 1));
- int new_lane0 = 3 - lane1;
- int new_lane1 = 3 - lane0;
- XVECEXP (parallel, 0, 0) = GEN_INT (new_lane0);
- XVECEXP (parallel, 0, 1) = GEN_INT (new_lane1);
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Changing lanes for xxpermdi %d\n", INSN_UID (insn));
-}
-
-/* Given OP that contains a VEC_CONCAT operation of two doublewords,
- reverse the order of those inputs. */
-static void
-adjust_concat (rtx_insn *insn)
-{
- rtx set = PATTERN (insn);
- rtx concat = XEXP (set, 1);
- rtx src0 = XEXP (concat, 0);
- XEXP (concat, 0) = XEXP (concat, 1);
- XEXP (concat, 1) = src0;
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "Reversing inputs for concat %d\n", INSN_UID (insn));
-}
-
-/* Given an UNSPEC_VPERM insn, modify the mask loaded from the
- constant pool to reflect swapped doublewords. */
-static void
-adjust_vperm (rtx_insn *insn)
-{
- /* We previously determined that the UNSPEC_VPERM was fed by a
- swap of a swapping load of a TOC-relative constant pool symbol.
- Find the MEM in the swapping load and replace it with a MEM for
- the adjusted mask constant. */
- rtx set = PATTERN (insn);
- rtx mask_reg = XVECEXP (SET_SRC (set), 0, 2);
-
- /* Find the swap. */
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref use;
- rtx_insn *swap_insn = 0;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- if (rtx_equal_p (DF_REF_REG (use), mask_reg))
- {
- struct df_link *def_link = DF_REF_CHAIN (use);
- gcc_assert (def_link && !def_link->next);
- swap_insn = DF_REF_INSN (def_link->ref);
- break;
- }
- gcc_assert (swap_insn);
-
- /* Find the load. */
- insn_info = DF_INSN_INFO_GET (swap_insn);
- rtx_insn *load_insn = 0;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- struct df_link *def_link = DF_REF_CHAIN (use);
- gcc_assert (def_link && !def_link->next);
- load_insn = DF_REF_INSN (def_link->ref);
- break;
- }
- gcc_assert (load_insn);
-
- /* Find the TOC-relative symbol access. */
- insn_info = DF_INSN_INFO_GET (load_insn);
- rtx_insn *tocrel_insn = 0;
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- struct df_link *def_link = DF_REF_CHAIN (use);
- gcc_assert (def_link && !def_link->next);
- tocrel_insn = DF_REF_INSN (def_link->ref);
- break;
- }
- gcc_assert (tocrel_insn);
-
- /* Find the embedded CONST_VECTOR. We have to call toc_relative_expr_p
- to set tocrel_base; otherwise it would be unnecessary as we've
- already established it will return true. */
- rtx base, offset;
- rtx tocrel_expr = SET_SRC (PATTERN (tocrel_insn));
- /* There is an extra level of indirection for small/large code models. */
- if (GET_CODE (tocrel_expr) == MEM)
- tocrel_expr = XEXP (tocrel_expr, 0);
- if (!toc_relative_expr_p (tocrel_expr, false))
- gcc_unreachable ();
- split_const (XVECEXP (tocrel_base, 0, 0), &base, &offset);
- rtx const_vector = get_pool_constant (base);
- /* With the extra indirection, get_pool_constant will produce the
- real constant from the reg_equal expression, so get the real
- constant. */
- if (GET_CODE (const_vector) == SYMBOL_REF)
- const_vector = get_pool_constant (const_vector);
- gcc_assert (GET_CODE (const_vector) == CONST_VECTOR);
-
- /* Create an adjusted mask from the initial mask. */
- unsigned int new_mask[16], i, val;
- for (i = 0; i < 16; ++i) {
- val = INTVAL (XVECEXP (const_vector, 0, i));
- if (val < 16)
- new_mask[i] = (val + 8) % 16;
- else
- new_mask[i] = ((val + 8) % 16) + 16;
- }
-
- /* Create a new CONST_VECTOR and a MEM that references it. */
- rtx vals = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
- for (i = 0; i < 16; ++i)
- XVECEXP (vals, 0, i) = GEN_INT (new_mask[i]);
- rtx new_const_vector = gen_rtx_CONST_VECTOR (V16QImode, XVEC (vals, 0));
- rtx new_mem = force_const_mem (V16QImode, new_const_vector);
- /* This gives us a MEM whose base operand is a SYMBOL_REF, which we
- can't recognize. Force the SYMBOL_REF into a register. */
- if (!REG_P (XEXP (new_mem, 0))) {
- rtx base_reg = force_reg (Pmode, XEXP (new_mem, 0));
- XEXP (new_mem, 0) = base_reg;
- /* Move the newly created insn ahead of the load insn. */
- rtx_insn *force_insn = get_last_insn ();
- remove_insn (force_insn);
- rtx_insn *before_load_insn = PREV_INSN (load_insn);
- add_insn_after (force_insn, before_load_insn, BLOCK_FOR_INSN (load_insn));
- df_insn_rescan (before_load_insn);
- df_insn_rescan (force_insn);
- }
-
- /* Replace the MEM in the load instruction and rescan it. */
- XEXP (SET_SRC (PATTERN (load_insn)), 0) = new_mem;
- INSN_CODE (load_insn) = -1; /* Force re-recognition. */
- df_insn_rescan (load_insn);
-
- if (dump_file)
- fprintf (dump_file, "Adjusting mask for vperm %d\n", INSN_UID (insn));
-}
-
-/* The insn described by INSN_ENTRY[I] can be swapped, but only
- with special handling. Take care of that here. */
-static void
-handle_special_swappables (swap_web_entry *insn_entry, unsigned i)
-{
- rtx_insn *insn = insn_entry[i].insn;
- rtx body = PATTERN (insn);
-
- switch (insn_entry[i].special_handling)
- {
- default:
- gcc_unreachable ();
- case SH_CONST_VECTOR:
- {
- /* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
- gcc_assert (GET_CODE (body) == SET);
- rtx rhs = SET_SRC (body);
- swap_const_vector_halves (rhs);
- if (dump_file)
- fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
- break;
- }
- case SH_SUBREG:
- /* A subreg of the same size is already safe. For subregs that
- select a smaller portion of a reg, adjust the index for
- swapped doublewords. */
- adjust_subreg_index (body);
- if (dump_file)
- fprintf (dump_file, "Adjusting subreg in insn %d\n", i);
- break;
- case SH_NOSWAP_LD:
- /* Convert a non-permuting load to a permuting one. */
- permute_load (insn);
- break;
- case SH_NOSWAP_ST:
- /* Convert a non-permuting store to a permuting one. */
- permute_store (insn);
- break;
- case SH_EXTRACT:
- /* Change the lane on an extract operation. */
- adjust_extract (insn);
- break;
- case SH_SPLAT:
- /* Change the lane on a direct-splat operation. */
- adjust_splat (insn);
- break;
- case SH_XXPERMDI:
- /* Change the lanes on an XXPERMDI operation. */
- adjust_xxpermdi (insn);
- break;
- case SH_CONCAT:
- /* Reverse the order of a concatenation operation. */
- adjust_concat (insn);
- break;
- case SH_VPERM:
- /* Change the mask loaded from the constant pool for a VPERM. */
- adjust_vperm (insn);
- break;
- }
-}
-
-/* Find the insn from the Ith table entry, which is known to be a
- register swap Y = SWAP(X). Replace it with a copy Y = X. */
-static void
-replace_swap_with_copy (swap_web_entry *insn_entry, unsigned i)
-{
- rtx_insn *insn = insn_entry[i].insn;
- rtx body = PATTERN (insn);
- rtx src_reg = XEXP (SET_SRC (body), 0);
- rtx copy = gen_rtx_SET (SET_DEST (body), src_reg);
- rtx_insn *new_insn = emit_insn_before (copy, insn);
- set_block_for_insn (new_insn, BLOCK_FOR_INSN (insn));
- df_insn_rescan (new_insn);
-
- if (dump_file)
- {
- unsigned int new_uid = INSN_UID (new_insn);
- fprintf (dump_file, "Replacing swap %d with copy %d\n", i, new_uid);
- }
-
- df_insn_delete (insn);
- remove_insn (insn);
- insn->set_deleted ();
-}
-
-/* Dump the swap table to DUMP_FILE. */
-static void
-dump_swap_insn_table (swap_web_entry *insn_entry)
-{
- int e = get_max_uid ();
- fprintf (dump_file, "\nRelevant insns with their flag settings\n\n");
-
- for (int i = 0; i < e; ++i)
- if (insn_entry[i].is_relevant)
- {
- swap_web_entry *pred_entry = (swap_web_entry *)insn_entry[i].pred ();
- fprintf (dump_file, "%6d %6d ", i,
- pred_entry && pred_entry->insn
- ? INSN_UID (pred_entry->insn) : 0);
- if (insn_entry[i].is_load)
- fputs ("load ", dump_file);
- if (insn_entry[i].is_store)
- fputs ("store ", dump_file);
- if (insn_entry[i].is_swap)
- fputs ("swap ", dump_file);
- if (insn_entry[i].is_live_in)
- fputs ("live-in ", dump_file);
- if (insn_entry[i].is_live_out)
- fputs ("live-out ", dump_file);
- if (insn_entry[i].contains_subreg)
- fputs ("subreg ", dump_file);
- if (insn_entry[i].is_128_int)
- fputs ("int128 ", dump_file);
- if (insn_entry[i].is_call)
- fputs ("call ", dump_file);
- if (insn_entry[i].is_swappable)
- {
- fputs ("swappable ", dump_file);
- if (insn_entry[i].special_handling == SH_CONST_VECTOR)
- fputs ("special:constvec ", dump_file);
- else if (insn_entry[i].special_handling == SH_SUBREG)
- fputs ("special:subreg ", dump_file);
- else if (insn_entry[i].special_handling == SH_NOSWAP_LD)
- fputs ("special:load ", dump_file);
- else if (insn_entry[i].special_handling == SH_NOSWAP_ST)
- fputs ("special:store ", dump_file);
- else if (insn_entry[i].special_handling == SH_EXTRACT)
- fputs ("special:extract ", dump_file);
- else if (insn_entry[i].special_handling == SH_SPLAT)
- fputs ("special:splat ", dump_file);
- else if (insn_entry[i].special_handling == SH_XXPERMDI)
- fputs ("special:xxpermdi ", dump_file);
- else if (insn_entry[i].special_handling == SH_CONCAT)
- fputs ("special:concat ", dump_file);
- else if (insn_entry[i].special_handling == SH_VPERM)
- fputs ("special:vperm ", dump_file);
- }
- if (insn_entry[i].web_not_optimizable)
- fputs ("unoptimizable ", dump_file);
- if (insn_entry[i].will_delete)
- fputs ("delete ", dump_file);
- fputs ("\n", dump_file);
- }
- fputs ("\n", dump_file);
-}
-
-/* Return RTX with its address canonicalized to (reg) or (+ reg reg).
- Here RTX is an (& addr (const_int -16)). Always return a new copy
- to avoid problems with combine. */
-static rtx
-alignment_with_canonical_addr (rtx align)
-{
- rtx canon;
- rtx addr = XEXP (align, 0);
-
- if (REG_P (addr))
- canon = addr;
-
- else if (GET_CODE (addr) == PLUS)
- {
- rtx addrop0 = XEXP (addr, 0);
- rtx addrop1 = XEXP (addr, 1);
-
- if (!REG_P (addrop0))
- addrop0 = force_reg (GET_MODE (addrop0), addrop0);
-
- if (!REG_P (addrop1))
- addrop1 = force_reg (GET_MODE (addrop1), addrop1);
-
- canon = gen_rtx_PLUS (GET_MODE (addr), addrop0, addrop1);
- }
-
- else
- canon = force_reg (GET_MODE (addr), addr);
-
- return gen_rtx_AND (GET_MODE (align), canon, GEN_INT (-16));
-}
-
-/* Check whether an rtx is an alignment mask, and if so, return
- a fully-expanded rtx for the masking operation. */
-static rtx
-alignment_mask (rtx_insn *insn)
-{
- rtx body = PATTERN (insn);
-
- if (GET_CODE (body) != SET
- || GET_CODE (SET_SRC (body)) != AND
- || !REG_P (XEXP (SET_SRC (body), 0)))
- return 0;
-
- rtx mask = XEXP (SET_SRC (body), 1);
-
- if (GET_CODE (mask) == CONST_INT)
- {
- if (INTVAL (mask) == -16)
- return alignment_with_canonical_addr (SET_SRC (body));
- else
- return 0;
- }
-
- if (!REG_P (mask))
- return 0;
-
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref use;
- rtx real_mask = 0;
-
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- if (!rtx_equal_p (DF_REF_REG (use), mask))
- continue;
-
- struct df_link *def_link = DF_REF_CHAIN (use);
- if (!def_link || def_link->next)
- return 0;
-
- rtx_insn *const_insn = DF_REF_INSN (def_link->ref);
- rtx const_body = PATTERN (const_insn);
- if (GET_CODE (const_body) != SET)
- return 0;
-
- real_mask = SET_SRC (const_body);
-
- if (GET_CODE (real_mask) != CONST_INT
- || INTVAL (real_mask) != -16)
- return 0;
- }
-
- if (real_mask == 0)
- return 0;
-
- return alignment_with_canonical_addr (SET_SRC (body));
-}
-
-/* Given INSN that's a load or store based at BASE_REG, look for a
- feeding computation that aligns its address on a 16-byte boundary. */
-static rtx
-find_alignment_op (rtx_insn *insn, rtx base_reg)
-{
- df_ref base_use;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- rtx and_operation = 0;
-
- FOR_EACH_INSN_INFO_USE (base_use, insn_info)
- {
- if (!rtx_equal_p (DF_REF_REG (base_use), base_reg))
- continue;
-
- struct df_link *base_def_link = DF_REF_CHAIN (base_use);
- if (!base_def_link || base_def_link->next)
- break;
-
- /* With stack-protector code enabled, and possibly in other
- circumstances, there may not be an associated insn for
- the def. */
- if (DF_REF_IS_ARTIFICIAL (base_def_link->ref))
- break;
-
- rtx_insn *and_insn = DF_REF_INSN (base_def_link->ref);
- and_operation = alignment_mask (and_insn);
- if (and_operation != 0)
- break;
- }
-
- return and_operation;
-}
-
-struct del_info { bool replace; rtx_insn *replace_insn; };
-
-/* If INSN is the load for an lvx pattern, put it in canonical form. */
-static void
-recombine_lvx_pattern (rtx_insn *insn, del_info *to_delete)
-{
- rtx body = PATTERN (insn);
- gcc_assert (GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) == VEC_SELECT
- && GET_CODE (XEXP (SET_SRC (body), 0)) == MEM);
-
- rtx mem = XEXP (SET_SRC (body), 0);
- rtx base_reg = XEXP (mem, 0);
-
- rtx and_operation = find_alignment_op (insn, base_reg);
-
- if (and_operation != 0)
- {
- df_ref def;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- FOR_EACH_INSN_INFO_DEF (def, insn_info)
- {
- struct df_link *link = DF_REF_CHAIN (def);
- if (!link || link->next)
- break;
-
- rtx_insn *swap_insn = DF_REF_INSN (link->ref);
- if (!insn_is_swap_p (swap_insn)
- || insn_is_load_p (swap_insn)
- || insn_is_store_p (swap_insn))
- break;
-
- /* Expected lvx pattern found. Change the swap to
- a copy, and propagate the AND operation into the
- load. */
- to_delete[INSN_UID (swap_insn)].replace = true;
- to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn;
-
- XEXP (mem, 0) = and_operation;
- SET_SRC (body) = mem;
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "lvx opportunity found at %d\n",
- INSN_UID (insn));
- }
- }
-}
-
-/* If INSN is the store for an stvx pattern, put it in canonical form. */
-static void
-recombine_stvx_pattern (rtx_insn *insn, del_info *to_delete)
-{
- rtx body = PATTERN (insn);
- gcc_assert (GET_CODE (body) == SET
- && GET_CODE (SET_DEST (body)) == MEM
- && GET_CODE (SET_SRC (body)) == VEC_SELECT);
- rtx mem = SET_DEST (body);
- rtx base_reg = XEXP (mem, 0);
-
- rtx and_operation = find_alignment_op (insn, base_reg);
-
- if (and_operation != 0)
- {
- rtx src_reg = XEXP (SET_SRC (body), 0);
- df_ref src_use;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- FOR_EACH_INSN_INFO_USE (src_use, insn_info)
- {
- if (!rtx_equal_p (DF_REF_REG (src_use), src_reg))
- continue;
-
- struct df_link *link = DF_REF_CHAIN (src_use);
- if (!link || link->next)
- break;
-
- rtx_insn *swap_insn = DF_REF_INSN (link->ref);
- if (!insn_is_swap_p (swap_insn)
- || insn_is_load_p (swap_insn)
- || insn_is_store_p (swap_insn))
- break;
-
- /* Expected stvx pattern found. Change the swap to
- a copy, and propagate the AND operation into the
- store. */
- to_delete[INSN_UID (swap_insn)].replace = true;
- to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn;
-
- XEXP (mem, 0) = and_operation;
- SET_SRC (body) = src_reg;
- INSN_CODE (insn) = -1; /* Force re-recognition. */
- df_insn_rescan (insn);
-
- if (dump_file)
- fprintf (dump_file, "stvx opportunity found at %d\n",
- INSN_UID (insn));
- }
- }
-}
-
-/* Look for patterns created from builtin lvx and stvx calls, and
- canonicalize them to be properly recognized as such. */
-static void
-recombine_lvx_stvx_patterns (function *fun)
-{
- int i;
- basic_block bb;
- rtx_insn *insn;
-
- int num_insns = get_max_uid ();
- del_info *to_delete = XCNEWVEC (del_info, num_insns);
-
- FOR_ALL_BB_FN (bb, fun)
- FOR_BB_INSNS (bb, insn)
- {
- if (!NONDEBUG_INSN_P (insn))
- continue;
-
- if (insn_is_load_p (insn) && insn_is_swap_p (insn))
- recombine_lvx_pattern (insn, to_delete);
- else if (insn_is_store_p (insn) && insn_is_swap_p (insn))
- recombine_stvx_pattern (insn, to_delete);
- }
-
- /* Turning swaps into copies is delayed until now, to avoid problems
- with deleting instructions during the insn walk. */
- for (i = 0; i < num_insns; i++)
- if (to_delete[i].replace)
- {
- rtx swap_body = PATTERN (to_delete[i].replace_insn);
- rtx src_reg = XEXP (SET_SRC (swap_body), 0);
- rtx copy = gen_rtx_SET (SET_DEST (swap_body), src_reg);
- rtx_insn *new_insn = emit_insn_before (copy,
- to_delete[i].replace_insn);
- set_block_for_insn (new_insn,
- BLOCK_FOR_INSN (to_delete[i].replace_insn));
- df_insn_rescan (new_insn);
- df_insn_delete (to_delete[i].replace_insn);
- remove_insn (to_delete[i].replace_insn);
- to_delete[i].replace_insn->set_deleted ();
- }
-
- free (to_delete);
-}
-
-/* Main entry point for this pass. */
-unsigned int
-rs6000_analyze_swaps (function *fun)
-{
- swap_web_entry *insn_entry;
- basic_block bb;
- rtx_insn *insn, *curr_insn = 0;
-
- /* Dataflow analysis for use-def chains. */
- df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
- df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
- df_analyze ();
- df_set_flags (DF_DEFER_INSN_RESCAN);
-
- /* Pre-pass to recombine lvx and stvx patterns so we don't lose info. */
- recombine_lvx_stvx_patterns (fun);
-
- /* Allocate structure to represent webs of insns. */
- insn_entry = XCNEWVEC (swap_web_entry, get_max_uid ());
-
- /* Walk the insns to gather basic data. */
- FOR_ALL_BB_FN (bb, fun)
- FOR_BB_INSNS_SAFE (bb, insn, curr_insn)
- {
- unsigned int uid = INSN_UID (insn);
- if (NONDEBUG_INSN_P (insn))
- {
- insn_entry[uid].insn = insn;
-
- if (GET_CODE (insn) == CALL_INSN)
- insn_entry[uid].is_call = 1;
-
- /* Walk the uses and defs to see if we mention vector regs.
- Record any constraints on optimization of such mentions. */
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref mention;
- FOR_EACH_INSN_INFO_USE (mention, insn_info)
- {
- /* We use DF_REF_REAL_REG here to get inside any subregs. */
- machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention));
-
- /* If a use gets its value from a call insn, it will be
- a hard register and will look like (reg:V4SI 3 3).
- The df analysis creates two mentions for GPR3 and GPR4,
- both DImode. We must recognize this and treat it as a
- vector mention to ensure the call is unioned with this
- use. */
- if (mode == DImode && DF_REF_INSN_INFO (mention))
- {
- rtx feeder = DF_REF_INSN (mention);
- /* FIXME: It is pretty hard to get from the df mention
- to the mode of the use in the insn. We arbitrarily
- pick a vector mode here, even though the use might
- be a real DImode. We can be too conservative
- (create a web larger than necessary) because of
- this, so consider eventually fixing this. */
- if (GET_CODE (feeder) == CALL_INSN)
- mode = V4SImode;
- }
-
- if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
- {
- insn_entry[uid].is_relevant = 1;
- if (mode == TImode || mode == V1TImode
- || FLOAT128_VECTOR_P (mode))
- insn_entry[uid].is_128_int = 1;
- if (DF_REF_INSN_INFO (mention))
- insn_entry[uid].contains_subreg
- = !rtx_equal_p (DF_REF_REG (mention),
- DF_REF_REAL_REG (mention));
- union_defs (insn_entry, insn, mention);
- }
- }
- FOR_EACH_INSN_INFO_DEF (mention, insn_info)
- {
- /* We use DF_REF_REAL_REG here to get inside any subregs. */
- machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention));
-
- /* If we're loading up a hard vector register for a call,
- it looks like (set (reg:V4SI 9 9) (...)). The df
- analysis creates two mentions for GPR9 and GPR10, both
- DImode. So relying on the mode from the mentions
- isn't sufficient to ensure we union the call into the
- web with the parameter setup code. */
- if (mode == DImode && GET_CODE (insn) == SET
- && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
- mode = GET_MODE (SET_DEST (insn));
-
- if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
- {
- insn_entry[uid].is_relevant = 1;
- if (mode == TImode || mode == V1TImode
- || FLOAT128_VECTOR_P (mode))
- insn_entry[uid].is_128_int = 1;
- if (DF_REF_INSN_INFO (mention))
- insn_entry[uid].contains_subreg
- = !rtx_equal_p (DF_REF_REG (mention),
- DF_REF_REAL_REG (mention));
- /* REG_FUNCTION_VALUE_P is not valid for subregs. */
- else if (REG_FUNCTION_VALUE_P (DF_REF_REG (mention)))
- insn_entry[uid].is_live_out = 1;
- union_uses (insn_entry, insn, mention);
- }
- }
-
- if (insn_entry[uid].is_relevant)
- {
- /* Determine if this is a load or store. */
- insn_entry[uid].is_load = insn_is_load_p (insn);
- insn_entry[uid].is_store = insn_is_store_p (insn);
-
- /* Determine if this is a doubleword swap. If not,
- determine whether it can legally be swapped. */
- if (insn_is_swap_p (insn))
- insn_entry[uid].is_swap = 1;
- else
- {
- unsigned int special = SH_NONE;
- insn_entry[uid].is_swappable
- = insn_is_swappable_p (insn_entry, insn, &special);
- if (special != SH_NONE && insn_entry[uid].contains_subreg)
- insn_entry[uid].is_swappable = 0;
- else if (special != SH_NONE)
- insn_entry[uid].special_handling = special;
- else if (insn_entry[uid].contains_subreg)
- insn_entry[uid].special_handling = SH_SUBREG;
- }
- }
- }
- }
-
- if (dump_file)
- {
- fprintf (dump_file, "\nSwap insn entry table when first built\n");
- dump_swap_insn_table (insn_entry);
- }
-
- /* Record unoptimizable webs. */
- unsigned e = get_max_uid (), i;
- for (i = 0; i < e; ++i)
- {
- if (!insn_entry[i].is_relevant)
- continue;
-
- swap_web_entry *root
- = (swap_web_entry*)(&insn_entry[i])->unionfind_root ();
-
- if (insn_entry[i].is_live_in || insn_entry[i].is_live_out
- || (insn_entry[i].contains_subreg
- && insn_entry[i].special_handling != SH_SUBREG)
- || insn_entry[i].is_128_int || insn_entry[i].is_call
- || !(insn_entry[i].is_swappable || insn_entry[i].is_swap))
- root->web_not_optimizable = 1;
-
- /* If we have loads or stores that aren't permuting then the
- optimization isn't appropriate. */
- else if ((insn_entry[i].is_load || insn_entry[i].is_store)
- && !insn_entry[i].is_swap && !insn_entry[i].is_swappable)
- root->web_not_optimizable = 1;
-
- /* If we have permuting loads or stores that are not accompanied
- by a register swap, the optimization isn't appropriate. */
- else if (insn_entry[i].is_load && insn_entry[i].is_swap)
- {
- rtx insn = insn_entry[i].insn;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref def;
-
- FOR_EACH_INSN_INFO_DEF (def, insn_info)
- {
- struct df_link *link = DF_REF_CHAIN (def);
-
- if (!chain_contains_only_swaps (insn_entry, link, FOR_LOADS))
- {
- root->web_not_optimizable = 1;
- break;
- }
- }
- }
- else if (insn_entry[i].is_store && insn_entry[i].is_swap)
- {
- rtx insn = insn_entry[i].insn;
- struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
- df_ref use;
-
- FOR_EACH_INSN_INFO_USE (use, insn_info)
- {
- struct df_link *link = DF_REF_CHAIN (use);
-
- if (!chain_contains_only_swaps (insn_entry, link, FOR_STORES))
- {
- root->web_not_optimizable = 1;
- break;
- }
- }
- }
- }
-
- if (dump_file)
- {
- fprintf (dump_file, "\nSwap insn entry table after web analysis\n");
- dump_swap_insn_table (insn_entry);
- }
-
- /* For each load and store in an optimizable web (which implies
- the loads and stores are permuting), find the associated
- register swaps and mark them for removal. Due to various
- optimizations we may mark the same swap more than once. Also
- perform special handling for swappable insns that require it. */
- for (i = 0; i < e; ++i)
- if ((insn_entry[i].is_load || insn_entry[i].is_store)
- && insn_entry[i].is_swap)
- {
- swap_web_entry* root_entry
- = (swap_web_entry*)((&insn_entry[i])->unionfind_root ());
- if (!root_entry->web_not_optimizable)
- mark_swaps_for_removal (insn_entry, i);
- }
- else if (insn_entry[i].is_swappable && insn_entry[i].special_handling)
- {
- swap_web_entry* root_entry
- = (swap_web_entry*)((&insn_entry[i])->unionfind_root ());
- if (!root_entry->web_not_optimizable)
- handle_special_swappables (insn_entry, i);
- }
-
- /* Now delete the swaps marked for removal. */
- for (i = 0; i < e; ++i)
- if (insn_entry[i].will_delete)
- replace_swap_with_copy (insn_entry, i);
-
- /* Clean up. */
- free (insn_entry);
- return 0;
-}
-
-const pass_data pass_data_analyze_swaps =
-{
- RTL_PASS, /* type */
- "swaps", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_df_finish, /* todo_flags_finish */
-};
-
-class pass_analyze_swaps : public rtl_opt_pass
-{
-public:
- pass_analyze_swaps(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_analyze_swaps, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *)
- {
- return (optimize > 0 && !BYTES_BIG_ENDIAN && TARGET_VSX
- && !TARGET_P9_VECTOR && rs6000_optimize_swaps);
- }
-
- virtual unsigned int execute (function *fun)
- {
- return rs6000_analyze_swaps (fun);
- }
-
- opt_pass *clone ()
- {
- return new pass_analyze_swaps (m_ctxt);
- }
-
-}; // class pass_analyze_swaps
-
-rtl_opt_pass *
-make_pass_analyze_swaps (gcc::context *ctxt)
-{
- return new pass_analyze_swaps (ctxt);
-}
-
#ifdef RS6000_GLIBC_ATOMIC_FENV
/* Function declarations for rs6000_atomic_assign_expand_fenv. */
static tree atomic_hold_decl, atomic_clear_decl, atomic_update_decl;
@@ -41074,6 +38851,35 @@ rs6000_generate_float2_code (bool signed_convert, rtx dst, rtx src1, rtx src2)
emit_insn (gen_p8_vmrgew_v4sf (dst, rtx_tmp3, rtx_tmp2));
}
+void
+rs6000_generate_vsigned2_code (bool signed_convert, rtx dst, rtx src1,
+ rtx src2)
+{
+ rtx rtx_tmp0, rtx_tmp1, rtx_tmp2, rtx_tmp3;
+
+ rtx_tmp0 = gen_reg_rtx (V2DFmode);
+ rtx_tmp1 = gen_reg_rtx (V2DFmode);
+
+ emit_insn (gen_vsx_xxpermdi_v2df (rtx_tmp0, src1, src2, GEN_INT (0)));
+ emit_insn (gen_vsx_xxpermdi_v2df (rtx_tmp1, src1, src2, GEN_INT (3)));
+
+ rtx_tmp2 = gen_reg_rtx (V4SImode);
+ rtx_tmp3 = gen_reg_rtx (V4SImode);
+
+ if (signed_convert)
+ {
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp2, rtx_tmp0));
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp3, rtx_tmp1));
+ }
+ else
+ {
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp2, rtx_tmp0));
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp3, rtx_tmp1));
+ }
+
+ emit_insn (gen_p8_vmrgew_v4si (dst, rtx_tmp2, rtx_tmp3));
+}
+
/* Implement the TARGET_OPTAB_SUPPORTED_P hook. */
static bool
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 9b73be1e176..82a0bda48c6 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -600,8 +600,7 @@ extern int rs6000_vector_align[];
#define TARGET_DIRECT_MOVE_128 (TARGET_P9_VECTOR && TARGET_DIRECT_MOVE \
&& TARGET_POWERPC64)
#define TARGET_VEXTRACTUB (TARGET_P9_VECTOR && TARGET_DIRECT_MOVE \
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64)
-
+ && TARGET_POWERPC64)
/* Whether we should avoid (SUBREG:SI (REG:SF) and (SUBREG:SF (REG:SI). */
#define TARGET_NO_SF_SUBREG TARGET_DIRECT_MOVE_64BIT
@@ -761,7 +760,6 @@ extern int rs6000_vector_align[];
#define TARGET_DIRECT_MOVE_64BIT (TARGET_DIRECT_MOVE \
&& TARGET_P8_VECTOR \
&& TARGET_POWERPC64 \
- && TARGET_UPPER_REGS_DI \
&& (rs6000_altivec_element_order != 2))
/* Whether the various reciprocal divide/square root estimate instructions
@@ -1585,13 +1583,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
rs6000_secondary_memory_needed_ptr (CLASS1, CLASS2, MODE)
-/* For cpus that cannot load/store SDmode values from the 64-bit
- FP registers without using a full 64-bit load/store, we need
- to allocate a full 64-bit stack slot for them. */
-
-#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
- rs6000_secondary_memory_needed_rtx (MODE)
-
/* Specify the mode to be used for memory when a secondary memory
location is needed. For cpus that cannot load/store SDmode values
from the 64-bit FP registers without using a full 64-bit
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f78dbf913ec..6985b9f82da 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -691,7 +691,7 @@
;; D-form load to FPR register & move to Altivec register
;; Move Altivec register to FPR register and store
(define_mode_iterator ALTIVEC_DFORM [DF
- SF
+ (SF "TARGET_P8_VECTOR")
(DI "TARGET_POWERPC64")])
@@ -940,7 +940,7 @@
(set (match_dup 0)
(sign_extend:EXTHI (match_dup 2)))]
{
- operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
+ operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
})
(define_insn_and_split "*extendhi<mode>2_dot"
@@ -1004,8 +1004,7 @@
(define_split
[(set (match_operand:DI 0 "altivec_register_operand")
(sign_extend:DI (match_operand:SI 1 "altivec_register_operand")))]
- "TARGET_VSX_SMALL_INTEGER && TARGET_P8_VECTOR && !TARGET_P9_VECTOR
- && reload_completed"
+ "TARGET_P8_VECTOR && !TARGET_P9_VECTOR && reload_completed"
[(const_int 0)]
{
rtx dest = operands[0];
@@ -5161,7 +5160,7 @@
operands[1] = rs6000_address_for_fpconvert (operands[1]);
if (GET_CODE (operands[2]) == SCRATCH)
operands[2] = gen_reg_rtx (DImode);
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
emit_insn (gen_extendsidi2 (operands[2], operands[1]));
else
emit_insn (gen_lfiwax (operands[2], operands[1]));
@@ -5238,7 +5237,7 @@
operands[1] = rs6000_address_for_fpconvert (operands[1]);
if (GET_CODE (operands[2]) == SCRATCH)
operands[2] = gen_reg_rtx (DImode);
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
emit_insn (gen_zero_extendsidi2 (operands[2], operands[1]));
else
emit_insn (gen_lfiwzx (operands[2], operands[1]));
@@ -5423,8 +5422,7 @@
(clobber (match_scratch:DI 2))
(clobber (match_scratch:DI 3))
(clobber (match_scratch:<QHI:MODE> 4))])]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
{
if (MEM_P (operands[1]))
operands[1] = rs6000_address_for_fpconvert (operands[1]);
@@ -5437,8 +5435,7 @@
(clobber (match_scratch:DI 2 "=wK,wi,wK"))
(clobber (match_scratch:DI 3 "=X,r,X"))
(clobber (match_scratch:<QHI:MODE> 4 "=X,X,wK"))]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
- && TARGET_UPPER_REGS_DI && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -5477,8 +5474,7 @@
(match_operand:QHI 1 "input_operand" "")))
(clobber (match_scratch:DI 2 ""))
(clobber (match_scratch:DI 3 ""))])]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
{
if (MEM_P (operands[1]))
operands[1] = rs6000_address_for_fpconvert (operands[1]);
@@ -5490,8 +5486,7 @@
(match_operand:QHI 1 "reg_or_indexed_operand" "wK,r,Z")))
(clobber (match_scratch:DI 2 "=wK,wi,wJwK"))
(clobber (match_scratch:DI 3 "=X,r,X"))]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -5524,7 +5519,7 @@
"TARGET_HARD_FLOAT && <TARGET_FLOAT>"
"
{
- if (!TARGET_VSX_SMALL_INTEGER)
+ if (!TARGET_P8_VECTOR)
{
rtx src = force_reg (<MODE>mode, operands[1]);
@@ -5551,7 +5546,7 @@
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
&& (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
&& TARGET_STFIWX && can_create_pseudo_p ()
- && !TARGET_VSX_SMALL_INTEGER"
+ && !TARGET_P8_VECTOR"
"#"
""
[(pc)]
@@ -5592,7 +5587,7 @@
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d"))
(clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_VSX_SMALL_INTEGER"
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_P8_VECTOR"
"#"
""
[(pc)]
@@ -5629,8 +5624,7 @@
[(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand")
(fix:QHI (match_operand:SFDF 1 "gpc_reg_operand")))
(clobber (match_scratch:DI 2))])]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT"
{
if (MEM_P (operands[0]))
operands[0] = rs6000_address_for_fpconvert (operands[0]);
@@ -5641,8 +5635,7 @@
(fix:QHI
(match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>")))
(clobber (match_scratch:DI 2 "=X,wi"))]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -5672,7 +5665,7 @@
"TARGET_HARD_FLOAT && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX"
"
{
- if (!TARGET_VSX_SMALL_INTEGER)
+ if (!TARGET_P8_VECTOR)
{
emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
DONE;
@@ -5685,7 +5678,7 @@
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && <TARGET_FLOAT> && TARGET_FCTIWUZ
&& TARGET_STFIWX && can_create_pseudo_p ()
- && !TARGET_VSX_SMALL_INTEGER"
+ && !TARGET_P8_VECTOR"
"#"
""
[(pc)]
@@ -5734,8 +5727,7 @@
[(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand")
(unsigned_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand")))
(clobber (match_scratch:DI 2))])]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT"
{
if (MEM_P (operands[0]))
operands[0] = rs6000_address_for_fpconvert (operands[0]);
@@ -5746,8 +5738,7 @@
(unsigned_fix:QHI
(match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>")))
(clobber (match_scratch:DI 2 "=X,wi"))]
- "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT
- && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -5777,7 +5768,7 @@
(define_insn "*fctiw<u>z_<mode>_smallint"
[(set (match_operand:SI 0 "vsx_register_operand" "=d,wi")
(any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_P8_VECTOR"
"@
fctiw<u>z %0,%1
xscvdp<su>xws %x0,%x1"
@@ -5789,7 +5780,7 @@
[(set (match_operand:SI 0 "memory_operand" "=Z")
(any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "wa")))
(clobber (match_scratch:SI 2 "=wa"))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_VSX_SMALL_INTEGER"
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_P8_VECTOR"
"#"
"&& reload_completed"
[(set (match_dup 2)
@@ -6681,7 +6672,7 @@
UNSPEC_MOVSI_GOT))]
"DEFAULT_ABI == ABI_V4
&& flag_pic == 1
- && (reload_in_progress || reload_completed)"
+ && reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (unspec:SI [(match_dup 1)(match_dup 0)]
UNSPEC_MOVSI_GOT))]
@@ -6959,7 +6950,7 @@
(define_split
[(set (match_operand:DI 0 "altivec_register_operand")
(match_operand:DI 1 "xxspltib_constant_split"))]
- "TARGET_VSX_SMALL_INTEGER && TARGET_P9_VECTOR && reload_completed"
+ "TARGET_P9_VECTOR && reload_completed"
[(const_int 0)]
{
rtx op0 = operands[0];
@@ -8234,7 +8225,7 @@
(and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "reg_or_cint_operand" "rI"))
(const_int -16)))]
- "TARGET_ALTIVEC && (reload_in_progress || reload_completed)"
+ "TARGET_ALTIVEC && reload_completed"
"#"
"&& reload_completed"
[(set (match_dup 0)
@@ -8664,7 +8655,7 @@
(define_split
[(set (match_operand:DI 0 "altivec_register_operand" "")
(match_operand:DI 1 "s5bit_cint_operand" ""))]
- "TARGET_UPPER_REGS_DI && TARGET_VSX && reload_completed"
+ "TARGET_VSX && reload_completed"
[(const_int 0)]
{
rtx op0 = operands[0];
@@ -8686,7 +8677,7 @@
(define_split
[(set (match_operand:INT_ISA3 0 "altivec_register_operand" "")
(match_operand:INT_ISA3 1 "xxspltib_constant_split" ""))]
- "TARGET_UPPER_REGS_DI && TARGET_P9_VECTOR && reload_completed"
+ "TARGET_P9_VECTOR && reload_completed"
[(const_int 0)]
{
rtx op0 = operands[0];
@@ -9766,7 +9757,7 @@
(match_operand:DF 1 "any_operand" ""))
(set (match_operand:DF 2 "gpc_reg_operand" "")
(match_dup 0))]
- "!TARGET_UPPER_REGS_DF
+ "!TARGET_VSX
&& peep2_reg_dead_p (2, operands[0])"
[(set (match_dup 2) (match_dup 1))])
@@ -9775,7 +9766,7 @@
(match_operand:SF 1 "any_operand" ""))
(set (match_operand:SF 2 "gpc_reg_operand" "")
(match_dup 0))]
- "!TARGET_UPPER_REGS_SF
+ "!TARGET_P8_VECTOR
&& peep2_reg_dead_p (2, operands[0])"
[(set (match_dup 2) (match_dup 1))])
@@ -13974,8 +13965,7 @@
(match_operand:ALTIVEC_DFORM 2 "simple_offsettable_mem_operand"))
(set (match_operand:ALTIVEC_DFORM 3 "altivec_register_operand")
(match_dup 1))]
- "TARGET_VSX && TARGET_UPPER_REGS_<MODE> && !TARGET_P9_DFORM_SCALAR
- && peep2_reg_dead_p (2, operands[1])"
+ "TARGET_VSX && !TARGET_P9_DFORM_SCALAR && peep2_reg_dead_p (2, operands[1])"
[(set (match_dup 0)
(match_dup 4))
(set (match_dup 3)
@@ -14011,8 +14001,7 @@
(match_operand:ALTIVEC_DFORM 2 "altivec_register_operand"))
(set (match_operand:ALTIVEC_DFORM 3 "simple_offsettable_mem_operand")
(match_dup 1))]
- "TARGET_VSX && TARGET_UPPER_REGS_<MODE> && !TARGET_P9_DFORM_SCALAR
- && peep2_reg_dead_p (2, operands[1])"
+ "TARGET_VSX && !TARGET_P9_DFORM_SCALAR && peep2_reg_dead_p (2, operands[1])"
[(set (match_dup 0)
(match_dup 4))
(set (match_dup 5)
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 28d899391fb..e94aa07bc7a 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -200,9 +200,6 @@ mvsx-scalar-double
Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(1)
; If -mvsx, use VSX arithmetic instructions for DFmode (on by default)
-mvsx-scalar-memory
-Target Undocumented Report Alias(mupper-regs-df)
-
mvsx-align-128
Target Undocumented Report Var(TARGET_VSX_ALIGN_128) Save
; If -mvsx, set alignment to 128 bits instead of 32/64
@@ -433,9 +430,9 @@ mlong-double-
Target RejectNegative Joined UInteger Var(rs6000_long_double_type_size) Save
-mlong-double-<n> Specify size of long double (64 or 128 bits).
+; This option existed in the past, but now is always on.
mlra
-Target Report Mask(LRA) Var(rs6000_isa_flags)
-Enable Local Register Allocation.
+Target RejectNegative Undocumented Ignore
msched-costly-dep=
Target RejectNegative Joined Var(rs6000_sched_costly_dep_str)
@@ -549,22 +546,6 @@ mcompat-align-parm
Target Report Var(rs6000_compat_align_parm) Init(0) Save
Generate aggregate parameter passing code with at most 64-bit alignment.
-mupper-regs-df
-Target Report Mask(UPPER_REGS_DF) Var(rs6000_isa_flags)
-Allow double variables in upper registers with -mcpu=power7 or -mvsx.
-
-mupper-regs-sf
-Target Report Mask(UPPER_REGS_SF) Var(rs6000_isa_flags)
-Allow float variables in upper registers with -mcpu=power8 or -mpower8-vector.
-
-mupper-regs
-Target Report Var(TARGET_UPPER_REGS) Init(-1) Save
-Allow float/double variables in upper registers if cpu allows it.
-
-mupper-regs-di
-Target Report Mask(UPPER_REGS_DI) Var(rs6000_isa_flags)
-Allow 64-bit integer variables in upper registers with -mcpu=power7 or -mvsx.
-
moptimize-swaps
Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
Analyze and remove doubleword swaps from VSX computations.
@@ -625,10 +606,6 @@ mfloat128-convert
Target Undocumented Mask(FLOAT128_CVT) Var(rs6000_isa_flags)
Enable default conversions between __float128 & long double.
-mvsx-small-integer
-Target Report Mask(VSX_SMALL_INTEGER) Var(rs6000_isa_flags)
-Enable small integers to be in VSX registers.
-
mstack-protector-guard=
Target RejectNegative Joined Enum(stack_protector_guard) Var(rs6000_stack_protector_guard) Init(SSP_TLS)
Use given stack-protector guard.
diff --git a/gcc/config/rs6000/rtems.h b/gcc/config/rs6000/rtems.h
index 54a36de6eb4..8a62fdcbaf3 100644
--- a/gcc/config/rs6000/rtems.h
+++ b/gcc/config/rs6000/rtems.h
@@ -14,33 +14,172 @@
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
+ 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/>. */
-/* Specify predefined symbols in preprocessor. */
+/* Copy and paste from linux64.h and freebsd64.h */
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __powerpc64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef TARGET_AIX
+#define TARGET_AIX TARGET_64BIT
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("PPC"); \
- builtin_define ("__rtems__"); \
- builtin_define ("__USE_INIT_FINI__"); \
- builtin_assert ("system=rtems"); \
- builtin_assert ("cpu=powerpc"); \
- builtin_assert ("machine=powerpc"); \
- TARGET_OS_SYSV_CPP_BUILTINS (); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+ if (TARGET_64BIT) \
+ { \
+ builtin_define ("__PPC__"); \
+ builtin_define ("__PPC64__"); \
+ builtin_define ("__powerpc64__"); \
+ builtin_assert ("cpu=powerpc64"); \
+ builtin_assert ("machine=powerpc64"); \
+ } \
+ else \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define_std ("powerpc"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ TARGET_OS_SYSV_CPP_BUILTINS (); \
+ } \
+ } \
+ while (0)
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#define INVALID_64BIT "-m%s not supported in this configuration"
+
+/* A lot of copy and paste from linux64.h and freebsd64.h */
+#undef SUBSUBTARGET_OVERRIDE_OPTIONS
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+ if (rs6000_isa_flags & OPTION_MASK_64BIT) \
+ { \
+ rs6000_elf_abi = 2; \
+ rs6000_current_abi = ABI_ELFv2; \
+ if (rs6000_isa_flags & OPTION_MASK_RELOCATABLE) \
+ { \
+ rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE; \
+ error (INVALID_64BIT, "relocatable"); \
+ } \
+ if (rs6000_isa_flags & OPTION_MASK_EABI) \
+ { \
+ rs6000_isa_flags &= ~OPTION_MASK_EABI; \
+ error (INVALID_64BIT, "eabi"); \
+ } \
+ if (TARGET_PROTOTYPE) \
+ { \
+ target_prototype = 0; \
+ error (INVALID_64BIT, "prototype"); \
+ } \
+ if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) == 0) \
+ { \
+ rs6000_isa_flags |= OPTION_MASK_POWERPC64; \
+ error ("-m64 requires a PowerPC64 cpu"); \
+ } \
+ } \
+ } \
while (0)
#undef TARGET_LIBGCC_SDATA_SECTION
#define TARGET_LIBGCC_SDATA_SECTION ".sdata"
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_rtems)"
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef SIZE_TYPE
+#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
+
+/* Copy and paste from freebsd64.h */
+#undef WCHAR_TYPE
+
+/* Copy and paste from freebsd64.h */
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#ifdef __powerpc64__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n" \
+" bl " #FUNC "\n" \
+" nop\n" \
+" .previous");
+#endif
+
+/* This could be also POWERPC_FREEBSD. It is related to the save/restore
+ defines below. */
+#define POWERPC_LINUX
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef SAVE_FP_PREFIX
+#define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
+#undef SAVE_FP_SUFFIX
+#define SAVE_FP_SUFFIX ""
+#undef RESTORE_FP_PREFIX
+#define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
+#undef RESTORE_FP_SUFFIX
+#define RESTORE_FP_SUFFIX ""
-#define CPP_OS_RTEMS_SPEC "\
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ fputs ("\t.size\t", (FILE)); \
+ if (TARGET_64BIT && DOT_SYMBOLS) \
+ putc ('.', (FILE)); \
+ assemble_name ((FILE), (FNAME)); \
+ fputs (",.-", (FILE)); \
+ rs6000_output_function_entry (FILE, FNAME); \
+ putc ('\n', (FILE)); \
+ } \
+ } \
+ while (0)
+
+/* Copy and paste from linux64.h and freebsd64.h */
+#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) \
+ (TARGET_TOC \
+ && (GET_CODE (X) == SYMBOL_REF \
+ || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST_INT \
+ && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
+ || (GET_CODE (X) == CONST_DOUBLE \
+ && ((TARGET_64BIT \
+ && (TARGET_MINIMAL_TOC \
+ || (SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
+ && ! TARGET_NO_FP_IN_TOC))) \
+ || (!TARGET_64BIT \
+ && !TARGET_NO_FP_IN_TOC \
+ && SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
+ && BITS_PER_WORD == HOST_BITS_PER_INT)))))
+
+#undef CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC "\
%{!mcpu*: %{!Dppc*: %{!Dmpc*: -Dmpc750} } }\
%{mcpu=403: %{!Dppc*: %{!Dmpc*: -Dppc403} } } \
%{mcpu=505: %{!Dppc*: %{!Dmpc*: -Dmpc505} } } \
@@ -55,6 +194,37 @@
%{mcpu=8540: %{!Dppc*: %{!Dmpc*: -Dppc8540} } } \
%{mcpu=e6500: -D__PPC_CPU_E6500__}"
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mppc%{m64:64}"
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{!m64:%(asm_spec32)}%{m64:%(asm_spec64)} %(asm_spec_common)"
+
+#define ASM_SPEC32 "-a32 \
+%{mrelocatable} %{mrelocatable-lib} %{" FPIE_OR_FPIC_SPEC ":-K PIC} \
+%{memb|msdata=eabi: -memb}"
+
+#define ASM_SPEC64 "-a64"
+
+#define ASM_SPEC_COMMON "%(asm_cpu) \
+%{,assembler|,assembler-with-cpp: %{mregnames} %{mno-regnames}}" \
+ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
+
+#undef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC \
+"%{!m64:%(link_os_spec32)}%{m64:%(link_os_spec64)}"
+
+#define LINK_OS_SPEC32 ENDIAN_SELECT(" -m elf32ppc", \
+ " -m elf32lppc", \
+ " -m elf32ppc")
+#define LINK_OS_SPEC64 ENDIAN_SELECT(" -m elf64ppc", \
+ " -m elf64lppc", \
+ " -m elf64ppc")
+
#undef SUBSUBTARGET_EXTRA_SPECS
#define SUBSUBTARGET_EXTRA_SPECS \
- { "cpp_os_rtems", CPP_OS_RTEMS_SPEC }
+ { "asm_spec_common", ASM_SPEC_COMMON }, \
+ { "asm_spec32", ASM_SPEC32 }, \
+ { "asm_spec64", ASM_SPEC64 }, \
+ { "link_os_spec32", LINK_OS_SPEC32 }, \
+ { "link_os_spec64", LINK_OS_SPEC64 },
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index a47091ad1b4..304f322f435 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -30,6 +30,10 @@ rs6000-string.o: $(srcdir)/config/rs6000/rs6000-string.c
$(COMPILE) $<
$(POSTCOMPILE)
+rs6000-p8swap.o: $(srcdir)/config/rs6000/rs6000-p8swap.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
$(srcdir)/config/rs6000/rs6000-tables.opt: $(srcdir)/config/rs6000/genopt.sh \
$(srcdir)/config/rs6000/rs6000-cpus.def
$(SHELL) $(srcdir)/config/rs6000/genopt.sh $(srcdir)/config/rs6000 > \
diff --git a/gcc/config/rs6000/t-rtems b/gcc/config/rs6000/t-rtems
index 8290f5c5bdd..0e39c6320c8 100644
--- a/gcc/config/rs6000/t-rtems
+++ b/gcc/config/rs6000/t-rtems
@@ -27,8 +27,8 @@ MULTILIB_REQUIRED =
MULTILIB_OPTIONS += mcpu=403/mcpu=505/mcpu=603e/mcpu=604/mcpu=860/mcpu=7400/mcpu=8540/mcpu=e6500
MULTILIB_DIRNAMES += m403 m505 m603e m604 m860 m7400 m8540 me6500
-MULTILIB_OPTIONS += m32
-MULTILIB_DIRNAMES += m32
+MULTILIB_OPTIONS += m32/m64
+MULTILIB_DIRNAMES += m32 m64
MULTILIB_OPTIONS += msoft-float
MULTILIB_DIRNAMES += nof
@@ -72,3 +72,5 @@ MULTILIB_REQUIRED += mcpu=8540/msoft-float
MULTILIB_REQUIRED += mcpu=860
MULTILIB_REQUIRED += mcpu=e6500/m32
MULTILIB_REQUIRED += mcpu=e6500/m32/msoft-float/mno-altivec
+MULTILIB_REQUIRED += mcpu=e6500/m64
+MULTILIB_REQUIRED += mcpu=e6500/m64/msoft-float/mno-altivec
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 4d73f0abe0a..2937499c4a6 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -37,6 +37,9 @@
(TI "TARGET_VSX_TIMODE")
V1TI])
+;; Iterator for 128-bit integer types that go in a single vector register.
+(define_mode_iterator VSX_TI [(TI "TARGET_VSX_TIMODE") V1TI])
+
;; Iterator for the 2 32-bit vector types
(define_mode_iterator VSX_W [V4SF V4SI])
@@ -326,6 +329,7 @@
UNSPEC_VSX_CVDPSXWS
UNSPEC_VSX_CVDPUXWS
UNSPEC_VSX_CVSPDP
+ UNSPEC_VSX_CVHPSP
UNSPEC_VSX_CVSPDPN
UNSPEC_VSX_CVDPSPN
UNSPEC_VSX_CVSXWDP
@@ -348,6 +352,8 @@
UNSPEC_VSX_ROUND_I
UNSPEC_VSX_ROUND_IC
UNSPEC_VSX_SLDWI
+ UNSPEC_VSX_XXPERM
+
UNSPEC_VSX_XXSPLTW
UNSPEC_VSX_XXSPLTD
UNSPEC_VSX_DIVSD
@@ -358,18 +364,24 @@
UNSPEC_VSX_XVCVDPSXDS
UNSPEC_VSX_XVCVDPUXDS
UNSPEC_VSX_SIGN_EXTEND
+ UNSPEC_VSX_XVCVSPSXWS
+ UNSPEC_VSX_XVCVSPSXDS
UNSPEC_VSX_VSLO
UNSPEC_VSX_EXTRACT
UNSPEC_VSX_SXEXPDP
- UNSPEC_VSX_SXSIGDP
+ UNSPEC_VSX_SXSIG
UNSPEC_VSX_SIEXPDP
+ UNSPEC_VSX_SIEXPQP
UNSPEC_VSX_SCMPEXPDP
UNSPEC_VSX_STSTDC
+ UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTH
+ UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTL
UNSPEC_VSX_VXEXP
UNSPEC_VSX_VXSIG
UNSPEC_VSX_VIEXP
UNSPEC_VSX_VTSTDC
UNSPEC_VSX_VEC_INIT
+ UNSPEC_VSX_VSIGNED2
UNSPEC_LXVL
UNSPEC_STXVL
UNSPEC_VCLZLSBB
@@ -747,9 +759,9 @@
;; special V1TI container class, which it is not appropriate to use vec_select
;; for the type.
(define_insn "*vsx_le_permute_<mode>"
- [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
- (rotate:VSX_LE_128
- (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
+ [(set (match_operand:VSX_TI 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
+ (rotate:VSX_TI
+ (match_operand:VSX_TI 1 "input_operand" "<VSa>,Z,<VSa>")
(const_int 64)))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"@
@@ -760,10 +772,10 @@
(set_attr "type" "vecperm,vecload,vecstore")])
(define_insn_and_split "*vsx_le_undo_permute_<mode>"
- [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
- (rotate:VSX_LE_128
- (rotate:VSX_LE_128
- (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
+ [(set (match_operand:VSX_TI 0 "vsx_register_operand" "=<VSa>,<VSa>")
+ (rotate:VSX_TI
+ (rotate:VSX_TI
+ (match_operand:VSX_TI 1 "vsx_register_operand" "0,<VSa>")
(const_int 64))
(const_int 64)))]
"!BYTES_BIG_ENDIAN && TARGET_VSX"
@@ -788,16 +800,15 @@
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
- [(set (match_dup 2)
- (rotate:VSX_LE_128 (match_dup 1)
- (const_int 64)))
- (set (match_dup 0)
- (rotate:VSX_LE_128 (match_dup 2)
- (const_int 64)))]
+ [(const_int 0)]
"
{
- operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
- : operands[0];
+ rtx tmp = (can_create_pseudo_p ()
+ ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0]);
+ rs6000_emit_le_vsx_permute (tmp, operands[1], <MODE>mode);
+ rs6000_emit_le_vsx_permute (operands[0], tmp, <MODE>mode);
+ DONE;
}
"
[(set_attr "type" "vecload")
@@ -815,15 +826,14 @@
[(set (match_operand:VSX_LE_128 0 "memory_operand" "")
(match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed && !TARGET_P9_VECTOR"
- [(set (match_dup 2)
- (rotate:VSX_LE_128 (match_dup 1)
- (const_int 64)))
- (set (match_dup 0)
- (rotate:VSX_LE_128 (match_dup 2)
- (const_int 64)))]
+ [(const_int 0)]
{
- operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
- : operands[0];
+ rtx tmp = (can_create_pseudo_p ()
+ ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0]);
+ rs6000_emit_le_vsx_permute (tmp, operands[1], <MODE>mode);
+ rs6000_emit_le_vsx_permute (operands[0], tmp, <MODE>mode);
+ DONE;
})
;; Peephole to catch memory to memory transfers for TImode if TImode landed in
@@ -847,16 +857,13 @@
[(set (match_operand:VSX_LE_128 0 "memory_operand" "")
(match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed && !TARGET_P9_VECTOR"
- [(set (match_dup 1)
- (rotate:VSX_LE_128 (match_dup 1)
- (const_int 64)))
- (set (match_dup 0)
- (rotate:VSX_LE_128 (match_dup 1)
- (const_int 64)))
- (set (match_dup 1)
- (rotate:VSX_LE_128 (match_dup 1)
- (const_int 64)))]
- "")
+ [(const_int 0)]
+{
+ rs6000_emit_le_vsx_permute (operands[1], operands[1], <MODE>mode);
+ rs6000_emit_le_vsx_permute (operands[0], operands[1], <MODE>mode);
+ rs6000_emit_le_vsx_permute (operands[1], operands[1], <MODE>mode);
+ DONE;
+})
;; Vector constants that can be generated with XXSPLTIB that was added in ISA
;; 3.0. Both (const_vector [..]) and (vec_duplicate ...) forms are recognized.
@@ -1194,7 +1201,7 @@
UNSPEC_VSX_MULSD))]
"VECTOR_MEM_VSX_P (V2DImode)"
"#"
- "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
+ "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
[(const_int 0)]
"
{
@@ -1232,7 +1239,7 @@
UNSPEC_VSX_DIVSD))]
"VECTOR_MEM_VSX_P (V2DImode)"
"#"
- "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
+ "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
[(const_int 0)]
"
{
@@ -1260,7 +1267,7 @@
UNSPEC_VSX_DIVUD))]
"VECTOR_MEM_VSX_P (V2DImode)"
"#"
- "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress"
+ "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed"
[(const_int 0)]
"
{
@@ -1742,6 +1749,15 @@
"xscvspdp %x0,%x1"
[(set_attr "type" "fp")])
+;; Generate xvcvhpsp instruction
+(define_insn "vsx_xvcvhpsp"
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand: V16QI 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_CVHPSP))]
+ "TARGET_P9_VECTOR"
+ "xvcvhpsp %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
;; xscvdpsp used for splat'ing a scalar to V4SF, knowing that the internal SF
;; format of scalars is actually DF.
(define_insn "vsx_xscvdpsp_scalar"
@@ -1864,6 +1880,8 @@
DONE;
})
+;; convert vector of 64-bit floating point numbers to vector of
+;; 64-bit signed integer
(define_insn "vsx_xvcvdpsxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
(unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
@@ -1872,6 +1890,18 @@
"xvcvdpsxds %x0,%x1"
[(set_attr "type" "vecdouble")])
+;; convert vector of 32-bit floating point numbers to vector of
+;; 32-bit signed integer
+(define_insn "vsx_xvcvspsxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_XVCVSPSXWS))]
+ "VECTOR_UNIT_VSX_P (V4SFmode)"
+ "xvcvspsxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
+;; convert vector of 64-bit floating point numbers to vector of
+;; 64-bit unsigned integer
(define_expand "vsx_xvcvdpuxds_scale"
[(match_operand:V2DI 0 "vsx_register_operand" "")
(match_operand:V2DF 1 "vsx_register_operand" "")
@@ -1893,6 +1923,16 @@
DONE;
})
+;; convert vector of 32-bit floating point numbers to vector of
+;; 32-bit unsigned integer
+(define_insn "vsx_xvcvspuxws"
+ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_XVCVSPSXWS))]
+ "VECTOR_UNIT_VSX_P (V4SFmode)"
+ "xvcvspuxws %x0,%x1"
+ [(set_attr "type" "vecfloat")])
+
(define_insn "vsx_xvcvdpuxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
(unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
@@ -2137,6 +2177,173 @@
DONE;
})
+;; Generate vsigned2
+;; convert two double float vectors to a vector of single precision ints
+(define_expand "vsigned2_v2df"
+ [(match_operand:V4SI 0 "register_operand" "=wa")
+ (unspec:V4SI [(match_operand:V2DF 1 "register_operand" "wa")
+ (match_operand:V2DF 2 "register_operand" "wa")]
+ UNSPEC_VSX_VSIGNED2)]
+ "TARGET_VSX"
+{
+ rtx rtx_src1, rtx_src2, rtx_dst;
+ bool signed_convert=true;
+
+ rtx_dst = operands[0];
+ rtx_src1 = operands[1];
+ rtx_src2 = operands[2];
+
+ rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
+ DONE;
+})
+
+;; Generate vsignedo_v2df
+;; signed double float to int convert odd word
+(define_expand "vsignedo_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=wa")
+ (match_operand:V2DF 1 "register_operand" "wa"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[1]));
+
+ /* Big endian word numbering for words in operand is 0 1 2 3.
+ take (operand[1] operand[1]) and shift left one word
+ 0 1 2 3 0 1 2 3 => 1 2 3 0
+ Words 1 and 3 are now are now where they need to be for result. */
+
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ else
+ /* Little endian word numbering for operand is 3 2 1 0.
+ Result words 3 and 1 are where they need to be. */
+ emit_insn (gen_vsx_xvcvdpsxws (operands[0], operands[1]));
+
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate vsignede_v2df
+;; signed double float to int even word
+(define_expand "vsignede_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ /* Big endian word numbering for words in operand is 0 1
+ Result words 0 is where they need to be. */
+ emit_insn (gen_vsx_xvcvdpsxws (operands[0], operands[1]));
+
+ else
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpsxws (rtx_tmp, operands[1]));
+
+ /* Little endian word numbering for operand is 3 2 1 0.
+ take (operand[1] operand[1]) and shift left three words
+ 0 1 2 3 0 1 2 3 => 3 0 1 2
+ Words 0 and 2 are now where they need to be for the result. */
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate unsigned2
+;; convert two double float vectors to a vector of single precision
+;; unsigned ints
+(define_expand "vunsigned2_v2df"
+[(match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V2DF 1 "register_operand" "v")
+ (match_operand:V2DF 2 "register_operand" "v")]
+ UNSPEC_VSX_VSIGNED2)]
+ "TARGET_VSX"
+{
+ rtx rtx_src1, rtx_src2, rtx_dst;
+ bool signed_convert=false;
+
+ rtx_dst = operands[0];
+ rtx_src1 = operands[1];
+ rtx_src2 = operands[2];
+
+ rs6000_generate_vsigned2_code (signed_convert, rtx_dst, rtx_src1, rtx_src2);
+ DONE;
+})
+
+;; Generate vunsignedo_v2df
+;; unsigned double float to int convert odd word
+(define_expand "vunsignedo_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[1]));
+
+ /* Big endian word numbering for words in operand is 0 1 2 3.
+ take (operand[1] operand[1]) and shift left one word
+ 0 1 2 3 0 1 2 3 => 1 2 3 0
+ Words 1 and 3 are now are now where they need to be for result. */
+
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ else
+ /* Little endian word numbering for operand is 3 2 1 0.
+ Result words 3 and 1 are where they need to be. */
+ emit_insn (gen_vsx_xvcvdpuxws (operands[0], operands[1]));
+
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
+;; Generate vunsignede_v2df
+;; unsigned double float to int even word
+(define_expand "vunsignede_v2df"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (match_operand:V2DF 1 "register_operand" "v"))]
+ "TARGET_VSX"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ /* Big endian word numbering for words in operand is 0 1
+ Result words 0 is where they need to be. */
+ emit_insn (gen_vsx_xvcvdpuxws (operands[0], operands[1]));
+
+ else
+ {
+ rtx rtx_tmp;
+ rtx rtx_val = GEN_INT (12);
+ rtx_tmp = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_vsx_xvcvdpuxws (rtx_tmp, operands[1]));
+
+ /* Little endian word numbering for operand is 3 2 1 0.
+ take (operand[1] operand[1]) and shift left three words
+ 0 1 2 3 0 1 2 3 => 3 0 1 2
+ Words 0 and 2 are now where they need to be for the result. */
+ emit_insn (gen_altivec_vsldoi_v4si (operands[0], rtx_tmp,
+ rtx_tmp, rtx_val));
+ }
+ DONE;
+}
+ [(set_attr "type" "veccomplex")])
+
;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
;; since the xvrdpiz instruction does not truncate the value if the floating
;; point value is < LONG_MIN or > LONG_MAX.
@@ -2729,7 +2936,7 @@
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
{
/* If we have ISA 3.0, we can do a xxextractuw/vextractu{b,h}. */
- if (TARGET_VSX_SMALL_INTEGER && TARGET_P9_VECTOR)
+ if (TARGET_P9_VECTOR)
{
emit_insn (gen_vsx_extract_<mode>_p9 (operands[0], operands[1],
operands[2]));
@@ -2743,8 +2950,7 @@
(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
(parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
(clobber (match_scratch:SI 3 "=r,X"))]
- "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
- && TARGET_VSX_SMALL_INTEGER"
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
{
if (which_alternative == 0)
return "#";
@@ -2774,8 +2980,7 @@
(match_operand:VSX_EXTRACT_I 1 "altivec_register_operand")
(parallel [(match_operand:QI 2 "const_int_operand")])))
(clobber (match_operand:SI 3 "int_reg_operand"))]
- "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
- && TARGET_VSX_SMALL_INTEGER && reload_completed"
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB && reload_completed"
[(const_int 0)]
{
rtx op0_si = gen_rtx_REG (SImode, REGNO (operands[0]));
@@ -2800,8 +3005,7 @@
(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
(parallel [(match_operand:QI 2 "const_int_operand" "n,n")]))))
(clobber (match_scratch:SI 3 "=r,X"))]
- "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
- && TARGET_VSX_SMALL_INTEGER"
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 4)
@@ -2821,8 +3025,7 @@
(parallel [(match_operand:QI 2 "const_int_operand" "n,n")])))
(clobber (match_scratch:<VS_scalar> 3 "=<VSX_EX>,&r"))
(clobber (match_scratch:SI 4 "=X,&r"))]
- "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB
- && TARGET_VSX_SMALL_INTEGER"
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 3)
@@ -2839,8 +3042,7 @@
(match_operand:V4SI 1 "gpc_reg_operand" "wJv,wJv,wJv")
(parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n")])))
(clobber (match_scratch:V4SI 3 "=wJv,wJv,wJv"))]
- "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT
- && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
+ "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT && !TARGET_P9_VECTOR"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -2858,15 +3060,7 @@
instruction. */
value = INTVAL (element);
if (value != 1)
- {
- if (TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER)
- {
- rtx si_tmp = gen_rtx_REG (SImode, REGNO (vec_tmp));
- emit_insn (gen_vsx_extract_v4si_p9 (si_tmp,src, element));
- }
- else
- emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
- }
+ emit_insn (gen_altivec_vspltw_direct (vec_tmp, src, element));
else
vec_tmp = src;
@@ -2875,13 +3069,13 @@
if (can_create_pseudo_p ())
dest = rs6000_address_for_fpconvert (dest);
- if (TARGET_VSX_SMALL_INTEGER)
+ if (TARGET_P8_VECTOR)
emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
else
emit_insn (gen_stfiwx (dest, gen_rtx_REG (DImode, REGNO (vec_tmp))));
}
- else if (TARGET_VSX_SMALL_INTEGER)
+ else if (TARGET_P8_VECTOR)
emit_move_insn (dest, gen_rtx_REG (SImode, REGNO (vec_tmp)));
else
emit_move_insn (gen_rtx_REG (DImode, REGNO (dest)),
@@ -2899,7 +3093,7 @@
(parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")])))
(clobber (match_scratch:VSX_EXTRACT_I2 3 "=v"))]
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT
- && (!TARGET_P9_VECTOR || !TARGET_VSX_SMALL_INTEGER)"
+ && !TARGET_P9_VECTOR"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -3110,7 +3304,7 @@
(parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
(clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
"VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
- && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
+ && TARGET_P9_VECTOR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 3)
@@ -3134,7 +3328,7 @@
(parallel [(match_operand:QI 2 "const_int_operand" "n")]))))
(clobber (match_scratch:<VSX_EXTRACT_I:VS_scalar> 3 "=v"))]
"VECTOR_MEM_VSX_P (<VSX_EXTRACT_I:MODE>mode) && TARGET_DIRECT_MOVE_64BIT
- && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER"
+ && TARGET_P9_VECTOR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 3)
@@ -3156,8 +3350,7 @@
(match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VSX_EX>")
(match_operand:QI 3 "<VSX_EXTRACT_PREDICATE>" "n")]
UNSPEC_VSX_SET))]
- "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
+ "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
{
int ele = INTVAL (operands[3]);
int nunits = GET_MODE_NUNITS (<MODE>mode);
@@ -3181,8 +3374,7 @@
(match_operand:QI 3 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))
(clobber (match_scratch:SI 4 "=&wJwK"))]
- "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
+ "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
"#"
"&& reload_completed"
[(set (match_dup 5)
@@ -3217,8 +3409,7 @@
(match_operand:QI 3 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))
(clobber (match_scratch:SI 4 "=&wJwK"))]
- "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
+ "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
"#"
"&& reload_completed"
[(set (match_dup 4)
@@ -3248,8 +3439,7 @@
[(match_operand:QI 3 "const_0_to_3_operand" "n")]))
(match_operand:QI 4 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))]
- "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64
+ "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64
&& (INTVAL (operands[3]) == (VECTOR_ELT_ORDER_BIG ? 1 : 2))"
{
int ele = INTVAL (operands[4]);
@@ -3277,8 +3467,7 @@
UNSPEC_VSX_SET))
(clobber (match_scratch:SI 5 "=&wJwK"))]
"VECTOR_MEM_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SImode)
- && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
- && TARGET_UPPER_REGS_DI && TARGET_POWERPC64
+ && TARGET_P9_VECTOR && TARGET_POWERPC64
&& (INTVAL (operands[3]) != (VECTOR_ELT_ORDER_BIG ? 1 : 2))"
"#"
"&& 1"
@@ -3740,6 +3929,15 @@
;; ISA 3.0 Binary Floating-Point Support
+;; VSX Scalar Extract Exponent Quad-Precision
+(define_insn "xsxexpqp"
+ [(set (match_operand:DI 0 "altivec_register_operand" "=v")
+ (unspec:DI [(match_operand:KF 1 "altivec_register_operand" "v")]
+ UNSPEC_VSX_SXEXPDP))]
+ "TARGET_P9_VECTOR"
+ "xsxexpqp %0,%1"
+ [(set_attr "type" "vecmove")])
+
;; VSX Scalar Extract Exponent Double-Precision
(define_insn "xsxexpdp"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -3749,15 +3947,44 @@
"xsxexpdp %0,%x1"
[(set_attr "type" "integer")])
+;; VSX Scalar Extract Significand Quad-Precision
+(define_insn "xsxsigqp"
+ [(set (match_operand:TI 0 "altivec_register_operand" "=v")
+ (unspec:TI [(match_operand:KF 1 "altivec_register_operand" "v")]
+ UNSPEC_VSX_SXSIG))]
+ "TARGET_P9_VECTOR"
+ "xsxsigqp %0,%1"
+ [(set_attr "type" "vecmove")])
+
;; VSX Scalar Extract Significand Double-Precision
(define_insn "xsxsigdp"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DF 1 "vsx_register_operand" "wa")]
- UNSPEC_VSX_SXSIGDP))]
+ UNSPEC_VSX_SXSIG))]
"TARGET_P9_VECTOR && TARGET_64BIT"
"xsxsigdp %0,%x1"
[(set_attr "type" "integer")])
+;; VSX Scalar Insert Exponent Quad-Precision Floating Point Argument
+(define_insn "xsiexpqpf"
+ [(set (match_operand:KF 0 "altivec_register_operand" "=v")
+ (unspec:KF [(match_operand:KF 1 "altivec_register_operand" "v")
+ (match_operand:DI 2 "altivec_register_operand" "v")]
+ UNSPEC_VSX_SIEXPQP))]
+ "TARGET_P9_VECTOR"
+ "xsiexpqp %0,%1,%2"
+ [(set_attr "type" "vecmove")])
+
+;; VSX Scalar Insert Exponent Quad-Precision
+(define_insn "xsiexpqp"
+ [(set (match_operand:KF 0 "altivec_register_operand" "=v")
+ (unspec:KF [(match_operand:TI 1 "altivec_register_operand" "v")
+ (match_operand:DI 2 "altivec_register_operand" "v")]
+ UNSPEC_VSX_SIEXPQP))]
+ "TARGET_P9_VECTOR"
+ "xsiexpqp %0,%1,%2"
+ [(set_attr "type" "vecmove")])
+
;; VSX Scalar Insert Exponent Double-Precision
(define_insn "xsiexpdp"
[(set (match_operand:DF 0 "vsx_register_operand" "=wa")
@@ -3806,6 +4033,27 @@
"xscmpexpdp %0,%x1,%x2"
[(set_attr "type" "fpcompare")])
+;; VSX Scalar Test Data Class Quad-Precision
+;; (Expansion for scalar_test_data_class (__ieee128, int))
+;; (Has side effect of setting the lt bit if operand 1 is negative,
+;; setting the eq bit if any of the conditions tested by operand 2
+;; are satisfied, and clearing the gt and undordered bits to zero.)
+(define_expand "xststdcqp"
+ [(set (match_dup 3)
+ (compare:CCFP
+ (unspec:KF
+ [(match_operand:KF 1 "altivec_register_operand" "v")
+ (match_operand:SI 2 "u7bit_cint_operand" "n")]
+ UNSPEC_VSX_STSTDC)
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (match_dup 3)
+ (const_int 0)))]
+ "TARGET_P9_VECTOR"
+{
+ operands[3] = gen_reg_rtx (CCFPmode);
+})
+
;; VSX Scalar Test Data Class Double- and Single-Precision
;; (The lt bit is set if operand 1 is negative. The eq bit is set
;; if any of the conditions tested by operand 2 are satisfied.
@@ -3827,8 +4075,24 @@
operands[4] = CONST0_RTX (SImode);
})
-;; The VSX Scalar Test Data Class Double- and Single-Precision
-;; instruction may also be used to test for negative value.
+;; The VSX Scalar Test Negative Quad-Precision
+(define_expand "xststdcnegqp"
+ [(set (match_dup 2)
+ (compare:CCFP
+ (unspec:KF
+ [(match_operand:KF 1 "altivec_register_operand" "v")
+ (const_int 0)]
+ UNSPEC_VSX_STSTDC)
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (match_dup 2)
+ (const_int 0)))]
+ "TARGET_P9_VECTOR"
+{
+ operands[2] = gen_reg_rtx (CCFPmode);
+})
+
+;; The VSX Scalar Test Negative Double- and Single-Precision
(define_expand "xststdcneg<Fvsx>"
[(set (match_dup 2)
(compare:CCFP
@@ -3846,6 +4110,17 @@
operands[3] = CONST0_RTX (SImode);
})
+(define_insn "*xststdcqp"
+ [(set (match_operand:CCFP 0 "" "=y")
+ (compare:CCFP
+ (unspec:KF [(match_operand:KF 1 "altivec_register_operand" "v")
+ (match_operand:SI 2 "u7bit_cint_operand" "n")]
+ UNSPEC_VSX_STSTDC)
+ (const_int 0)))]
+ "TARGET_P9_VECTOR"
+ "xststdcqp %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
(define_insn "*xststdc<Fvsx>"
[(set (match_operand:CCFP 0 "" "=y")
(compare:CCFP
@@ -4225,7 +4500,65 @@
"xxinsertw %x0,%x1,%3"
[(set_attr "type" "vecperm")])
-
+;; Generate vector extract four float 32 values from left four elements
+;; of eight element vector of float 16 values.
+(define_expand "vextract_fp_from_shorth"
+ [(set (match_operand:V4SF 0 "register_operand" "=wa")
+ (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "wa")]
+ UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTH))]
+ "TARGET_P9_VECTOR"
+{
+ int vals[16] = {15, 14, 0, 0, 13, 12, 0, 0, 11, 10, 0, 0, 9, 8, 0, 0};
+ int i;
+
+ rtx rvals[16];
+ rtx mask = gen_reg_rtx (V16QImode);
+ rtx tmp = gen_reg_rtx (V16QImode);
+ rtvec v;
+
+ for (i = 0; i < 16; i++)
+ rvals[i] = GEN_INT (vals[i]);
+
+ /* xvcvhpsp - vector convert F16 to vector F32 requires the four F16
+ inputs in half words 1,3,5,7 (IBM numbering). Use xxperm to move
+ src half words 0,1,2,3 for the conversion instruction. */
+ v = gen_rtvec_v (16, rvals);
+ emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
+ emit_insn (gen_altivec_vperm_v8hiv16qi (tmp, operands[1],
+ operands[1], mask));
+ emit_insn (gen_vsx_xvcvhpsp (operands[0], tmp));
+ DONE;
+})
+
+;; Generate vector extract four float 32 values from right four elements
+;; of eight element vector of float 16 values.
+(define_expand "vextract_fp_from_shortl"
+ [(set (match_operand:V4SF 0 "register_operand" "=wa")
+ (unspec:V4SF [(match_operand:V8HI 1 "register_operand" "wa")]
+ UNSPEC_VSX_VEXTRACT_FP_FROM_SHORTL))]
+ "TARGET_P9_VECTOR"
+{
+ int vals[16] = {7, 6, 0, 0, 5, 4, 0, 0, 3, 2, 0, 0, 1, 0, 0, 0};
+ int i;
+ rtx rvals[16];
+ rtx mask = gen_reg_rtx (V16QImode);
+ rtx tmp = gen_reg_rtx (V16QImode);
+ rtvec v;
+
+ for (i = 0; i < 16; i++)
+ rvals[i] = GEN_INT (vals[i]);
+
+ /* xvcvhpsp - vector convert F16 to vector F32 requires the four F16
+ inputs in half words 1,3,5,7 (IBM numbering). Use xxperm to move
+ src half words 4,5,6,7 for the conversion instruction. */
+ v = gen_rtvec_v (16, rvals);
+ emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
+ emit_insn (gen_altivec_vperm_v8hiv16qi (tmp, operands[1],
+ operands[1], mask));
+ emit_insn (gen_vsx_xvcvhpsp (operands[0], tmp));
+ DONE;
+})
+
;; Support for ISA 3.0 vector byte reverse
;; Swap all bytes with in a vector
diff --git a/gcc/config/rs6000/x86intrin.h b/gcc/config/rs6000/x86intrin.h
index 4aa33fdbbf5..1526a7de2ef 100644
--- a/gcc/config/rs6000/x86intrin.h
+++ b/gcc/config/rs6000/x86intrin.h
@@ -35,9 +35,12 @@
#ifndef _X86INTRIN_H_INCLUDED
#define _X86INTRIN_H_INCLUDED
+#ifdef __ALTIVEC__
+#include <mmintrin.h>
+#endif /* __ALTIVEC__ */
+
#include <bmiintrin.h>
#include <bmi2intrin.h>
-
#endif /* _X86INTRIN_H_INCLUDED */
diff --git a/gcc/config/rtems.h b/gcc/config/rtems.h
index 306459ab1d1..439199d4cbb 100644
--- a/gcc/config/rtems.h
+++ b/gcc/config/rtems.h
@@ -1,26 +1,26 @@
/* Configuration common to all targets running RTEMS.
Copyright (C) 2000-2017 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.
-
-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/>. */
+ 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/>. */
/* The system headers under RTEMS are C++-aware. */
#undef NO_IMPLICIT_EXTERN_C
diff --git a/gcc/config/s390/driver-native.c b/gcc/config/s390/driver-native.c
index 4bcddb4bab6..acb983613c2 100644
--- a/gcc/config/s390/driver-native.c
+++ b/gcc/config/s390/driver-native.c
@@ -112,10 +112,14 @@ s390_host_detect_local_cpu (int argc, const char **argv)
cpu = "zEC12";
break;
case 0x2964:
+ case 0x2965:
cpu = "z13";
break;
+ case 0x3906:
+ cpu = "z14";
+ break;
default:
- cpu = "arch12";
+ cpu = "z14";
break;
}
}
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 34a7ea28455..fc151ac1d28 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -131,10 +131,10 @@
/* Allow labels and local symbols. */
if (GET_CODE (op) == LABEL_REF)
return true;
- if (GET_CODE (op) == SYMBOL_REF)
+ if (SYMBOL_REF_P (op))
return (!SYMBOL_FLAG_NOTALIGN2_P (op)
&& SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+ && s390_rel_address_ok_p (op));
/* Everything else must have a CONST, so strip it. */
if (GET_CODE (op) != CONST)
@@ -156,10 +156,11 @@
/* Labels and local symbols allowed here as well. */
if (GET_CODE (op) == LABEL_REF)
return true;
- if (GET_CODE (op) == SYMBOL_REF)
+ if (SYMBOL_REF_P (op))
return (!SYMBOL_FLAG_NOTALIGN2_P (op)
&& SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+ && s390_rel_address_ok_p (op));
+
/* Now we must have a @GOTENT offset or @PLT stub
or an @INDNTPOFF TLS offset. */
diff --git a/gcc/config/s390/s390-c.c b/gcc/config/s390/s390-c.c
index 35c35458791..07224ad7f39 100644
--- a/gcc/config/s390/s390-c.c
+++ b/gcc/config/s390/s390-c.c
@@ -886,7 +886,7 @@ s390_resolve_overloaded_builtin (location_t loc,
if (!TARGET_VXE && (ob_flags & B_VXE))
{
- error_at (loc, "%qF requires -march=arch12 or higher", ob_fndecl);
+ error_at (loc, "%qF requires z14 or higher", ob_fndecl);
return error_mark_node;
}
@@ -963,7 +963,7 @@ s390_resolve_overloaded_builtin (location_t loc,
if (!TARGET_VXE
&& bflags_overloaded_builtin_var[last_match_index] & B_VXE)
{
- error_at (loc, "%qs matching variant requires -march=arch12 or higher",
+ error_at (loc, "%qs matching variant requires z14 or higher",
IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
return error_mark_node;
}
diff --git a/gcc/config/s390/s390-opts.h b/gcc/config/s390/s390-opts.h
index 65ac4f8ebbd..6d506e2c9e3 100644
--- a/gcc/config/s390/s390-opts.h
+++ b/gcc/config/s390/s390-opts.h
@@ -38,7 +38,7 @@ enum processor_type
PROCESSOR_2817_Z196,
PROCESSOR_2827_ZEC12,
PROCESSOR_2964_Z13,
- PROCESSOR_ARCH12,
+ PROCESSOR_3906_Z14,
PROCESSOR_NATIVE,
PROCESSOR_max
};
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 3fdb32059cd..6df37ef9bf7 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -79,6 +79,7 @@ extern bool s390_bytemask_vector_p (rtx, unsigned *);
extern bool s390_split_ok_p (rtx, rtx, machine_mode, int);
extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
extern bool s390_offset_p (rtx, rtx, rtx);
+extern bool s390_rel_address_ok_p (rtx);
extern int tls_symbolic_operand (rtx);
extern bool s390_match_ccmode (rtx_insn *, machine_mode);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index eb94237d969..77b0e7f5404 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -318,24 +318,27 @@ struct processor_costs zEC12_cost =
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", PROCESSOR_9672_G5, &z900_cost },
- { "g6", PROCESSOR_9672_G6, &z900_cost },
- { "z900", PROCESSOR_2064_Z900, &z900_cost },
- { "z990", PROCESSOR_2084_Z990, &z990_cost },
- { "z9-109", PROCESSOR_2094_Z9_109, &z9_109_cost },
- { "z9-ec", PROCESSOR_2094_Z9_EC, &z9_109_cost },
- { "z10", PROCESSOR_2097_Z10, &z10_cost },
- { "z196", PROCESSOR_2817_Z196, &z196_cost },
- { "zEC12", PROCESSOR_2827_ZEC12, &zEC12_cost },
- { "z13", PROCESSOR_2964_Z13, &zEC12_cost },
- { "arch12", PROCESSOR_ARCH12, &zEC12_cost },
- { "native", PROCESSOR_NATIVE, NULL }
+ { "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 }
};
extern int reload_completed;
@@ -847,7 +850,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
if ((bflags & B_VXE) && !TARGET_VXE)
{
- error ("Builtin %qF requires arch12 or higher.", fndecl);
+ error ("Builtin %qF requires z14 or higher.", fndecl);
return const0_rtx;
}
}
@@ -1179,6 +1182,23 @@ s390_label_align (rtx_insn *label)
return align_labels_log;
}
+static GTY(()) rtx got_symbol;
+
+/* Return the GOT table symbol. The symbol will be created when the
+ function is invoked for the first time. */
+
+static rtx
+s390_got_symbol (void)
+{
+ if (!got_symbol)
+ {
+ got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
+ }
+
+ return got_symbol;
+}
+
static machine_mode
s390_libgcc_cmp_return_mode (void)
{
@@ -3397,6 +3417,48 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
*total = 0;
return true;
+ case SET:
+ {
+ /* Without this a conditional move instruction would be
+ accounted as 3 * COSTS_N_INSNS (set, if_then_else,
+ comparison operator). That's a bit pessimistic. */
+
+ if (!TARGET_Z196 || GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
+ return false;
+
+ rtx cond = XEXP (SET_SRC (x), 0);
+
+ if (!CC_REG_P (XEXP (cond, 0)) || !CONST_INT_P (XEXP (cond, 1)))
+ return false;
+
+ /* It is going to be a load/store on condition. Make it
+ slightly more expensive than a normal load. */
+ *total = COSTS_N_INSNS (1) + 1;
+
+ rtx dst = SET_DEST (x);
+ rtx then = XEXP (SET_SRC (x), 1);
+ rtx els = XEXP (SET_SRC (x), 2);
+
+ /* It is a real IF-THEN-ELSE. An additional move will be
+ needed to implement that. */
+ if (reload_completed
+ && !rtx_equal_p (dst, then)
+ && !rtx_equal_p (dst, els))
+ *total += COSTS_N_INSNS (1) / 2;
+
+ /* A minor penalty for constants we cannot directly handle. */
+ if ((CONST_INT_P (then) || CONST_INT_P (els))
+ && (!TARGET_Z13 || MEM_P (dst)
+ || (CONST_INT_P (then) && !satisfies_constraint_K (then))
+ || (CONST_INT_P (els) && !satisfies_constraint_K (els))))
+ *total += COSTS_N_INSNS (1) / 2;
+
+ /* A store on condition can only handle register src operands. */
+ if (MEM_P (dst) && (!REG_P (then) || !REG_P (els)))
+ *total += COSTS_N_INSNS (1) / 2;
+
+ return true;
+ }
case IOR:
/* risbg */
if (GET_CODE (XEXP (x, 0)) == AND
@@ -4496,6 +4558,26 @@ s390_load_address (rtx dst, rtx src)
emit_insn (gen_force_la_31 (dst, src));
}
+/* Return true if it ok to use SYMBOL_REF in a relative address. */
+
+bool
+s390_rel_address_ok_p (rtx symbol_ref)
+{
+ tree decl;
+
+ if (symbol_ref == s390_got_symbol () || CONSTANT_POOL_ADDRESS_P (symbol_ref))
+ return true;
+
+ decl = SYMBOL_REF_DECL (symbol_ref);
+
+ if (!flag_pic || SYMBOL_REF_LOCAL_P (symbol_ref))
+ return (s390_pic_data_is_text_relative
+ || (decl
+ && TREE_CODE (decl) == FUNCTION_DECL));
+
+ return false;
+}
+
/* Return a legitimate reference for ORIG (an address) using the
register REG. If REG is 0, a new pseudo is generated.
@@ -4533,7 +4615,7 @@ legitimize_pic_address (rtx orig, rtx reg)
}
if ((GET_CODE (addr) == LABEL_REF
- || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr))
+ || (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))))
@@ -5312,8 +5394,6 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
void
s390_expand_setmem (rtx dst, rtx len, rtx val)
{
- const int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
-
if (GET_CODE (len) == CONST_INT && INTVAL (len) <= 0)
return;
@@ -5387,7 +5467,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
convert_move (count, len, 1);
emit_cmp_and_jump_insns (count, const0_rtx,
EQ, NULL_RTX, mode, 1, zerobyte_end_label,
- very_unlikely);
+ profile_probability::very_unlikely ());
/* We need to make a copy of the target address since memset is
supposed to return it unmodified. We have to make it here
@@ -5404,7 +5484,8 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
dstp1 = adjust_address (dst, VOIDmode, 1);
emit_cmp_and_jump_insns (count,
const1_rtx, EQ, NULL_RTX, mode, 1,
- onebyte_end_label, very_unlikely);
+ onebyte_end_label,
+ profile_probability::very_unlikely ());
}
/* There is one unconditional (mvi+mvc)/xc after the loop
@@ -5642,8 +5723,6 @@ s390_emit_ccraw_jump (HOST_WIDE_INT mask, enum rtx_code comparison, rtx label)
void
s390_expand_vec_strlen (rtx target, rtx string, rtx alignment)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
- int very_likely = REG_BR_PROB_BASE - 1;
rtx highest_index_to_load_reg = gen_reg_rtx (Pmode);
rtx str_reg = gen_reg_rtx (V16QImode);
rtx str_addr_base_reg = gen_reg_rtx (Pmode);
@@ -5714,7 +5793,8 @@ s390_expand_vec_strlen (rtx target, rtx string, rtx alignment)
GEN_INT (VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
add_int_reg_note (s390_emit_ccraw_jump (8, NE, loop_start_label),
- REG_BR_PROB, very_likely);
+ REG_BR_PROB,
+ profile_probability::very_likely ().to_reg_br_prob_note ());
emit_insn (gen_vec_extractv16qi (len, result_reg, GEN_INT (7)));
/* If the string pointer wasn't aligned we have loaded less then 16
@@ -5734,8 +5814,8 @@ s390_expand_vec_strlen (rtx target, rtx string, rtx alignment)
emit_insn (gen_movsicc (str_idx_reg, cond,
highest_index_to_load_reg, str_idx_reg));
- add_int_reg_note (s390_emit_jump (is_aligned_label, cond), REG_BR_PROB,
- very_unlikely);
+ add_reg_br_prob_note (s390_emit_jump (is_aligned_label, cond),
+ profile_probability::very_unlikely ());
expand_binop (Pmode, add_optab, str_idx_reg,
GEN_INT (-16), str_idx_reg, 1, OPTAB_DIRECT);
@@ -5751,7 +5831,6 @@ s390_expand_vec_strlen (rtx target, rtx string, rtx alignment)
void
s390_expand_vec_movstr (rtx result, rtx dst, rtx src)
{
- int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx temp = gen_reg_rtx (Pmode);
rtx src_addr = XEXP (src, 0);
rtx dst_addr = XEXP (dst, 0);
@@ -5828,7 +5907,8 @@ s390_expand_vec_movstr (rtx result, rtx dst, rtx src)
emit_insn (gen_vec_vfenesv16qi (vpos, vsrc, vsrc,
GEN_INT (VSTRING_FLAG_ZS | VSTRING_FLAG_CS)));
add_int_reg_note (s390_emit_ccraw_jump (8, EQ, done_label),
- REG_BR_PROB, very_unlikely);
+ REG_BR_PROB, profile_probability::very_unlikely ()
+ .to_reg_br_prob_note ());
emit_move_insn (gen_rtx_MEM (V16QImode,
gen_rtx_PLUS (Pmode, dst_addr_reg, offset)),
@@ -6851,7 +6931,6 @@ s390_expand_cs_tdsi (machine_mode mode, rtx btarget, rtx vtarget, rtx mem,
if (do_const_opt)
{
- const int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx cc = gen_rtx_REG (CCZmode, CC_REGNUM);
skip_cs_label = gen_label_rtx ();
@@ -6872,7 +6951,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_int_reg_note (get_last_insn (), REG_BR_PROB, 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
@@ -7282,7 +7362,8 @@ s390_asm_output_machine_for_arch (FILE *asm_out_file)
{
fprintf (asm_out_file, "\t.machinemode %s\n",
(TARGET_ZARCH) ? "zarch" : "esa");
- fprintf (asm_out_file, "\t.machine \"%s", processor_table[s390_arch].name);
+ fprintf (asm_out_file, "\t.machine \"%s",
+ processor_table[s390_arch].binutils_name);
if (S390_USE_ARCHITECTURE_MODIFIERS)
{
int cpu_flags;
@@ -8016,7 +8097,7 @@ s390_issue_rate (void)
instruction gets issued per cycle. */
case PROCESSOR_2827_ZEC12:
case PROCESSOR_2964_Z13:
- case PROCESSOR_ARCH12:
+ case PROCESSOR_3906_Z14:
default:
return 1;
}
@@ -10791,7 +10872,6 @@ restore_gprs (rtx base, int offset, int first, int last)
/* Return insn sequence to load the GOT register. */
-static GTY(()) rtx got_symbol;
rtx_insn *
s390_load_got (void)
{
@@ -10803,23 +10883,17 @@ s390_load_got (void)
aren't usable. */
rtx got_rtx = gen_rtx_REG (Pmode, 12);
- if (!got_symbol)
- {
- got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
- }
-
start_sequence ();
if (TARGET_CPU_ZARCH)
{
- emit_move_insn (got_rtx, got_symbol);
+ emit_move_insn (got_rtx, s390_got_symbol ());
}
else
{
rtx offset;
- offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
+ 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);
@@ -11607,7 +11681,8 @@ s390_expand_split_stack_prologue (void)
LABEL_NUSES (call_done)++;
/* Mark the jump as very unlikely to be taken. */
- add_int_reg_note (insn, REG_BR_PROB, REG_BR_PROB_BASE / 100);
+ add_reg_br_prob_note (insn,
+ profile_probability::very_unlikely ());
if (cfun->machine->split_stack_varargs_pointer != NULL_RTX)
{
@@ -14238,7 +14313,7 @@ s390_get_sched_attrmask (rtx_insn *insn)
mask |= S390_SCHED_ATTR_MASK_GROUPALONE;
break;
case PROCESSOR_2964_Z13:
- case PROCESSOR_ARCH12:
+ case PROCESSOR_3906_Z14:
if (get_attr_z13_cracked (insn))
mask |= S390_SCHED_ATTR_MASK_CRACKED;
if (get_attr_z13_expanded (insn))
@@ -14262,7 +14337,7 @@ s390_get_unit_mask (rtx_insn *insn, int *units)
switch (s390_tune)
{
case PROCESSOR_2964_Z13:
- case PROCESSOR_ARCH12:
+ case PROCESSOR_3906_Z14:
*units = 3;
if (get_attr_z13_unit_lsu (insn))
mask |= 1 << 0;
@@ -14911,6 +14986,9 @@ s390_option_override (void)
if (flag_prefetch_loop_arrays < 0 && HAVE_prefetch && optimize >= 3)
flag_prefetch_loop_arrays = 1;
+ if (!s390_pic_data_is_text_relative && !flag_pic)
+ error ("-mno-pic-data-is-text-relative cannot be used without -fpic/-fPIC");
+
if (TARGET_TPF)
{
/* Don't emit DWARF3/4 unless specifically selected. The TPF
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index a372981ff3a..7847047d160 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -946,6 +946,10 @@ CUMULATIVE_ARGS;
#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
+#ifndef TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE
+#define TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE 1
+#endif
+
/* Assembler file format. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index cfae171c2a0..d1ac0b8395d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -6600,14 +6600,14 @@
})
; locr, loc, stoc, locgr, locg, stocg, lochi, locghi
-(define_insn_and_split "*mov<mode>cc"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d,S,S,&d")
+(define_insn "*mov<mode>cc"
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d,S,S")
(if_then_else:GPR
(match_operator 1 "s390_comparison"
- [(match_operand 2 "cc_reg_operand" " c,c,c,c,c,c,c,c,c")
+ [(match_operand 2 "cc_reg_operand" " c,c,c,c,c,c,c,c")
(match_operand 5 "const_int_operand" "")])
- (match_operand:GPR 3 "loc_operand" " d,0,S,0,K,0,d,0,S")
- (match_operand:GPR 4 "loc_operand" " 0,d,0,S,0,K,0,d,S")))]
+ (match_operand:GPR 3 "loc_operand" " d,0,S,0,K,0,d,0")
+ (match_operand:GPR 4 "loc_operand" " 0,d,0,S,0,K,0,d")))]
"TARGET_Z196"
"@
loc<g>r%C1\t%0,%3
@@ -6617,23 +6617,9 @@
loc<g>hi%C1\t%0,%h3
loc<g>hi%D1\t%0,%h4
stoc<g>%C1\t%3,%0
- stoc<g>%D1\t%4,%0
- #"
- "&& reload_completed
- && MEM_P (operands[3]) && MEM_P (operands[4])"
- [(set (match_dup 0)
- (if_then_else:GPR
- (match_op_dup 1 [(match_dup 2) (const_int 0)])
- (match_dup 3)
- (match_dup 0)))
- (set (match_dup 0)
- (if_then_else:GPR
- (match_op_dup 1 [(match_dup 2) (const_int 0)])
- (match_dup 0)
- (match_dup 4)))]
- ""
- [(set_attr "op_type" "RRF,RRF,RSY,RSY,RIE,RIE,RSY,RSY,*")
- (set_attr "cpu_facility" "*,*,*,*,z13,z13,*,*,*")])
+ stoc<g>%D1\t%4,%0"
+ [(set_attr "op_type" "RRF,RRF,RSY,RSY,RIE,RIE,RSY,RSY")
+ (set_attr "cpu_facility" "*,*,*,*,z13,z13,*,*")])
;;
;;- Multiply instructions.
@@ -10280,7 +10266,7 @@
; cdsg, csg
(define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:TDI 0 "register_operand" "=r")
- (match_operand:TDI 1 "s_operand" "+S"))
+ (match_operand:TDI 1 "memory_operand" "+S"))
(set (match_dup 1)
(unspec_volatile:TDI
[(match_dup 1)
@@ -10298,7 +10284,7 @@
; cds, cdsy
(define_insn "*atomic_compare_and_swapdi_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (match_operand:DI 1 "s_operand" "+Q,S"))
+ (match_operand:DI 1 "memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)
@@ -10319,7 +10305,7 @@
; cs, csy
(define_insn "*atomic_compare_and_swapsi_3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "s_operand" "+Q,S"))
+ (match_operand:SI 1 "memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_dup 1)
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index d0a0d46b0a7..4dab1b655a3 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -113,7 +113,10 @@ EnumValue
Enum(processor_type) String(arch11) Value(PROCESSOR_2964_Z13)
EnumValue
-Enum(processor_type) String(arch12) Value(PROCESSOR_ARCH12)
+Enum(processor_type) String(z14) Value(PROCESSOR_3906_Z14)
+
+EnumValue
+Enum(processor_type) String(arch12) Value(PROCESSOR_3906_Z14)
EnumValue
Enum(processor_type) String(native) Value(PROCESSOR_NATIVE) DriverOnly
@@ -226,3 +229,7 @@ values are small, non-negative integers. The default branch cost is
mlra
Target Report Var(s390_lra_flag) Init(1) Save
Use LRA instead of reload.
+
+mpic-data-is-text-relative
+Target Report Var(s390_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
+Assume data segments are relative to text segment.
diff --git a/gcc/config/sh/rtems.h b/gcc/config/sh/rtems.h
index 20a4d5ce27d..e05c4cec2b4 100644
--- a/gcc/config/sh/rtems.h
+++ b/gcc/config/sh/rtems.h
@@ -2,21 +2,26 @@
Copyright (C) 1997-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/sh/rtemself.h b/gcc/config/sh/rtemself.h
index c9b6b001cf7..c454c0e3e19 100644
--- a/gcc/config/sh/rtemself.h
+++ b/gcc/config/sh/rtemself.h
@@ -2,21 +2,26 @@
Copyright (C) 1997-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 59be4c0cf30..305ab2cd19b 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -68,7 +68,7 @@ extern bool sh_expand_strlen (rtx *);
extern void sh_expand_setmem (rtx *);
extern enum rtx_code prepare_cbranch_operands (rtx *, machine_mode mode,
enum rtx_code comparison);
-extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int);
+extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison);
extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison);
extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx);
extern void sh_emit_compare_and_branch (rtx *, machine_mode);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index ff79b93adc2..6f01dcb700c 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -1139,7 +1139,9 @@ sh_print_operand (FILE *stream, rtx x, int code)
{
rtx note = find_reg_note (current_output_insn, REG_BR_PROB, 0);
- if (note && XINT (note, 0) * 2 < REG_BR_PROB_BASE)
+ if (note
+ && profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ < profile_probability::even ())
fputs ("/u", stream);
break;
}
@@ -1999,8 +2001,9 @@ prepare_cbranch_operands (rtx *operands, machine_mode mode,
return comparison;
}
-void
-expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
+static void
+expand_cbranchsi4 (rtx *operands, enum rtx_code comparison,
+ profile_probability probability)
{
rtx (*branch_expander) (rtx) = gen_branch_true;
comparison = prepare_cbranch_operands (operands, SImode, comparison);
@@ -2015,8 +2018,15 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
gen_rtx_fmt_ee (comparison, SImode,
operands[1], operands[2])));
rtx_insn *jump = emit_jump_insn (branch_expander (operands[3]));
- if (probability >= 0)
- add_int_reg_note (jump, REG_BR_PROB, probability);
+ if (probability.initialized_p ())
+ add_reg_br_prob_note (jump, probability);
+}
+
+void
+expand_cbranchsi4 (rtx *operands, enum rtx_code comparison)
+{
+ expand_cbranchsi4 (operands, comparison,
+ profile_probability::uninitialized ());
}
/* ??? How should we distribute probabilities when more than one branch
@@ -2043,8 +2053,10 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
rtx_code_label *skip_label = NULL;
rtx op1h, op1l, op2h, op2l;
int num_branches;
- int prob, rev_prob;
- int msw_taken_prob = -1, msw_skip_prob = -1, lsw_taken_prob = -1;
+ profile_probability prob, rev_prob;
+ profile_probability msw_taken_prob = profile_probability::uninitialized (),
+ msw_skip_prob = profile_probability::uninitialized (),
+ lsw_taken_prob = profile_probability::uninitialized ();
comparison = prepare_cbranch_operands (operands, DImode, comparison);
op1h = gen_highpart_mode (SImode, DImode, operands[1]);
@@ -2053,34 +2065,28 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
op2l = gen_lowpart (SImode, operands[2]);
msw_taken = msw_skip = lsw_taken = LAST_AND_UNUSED_RTX_CODE;
prob = split_branch_probability;
- rev_prob = REG_BR_PROB_BASE - prob;
+ rev_prob = prob.invert ();
switch (comparison)
{
case EQ:
msw_skip = NE;
lsw_taken = EQ;
- if (prob >= 0)
+ if (prob.initialized_p ())
{
- // If we had more precision, we'd use rev_prob - (rev_prob >> 32) .
+ /* FIXME: This is not optimal. We do not really know the probablity
+ that values differ by MCW only, but we should probably distribute
+ probabilities more evenly. */
msw_skip_prob = rev_prob;
- if (REG_BR_PROB_BASE <= 65535)
- lsw_taken_prob = prob ? REG_BR_PROB_BASE : 0;
- else
- {
- lsw_taken_prob
- = (prob
- ? (REG_BR_PROB_BASE
- - ((gcov_type) REG_BR_PROB_BASE * rev_prob
- / ((gcov_type) prob << 32)))
- : 0);
- }
+ lsw_taken_prob = prob > profile_probability::never ()
+ ? profile_probability::guessed_always ()
+ : profile_probability::guessed_never ();
}
break;
case NE:
msw_taken = NE;
msw_taken_prob = prob;
lsw_taken = NE;
- lsw_taken_prob = 0;
+ lsw_taken_prob = profile_probability::guessed_never ();
break;
case GTU: case GT:
msw_taken = comparison;
@@ -2133,18 +2139,20 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
if (comparison != EQ && comparison != NE && num_branches > 1)
{
if (!CONSTANT_P (operands[2])
- && prob >= (int) (REG_BR_PROB_BASE * 3 / 8U)
- && prob <= (int) (REG_BR_PROB_BASE * 5 / 8U))
- {
- msw_taken_prob = prob / 2U;
- msw_skip_prob
- = REG_BR_PROB_BASE * rev_prob / (REG_BR_PROB_BASE + rev_prob);
+ && prob.initialized_p ()
+ && prob.to_reg_br_prob_base () >= (int) (REG_BR_PROB_BASE * 3 / 8U)
+ && prob.to_reg_br_prob_base () <= (int) (REG_BR_PROB_BASE * 5 / 8U))
+ {
+ msw_taken_prob = prob.apply_scale (1, 2);
+ msw_skip_prob = rev_prob.apply_scale (REG_BR_PROB_BASE,
+ rev_prob.to_reg_br_prob_base ()
+ + REG_BR_PROB_BASE);
lsw_taken_prob = prob;
}
else
{
msw_taken_prob = prob;
- msw_skip_prob = REG_BR_PROB_BASE;
+ msw_skip_prob = profile_probability::guessed_always ();
/* ??? If we have a constant op2h, should we use that when
calculating lsw_taken_prob? */
lsw_taken_prob = prob;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index e19e977087d..733c777ef56 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1188,7 +1188,7 @@
(clobber (reg:SI T_REG))]
"can_create_pseudo_p ()"
{
- expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1);
+ expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE);
DONE;
})
diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md
index 7c9ef74ce6a..cff5a61b1de 100644
--- a/gcc/config/sparc/constraints.md
+++ b/gcc/config/sparc/constraints.md
@@ -19,7 +19,7 @@
;;; Unused letters:
;;; B
-;;; a jkl q tuv xyz
+;;; a jkl uv xyz
;; Register constraints
@@ -58,6 +58,16 @@
;; Integer constant constraints
+(define_constraint "q"
+ "Unsigned 2-bit integer constant"
+ (and (match_code "const_int")
+ (match_test "SPARC_IMM2_P (ival)")))
+
+(define_constraint "t"
+ "Unsigned 5-bit integer constant"
+ (and (match_code "const_int")
+ (match_test "SPARC_IMM5_P (ival)")))
+
(define_constraint "A"
"Signed 5-bit integer constant"
(and (match_code "const_int")
diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c
index b96ef47ac60..0c25d6cfa15 100644
--- a/gcc/config/sparc/driver-sparc.c
+++ b/gcc/config/sparc/driver-sparc.c
@@ -79,6 +79,7 @@ static const struct cpu_names {
#endif
{ "SPARC-M7", "niagara7" },
{ "SPARC-S7", "niagara7" },
+ { "SPARC-M8", "m8" },
{ NULL, NULL }
};
diff --git a/gcc/config/sparc/m8.md b/gcc/config/sparc/m8.md
new file mode 100644
index 00000000000..f0fe1b27a20
--- /dev/null
+++ b/gcc/config/sparc/m8.md
@@ -0,0 +1,242 @@
+;; Scheduling description for the SPARC M8.
+;; Copyright (C) 2017 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/>.
+
+;; Thigs to improve:
+;;
+;; - Store instructions are implemented by micro-ops, one of which
+;; generates the store address and is executed in the store address
+;; generation unit in the slot0. We need to model that.
+;;
+;; - There are two V3 pipes connected to different slots. The current
+;; implementation assumes that all the instructions executing in a
+;; V3 pipe are issued to the unit in slot3.
+;;
+;; - Single-issue ALU operations incur an additional cycle of latency to
+;; slot 0 and slot 1 instructions. This is not currently reflected
+;; in the DFA.
+
+(define_automaton "m8_0")
+
+;; The S5 core has two dual-issue queues, PQLS and PQEX. Each queue
+;; is divided into two slots: PQLS corresponds to slots 0 and 1, and
+;; PQEX corresponds to slots 2 and 3. The core can issue 4
+;; instructions per-cycle, and up to 4 instructions are committed each
+;; cycle.
+;;
+;;
+;; m8_slot0 - Load Unit.
+;; - Store address gen. Unit.
+;;
+;;
+;; === PQLS ==> m8_slot1 - Store data unit.
+;; - Branch unit.
+;;
+;;
+;; === PQEX ==> m8_slot2 - Integer Unit (EXU2).
+;; - 3-cycles Crypto Unit (SPU2).
+;;
+;; m8_slot3 - Integer Unit (EXU3).
+;; - 3-cycles Crypto Unit (SPU3).
+;; - Floating-point and graphics unit (FPG).
+;; - Long-latency Crypto Unit.
+;; - Oracle Numbers Unit (ONU).
+
+(define_cpu_unit "m8_slot0,m8_slot1,m8_slot2,m8_slot3" "m8_0")
+
+;; Some instructions stall the pipeline and avoid any other
+;; instruction to be issued in the same cycle. We assume the same for
+;; multi-instruction insns.
+
+(define_reservation "m8_single_issue" "m8_slot0 + m8_slot1 + m8_slot2 + m8_slot3")
+
+(define_insn_reservation "m8_single" 1
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "multi,savew,flushw,trap,bmask"))
+ "m8_single_issue")
+
+;; Most of the instructions executing in the integer units have a
+;; latency of 1.
+
+(define_insn_reservation "m8_integer" 1
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "ialu,ialuX,shift,cmove,compare,bmask"))
+ "(m8_slot2 | m8_slot3)")
+
+;; Flushing the instruction memory takes 27 cycles.
+
+
+(define_insn_reservation "m8_iflush" 27
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "iflush"))
+ "(m8_slot2 | m8_slot3), nothing*26")
+
+;; The integer multiplication instructions have a latency of 10 cycles
+;; and execute in integer units.
+;;
+;; Likewise for array*, edge* and pdistn instructions.
+;;
+;; However, the latency is only 9 cycles if the consumer of the
+;; operation is also capable of 9 cycles latency. We model this with
+;; a bypass.
+
+(define_insn_reservation "m8_imul" 10
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "imul,array,edge,edgen,pdistn"))
+ "(m8_slot2 | m8_slot3), nothing*12")
+
+(define_bypass 9 "m8_imul" "m8_imul")
+
+;; The integer division instructions `sdiv' and `udivx' have a latency
+;; of 30 cycles and execute in integer units.
+
+(define_insn_reservation "m8_idiv" 30
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "idiv"))
+ "(m8_slot2 | m8_slot3), nothing*29")
+
+;; Both integer and floating-point load instructions have a latency of
+;; only 3 cycles,and execute in the slot0.
+;;
+;; Misaligned load instructions feature a latency of 11 cycles.
+;;
+;; The prefetch instruction also executes in the load unit, but it's
+;; latency is only 1 cycle.
+
+(define_insn_reservation "m8_load" 3
+ (and (eq_attr "cpu" "m8")
+ (ior (eq_attr "type" "fpload,sload")
+ (and (eq_attr "type" "load")
+ (eq_attr "subtype" "regular"))))
+ "m8_slot0, nothing*2")
+
+;; (define_insn_reservation "m8_load_misalign" 11
+;; (and (eq_attr "cpu" "m8")
+;; (eq_attr "type" "load_mis,fpload_mis"))
+;; "m8_slot0, nothing*10")
+
+(define_insn_reservation "m8_prefetch" 1
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "load")
+ (eq_attr "subtype" "prefetch"))
+ "m8_slot0")
+
+;; Both integer and floating-point store instructions have a latency
+;; of 1 cycle, and execute in the store data unit in slot1.
+;;
+;; However, misaligned store instructions feature a latency of 3
+;; cycles.
+
+(define_insn_reservation "m8_store" 1
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "store,fpstore"))
+ "m8_slot1")
+
+;; (define_insn_reservation "m8_store_misalign" 3
+;; (and (eq_attr "cpu" "m8")
+;; (eq_attr "type" "store_mis,fpstore_mis"))
+;; "m8_slot1, nothing*2")
+
+;; Control-transfer instructions execute in the Branch Unit in the
+;; slot1.
+
+(define_insn_reservation "m8_cti" 1
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "cbcond,uncond_cbcond,branch,call,sibcall,call_no_delay_slot,uncond_branch,return"))
+ "m8_slot1")
+
+;; Many instructions executing in the Floating-point and Graphics Unit
+;; (FGU) serving slot3 feature a default latency of 9 cycles.
+
+(define_insn_reservation "m8_fp" 9
+ (and (eq_attr "cpu" "m8")
+ (ior (eq_attr "type" "fpmove,fpcmove,fpcrmove,fp,fpcmp,fpmul,fgm_pack,fgm_mul,pdist")
+ (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "fpu"))))
+ "m8_slot3, nothing*8")
+
+;; Floating-point division and floating-point square-root instructions
+;; have high latencies. They execute in the FGU.
+
+(define_insn_reservation "m8_fpdivs" 26
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "fpdivs"))
+ "m8_slot3, nothing*25")
+
+(define_insn_reservation "m8_fpsqrts" 33
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "fpsqrts"))
+ "m8_slot3, nothing*32")
+
+(define_insn_reservation "m8_fpdivd" 30
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "fpdivd"))
+ "m8_slot3, nothing*29")
+
+(define_insn_reservation "m8_fpsqrtd" 41
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "fpsqrtd"))
+ "m8_slot3, nothing*40")
+
+;; SIMD VIS instructions executing in the Floating-point and graphics
+;; unit (FPG) in slot3 usually have a latency of 5 cycles.
+;;
+;; However, the latency for many instructions is only 3 cycles if the
+;; consumer can also be executed in 3 cycles. We model this with a
+;; bypass. In these cases the instructions are executed in one of the
+;; two 3-cycle crypto units (SPU, also known as "v3-pipes") in slots 2
+;; and 3.
+
+(define_insn_reservation "m8_vis" 5
+ (and (eq_attr "cpu" "m8")
+ (ior (eq_attr "type" "viscmp,lzd")
+ (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "maxmin,cmask,other"))
+ (and (eq_attr "type" "vismv")
+ (eq_attr "subtype" "single,movstouw"))
+ (and (eq_attr "type" "visl")
+ (eq_attr "subtype" "single"))))
+ "m8_slot3, nothing*4")
+
+(define_bypass 3 "m8_vis" "m8_vis")
+
+(define_insn_reservation "m8_gsr" 5
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "gsr")
+ (eq_attr "subtype" "alignaddr"))
+ "m8_slot3, nothing*4")
+
+;; A few VIS instructions have a latency of 1.
+
+(define_insn_reservation "m8_vis_1cycle" 1
+ (and (eq_attr "cpu" "m8")
+ (ior (and (eq_attr "type" "vismv")
+ (eq_attr "subtype" "double,movxtod,movdtox"))
+ (and (eq_attr "type" "visl")
+ (eq_attr "subtype" "double"))
+ (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "addsub64"))))
+ "m8_slot3")
+
+;; Reading and writing to the gsr register takes more than 70 cycles.
+
+(define_insn_reservation "m8_gsr_reg" 70
+ (and (eq_attr "cpu" "m8")
+ (eq_attr "type" "gsr")
+ (eq_attr "subtype" "reg"))
+ "m8_slot3, nothing*69")
diff --git a/gcc/config/sparc/niagara.md b/gcc/config/sparc/niagara.md
index f79771fc2f3..a8e23b8f894 100644
--- a/gcc/config/sparc/niagara.md
+++ b/gcc/config/sparc/niagara.md
@@ -114,5 +114,5 @@
*/
(define_insn_reservation "niag_vis" 8
(and (eq_attr "cpu" "niagara")
- (eq_attr "type" "fga,visl,vismv,fgm_pack,fgm_mul,pdist,edge,edgen,gsr,array"))
+ (eq_attr "type" "fga,visl,viscmp,vismv,fgm_pack,fgm_mul,pdist,edge,edgen,gsr,array,bmask"))
"niag_pipe*8")
diff --git a/gcc/config/sparc/niagara2.md b/gcc/config/sparc/niagara2.md
index 9bcdd064f36..3190d556e53 100644
--- a/gcc/config/sparc/niagara2.md
+++ b/gcc/config/sparc/niagara2.md
@@ -111,10 +111,10 @@
(define_insn_reservation "niag2_vis" 6
(and (eq_attr "cpu" "niagara2")
- (eq_attr "type" "fga,vismv,visl,fgm_pack,fgm_mul,pdist,edge,edgen,array,gsr"))
+ (eq_attr "type" "fga,vismv,visl,viscmp,fgm_pack,fgm_mul,pdist,edge,edgen,array,bmask,gsr"))
"niag2_pipe*6")
(define_insn_reservation "niag3_vis" 9
(and (eq_attr "cpu" "niagara3")
- (eq_attr "type" "fga,vismv,visl,fgm_pack,fgm_mul,pdist,pdistn,edge,edgen,array,gsr"))
+ (eq_attr "type" "fga,vismv,visl,viscmp,fgm_pack,fgm_mul,pdist,pdistn,edge,edgen,array,bmask,gsr"))
"niag2_pipe*9")
diff --git a/gcc/config/sparc/niagara4.md b/gcc/config/sparc/niagara4.md
index ad0a04b12d3..a3417d21c71 100644
--- a/gcc/config/sparc/niagara4.md
+++ b/gcc/config/sparc/niagara4.md
@@ -66,7 +66,7 @@
(define_insn_reservation "n4_array" 12
(and (eq_attr "cpu" "niagara4")
- (eq_attr "type" "array,edge,edgen"))
+ (eq_attr "type" "array,bmask,edge,edgen"))
"n4_slot1, nothing*11")
(define_insn_reservation "n4_vis_move_1cycle" 1
@@ -90,8 +90,9 @@
(define_insn_reservation "n4_vis_logical" 3
(and (eq_attr "cpu" "niagara4")
- (and (eq_attr "type" "visl,pdistn")
- (eq_attr "fptype" "double")))
+ (ior (and (eq_attr "type" "visl,pdistn")
+ (eq_attr "fptype" "double"))
+ (eq_attr "type" "viscmp")))
"n4_slot1, nothing*2")
(define_insn_reservation "n4_vis_logical_11cycle" 11
diff --git a/gcc/config/sparc/niagara7.md b/gcc/config/sparc/niagara7.md
index 12d6ab0fba5..23b67075e2b 100644
--- a/gcc/config/sparc/niagara7.md
+++ b/gcc/config/sparc/niagara7.md
@@ -19,64 +19,120 @@
(define_automaton "niagara7_0")
-(define_cpu_unit "n7_slot0,n7_slot1,n7_slot2" "niagara7_0")
-(define_reservation "n7_single_issue" "n7_slot0 + n7_slot1 + n7_slot2")
+;; The S4 core has a dual-issue queue. This queue is divided into two
+;; slots. One instruction can be issued each cycle to each slot, and
+;; up to 2 instructions are committed each cycle. Each slot serves
+;; several execution units, as depicted below:
+;;
+;;
+;; m7_slot0 - Integer unit.
+;; - Load/Store unit.
+;; === QUEUE ==>
+;;
+;; m7_slot1 - Integer unit.
+;; - Branch unit.
+;; - Floating-point and graphics unit.
+;; - 3-cycles crypto unit.
-(define_cpu_unit "n7_load_store" "niagara7_0")
+(define_cpu_unit "n7_slot0,n7_slot1" "niagara7_0")
+
+;; Some instructions stall the pipeline and avoid any other
+;; instruction to be issued in the same cycle. We assume the same for
+;; multi-instruction insns.
+
+(define_reservation "n7_single_issue" "n7_slot0 + n7_slot1")
(define_insn_reservation "n7_single" 1
(and (eq_attr "cpu" "niagara7")
(eq_attr "type" "multi,savew,flushw,trap"))
"n7_single_issue")
-(define_insn_reservation "n7_iflush" 27
- (and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "iflush"))
- "(n7_slot0 | n7_slot1), nothing*26")
+;; Most of the instructions executing in the integer unit have a
+;; latency of 1.
(define_insn_reservation "n7_integer" 1
(and (eq_attr "cpu" "niagara7")
(eq_attr "type" "ialu,ialuX,shift,cmove,compare"))
"(n7_slot0 | n7_slot1)")
+;; Flushing the instruction memory takes 27 cycles.
+
+(define_insn_reservation "n7_iflush" 27
+ (and (eq_attr "cpu" "niagara7")
+ (eq_attr "type" "iflush"))
+ "(n7_slot0 | n7_slot1), nothing*26")
+
+;; The integer multiplication instructions have a latency of 12 cycles
+;; and execute in the integer unit.
+;;
+;; Likewise for array*, edge* and pdistn instructions.
+
(define_insn_reservation "n7_imul" 12
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "imul"))
- "n7_slot1, nothing*11")
+ (eq_attr "type" "imul,array,edge,edgen,pdistn"))
+ "(n7_slot0 | n7_slot1), nothing*11")
+
+;; The integer division instructions have a latency of 35 cycles and
+;; execute in the integer unit.
(define_insn_reservation "n7_idiv" 35
(and (eq_attr "cpu" "niagara7")
(eq_attr "type" "idiv"))
- "n7_slot1, nothing*34")
+ "(n7_slot0 | n7_slot1), nothing*34")
+
+;; Both integer and floating-point load instructions have a latency of
+;; 5 cycles, and execute in the slot0.
+;;
+;; The prefetch instruction also executes in the load/store unit, but
+;; its latency is only 1 cycle.
(define_insn_reservation "n7_load" 5
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "load,fpload,sload"))
- "(n7_slot0 + n7_load_store), nothing*4")
+ (ior (eq_attr "type" "fpload,sload")
+ (and (eq_attr "type" "load")
+ (eq_attr "subtype" "regular"))))
+ "n7_slot0, nothing*4")
+
+(define_insn_reservation "n7_prefetch" 1
+ (and (eq_attr "cpu" "niagara7")
+ (eq_attr "type" "load")
+ (eq_attr "subtype" "prefetch"))
+ "n7_slot0")
+
+;; Both integer and floating-point store instructions have a latency
+;; of 1 cycle, and execute in the load/store unit in slot0.
(define_insn_reservation "n7_store" 1
(and (eq_attr "cpu" "niagara7")
(eq_attr "type" "store,fpstore"))
- "(n7_slot0 | n7_slot2) + n7_load_store")
+ "n7_slot0")
+
+;; Control-transfer instructions execute in the Branch Unit in the
+;; slot1.
(define_insn_reservation "n7_cti" 1
(and (eq_attr "cpu" "niagara7")
(eq_attr "type" "cbcond,uncond_cbcond,branch,call,sibcall,call_no_delay_slot,uncond_branch,return"))
"n7_slot1")
+;; Many instructions executing in the Floating-point and Graphics unit
+;; in the slot1 feature a latency of 11 cycles.
+
(define_insn_reservation "n7_fp" 11
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "fpmove,fpcmove,fpcrmove,fp,fpcmp,fpmul"))
+ (ior (eq_attr "type" "fpmove,fpcmove,fpcrmove,fp,fpcmp,fpmul,fgm_pack,fgm_mul,pdist")
+ (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "fpu,maxmin"))))
"n7_slot1, nothing*10")
-(define_insn_reservation "n7_array" 12
- (and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "array,edge,edgen"))
- "n7_slot1, nothing*11")
+;; Floating-point division and floating-point square-root instructions
+;; have high latencies. They execute in the floating-point and
+;; graphics unit in the slot1.
+
(define_insn_reservation "n7_fpdivs" 24
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "fpdivs,fpsqrts"))
+ (eq_attr "type" "fpdivs,fpsqrts"))
"n7_slot1, nothing*23")
(define_insn_reservation "n7_fpdivd" 37
@@ -84,53 +140,66 @@
(eq_attr "type" "fpdivd,fpsqrtd"))
"n7_slot1, nothing*36")
-(define_insn_reservation "n7_lzd" 12
- (and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "lzd"))
- "(n7_slot0 | n7_slot1), nothing*11")
-
-;; There is an internal unit called the "V3 pipe", that was originally
-;; intended to process some of the short cryptographic instructions.
-;; However, as soon as in the T4 several of the VIS instructions
-;; (notably non-FP instructions) have been moved to the V3 pipe.
-;; Consequently, these instructions feature a latency of 3 instead of
-;; 11 or 12 cycles, provided their consumers also execute in the V3
-;; pipe.
+;; SIMD VIS instructions executing in the Floating-point and graphics
+;; unit (FPG) in slot1 usually have a latency of either 11 or 12
+;; cycles.
;;
-;; This is modelled here with a bypass.
+;; However, the latency for many instructions is only 3 cycles if the
+;; consumer can also be executed in 3 cycles. We model this with a
+;; bypass. In these cases the instructions are executed in the
+;; 3-cycle crypto unit which also serves slot1.
+
+(define_insn_reservation "n7_vis_11cycles" 11
+ (and (eq_attr "cpu" "niagara7")
+ (ior (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "addsub64,other"))
+ (and (eq_attr "type" "vismv")
+ (eq_attr "subtype" "double,single"))
+ (and (eq_attr "type" "visl")
+ (eq_attr "subtype" "double,single"))))
+ "n7_slot1, nothing*10")
-(define_insn_reservation "n7_vis_fga" 11
+(define_insn_reservation "n7_vis_12cycles" 12
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "fga,gsr"))
- "n7_slot1, nothing*10")
+ (ior (eq_attr "type" "bmask,viscmp")
+ (and (eq_attr "type" "fga")
+ (eq_attr "subtype" "cmask"))
+ (and (eq_attr "type" "vismv")
+ (eq_attr "subtype" "movstouw"))))
+ "n7_slot1, nothing*11")
+
+(define_bypass 3 "n7_vis_*" "n7_vis_*")
+
+;; Some other VIS instructions have a latency of 12 cycles, and won't
+;; be executed in the 3-cycle crypto pipe.
-(define_insn_reservation "n7_vis_fgm" 11
+(define_insn_reservation "n7_lzd" 12
(and (eq_attr "cpu" "niagara7")
- (eq_attr "type" "fgm_pack,fgm_mul,pdist"))
- "n7_slot1, nothing*10")
+ (ior (eq_attr "type" "lzd,")
+ (and (eq_attr "type" "gsr")
+ (eq_attr "subtype" "alignaddr"))))
+ "n7_slot1, nothing*11")
-(define_insn_reservation "n7_vis_move_v3pipe" 11
+;; A couple of VIS instructions feature very low latencies in the M7.
+
+(define_insn_reservation "n7_single_vis" 1
(and (eq_attr "cpu" "niagara7")
- (and (eq_attr "type" "vismv")
- (eq_attr "v3pipe" "true")))
+ (eq_attr "type" "vismv")
+ (eq_attr "subtype" "movxtod"))
"n7_slot1")
-(define_insn_reservation "n7_vis_move_11cycle" 11
+(define_insn_reservation "n7_double_vis" 2
(and (eq_attr "cpu" "niagara7")
- (and (eq_attr "type" "vismv")
- (eq_attr "v3pipe" "false")))
- "n7_slot1, nothing*10")
+ (eq_attr "type" "vismv")
+ (eq_attr "subtype" "movdtox"))
+ "n7_slot1, nothing")
-(define_insn_reservation "n7_vis_logical_v3pipe" 11
- (and (eq_attr "cpu" "niagara7")
- (and (eq_attr "type" "visl,pdistn")
- (eq_attr "v3pipe" "true")))
- "n7_slot1, nothing*2")
+;; Reading and writing to the gsr register takes a high number of
+;; cycles that is not documented in the PRM. Let's use the same value
+;; than the M8.
-(define_insn_reservation "n7_vis_logical_11cycle" 11
+(define_insn_reservation "n7_gsr_reg" 70
(and (eq_attr "cpu" "niagara7")
- (and (eq_attr "type" "visl")
- (eq_attr "v3pipe" "false")))
- "n7_slot1, nothing*10")
-
-(define_bypass 3 "*_v3pipe" "*_v3pipe")
+ (eq_attr "type" "gsr")
+ (eq_attr "subtype" "reg"))
+ "n7_slot1, nothing*70")
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md
index 951933efb39..3f8526dc3ef 100644
--- a/gcc/config/sparc/predicates.md
+++ b/gcc/config/sparc/predicates.md
@@ -328,6 +328,33 @@
(and (match_code "const_int")
(match_test "SPARC_SIMM5_P (INTVAL (op))"))))
+;; Return true if OP is a constant in the range 0..7. This is an
+;; acceptable second operand for dictunpack instructions setting a
+;; V8QI mode in the destination register.
+(define_predicate "imm5_operand_dictunpack8"
+ (and (match_code "const_int")
+ (match_test "(INTVAL (op) >= 0 && INTVAL (op) < 8)")))
+
+;; Return true if OP is a constant in the range 7..15. This is an
+;; acceptable second operand for dictunpack instructions setting a
+;; V4HI mode in the destination register.
+(define_predicate "imm5_operand_dictunpack16"
+ (and (match_code "const_int")
+ (match_test "(INTVAL (op) >= 8 && INTVAL (op) < 16)")))
+
+;; Return true if OP is a constant in the range 15..31. This is an
+;; acceptable second operand for dictunpack instructions setting a
+;; V2SI mode in the destination register.
+(define_predicate "imm5_operand_dictunpack32"
+ (and (match_code "const_int")
+ (match_test "(INTVAL (op) >= 16 && INTVAL (op) < 32)")))
+
+;; Return true if OP is a constant that is representable by a 2-bit
+;; unsigned field. This is an acceptable third operand for
+;; fpcmp*shl instructions.
+(define_predicate "imm2_operand"
+ (and (match_code "const_int")
+ (match_test "SPARC_IMM2_P (INTVAL (op))")))
;; Predicates for miscellaneous instructions.
diff --git a/gcc/config/sparc/rtemself.h b/gcc/config/sparc/rtemself.h
index e5a3f6eae03..0fb56ee2c67 100644
--- a/gcc/config/sparc/rtemself.h
+++ b/gcc/config/sparc/rtemself.h
@@ -2,21 +2,26 @@
Copyright (C) 1996-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ 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/>. */
/* Target OS builtins. */
#undef TARGET_OS_CPP_BUILTINS
@@ -26,6 +31,8 @@ along with GCC; see the file COPYING3. If not see
builtin_define ("__rtems__"); \
builtin_define ("__USE_INIT_FINI__"); \
builtin_assert ("system=rtems"); \
+ if (sparc_fix_b2bst) \
+ builtin_define ("__FIX_LEON3FT_B2BST"); \
} \
while (0)
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index 8a50bfeefc7..b8177c0b692 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -174,13 +174,22 @@ along with GCC; see the file COPYING3. If not see
#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG AS_NIAGARA7_FLAG
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_m8
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC AS_SPARC32_FLAG AS_M8_FLAG
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG AS_M8_FLAG
+#endif
+
#undef CPP_CPU_SPEC
#define CPP_CPU_SPEC "\
%{mcpu=sparclet|mcpu=tsc701:-D__sparclet__} \
%{mcpu=sparclite|mcpu-f930|mcpu=f934:-D__sparclite__} \
%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3|mcpu=niagara|mcpu=niagara2|mcpu=niagara3|mcpu=niagara4|mcpu=niagara7:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3|mcpu=niagara|mcpu=niagara2|mcpu=niagara3|mcpu=niagara4|mcpu=niagara7|mcpu=m8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{!mcpu*:%(cpp_cpu_default)} \
"
@@ -290,7 +299,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
%{mcpu=niagara3:" DEF_ARCH32_SPEC("-xarch=v8plus" AS_NIAGARA3_FLAG) DEF_ARCH64_SPEC("-xarch=v9" AS_NIAGARA3_FLAG) "} \
%{mcpu=niagara4:" DEF_ARCH32_SPEC(AS_SPARC32_FLAG AS_NIAGARA4_FLAG) DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_NIAGARA4_FLAG) "} \
%{mcpu=niagara7:" DEF_ARCH32_SPEC(AS_SPARC32_FLAG AS_NIAGARA7_FLAG) DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_NIAGARA7_FLAG) "} \
-%{!mcpu=niagara7:%{!mcpu=niagara4:%{!mcpu=niagara3:%{!mcpu=niagara2:%{!mcpu=niagara:%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC("-xarch=v9") "}}}}}}}}} \
+%{mcpu=m8:" DEF_ARCH32_SPEC(AS_SPARC32_FLAG AS_M8_FLAG) DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_M8_FLAG) "} \
+%{!mcpu=m8:%{!mcpu=niagara7:%{!mcpu=niagara4:%{!mcpu=niagara3:%{!mcpu=niagara2:%{!mcpu=niagara:%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC("-xarch=v9") "}}}}}}}}}} \
%{!mcpu*:%(asm_cpu_default)} \
"
diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c
index 960317350fe..4aacfff05ff 100644
--- a/gcc/config/sparc/sparc-c.c
+++ b/gcc/config/sparc/sparc-c.c
@@ -40,7 +40,12 @@ sparc_target_macros (void)
cpp_assert (parse_in, "machine=sparc");
}
- if (TARGET_VIS4)
+ if (TARGET_VIS4B)
+ {
+ cpp_define (parse_in, "__VIS__=0x410");
+ cpp_define (parse_in, "__VIS=0x410");
+ }
+ else if (TARGET_VIS4)
{
cpp_define (parse_in, "__VIS__=0x400");
cpp_define (parse_in, "__VIS=0x400");
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
index 6e7c2ace277..581e86e49d1 100644
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -46,6 +46,7 @@ enum processor_type {
PROCESSOR_NIAGARA3,
PROCESSOR_NIAGARA4,
PROCESSOR_NIAGARA7,
+ PROCESSOR_M8,
PROCESSOR_NATIVE
};
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 790a0367b67..59761aac310 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -448,6 +448,30 @@ struct processor_costs niagara7_costs = {
0, /* shift penalty */
};
+static const
+struct processor_costs m8_costs = {
+ COSTS_N_INSNS (3), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (3), /* int zeroed load */
+ COSTS_N_INSNS (3), /* float load */
+ COSTS_N_INSNS (9), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (9), /* fadd, fsub */
+ COSTS_N_INSNS (9), /* fcmp */
+ COSTS_N_INSNS (9), /* fmov, fmovr */
+ COSTS_N_INSNS (9), /* fmul */
+ COSTS_N_INSNS (26), /* fdivs */
+ COSTS_N_INSNS (30), /* fdivd */
+ COSTS_N_INSNS (33), /* fsqrts */
+ COSTS_N_INSNS (41), /* fsqrtd */
+ COSTS_N_INSNS (12), /* imul */
+ COSTS_N_INSNS (10), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (57), /* udiv/sdiv */
+ COSTS_N_INSNS (30), /* udivx/sdivx */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
static const struct processor_costs *sparc_costs = &cypress_costs;
#ifdef HAVE_AS_RELAX_OPTION
@@ -896,6 +920,12 @@ mem_ref (rtx x)
to properly detect the various hazards. Therefore, this machine specific
pass runs as late as possible. */
+/* True if INSN is a md pattern or asm statement. */
+#define USEFUL_INSN_P(INSN) \
+ (NONDEBUG_INSN_P (INSN) \
+ && GET_CODE (PATTERN (INSN)) != USE \
+ && GET_CODE (PATTERN (INSN)) != CLOBBER)
+
static unsigned int
sparc_do_work_around_errata (void)
{
@@ -915,6 +945,81 @@ sparc_do_work_around_errata (void)
if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
insn = seq->insn (1);
+ /* Look for either of these two sequences:
+
+ Sequence A:
+ 1. store of word size or less (e.g. st / stb / sth / stf)
+ 2. any single instruction that is not a load or store
+ 3. any store instruction (e.g. st / stb / sth / stf / std / stdf)
+
+ Sequence B:
+ 1. store of double word size (e.g. std / stdf)
+ 2. any store instruction (e.g. st / stb / sth / stf / std / stdf) */
+ if (sparc_fix_b2bst
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && MEM_P (SET_DEST (set)))
+ {
+ /* Sequence B begins with a double-word store. */
+ bool seq_b = GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8;
+ rtx_insn *after;
+ int i;
+
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+
+ for (after = next, i = 0; i < 2; i++)
+ {
+ /* Skip empty assembly statements. */
+ if ((GET_CODE (PATTERN (after)) == UNSPEC_VOLATILE)
+ || (USEFUL_INSN_P (after)
+ && (asm_noperands (PATTERN (after))>=0)
+ && !strcmp (decode_asm_operands (PATTERN (after),
+ NULL, NULL, NULL,
+ NULL, NULL), "")))
+ after = next_active_insn (after);
+ if (!after)
+ break;
+
+ /* If the insn is a branch, then it cannot be problematic. */
+ if (!NONJUMP_INSN_P (after)
+ || GET_CODE (PATTERN (after)) == SEQUENCE)
+ break;
+
+ /* Sequence B is only two instructions long. */
+ if (seq_b)
+ {
+ /* Add NOP if followed by a store. */
+ if ((set = single_set (after)) != NULL_RTX
+ && MEM_P (SET_DEST (set)))
+ insert_nop = true;
+
+ /* Otherwise it is ok. */
+ break;
+ }
+
+ /* If the second instruction is a load or a store,
+ then the sequence cannot be problematic. */
+ if (i == 0)
+ {
+ if (((set = single_set (after)) != NULL_RTX)
+ && (MEM_P (SET_DEST (set)) || MEM_P (SET_SRC (set))))
+ break;
+
+ after = next_active_insn (after);
+ if (!after)
+ break;
+ }
+
+ /* Add NOP if third instruction is a store. */
+ if (i == 1
+ && ((set = single_set (after)) != NULL_RTX)
+ && MEM_P (SET_DEST (set)))
+ insert_nop = true;
+ }
+ }
+ else
/* Look for a single-word load into an odd-numbered FP register. */
if (sparc_fix_at697f
&& NONJUMP_INSN_P (insn)
@@ -1167,8 +1272,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- /* The only errata we handle are those of the AT697F and UT699. */
- return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
+ return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst;
}
virtual unsigned int execute (function *)
@@ -1200,6 +1304,8 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "FLAT ");
if (flags & MASK_FMAF)
fprintf (stderr, "FMAF ");
+ if (flags & MASK_FSMULD)
+ fprintf (stderr, "FSMULD ");
if (flags & MASK_FPU)
fprintf (stderr, "FPU ");
if (flags & MASK_HARD_QUAD)
@@ -1222,6 +1328,8 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "VIS3 ");
if (flags & MASK_VIS4)
fprintf (stderr, "VIS4 ");
+ if (flags & MASK_VIS4B)
+ fprintf (stderr, "VIS4B ");
if (flags & MASK_CBCOND)
fprintf (stderr, "CBCOND ");
if (flags & MASK_DEPRECATED_V8_INSNS)
@@ -1286,6 +1394,7 @@ sparc_option_override (void)
{ TARGET_CPU_niagara3, PROCESSOR_NIAGARA3 },
{ TARGET_CPU_niagara4, PROCESSOR_NIAGARA4 },
{ TARGET_CPU_niagara7, PROCESSOR_NIAGARA7 },
+ { TARGET_CPU_m8, PROCESSOR_M8 },
{ -1, PROCESSOR_V7 }
};
const struct cpu_default *def;
@@ -1296,24 +1405,24 @@ sparc_option_override (void)
const int disable;
const int enable;
} const cpu_table[] = {
- { "v7", MASK_ISA, 0 },
- { "cypress", MASK_ISA, 0 },
+ { "v7", MASK_ISA|MASK_FSMULD, 0 },
+ { "cypress", MASK_ISA|MASK_FSMULD, 0 },
{ "v8", MASK_ISA, MASK_V8 },
/* TI TMS390Z55 supersparc */
{ "supersparc", MASK_ISA, MASK_V8 },
- { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
- { "leon", MASK_ISA, MASK_V8|MASK_LEON|MASK_FPU },
- { "leon3", MASK_ISA, MASK_V8|MASK_LEON3|MASK_FPU },
- { "leon3v7", MASK_ISA, MASK_LEON3|MASK_FPU },
- { "sparclite", MASK_ISA, MASK_SPARCLITE },
+ { "hypersparc", MASK_ISA, MASK_V8 },
+ { "leon", MASK_ISA|MASK_FSMULD, MASK_V8|MASK_LEON },
+ { "leon3", MASK_ISA, MASK_V8|MASK_LEON3 },
+ { "leon3v7", MASK_ISA|MASK_FSMULD, MASK_LEON3 },
+ { "sparclite", MASK_ISA|MASK_FSMULD, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
{ "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
/* The Fujitsu MB86934 is the recent sparclite chip, with an FPU. */
- { "f934", MASK_ISA, MASK_SPARCLITE|MASK_FPU },
+ { "f934", MASK_ISA|MASK_FSMULD, MASK_SPARCLITE },
{ "sparclite86x", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
- { "sparclet", MASK_ISA, MASK_SPARCLET },
+ { "sparclet", MASK_ISA|MASK_FSMULD, MASK_SPARCLET },
/* TEMIC sparclet */
- { "tsc701", MASK_ISA, MASK_SPARCLET },
+ { "tsc701", MASK_ISA|MASK_FSMULD, MASK_SPARCLET },
{ "v9", MASK_ISA, MASK_V9 },
/* UltraSPARC I, II, IIi */
{ "ultrasparc", MASK_ISA,
@@ -1337,7 +1446,10 @@ sparc_option_override (void)
MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF|MASK_CBCOND },
/* UltraSPARC M7 */
{ "niagara7", MASK_ISA,
- MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC }
+ MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC },
+ /* UltraSPARC M8 */
+ { "m8", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC|MASK_VIS4B }
};
const struct cpu_table *cpu;
unsigned int i;
@@ -1376,6 +1488,11 @@ sparc_option_override (void)
}
}
+ /* Enable the FsMULd instruction by default if not explicitly specified by
+ the user. It may be later disabled by the CPU (explicitly or not). */
+ if (TARGET_FPU && !(target_flags_explicit & MASK_FSMULD))
+ target_flags |= MASK_FSMULD;
+
if (TARGET_DEBUG_OPTIONS)
{
dump_target_flags("Initial target_flags", target_flags);
@@ -1421,7 +1538,7 @@ sparc_option_override (void)
sparc_cmodel = cmodel->value;
}
else
- error ("-mcmodel= is not supported on 32 bit systems");
+ error ("-mcmodel= is not supported on 32-bit systems");
}
/* Check that -fcall-saved-REG wasn't specified for out registers. */
@@ -1432,7 +1549,7 @@ sparc_option_override (void)
call_used_regs [i] = 1;
}
- /* Set the default CPU. */
+ /* Set the default CPU if no -mcpu option was specified. */
if (!global_options_set.x_sparc_cpu_and_features)
{
for (def = &cpu_default[0]; def->cpu != -1; ++def)
@@ -1442,6 +1559,7 @@ sparc_option_override (void)
sparc_cpu_and_features = def->processor;
}
+ /* Set the default CPU if no -mtune option was specified. */
if (!global_options_set.x_sparc_cpu)
sparc_cpu = sparc_cpu_and_features;
@@ -1450,8 +1568,6 @@ sparc_option_override (void)
if (TARGET_DEBUG_OPTIONS)
{
fprintf (stderr, "sparc_cpu_and_features: %s\n", cpu->name);
- fprintf (stderr, "sparc_cpu: %s\n",
- cpu_table[(int) sparc_cpu].name);
dump_target_flags ("cpu->disable", cpu->disable);
dump_target_flags ("cpu->enable", cpu->enable);
}
@@ -1467,6 +1583,9 @@ sparc_option_override (void)
#ifndef HAVE_AS_SPARC5_VIS4
& ~(MASK_VIS4 | MASK_SUBXC)
#endif
+#ifndef HAVE_AS_SPARC6
+ & ~(MASK_VIS4B)
+#endif
#ifndef HAVE_AS_LEON
& ~(MASK_LEON | MASK_LEON3)
#endif
@@ -1485,11 +1604,15 @@ sparc_option_override (void)
if (TARGET_VIS4)
target_flags |= MASK_VIS3 | MASK_VIS2 | MASK_VIS;
- /* Don't allow -mvis, -mvis2, -mvis3, -mvis4 or -mfmaf if FPU is
- disabled. */
- if (! TARGET_FPU)
+ /* -mvis4b implies -mvis4, -mvis3, -mvis2 and -mvis */
+ if (TARGET_VIS4B)
+ target_flags |= MASK_VIS4 | MASK_VIS3 | MASK_VIS2 | MASK_VIS;
+
+ /* Don't allow -mvis, -mvis2, -mvis3, -mvis4, -mvis4b, -mfmaf and -mfsmuld if
+ FPU is disabled. */
+ if (!TARGET_FPU)
target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_VIS4
- | MASK_FMAF);
+ | MASK_VIS4B | MASK_FMAF | MASK_FSMULD);
/* -mvis assumes UltraSPARC+, so we are sure v9 instructions
are available; -m64 also implies v9. */
@@ -1500,18 +1623,18 @@ sparc_option_override (void)
}
/* -mvis also implies -mv8plus on 32-bit. */
- if (TARGET_VIS && ! TARGET_ARCH64)
+ if (TARGET_VIS && !TARGET_ARCH64)
target_flags |= MASK_V8PLUS;
- /* Use the deprecated v8 insns for sparc64 in 32 bit mode. */
+ /* Use the deprecated v8 insns for sparc64 in 32-bit mode. */
if (TARGET_V9 && TARGET_ARCH32)
target_flags |= MASK_DEPRECATED_V8_INSNS;
- /* V8PLUS requires V9, makes no sense in 64 bit mode. */
- if (! TARGET_V9 || TARGET_ARCH64)
+ /* V8PLUS requires V9 and makes no sense in 64-bit mode. */
+ if (!TARGET_V9 || TARGET_ARCH64)
target_flags &= ~MASK_V8PLUS;
- /* Don't use stack biasing in 32 bit mode. */
+ /* Don't use stack biasing in 32-bit mode. */
if (TARGET_ARCH32)
target_flags &= ~MASK_STACK_BIAS;
@@ -1519,6 +1642,14 @@ sparc_option_override (void)
if (!(target_flags_explicit & MASK_LRA))
target_flags |= MASK_LRA;
+ /* Enable the back-to-back store errata workaround for LEON3FT. */
+ if (sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc)
+ sparc_fix_b2bst = 1;
+
+ /* Disable FsMULd for the UT699 since it doesn't work correctly. */
+ if (sparc_fix_ut699)
+ target_flags &= ~MASK_FSMULD;
+
/* Supply a default value for align_functions. */
if (align_functions == 0)
{
@@ -1529,7 +1660,8 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4)
align_functions = 32;
- else if (sparc_cpu == PROCESSOR_NIAGARA7)
+ else if (sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
align_functions = 64;
}
@@ -1597,6 +1729,9 @@ sparc_option_override (void)
case PROCESSOR_NIAGARA7:
sparc_costs = &niagara7_costs;
break;
+ case PROCESSOR_M8:
+ sparc_costs = &m8_costs;
+ break;
case PROCESSOR_NATIVE:
gcc_unreachable ();
};
@@ -1659,13 +1794,14 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA4)
? 2
: (sparc_cpu == PROCESSOR_ULTRASPARC3
- ? 8 : (sparc_cpu == PROCESSOR_NIAGARA7
+ ? 8 : ((sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
? 32 : 3))),
global_options.x_param_values,
global_options_set.x_param_values);
- /* For PARAM_L1_CACHE_LINE_SIZE we use the default 32 bytes (see
- params.def), so no maybe_set_param_value is needed.
+ /* PARAM_L1_CACHE_LINE_SIZE is the size of the L1 cache line, in
+ bytes.
The Oracle SPARC Architecture (previously the UltraSPARC
Architecture) specification states that when a PREFETCH[A]
@@ -1681,6 +1817,11 @@ sparc_option_override (void)
L2 and L3, but only 32B are brought into the L1D$. (Assuming it
is a read_n prefetch, which is the only type which allocates to
the L1.) */
+ maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
+ (sparc_cpu == PROCESSOR_M8
+ ? 64 : 32),
+ global_options.x_param_values,
+ global_options_set.x_param_values);
/* PARAM_L1_CACHE_SIZE is the size of the L1D$ (most SPARC chips use
Hardvard level-1 caches) in kilobytes. Both UltraSPARC and
@@ -1692,7 +1833,8 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA2
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
? 16 : 64),
global_options.x_param_values,
global_options_set.x_param_values);
@@ -1701,7 +1843,8 @@ sparc_option_override (void)
/* PARAM_L2_CACHE_SIZE is the size fo the L2 in kilobytes. Note
that 512 is the default in params.def. */
maybe_set_param_value (PARAM_L2_CACHE_SIZE,
- (sparc_cpu == PROCESSOR_NIAGARA4
+ ((sparc_cpu == PROCESSOR_NIAGARA4
+ || sparc_cpu == PROCESSOR_M8)
? 128 : (sparc_cpu == PROCESSOR_NIAGARA7
? 256 : 512)),
global_options.x_param_values,
@@ -4829,7 +4972,7 @@ enum sparc_mode_class {
??? Note that, despite the settings, non-double-aligned parameter
registers can hold double-word quantities in 32-bit mode. */
-/* This points to either the 32 bit or the 64 bit version. */
+/* This points to either the 32-bit or the 64-bit version. */
const int *hard_regno_mode_classes;
static const int hard_32bit_mode_classes[] = {
@@ -7163,7 +7306,7 @@ sparc_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
}
/* Handle the FUNCTION_ARG_PADDING macro.
- For the 64 bit ABI structs are always stored left shifted in their
+ For the 64-bit ABI structs are always stored left shifted in their
argument slot. */
enum direction
@@ -7865,7 +8008,8 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
{
strcpy (p,
- ((XINT (note, 0) >= REG_BR_PROB_BASE / 2) ^ far)
+ ((profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ >= profile_probability::even ()) ^ far)
? ",pt" : ",pn");
p += 3;
spaces -= 3;
@@ -8281,7 +8425,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
if (reversed ^ far)
code = reverse_condition (code);
- /* Only 64 bit versions of these instructions exist. */
+ /* Only 64-bit versions of these instructions exist. */
gcc_assert (mode == DImode);
/* Start by writing the branch condition. */
@@ -8328,7 +8472,8 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
{
strcpy (p,
- ((XINT (note, 0) >= REG_BR_PROB_BASE / 2) ^ far)
+ ((profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ >= profile_probability::even ()) ^ far)
? ",pt" : ",pn");
p += 3;
}
@@ -8709,7 +8854,7 @@ mems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
return 0;
/* The first offset must be evenly divisible by 8 to ensure the
- address is 64 bit aligned. */
+ address is 64-bit aligned. */
if (offset1 % 8 != 0)
return 0;
@@ -9478,7 +9623,8 @@ sparc32_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
&& sparc_cpu != PROCESSOR_NIAGARA2
&& sparc_cpu != PROCESSOR_NIAGARA3
&& sparc_cpu != PROCESSOR_NIAGARA4
- && sparc_cpu != PROCESSOR_NIAGARA7)
+ && sparc_cpu != PROCESSOR_NIAGARA7
+ && sparc_cpu != PROCESSOR_M8)
emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 8))));
/* Call __enable_execute_stack after writing onto the stack to make sure
@@ -9524,7 +9670,8 @@ sparc64_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
&& sparc_cpu != PROCESSOR_NIAGARA2
&& sparc_cpu != PROCESSOR_NIAGARA3
&& sparc_cpu != PROCESSOR_NIAGARA4
- && sparc_cpu != PROCESSOR_NIAGARA7)
+ && sparc_cpu != PROCESSOR_NIAGARA7
+ && sparc_cpu != PROCESSOR_M8)
emit_insn (gen_flushdi (validize_mem (adjust_address (m_tramp, DImode, 8))));
/* Call __enable_execute_stack after writing onto the stack to make sure
@@ -9724,7 +9871,8 @@ sparc_use_sched_lookahead (void)
|| sparc_cpu == PROCESSOR_NIAGARA3)
return 0;
if (sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
return 2;
if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3)
@@ -9758,6 +9906,7 @@ sparc_issue_rate (void)
return 2;
case PROCESSOR_ULTRASPARC:
case PROCESSOR_ULTRASPARC3:
+ case PROCESSOR_M8:
return 4;
}
}
@@ -10340,6 +10489,45 @@ enum sparc_builtins
SPARC_BUILTIN_FPSUBS8,
SPARC_BUILTIN_FPSUBUS8,
SPARC_BUILTIN_FPSUBUS16,
+
+ /* VIS 4.0B builtins. */
+
+ /* Note that all the DICTUNPACK* entries should be kept
+ contiguous. */
+ SPARC_BUILTIN_FIRST_DICTUNPACK,
+ SPARC_BUILTIN_DICTUNPACK8 = SPARC_BUILTIN_FIRST_DICTUNPACK,
+ SPARC_BUILTIN_DICTUNPACK16,
+ SPARC_BUILTIN_DICTUNPACK32,
+ SPARC_BUILTIN_LAST_DICTUNPACK = SPARC_BUILTIN_DICTUNPACK32,
+
+ /* Note that all the FPCMP*SHL entries should be kept
+ contiguous. */
+ SPARC_BUILTIN_FIRST_FPCMPSHL,
+ SPARC_BUILTIN_FPCMPLE8SHL = SPARC_BUILTIN_FIRST_FPCMPSHL,
+ SPARC_BUILTIN_FPCMPGT8SHL,
+ SPARC_BUILTIN_FPCMPEQ8SHL,
+ SPARC_BUILTIN_FPCMPNE8SHL,
+ SPARC_BUILTIN_FPCMPLE16SHL,
+ SPARC_BUILTIN_FPCMPGT16SHL,
+ SPARC_BUILTIN_FPCMPEQ16SHL,
+ SPARC_BUILTIN_FPCMPNE16SHL,
+ SPARC_BUILTIN_FPCMPLE32SHL,
+ SPARC_BUILTIN_FPCMPGT32SHL,
+ SPARC_BUILTIN_FPCMPEQ32SHL,
+ SPARC_BUILTIN_FPCMPNE32SHL,
+ SPARC_BUILTIN_FPCMPULE8SHL,
+ SPARC_BUILTIN_FPCMPUGT8SHL,
+ SPARC_BUILTIN_FPCMPULE16SHL,
+ SPARC_BUILTIN_FPCMPUGT16SHL,
+ SPARC_BUILTIN_FPCMPULE32SHL,
+ SPARC_BUILTIN_FPCMPUGT32SHL,
+ SPARC_BUILTIN_FPCMPDE8SHL,
+ SPARC_BUILTIN_FPCMPDE16SHL,
+ SPARC_BUILTIN_FPCMPDE32SHL,
+ SPARC_BUILTIN_FPCMPUR8SHL,
+ SPARC_BUILTIN_FPCMPUR16SHL,
+ SPARC_BUILTIN_FPCMPUR32SHL,
+ SPARC_BUILTIN_LAST_FPCMPSHL = SPARC_BUILTIN_FPCMPUR32SHL,
SPARC_BUILTIN_MAX
};
@@ -10347,6 +10535,27 @@ enum sparc_builtins
static GTY (()) tree sparc_builtins[(int) SPARC_BUILTIN_MAX];
static enum insn_code sparc_builtins_icode[(int) SPARC_BUILTIN_MAX];
+/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
+ The instruction should require a constant operand of some sort. The
+ function prints an error if OPVAL is not valid. */
+
+static int
+check_constant_argument (enum insn_code icode, int opnum, rtx opval)
+{
+ if (GET_CODE (opval) != CONST_INT)
+ {
+ error ("%qs expects a constant argument", insn_data[icode].name);
+ return false;
+ }
+
+ if (!(*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
+ {
+ error ("constant argument out of range for %qs", insn_data[icode].name);
+ return false;
+ }
+ return true;
+}
+
/* Add a SPARC builtin function with NAME, ICODE, CODE and TYPE. Return the
function decl or NULL_TREE if the builtin was not added. */
@@ -10440,6 +10649,12 @@ sparc_vis_init_builtins (void)
v8qi, v8qi, 0);
tree si_ftype_v8qi_v8qi = build_function_type_list (intSI_type_node,
v8qi, v8qi, 0);
+ tree v8qi_ftype_df_si = build_function_type_list (v8qi, double_type_node,
+ intSI_type_node, 0);
+ tree v4hi_ftype_df_si = build_function_type_list (v4hi, double_type_node,
+ intSI_type_node, 0);
+ tree v2si_ftype_df_si = build_function_type_list (v2si, double_type_node,
+ intDI_type_node, 0);
tree di_ftype_di_di = build_function_type_list (intDI_type_node,
intDI_type_node,
intDI_type_node, 0);
@@ -10894,6 +11109,156 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fpsubus16", CODE_FOR_ussubv4hi3,
SPARC_BUILTIN_FPSUBUS16, v4hi_ftype_v4hi_v4hi);
}
+
+ if (TARGET_VIS4B)
+ {
+ def_builtin_const ("__builtin_vis_dictunpack8", CODE_FOR_dictunpack8,
+ SPARC_BUILTIN_DICTUNPACK8, v8qi_ftype_df_si);
+ def_builtin_const ("__builtin_vis_dictunpack16", CODE_FOR_dictunpack16,
+ SPARC_BUILTIN_DICTUNPACK16, v4hi_ftype_df_si);
+ def_builtin_const ("__builtin_vis_dictunpack32", CODE_FOR_dictunpack32,
+ SPARC_BUILTIN_DICTUNPACK32, v2si_ftype_df_si);
+
+ if (TARGET_ARCH64)
+ {
+ tree di_ftype_v8qi_v8qi_si = build_function_type_list (intDI_type_node,
+ v8qi, v8qi,
+ intSI_type_node, 0);
+ tree di_ftype_v4hi_v4hi_si = build_function_type_list (intDI_type_node,
+ v4hi, v4hi,
+ intSI_type_node, 0);
+ tree di_ftype_v2si_v2si_si = build_function_type_list (intDI_type_node,
+ v2si, v2si,
+ intSI_type_node, 0);
+
+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8dishl,
+ SPARC_BUILTIN_FPCMPLE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8dishl,
+ SPARC_BUILTIN_FPCMPGT8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8dishl,
+ SPARC_BUILTIN_FPCMPEQ8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8dishl,
+ SPARC_BUILTIN_FPCMPNE8SHL, di_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16dishl,
+ SPARC_BUILTIN_FPCMPLE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16dishl,
+ SPARC_BUILTIN_FPCMPGT16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16dishl,
+ SPARC_BUILTIN_FPCMPEQ16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16dishl,
+ SPARC_BUILTIN_FPCMPNE16SHL, di_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32dishl,
+ SPARC_BUILTIN_FPCMPLE32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32dishl,
+ SPARC_BUILTIN_FPCMPGT32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32dishl,
+ SPARC_BUILTIN_FPCMPEQ32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32dishl,
+ SPARC_BUILTIN_FPCMPNE32SHL, di_ftype_v2si_v2si_si);
+
+
+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8dishl,
+ SPARC_BUILTIN_FPCMPULE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8dishl,
+ SPARC_BUILTIN_FPCMPUGT8SHL, di_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16dishl,
+ SPARC_BUILTIN_FPCMPULE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16dishl,
+ SPARC_BUILTIN_FPCMPUGT16SHL, di_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32dishl,
+ SPARC_BUILTIN_FPCMPULE32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32dishl,
+ SPARC_BUILTIN_FPCMPUGT32SHL, di_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8dishl,
+ SPARC_BUILTIN_FPCMPDE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16dishl,
+ SPARC_BUILTIN_FPCMPDE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32dishl,
+ SPARC_BUILTIN_FPCMPDE32SHL, di_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8dishl,
+ SPARC_BUILTIN_FPCMPUR8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16dishl,
+ SPARC_BUILTIN_FPCMPUR16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32dishl,
+ SPARC_BUILTIN_FPCMPUR32SHL, di_ftype_v2si_v2si_si);
+
+ }
+ else
+ {
+ tree si_ftype_v8qi_v8qi_si = build_function_type_list (intSI_type_node,
+ v8qi, v8qi,
+ intSI_type_node, 0);
+ tree si_ftype_v4hi_v4hi_si = build_function_type_list (intSI_type_node,
+ v4hi, v4hi,
+ intSI_type_node, 0);
+ tree si_ftype_v2si_v2si_si = build_function_type_list (intSI_type_node,
+ v2si, v2si,
+ intSI_type_node, 0);
+
+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8sishl,
+ SPARC_BUILTIN_FPCMPLE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8sishl,
+ SPARC_BUILTIN_FPCMPGT8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8sishl,
+ SPARC_BUILTIN_FPCMPEQ8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8sishl,
+ SPARC_BUILTIN_FPCMPNE8SHL, si_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16sishl,
+ SPARC_BUILTIN_FPCMPLE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16sishl,
+ SPARC_BUILTIN_FPCMPGT16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16sishl,
+ SPARC_BUILTIN_FPCMPEQ16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16sishl,
+ SPARC_BUILTIN_FPCMPNE16SHL, si_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32sishl,
+ SPARC_BUILTIN_FPCMPLE32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32sishl,
+ SPARC_BUILTIN_FPCMPGT32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32sishl,
+ SPARC_BUILTIN_FPCMPEQ32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32sishl,
+ SPARC_BUILTIN_FPCMPNE32SHL, si_ftype_v2si_v2si_si);
+
+
+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8sishl,
+ SPARC_BUILTIN_FPCMPULE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8sishl,
+ SPARC_BUILTIN_FPCMPUGT8SHL, si_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16sishl,
+ SPARC_BUILTIN_FPCMPULE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16sishl,
+ SPARC_BUILTIN_FPCMPUGT16SHL, si_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32sishl,
+ SPARC_BUILTIN_FPCMPULE32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32sishl,
+ SPARC_BUILTIN_FPCMPUGT32SHL, si_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8sishl,
+ SPARC_BUILTIN_FPCMPDE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16sishl,
+ SPARC_BUILTIN_FPCMPDE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32sishl,
+ SPARC_BUILTIN_FPCMPDE32SHL, si_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8sishl,
+ SPARC_BUILTIN_FPCMPUR8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16sishl,
+ SPARC_BUILTIN_FPCMPUR16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32sishl,
+ SPARC_BUILTIN_FPCMPUR32SHL, si_ftype_v2si_v2si_si);
+ }
+ }
}
/* Implement TARGET_BUILTIN_DECL hook. */
@@ -10948,6 +11313,19 @@ sparc_expand_builtin (tree exp, rtx target,
insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
+ /* Some of the builtins require constant arguments. We check
+ for this here. */
+ if ((code >= SPARC_BUILTIN_FIRST_FPCMPSHL
+ && code <= SPARC_BUILTIN_LAST_FPCMPSHL
+ && arg_count == 3)
+ || (code >= SPARC_BUILTIN_FIRST_DICTUNPACK
+ && code <= SPARC_BUILTIN_LAST_DICTUNPACK
+ && arg_count == 2))
+ {
+ if (!check_constant_argument (icode, idx, op[arg_count]))
+ return const0_rtx;
+ }
+
if (code == SPARC_BUILTIN_LDFSR || code == SPARC_BUILTIN_STFSR)
{
if (!address_operand (op[arg_count], SImode))
@@ -11458,7 +11836,8 @@ sparc_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
|| sparc_cpu == PROCESSOR_NIAGARA2
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
return 12;
return 6;
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 581774e586b..15a62179af5 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -143,6 +143,7 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CPU_niagara3 15
#define TARGET_CPU_niagara4 16
#define TARGET_CPU_niagara7 19
+#define TARGET_CPU_m8 20
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
@@ -151,7 +152,8 @@ extern enum cmodel sparc_cmodel;
|| TARGET_CPU_DEFAULT == TARGET_CPU_niagara2 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_niagara3 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_niagara4 \
- || TARGET_CPU_DEFAULT == TARGET_CPU_niagara7
+ || TARGET_CPU_DEFAULT == TARGET_CPU_niagara7 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_m8
#define CPP_CPU32_DEFAULT_SPEC ""
#define ASM_CPU32_DEFAULT_SPEC ""
@@ -192,6 +194,10 @@ extern enum cmodel sparc_cmodel;
#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
#define ASM_CPU64_DEFAULT_SPEC AS_NIAGARA7_FLAG
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_m8
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC AS_M8_FLAG
+#endif
#else
@@ -295,6 +301,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=niagara3:-D__sparc_v9__} \
%{mcpu=niagara4:-D__sparc_v9__} \
%{mcpu=niagara7:-D__sparc_v9__} \
+%{mcpu=m8:-D__sparc_v9__} \
%{!mcpu*:%(cpp_cpu_default)} \
"
#define CPP_ARCH32_SPEC ""
@@ -347,6 +354,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=niagara3:%{!mv8plus:-Av9" AS_NIAGARA3_FLAG "}} \
%{mcpu=niagara4:%{!mv8plus:" AS_NIAGARA4_FLAG "}} \
%{mcpu=niagara7:%{!mv8plus:" AS_NIAGARA7_FLAG "}} \
+%{mcpu=m8:%{!mv8plus:" AS_M8_FLAG "}} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -430,7 +438,8 @@ extern enum cmodel sparc_cmodel;
/* Mask of all CPU feature flags. */
#define MASK_FEATURES \
(MASK_FPU + MASK_HARD_QUAD + MASK_VIS + MASK_VIS2 + MASK_VIS3 \
- + MASK_VIS4 + MASK_CBCOND + MASK_FMAF + MASK_POPC + MASK_SUBXC)
+ + MASK_VIS4 + MASK_CBCOND + MASK_FMAF + MASK_FSMULD \
+ + MASK_POPC + MASK_SUBXC)
/* TARGET_HARD_MUL: Use 32-bit hardware multiply instructions but not %y. */
#define TARGET_HARD_MUL \
@@ -1039,6 +1048,10 @@ extern char leaf_reg_remap[];
/* Local macro to handle the two v9 classes of FP regs. */
#define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS || (CLASS) == EXTRA_FP_REGS)
+/* Predicate for 2-bit and 5-bit unsigned constants. */
+#define SPARC_IMM2_P(X) (((unsigned HOST_WIDE_INT) (X) & ~0x3) == 0)
+#define SPARC_IMM5_P(X) (((unsigned HOST_WIDE_INT) (X) & ~0x1F) == 0)
+
/* Predicates for 5-bit, 10-bit, 11-bit and 13-bit signed constants. */
#define SPARC_SIMM5_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x10 < 0x20)
#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
@@ -1799,6 +1812,12 @@ extern int sparc_indent_opcode;
#define AS_NIAGARA7_FLAG AS_NIAGARA4_FLAG
#endif
+#ifdef HAVE_AS_SPARC6
+#define AS_M8_FLAG "-xarch=sparc6"
+#else
+#define AS_M8_FLAG AS_NIAGARA7_FLAG
+#endif
+
#ifdef HAVE_AS_LEON
#define AS_LEON_FLAG "-Aleon"
#define AS_LEONV7_FLAG "-Aleon"
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 5c5096bca2a..751bacdbcac 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -94,6 +94,12 @@
UNSPEC_ADDV
UNSPEC_SUBV
UNSPEC_NEGV
+
+ UNSPEC_DICTUNPACK
+ UNSPEC_FPCMPSHL
+ UNSPEC_FPUCMPSHL
+ UNSPEC_FPCMPDESHL
+ UNSPEC_FPCMPURSHL
])
(define_c_enum "unspecv" [
@@ -238,7 +244,8 @@
niagara2,
niagara3,
niagara4,
- niagara7"
+ niagara7,
+ m8"
(const (symbol_ref "sparc_cpu_attr")))
;; Attribute for the instruction set.
@@ -251,7 +258,7 @@
(symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
(const_string "v7"))))
-(define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3,vis4"
+(define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3,vis4,vis4b"
(const_string "none"))
(define_attr "lra" "disabled,enabled"
@@ -265,10 +272,92 @@
(eq_attr "cpu_feature" "v9") (symbol_ref "TARGET_V9")
(eq_attr "cpu_feature" "vis") (symbol_ref "TARGET_VIS")
(eq_attr "cpu_feature" "vis3") (symbol_ref "TARGET_VIS3")
- (eq_attr "cpu_feature" "vis4") (symbol_ref "TARGET_VIS4")]
+ (eq_attr "cpu_feature" "vis4") (symbol_ref "TARGET_VIS4")
+ (eq_attr "cpu_feature" "vis4b") (symbol_ref "TARGET_VIS4B")]
(const_int 0)))
-;; Insn type.
+;; The SPARC instructions used by the backend are organized into a
+;; hierarchy using the insn attributes "type" and "subtype".
+;;
+;; The mnemonics used in the list below are the architectural names
+;; used in the Oracle SPARC Architecture specs. A / character
+;; separates the type from the subtype where appropriate. For
+;; brevity, text enclosed in {} denotes alternatives, while text
+;; enclosed in [] is optional.
+;;
+;; Please keep this list updated. It is of great help for keeping the
+;; correctness and coherence of the DFA schedulers.
+;;
+;; ialu: <empty>
+;; ialuX: ADD[X]C SUB[X]C
+;; shift: SLL[X] SRL[X] SRA[X]
+;; cmove: MOV{A,N,NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
+;; MOVF{A,N,U,G,UG,L,UL,LG,NE,E,UE,GE,UGE,LE,ULE,O}
+;; MOVR{Z,LEZ,LZ,NZ,GZ,GEZ}
+;; compare: ADDcc ADDCcc ANDcc ORcc SUBcc SUBCcc XORcc XNORcc
+;; imul: MULX SMUL[cc] UMUL UMULXHI XMULX XMULXHI
+;; idiv: UDIVX SDIVX
+;; flush: FLUSH
+;; load/regular: LD{UB,UH,UW} LDFSR
+;; load/prefetch: PREFETCH
+;; fpload: LDF LDDF LDQF
+;; sload: LD{SB,SH,SW}
+;; store: ST{B,H,W,X} STFSR
+;; fpstore: STF STDF STQF
+;; cbcond: CWB{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
+;; CXB{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
+;; uncond_branch: BA BPA JMPL
+;; branch: B{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
+;; BP{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
+;; FB{U,G,UG,L,UL,LG,NE,BE,UE,GE,UGE,LE,ULE,O}
+;; call: CALL
+;; return: RESTORE RETURN
+;; fpmove: FABS{s,d,q} FMOV{s,d,q} FNEG{s,d,q}
+;; fpcmove: FMOV{S,D,Q}{icc,xcc,fcc}
+;; fpcrmove: FMOVR{s,d,q}{Z,LEZ,LZ,NZ,GZ,GEZ}
+;; fp: FADD{s,d,q} FSUB{s,d,q} FHSUB{s,d} FNHADD{s,d} FNADD{s,d}
+;; FiTO{s,d,q} FsTO{i,x,d,q} FdTO{i,x,s,q} FxTO{d,s,q} FqTO{i,x,s,d}
+;; fpcmp: FCMP{s,d,q} FCMPE{s,d,q}
+;; fpmul: FMADD{s,d} FMSUB{s,d} FMUL{s,d,q} FNMADD{s,d}
+;; FNMSUB{s,d} FNMUL{s,d} FNsMULd FsMULd
+;; FdMULq
+;; array: ARRAY{8,16,32}
+;; bmask: BMASK
+;; edge: EDGE{8,16,32}[L]cc
+;; edgen: EDGE{8,16,32}[L]n
+;; fpdivs: FDIV{s,q}
+;; fpsqrts: FSQRT{s,q}
+;; fpdivd: FDIVd
+;; fpsqrtd: FSQRTd
+;; lzd: LZCNT
+;; fga/addsub64: FP{ADD,SUB}64
+;; fga/fpu: FCHKSM16 FEXPANd FMEAN16 FPMERGE
+;; FS{LL,RA,RL}{16,32}
+;; fga/maxmin: FP{MAX,MIN}[U]{8,16,32}
+;; fga/cmask: CMASK{8,16,32}
+;; fga/other: BSHUFFLE FALIGNDATAg FP{ADD,SUB}[S]{8,16,32}
+;; FP{ADD,SUB}US{8,16} DICTUNPACK
+;; gsr/reg: RDGSR WRGSR
+;; gsr/alignaddr: ALIGNADDRESS[_LITTLE]
+;; vismv/double: FSRC2d
+;; vismv/single: MOVwTOs FSRC2s
+;; vismv/movstouw: MOVsTOuw
+;; vismv/movxtod: MOVxTOd
+;; vismv/movdtox: MOVdTOx
+;; visl/single: F{AND,NAND,NOR,OR,NOT1}s
+;; F{AND,OR}NOT{1,2}s
+;; FONEs F{ZERO,XNOR,XOR}s FNOT2s
+;; visl/double: FONEd FZEROd FNOT1d F{OR,AND,XOR}d F{NOR,NAND,XNOR}d
+;; F{OR,AND}NOT1d F{OR,AND}NOT2d
+;; viscmp: FPCMP{LE,GT,NE,EQ}{8,16,32} FPCMPU{LE,GT,NE,EQ}{8,16,32}
+;; FPCMP{LE,GT,EQ,NE}{8,16,32}SHL FPCMPU{LE,GT,EQ,NE}{8,16,32}SHL
+;; FPCMPDE{8,16,32}SHL FPCMPUR{8,16,32}SHL
+;; fgm_pack: FPACKFIX FPACK{8,16,32}
+;; fgm_mul: FMUL8SUx16 FMUL8ULx16 FMUL8x16 FMUL8x16AL
+;; FMUL8x16AU FMULD8SUx16 FMULD8ULx16
+;; pdist: PDIST
+;; pdistn: PDISTN
+
(define_attr "type"
"ialu,compare,shift,
load,sload,store,
@@ -281,12 +370,20 @@
fpcmp,
fpmul,fpdivs,fpdivd,
fpsqrts,fpsqrtd,
- fga,visl,vismv,fgm_pack,fgm_mul,pdist,pdistn,edge,edgen,gsr,array,
+ fga,visl,vismv,viscmp,
+ fgm_pack,fgm_mul,pdist,pdistn,edge,edgen,gsr,array,bmask,
cmove,
ialuX,
multi,savew,flushw,iflush,trap,lzd"
(const_string "ialu"))
+(define_attr "subtype"
+ "single,double,movstouw,movxtod,movdtox,
+ addsub64,cmask,fpu,maxmin,other,
+ reg,alignaddr,
+ prefetch,regular"
+ (const_string "single"))
+
;; True if branch/call has empty delay slot and will emit a nop in it
(define_attr "empty_delay_slot" "false,true"
(symbol_ref "(empty_delay_slot (insn)
@@ -329,6 +426,10 @@
(symbol_ref "(sparc_fix_ut699 != 0
? FIX_UT699_TRUE : FIX_UT699_FALSE)"))
+(define_attr "fix_b2bst" "false,true"
+ (symbol_ref "(sparc_fix_b2bst != 0
+ ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)"))
+
;; Length (in # of insns).
;; Beware that setting a length greater or equal to 3 for conditional branches
;; has a side-effect (see output_cbranch and output_v9branch).
@@ -476,6 +577,8 @@
(define_attr "in_branch_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi")
(const_string "false")
+ (and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore"))
+ (const_string "false")
(and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload"))
(const_string "false")
(and (eq_attr "fix_ut699" "true")
@@ -487,9 +590,6 @@
(const_string "true")
] (const_string "false")))
-;; True if the instruction executes in the V3 pipeline, in M7 and later processors.
-(define_attr "v3pipe" "false,true" (const_string "false"))
-
(define_delay (eq_attr "type" "call")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
@@ -519,6 +619,7 @@
(include "niagara2.md")
(include "niagara4.md")
(include "niagara7.md")
+(include "m8.md")
;; Operand and operator predicates and constraints
@@ -1507,6 +1608,7 @@
ldub\t%1, %0
stb\t%r1, %0"
[(set_attr "type" "*,load,store")
+ (set_attr "subtype" "*,regular,*")
(set_attr "us3load_type" "*,3cycle,*")])
(define_expand "movhi"
@@ -1529,6 +1631,7 @@
lduh\t%1, %0
sth\t%r1, %0"
[(set_attr "type" "*,*,load,store")
+ (set_attr "subtype" "*,*,regular,*")
(set_attr "us3load_type" "*,*,3cycle,*")])
;; We always work with constants here.
@@ -1566,8 +1669,8 @@
fzeros\t%0
fones\t%0"
[(set_attr "type" "*,*,load,store,vismv,vismv,fpmove,fpload,fpstore,visl,visl")
- (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")
- (set_attr "v3pipe" "*,*,*,*,true,true,*,*,*,true,true")])
+ (set_attr "subtype" "*,*,regular,*,movstouw,single,*,*,*,single,single")
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1624,7 +1727,8 @@
return "ld\t[%1 + %2], %0";
#endif
}
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_expand "movsi_pic_label_ref"
[(set (match_dup 3) (high:SI
@@ -1733,11 +1837,12 @@
std\t%1, %0
fzero\t%0
fone\t%0"
- [(set_attr "type" "store,*,load,store,load,store,*,*,fpload,fpstore,*,*,fpmove,*,*,*,fpload,fpstore,visl,visl")
+ [(set_attr "type" "store,*,load,store,load,store,*,*,fpload,fpstore,*,*,fpmove,*,*,*,fpload,fpstore,visl,
+visl")
+ (set_attr "subtype" "*,*,regular,*,regular,*,*,*,*,*,*,*,*,*,*,*,*,*,double,double")
(set_attr "length" "*,2,*,*,*,*,2,2,*,*,2,2,*,2,2,2,*,*,*,*")
(set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double")
(set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis")
- (set_attr "v3pipe" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,true,true")
(set_attr "lra" "*,*,disabled,disabled,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
(define_insn "*movdi_insn_sp64"
@@ -1759,9 +1864,9 @@
fzero\t%0
fone\t%0"
[(set_attr "type" "*,*,load,store,vismv,vismv,fpmove,fpload,fpstore,visl,visl")
+ (set_attr "subtype" "*,*,regular,*,movdtox,movxtod,*,*,*,double,double")
(set_attr "fptype" "*,*,*,*,*,*,double,*,*,double,double")
- (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")
- (set_attr "v3pipe" "*,*,*,*,*,*,*,*,*,true,true")])
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
@@ -1847,7 +1952,8 @@
return "ldx\t[%1 + %2], %0";
#endif
}
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "*sethi_di_medlow_embmedany_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -2289,8 +2395,8 @@
}
}
[(set_attr "type" "visl,visl,fpmove,*,*,*,vismv,vismv,fpload,load,fpstore,store")
- (set_attr "cpu_feature" "vis,vis,fpu,*,*,*,vis3,vis3,fpu,*,fpu,*")
- (set_attr "v3pipe" "true,true,*,*,*,*,true,true,*,*,*,*")])
+ (set_attr "subtype" "single,single,*,*,*,*,movstouw,single,*,regular,*,*")
+ (set_attr "cpu_feature" "vis,vis,fpu,*,*,*,vis3,vis3,fpu,*,fpu,*")])
;; The following 3 patterns build SFmode constants in integer registers.
@@ -2362,10 +2468,10 @@
ldd\t%1, %0
std\t%1, %0"
[(set_attr "type" "store,*,visl,visl,fpmove,*,*,*,fpload,fpstore,load,store,*,*,*,load,store")
+ (set_attr "subtype" "*,*,double,double,*,*,*,*,*,*,regular,*,*,*,*,regular,*")
(set_attr "length" "*,2,*,*,*,2,2,2,*,*,*,*,2,2,2,*,*")
(set_attr "fptype" "*,*,double,double,double,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "cpu_feature" "v9,*,vis,vis,v9,fpunotv9,vis3,vis3,fpu,fpu,*,*,fpu,fpu,*,*,*")
- (set_attr "v3pipe" "*,*,true,true,*,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "lra" "*,*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")])
(define_insn "*movdf_insn_sp64"
@@ -2387,10 +2493,10 @@
stx\t%r1, %0
#"
[(set_attr "type" "visl,visl,fpmove,vismv,vismv,load,store,*,load,store,*")
+ (set_attr "subtype" "double,double,*,movdtox,movxtod,regular,*,*,regular,*,*")
(set_attr "length" "*,*,*,*,*,*,*,*,*,*,2")
(set_attr "fptype" "double,double,double,double,double,*,*,*,*,*,*")
- (set_attr "cpu_feature" "vis,vis,fpu,vis3,vis3,fpu,fpu,*,*,*,*")
- (set_attr "v3pipe" "true,true,*,*,*,*,*,*,*,*,*")])
+ (set_attr "cpu_feature" "vis,vis,fpu,vis3,vis3,fpu,fpu,*,*,*,*")])
;; This pattern builds DFmode constants in integer registers.
(define_split
@@ -2916,6 +3022,7 @@
""
"lduh\t%1, %0"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_expand "zero_extendqihi2"
@@ -2932,6 +3039,7 @@
and\t%1, 0xff, %0
ldub\t%1, %0"
[(set_attr "type" "*,load")
+ (set_attr "subtype" "*,regular")
(set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendqisi2"
@@ -2948,6 +3056,7 @@
and\t%1, 0xff, %0
ldub\t%1, %0"
[(set_attr "type" "*,load")
+ (set_attr "subtype" "*,regular")
(set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendqidi2"
@@ -2964,6 +3073,7 @@
and\t%1, 0xff, %0
ldub\t%1, %0"
[(set_attr "type" "*,load")
+ (set_attr "subtype" "*,regular")
(set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendhidi2"
@@ -2995,6 +3105,7 @@
"TARGET_ARCH64"
"lduh\t%1, %0"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
;; ??? Write truncdisi pattern using sra?
@@ -3015,8 +3126,8 @@
lduw\t%1, %0
movstouw\t%1, %0"
[(set_attr "type" "shift,load,vismv")
- (set_attr "cpu_feature" "*,*,vis3")
- (set_attr "v3pipe" "*,*,true")])
+ (set_attr "subtype" "*,regular,movstouw")
+ (set_attr "cpu_feature" "*,*,vis3")])
(define_insn_and_split "*zero_extendsidi2_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -3331,8 +3442,7 @@
movstosw\t%1, %0"
[(set_attr "type" "shift,sload,vismv")
(set_attr "us3load_type" "*,3cycle,*")
- (set_attr "cpu_feature" "*,*,vis3")
- (set_attr "v3pipe" "*,*,true")])
+ (set_attr "cpu_feature" "*,*,vis3")])
;; Special pattern for optimizing bit-field compares. This is needed
@@ -6011,7 +6121,7 @@
[(set (match_operand:DF 0 "register_operand" "=e")
(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
(float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
- "(TARGET_V8 || TARGET_V9) && TARGET_FPU && !sparc_fix_ut699"
+ "TARGET_FSMULD"
"fsmuld\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
@@ -6061,10 +6171,10 @@
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU && sparc_fix_ut699"
- "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]"
+ "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]\n\tnop"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -6313,10 +6423,10 @@
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && sparc_fix_ut699"
- "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]"
+ "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]\n\tnop"
[(set_attr "type" "fpsqrtd")
(set_attr "fptype" "double")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -7356,7 +7466,8 @@
[(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_LDFSR)]
"TARGET_FPU"
"ld\t%0, %%fsr"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "stfsr"
[(set (match_operand:SI 0 "memory_operand" "=m")
@@ -7720,7 +7831,8 @@
gcc_assert (locality >= 0 && locality < 4);
return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "prefetch")])
(define_insn "prefetch_32"
[(prefetch (match_operand:SI 0 "address_operand" "p")
@@ -7745,7 +7857,8 @@
gcc_assert (locality >= 0 && locality < 4);
return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "prefetch")])
;; Trap instructions.
@@ -7966,7 +8079,8 @@
UNSPEC_TLSIE))]
"TARGET_TLS && TARGET_ARCH32"
"ld\\t[%1 + %2], %0, %%tie_ld(%a3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "tie_ld64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -7976,7 +8090,8 @@
UNSPEC_TLSIE))]
"TARGET_TLS && TARGET_ARCH64"
"ldx\\t[%1 + %2], %0, %%tie_ldx(%a3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "tie_add32"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -8036,6 +8151,7 @@
"TARGET_TLS && TARGET_ARCH32"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldub1_sp32"
@@ -8048,6 +8164,7 @@
"TARGET_TLS && TARGET_ARCH32"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldub2_sp32"
@@ -8060,6 +8177,7 @@
"TARGET_TLS && TARGET_ARCH32"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldsb1_sp32"
@@ -8095,6 +8213,7 @@
"TARGET_TLS && TARGET_ARCH64"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldub1_sp64"
@@ -8107,6 +8226,7 @@
"TARGET_TLS && TARGET_ARCH64"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldub2_sp64"
@@ -8119,6 +8239,7 @@
"TARGET_TLS && TARGET_ARCH64"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldub3_sp64"
@@ -8131,6 +8252,7 @@
"TARGET_TLS && TARGET_ARCH64"
"ldub\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldsb1_sp64"
@@ -8178,6 +8300,7 @@
"TARGET_TLS && TARGET_ARCH32"
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_lduh1_sp32"
@@ -8190,6 +8313,7 @@
"TARGET_TLS && TARGET_ARCH32"
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldsh1_sp32"
@@ -8213,6 +8337,7 @@
"TARGET_TLS && TARGET_ARCH64"
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_lduh1_sp64"
@@ -8225,6 +8350,7 @@
"TARGET_TLS && TARGET_ARCH64"
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_lduh2_sp64"
@@ -8237,6 +8363,7 @@
"TARGET_TLS && TARGET_ARCH64"
"lduh\t[%1 + %2], %0, %%tldo_add(%3)"
[(set_attr "type" "load")
+ (set_attr "subtype" "regular")
(set_attr "us3load_type" "3cycle")])
(define_insn "*tldo_ldsh1_sp64"
@@ -8271,7 +8398,8 @@
(match_operand:SI 1 "register_operand" "r"))))]
"TARGET_TLS && TARGET_ARCH32"
"ld\t[%1 + %2], %0, %%tldo_add(%3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "*tldo_lduw_sp64"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -8281,7 +8409,8 @@
(match_operand:DI 1 "register_operand" "r"))))]
"TARGET_TLS && TARGET_ARCH64"
"lduw\t[%1 + %2], %0, %%tldo_add(%3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "*tldo_lduw1_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -8292,7 +8421,8 @@
(match_operand:DI 1 "register_operand" "r")))))]
"TARGET_TLS && TARGET_ARCH64"
"lduw\t[%1 + %2], %0, %%tldo_add(%3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "*tldo_ldsw1_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -8314,7 +8444,8 @@
(match_operand:DI 1 "register_operand" "r"))))]
"TARGET_TLS && TARGET_ARCH64"
"ldx\t[%1 + %2], %0, %%tldo_add(%3)"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "subtype" "regular")])
(define_insn "*tldo_stb_sp32"
[(set (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
@@ -8519,8 +8650,8 @@
movstouw\t%1, %0
movwtos\t%1, %0"
[(set_attr "type" "visl,visl,vismv,fpload,fpstore,store,load,store,*,vismv,vismv")
- (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,*,vis3,vis3")
- (set_attr "v3pipe" "true,true,true,*,*,*,*,*,*,true,true")])
+ (set_attr "subtype" "single,single,single,*,*,*,regular,*,*,movstouw,single")
+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,*,vis3,vis3")])
(define_insn "*mov<VM64:mode>_insn_sp64"
[(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,W,m,*r, m,*r, e,*r")
@@ -8542,8 +8673,8 @@
movxtod\t%1, %0
mov\t%1, %0"
[(set_attr "type" "visl,visl,vismv,fpload,fpstore,store,load,store,vismv,vismv,*")
- (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,vis3,vis3,*")
- (set_attr "v3pipe" "true,true,true,*,*,*,*,*,*,*,*")])
+ (set_attr "subtype" "double,double,double,*,*,*,regular,*,movdtox,movxtod,*")
+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,vis3,vis3,*")])
(define_insn "*mov<VM64:mode>_insn_sp32"
[(set (match_operand:VM64 0 "nonimmediate_operand"
@@ -8572,9 +8703,9 @@
ldd\t%1, %0
std\t%1, %0"
[(set_attr "type" "store,*,visl,visl,vismv,*,*,fpload,fpstore,load,store,*,*,*,load,store")
+ (set_attr "subtype" "*,*,double,double,double,*,*,*,*,regular,*,*,*,*,regular,*")
(set_attr "length" "*,2,*,*,*,2,2,*,*,*,*,2,2,2,*,*")
(set_attr "cpu_feature" "*,*,vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*,*,*")
- (set_attr "v3pipe" "*,*,true,true,true,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "lra" "*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")])
(define_split
@@ -8652,8 +8783,8 @@
"TARGET_VIS"
"fp<plusminus_insn><vbits>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "other")
+ (set_attr "fptype" "<vfptype>")])
(define_mode_iterator VL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
(define_mode_attr vlsuf [(V1SI "s") (V2HI "s") (V4QI "s")
@@ -8669,8 +8800,7 @@
"TARGET_VIS"
"f<vlinsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
(define_insn "*not_<vlop:code><VL:mode>3"
[(set (match_operand:VL 0 "register_operand" "=<vconstr>")
@@ -8679,8 +8809,7 @@
"TARGET_VIS"
"f<vlninsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
(define_insn "*nand<VL:mode>_vis"
@@ -8690,8 +8819,7 @@
"TARGET_VIS"
"fnand<vlsuf>\t%1, %2, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
(define_code_iterator vlnotop [ior and])
@@ -8702,8 +8830,7 @@
"TARGET_VIS"
"f<vlinsn>not1<vlsuf>\t%1, %2, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
(define_insn "*<vlnotop:code>_not2<VL:mode>_vis"
[(set (match_operand:VL 0 "register_operand" "=<vconstr>")
@@ -8712,8 +8839,7 @@
"TARGET_VIS"
"f<vlinsn>not2<vlsuf>\t%1, %2, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
(define_insn "one_cmpl<VL:mode>2"
[(set (match_operand:VL 0 "register_operand" "=<vconstr>")
@@ -8721,8 +8847,7 @@
"TARGET_VIS"
"fnot1<vlsuf>\t%1, %0"
[(set_attr "type" "visl")
- (set_attr "fptype" "<vfptype>")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "<vfptype>")])
;; Hard to generate VIS instructions. We have builtins for these.
@@ -8764,6 +8889,7 @@
"TARGET_VIS"
"fexpand\t%1, %0"
[(set_attr "type" "fga")
+ (set_attr "subtype" "fpu")
(set_attr "fptype" "double")])
(define_insn "fpmerge_vis"
@@ -8778,6 +8904,7 @@
"TARGET_VIS"
"fpmerge\t%1, %2, %0"
[(set_attr "type" "fga")
+ (set_attr "subtype" "fpu")
(set_attr "fptype" "double")])
;; Partitioned multiply instructions
@@ -8866,7 +8993,8 @@
[(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "rI"))]
"TARGET_VIS && TARGET_ARCH64"
"wr\t%%g0, %0, %%gsr"
- [(set_attr "type" "gsr")])
+ [(set_attr "type" "gsr")
+ (set_attr "subtype" "reg")])
(define_insn "wrgsr_v8plus"
[(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "I,r"))
@@ -8897,7 +9025,8 @@
[(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))]
"TARGET_VIS && TARGET_ARCH64"
"rd\t%%gsr, %0"
- [(set_attr "type" "gsr")])
+ [(set_attr "type" "gsr")
+ (set_attr "subtype" "reg")])
(define_insn "rdgsr_v8plus"
[(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))
@@ -8920,8 +9049,8 @@
"TARGET_VIS"
"faligndata\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "other")
+ (set_attr "fptype" "double")])
(define_insn "alignaddrsi_vis"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -8932,7 +9061,7 @@
"TARGET_VIS"
"alignaddr\t%r1, %r2, %0"
[(set_attr "type" "gsr")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "alignaddr")])
(define_insn "alignaddrdi_vis"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -8943,7 +9072,7 @@
"TARGET_VIS"
"alignaddr\t%r1, %r2, %0"
[(set_attr "type" "gsr")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "alignaddr")])
(define_insn "alignaddrlsi_vis"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -8955,7 +9084,7 @@
"TARGET_VIS"
"alignaddrl\t%r1, %r2, %0"
[(set_attr "type" "gsr")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "alignaddr")])
(define_insn "alignaddrldi_vis"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -8967,7 +9096,7 @@
"TARGET_VIS"
"alignaddrl\t%r1, %r2, %0"
[(set_attr "type" "gsr")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "alignaddr")])
(define_insn "pdist_vis"
[(set (match_operand:DI 0 "register_operand" "=e")
@@ -9059,9 +9188,7 @@
UNSPEC_FCMP))]
"TARGET_VIS"
"fcmp<gcond:code><GCM:gcm_name>\t%1, %2, %0"
- [(set_attr "type" "visl")
- (set_attr "fptype" "double")
- (set_attr "v3pipe" "true")])
+ [(set_attr "type" "viscmp")])
(define_insn "fpcmp<gcond:code>8<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
@@ -9070,8 +9197,7 @@
UNSPEC_FCMP))]
"TARGET_VIS4"
"fpcmp<gcond:code>8\t%1, %2, %0"
- [(set_attr "type" "visl")
- (set_attr "fptype" "double")])
+ [(set_attr "type" "viscmp")])
(define_expand "vcond<GCM:mode><GCM:mode>"
[(match_operand:GCM 0 "register_operand" "")
@@ -9134,8 +9260,7 @@
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_VIS2 && TARGET_ARCH64"
"bmask\t%r1, %r2, %0"
- [(set_attr "type" "array")
- (set_attr "v3pipe" "true")])
+ [(set_attr "type" "bmask")])
(define_insn "bmasksi_vis"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -9145,8 +9270,7 @@
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_VIS2"
"bmask\t%r1, %r2, %0"
- [(set_attr "type" "array")
- (set_attr "v3pipe" "true")])
+ [(set_attr "type" "bmask")])
(define_insn "bshuffle<VM64:mode>_vis"
[(set (match_operand:VM64 0 "register_operand" "=e")
@@ -9157,8 +9281,8 @@
"TARGET_VIS2"
"bshuffle\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "other")
+ (set_attr "fptype" "double")])
;; The rtl expanders will happily convert constant permutations on other
;; modes down to V8QI. Rely on this to avoid the complexity of the byte
@@ -9261,7 +9385,7 @@
"TARGET_VIS3"
"cmask8\t%r0"
[(set_attr "type" "fga")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "cmask")])
(define_insn "cmask16<P:mode>_vis"
[(set (reg:DI GSR_REG)
@@ -9271,7 +9395,7 @@
"TARGET_VIS3"
"cmask16\t%r0"
[(set_attr "type" "fga")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "cmask")])
(define_insn "cmask32<P:mode>_vis"
[(set (reg:DI GSR_REG)
@@ -9281,7 +9405,7 @@
"TARGET_VIS3"
"cmask32\t%r0"
[(set_attr "type" "fga")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "cmask")])
(define_insn "fchksm16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
@@ -9290,7 +9414,8 @@
UNSPEC_FCHKSM16))]
"TARGET_VIS3"
"fchksm16\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "fpu")])
(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
(define_code_attr vis3_shift_insn
@@ -9304,7 +9429,8 @@
(match_operand:GCM 2 "register_operand" "<vconstr>")))]
"TARGET_VIS3"
"<vis3_shift_insn><vbits>\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "fpu")])
(define_insn "pdistn<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
@@ -9314,8 +9440,7 @@
"TARGET_VIS3"
"pdistn\t%1, %2, %0"
[(set_attr "type" "pdistn")
- (set_attr "fptype" "double")
- (set_attr "v3pipe" "true")])
+ (set_attr "fptype" "double")])
(define_insn "fmean16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
@@ -9332,7 +9457,8 @@
(const_int 1))))]
"TARGET_VIS3"
"fmean16\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "fpu")])
(define_insn "fp<plusminus_insn>64_vis"
[(set (match_operand:V1DI 0 "register_operand" "=e")
@@ -9340,7 +9466,8 @@
(match_operand:V1DI 2 "register_operand" "e")))]
"TARGET_VIS3"
"fp<plusminus_insn>64\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "addsub64")])
(define_insn "<plusminus_insn>v8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=e")
@@ -9348,7 +9475,8 @@
(match_operand:V8QI 2 "register_operand" "e")))]
"TARGET_VIS4"
"fp<plusminus_insn>8\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "other")])
(define_mode_iterator VASS [V4HI V2SI V2HI V1SI])
(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
@@ -9364,7 +9492,7 @@
"TARGET_VIS3"
"<vis3_addsub_ss_insn><vbits>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "v3pipe" "true")])
+ (set_attr "subtype" "other")])
(define_mode_iterator VMMAX [V8QI V4HI V2SI])
(define_code_iterator vis4_minmax [smin smax])
@@ -9379,7 +9507,8 @@
(match_operand:VMMAX 2 "register_operand" "<vconstr>")))]
"TARGET_VIS4"
"<vis4_minmax_insn><vbits>\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "maxmin")])
(define_code_iterator vis4_uminmax [umin umax])
(define_code_attr vis4_uminmax_insn
@@ -9393,7 +9522,8 @@
(match_operand:VMMAX 2 "register_operand" "<vconstr>")))]
"TARGET_VIS4"
"<vis4_uminmax_insn><vbits>\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "maxmin")])
;; The use of vis3_addsub_ss_patname in the VIS4 instruction below is
;; intended.
@@ -9403,7 +9533,8 @@
(match_operand:V8QI 2 "register_operand" "e")))]
"TARGET_VIS4"
"<vis3_addsub_ss_insn>8\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "other")])
(define_mode_iterator VAUS [V4HI V8QI])
(define_code_iterator vis4_addsub_us [us_plus us_minus])
@@ -9418,7 +9549,8 @@
(match_operand:VAUS 2 "register_operand" "<vconstr>")))]
"TARGET_VIS4"
"<vis4_addsub_us_insn><vbits>\t%1, %2, %0"
- [(set_attr "type" "fga")])
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "other")])
(define_insn "fucmp<gcond:code>8<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
@@ -9427,8 +9559,7 @@
UNSPEC_FUCMP))]
"TARGET_VIS3"
"fucmp<gcond:code>8\t%1, %2, %0"
- [(set_attr "type" "visl")
- (set_attr "v3pipe" "true")])
+ [(set_attr "type" "viscmp")])
(define_insn "fpcmpu<gcond:code><GCM:gcm_name><P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
@@ -9437,8 +9568,7 @@
UNSPEC_FUCMP))]
"TARGET_VIS4"
"fpcmpu<gcond:code><GCM:gcm_name>\t%1, %2, %0"
- [(set_attr "type" "visl")
- (set_attr "fptype" "double")])
+ [(set_attr "type" "viscmp")])
(define_insn "*naddsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -9542,4 +9672,62 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+;; VIS4B instructions.
+
+(define_mode_iterator DUMODE [V2SI V4HI V8QI])
+
+(define_insn "dictunpack<DUMODE:vbits>"
+ [(set (match_operand:DUMODE 0 "register_operand" "=e")
+ (unspec:DUMODE [(match_operand:DF 1 "register_operand" "e")
+ (match_operand:SI 2 "imm5_operand_dictunpack<DUMODE:vbits>" "t")]
+ UNSPEC_DICTUNPACK))]
+ "TARGET_VIS4B"
+ "dictunpack\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "subtype" "other")])
+
+(define_mode_iterator FPCSMODE [V2SI V4HI V8QI])
+(define_code_iterator fpcscond [le gt eq ne])
+(define_code_iterator fpcsucond [le gt])
+
+(define_insn "fpcmp<fpcscond:code><FPCSMODE:vbits><P:mode>shl"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(fpcscond:FPCSMODE (match_operand:FPCSMODE 1 "register_operand" "e")
+ (match_operand:FPCSMODE 2 "register_operand" "e"))
+ (match_operand:SI 3 "imm2_operand" "q")]
+ UNSPEC_FPCMPSHL))]
+ "TARGET_VIS4B"
+ "fpcmp<fpcscond:code><FPCSMODE:vbits>shl\t%1, %2, %3, %0"
+ [(set_attr "type" "viscmp")])
+
+(define_insn "fpcmpu<fpcsucond:code><FPCSMODE:vbits><P:mode>shl"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(fpcsucond:FPCSMODE (match_operand:FPCSMODE 1 "register_operand" "e")
+ (match_operand:FPCSMODE 2 "register_operand" "e"))
+ (match_operand:SI 3 "imm2_operand" "q")]
+ UNSPEC_FPUCMPSHL))]
+ "TARGET_VIS4B"
+ "fpcmpu<fpcsucond:code><FPCSMODE:vbits>shl\t%1, %2, %3, %0"
+ [(set_attr "type" "viscmp")])
+
+(define_insn "fpcmpde<FPCSMODE:vbits><P:mode>shl"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:FPCSMODE 1 "register_operand" "e")
+ (match_operand:FPCSMODE 2 "register_operand" "e")
+ (match_operand:SI 3 "imm2_operand" "q")]
+ UNSPEC_FPCMPDESHL))]
+ "TARGET_VIS4B"
+ "fpcmpde<FPCSMODE:vbits>shl\t%1, %2, %3, %0"
+ [(set_attr "type" "viscmp")])
+
+(define_insn "fpcmpur<FPCSMODE:vbits><P:mode>shl"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:FPCSMODE 1 "register_operand" "e")
+ (match_operand:FPCSMODE 2 "register_operand" "e")
+ (match_operand:SI 3 "imm2_operand" "q")]
+ UNSPEC_FPCMPURSHL))]
+ "TARGET_VIS4B"
+ "fpcmpur<FPCSMODE:vbits>shl\t%1, %2, %3, %0"
+ [(set_attr "type" "viscmp")])
+
(include "sync.md")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 86f85d9058f..22267f50e90 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -81,6 +81,10 @@ mvis4
Target Report Mask(VIS4)
Use UltraSPARC Visual Instruction Set version 4.0 extensions.
+mvis4b
+Target Report Mask(VIS4B)
+Use additional VIS instructions introduced in OSA2017.
+
mcbcond
Target Report Mask(CBCOND)
Use UltraSPARC Compare-and-Branch extensions.
@@ -89,6 +93,10 @@ mfmaf
Target Report Mask(FMAF)
Use UltraSPARC Fused Multiply-Add extensions.
+mfsmuld
+Target Report Mask(FSMULD)
+Use Floating-point Multiply Single to Double (FsMULd) instruction.
+
mpopc
Target Report Mask(POPC)
Use UltraSPARC Population-Count instruction.
@@ -209,6 +217,9 @@ Enum(sparc_processor_type) String(niagara4) Value(PROCESSOR_NIAGARA4)
EnumValue
Enum(sparc_processor_type) String(niagara7) Value(PROCESSOR_NIAGARA7)
+EnumValue
+Enum(sparc_processor_type) String(m8) Value(PROCESSOR_M8)
+
mcmodel=
Target RejectNegative Joined Var(sparc_cmodel_string)
Use given SPARC-V9 code model.
@@ -230,6 +241,18 @@ mfix-ut699
Target Report RejectNegative Var(sparc_fix_ut699)
Enable workarounds for the errata of the UT699 processor.
+mfix-ut700
+Target Report RejectNegative Var(sparc_fix_ut700)
+Enable workarounds for the errata of the UT699E/UT700 processor.
+
+mfix-gr712rc
+Target Report RejectNegative Var(sparc_fix_gr712rc)
+Enable workarounds for the errata of the GR712RC processor.
+
+;; Enable workaround for back-to-back store errata
+TargetVariable
+unsigned int sparc_fix_b2bst
+
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double
diff --git a/gcc/config/sparc/t-rtems b/gcc/config/sparc/t-rtems
index 7411aaab785..809840ca1f3 100644
--- a/gcc/config/sparc/t-rtems
+++ b/gcc/config/sparc/t-rtems
@@ -18,19 +18,25 @@
#
MULTILIB_OPTIONS = msoft-float mcpu=v8/mcpu=leon3/mcpu=leon3v7/mcpu=leon \
- mfix-ut699/mfix-at697f
-MULTILIB_DIRNAMES = soft v8 leon3 leon3v7 leon ut699 at697f
-MULTILIB_MATCHES = msoft-float=mno-fpu
+ mfix-ut699/mfix-at697f/mfix-gr712rc
+MULTILIB_DIRNAMES = soft v8 leon3 leon3v7 leon ut699 at697f gr712rc
+MULTILIB_MATCHES = msoft-float=mno-fpu mfix-gr712rc=mfix-ut700
-MULTILIB_EXCEPTIONS = mfix-ut699
-MULTILIB_EXCEPTIONS += msoft-float/mfix-ut699
-MULTILIB_EXCEPTIONS += msoft-float/mcpu=v8/mfix-ut699
-MULTILIB_EXCEPTIONS += msoft-float/mcpu=leon3*/mfix-ut699
-MULTILIB_EXCEPTIONS += mcpu=v8/mfix-ut699
-MULTILIB_EXCEPTIONS += mcpu=leon3*/mfix-ut699
-MULTILIB_EXCEPTIONS += mfix-at697f
-MULTILIB_EXCEPTIONS += msoft-float/mfix-at697f
-MULTILIB_EXCEPTIONS += msoft-float/mcpu=v8/mfix-at697f
-MULTILIB_EXCEPTIONS += msoft-float/mcpu=leon3*/mfix-at697f
-MULTILIB_EXCEPTIONS += mcpu=v8/mfix-at697f
-MULTILIB_EXCEPTIONS += mcpu=leon3*/mfix-at697f
+MULTILIB_REQUIRED =
+MULTILIB_REQUIRED += msoft-float
+MULTILIB_REQUIRED += mcpu=v8
+MULTILIB_REQUIRED += mcpu=leon3
+MULTILIB_REQUIRED += mcpu=leon3v7
+MULTILIB_REQUIRED += mcpu=leon
+MULTILIB_REQUIRED += mcpu=leon3/mfix-gr712rc
+MULTILIB_REQUIRED += mcpu=leon3v7/mfix-gr712rc
+MULTILIB_REQUIRED += mcpu=leon/mfix-ut699
+MULTILIB_REQUIRED += mcpu=leon/mfix-at697f
+MULTILIB_REQUIRED += msoft-float/mcpu=v8
+MULTILIB_REQUIRED += msoft-float/mcpu=leon3
+MULTILIB_REQUIRED += msoft-float/mcpu=leon3v7
+MULTILIB_REQUIRED += msoft-float/mcpu=leon
+MULTILIB_REQUIRED += msoft-float/mcpu=leon3/mfix-gr712rc
+MULTILIB_REQUIRED += msoft-float/mcpu=leon3v7/mfix-gr712rc
+MULTILIB_REQUIRED += msoft-float/mcpu=leon/mfix-ut699
+MULTILIB_REQUIRED += msoft-float/mcpu=leon/mfix-at697f
diff --git a/gcc/config/sparc/ultra1_2.md b/gcc/config/sparc/ultra1_2.md
index 6af285931e4..a4fb88345d6 100644
--- a/gcc/config/sparc/ultra1_2.md
+++ b/gcc/config/sparc/ultra1_2.md
@@ -263,10 +263,10 @@
(define_insn_reservation "us1_fga_double"
2
- (and (and
- (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fga,visl,vismv"))
- (eq_attr "fptype" "double"))
+ (and (eq_attr "cpu" "ultrasparc")
+ (ior (and (eq_attr "type" "fga,visl,vismv")
+ (eq_attr "fptype" "double"))
+ (eq_attr "type" "viscmp")))
"us1_fpa + us1_fp_double + us1_slotany, nothing")
(define_bypass 1 "us1_fga_double" "us1_fga_double")
diff --git a/gcc/config/sparc/ultra3.md b/gcc/config/sparc/ultra3.md
index 6296b38cbbd..db20cd9c982 100644
--- a/gcc/config/sparc/ultra3.md
+++ b/gcc/config/sparc/ultra3.md
@@ -56,7 +56,7 @@
(define_insn_reservation "us3_array" 2
(and (eq_attr "cpu" "ultrasparc3")
- (eq_attr "type" "array,edgen"))
+ (eq_attr "type" "array,edgen,bmask"))
"us3_ms + us3_slotany, nothing")
;; ??? Not entirely accurate.
@@ -176,7 +176,7 @@
(define_insn_reservation "us3_fga"
3
(and (eq_attr "cpu" "ultrasparc3")
- (eq_attr "type" "fga,visl,vismv"))
+ (eq_attr "type" "fga,visl,viscmp,vismv"))
"us3_fpa + us3_slotany, nothing*2")
(define_insn_reservation "us3_fgm"
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index fcb85c0ee16..efee614b103 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -2195,7 +2195,8 @@ get_branch_target (rtx_insn *branch)
{
/* If the more probable case is not a fall through, then
try a branch hint. */
- int prob = XINT (note, 0);
+ int prob = profile_probability::from_reg_br_prob_note
+ (XINT (note, 0)).to_reg_br_prob_base ();
if (prob > (REG_BR_PROB_BASE * 6 / 10)
&& GET_CODE (XEXP (src, 1)) != PC)
lab = XEXP (src, 1);
@@ -4335,8 +4336,7 @@ ea_load_store_inline (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
hit_ref, pc_rtx)));
/* Say that this branch is very likely to happen. */
- v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1;
- add_int_reg_note (insn, REG_BR_PROB, v);
+ add_reg_br_prob_note (insn, profile_probability::very_likely ());
ea_load_store (mem, is_store, ea_addr, data_addr);
cont_label = gen_label_rtx ();
diff --git a/gcc/config/t-musl b/gcc/config/t-musl
new file mode 100644
index 00000000000..e203fce7619
--- /dev/null
+++ b/gcc/config/t-musl
@@ -0,0 +1,2 @@
+MULTIARCH_DIRNAME := $(subst -linux-gnu,-linux-musl,$(MULTIARCH_DIRNAME))
+MULTILIB_OSDIRNAMES := $(subst -linux-gnu,-linux-musl,$(MULTILIB_OSDIRNAMES))
diff --git a/gcc/config/t-uclibc b/gcc/config/t-uclibc
new file mode 100644
index 00000000000..c9b3a7bdfe2
--- /dev/null
+++ b/gcc/config/t-uclibc
@@ -0,0 +1,2 @@
+MULTIARCH_DIRNAME := $(subst -linux-gnu,-linux-uclibc,$(MULTIARCH_DIRNAME))
+MULTILIB_OSDIRNAMES := $(subst -linux-gnu,-linux-uclibc,$(MULTILIB_OSDIRNAMES))
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index e070e7ee520..dafb49daf1f 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -2619,9 +2619,8 @@ cbranch_predicted_p (rtx_insn *insn)
if (x)
{
- int pred_val = XINT (x, 0);
-
- return pred_val >= REG_BR_PROB_BASE / 2;
+ return profile_probability::from_reg_br_prob_note (XINT (x, 0))
+ >= profile_probability::even ();
}
return false;
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 81019c13a4c..80475b959ee 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -2419,9 +2419,8 @@ cbranch_predicted_p (rtx_insn *insn)
if (x)
{
- int pred_val = XINT (x, 0);
-
- return pred_val >= REG_BR_PROB_BASE / 2;
+ return profile_probability::from_reg_br_prob_note (XINT (x, 0))
+ >= profile_probability::even ();
}
return false;
diff --git a/gcc/config/v850/rtems.h b/gcc/config/v850/rtems.h
index b779a0d974c..231503ba26f 100644
--- a/gcc/config/v850/rtems.h
+++ b/gcc/config/v850/rtems.h
@@ -3,15 +3,15 @@
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.
+ 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
diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md
index fb0f69acbff..e805a7ee812 100644
--- a/gcc/config/vax/builtins.md
+++ b/gcc/config/vax/builtins.md
@@ -41,7 +41,7 @@
(define_insn "ffssi2_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
- (ffs:SI (match_operand:SI 1 "general_operand" "nrmT")))
+ (ffs:SI (match_operand:SI 1 "general_operand" "nrQt")))
(set (cc0) (match_dup 0))]
""
"ffs $0,$32,%1,%0")
diff --git a/gcc/config/visium/visium-protos.h b/gcc/config/visium/visium-protos.h
index a9f8fc91254..d4aa17678ba 100644
--- a/gcc/config/visium/visium-protos.h
+++ b/gcc/config/visium/visium-protos.h
@@ -32,28 +32,28 @@ extern void visium_profile_hook (void);
extern int visium_hard_regno_rename_ok (unsigned int, unsigned int);
extern int visium_initial_elimination_offset (int from, int to);
#ifdef RTX_CODE
-extern void prepare_move_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_move_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_move_strict_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_arith_logic_operands (rtx *, enum machine_mode);
+extern void prepare_move_operands (rtx *, machine_mode);
+extern bool ok_for_simple_move_operands (rtx *, machine_mode);
+extern bool ok_for_simple_move_strict_operands (rtx *, machine_mode);
+extern bool ok_for_simple_arith_logic_operands (rtx *, machine_mode);
extern void visium_initialize_trampoline (rtx, rtx, rtx);
extern int empty_delay_slot (rtx_insn *);
extern int gr5_hazard_bypass_p (rtx_insn *, rtx_insn *);
extern rtx visium_return_addr_rtx (int, rtx);
extern rtx visium_eh_return_handler_rtx (void);
extern rtx visium_dynamic_chain_address (rtx);
-extern rtx visium_legitimize_reload_address (rtx, enum machine_mode, int, int,
+extern rtx visium_legitimize_reload_address (rtx, machine_mode, int, int,
int);
-extern enum machine_mode visium_select_cc_mode (enum rtx_code, rtx, rtx);
+extern machine_mode visium_select_cc_mode (enum rtx_code, rtx, rtx);
extern void visium_split_cbranch (enum rtx_code, rtx, rtx, rtx);
extern const char *output_ubranch (rtx, rtx_insn *);
-extern const char *output_cbranch (rtx, enum rtx_code, enum machine_mode, int,
+extern const char *output_cbranch (rtx, enum rtx_code, machine_mode, int,
rtx_insn *);
-extern void visium_split_double_move (rtx *, enum machine_mode);
+extern void visium_split_double_move (rtx *, machine_mode);
extern void visium_split_double_add (enum rtx_code, rtx, rtx, rtx);
-extern void visium_expand_copysign (rtx *, enum machine_mode);
-extern void visium_expand_int_cstore (rtx *, enum machine_mode);
-extern void visium_expand_fp_cstore (rtx *, enum machine_mode);
+extern void visium_expand_copysign (rtx *, machine_mode);
+extern void visium_expand_int_cstore (rtx *, machine_mode);
+extern void visium_expand_fp_cstore (rtx *, machine_mode);
extern void visium_split_cstore (enum rtx_code, rtx, rtx,
enum rtx_code, rtx, rtx);
extern int visium_expand_block_move (rtx *);
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index fac254c4c1e..e5d843e8d4c 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -154,13 +154,13 @@ static struct machine_function *visium_init_machine_status (void);
/* Target hooks and TARGET_INITIALIZER */
-static bool visium_pass_by_reference (cumulative_args_t, enum machine_mode,
+static bool visium_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static rtx visium_function_arg (cumulative_args_t, enum machine_mode,
+static rtx visium_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
-static void visium_function_arg_advance (cumulative_args_t, enum machine_mode,
+static void visium_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
static bool visium_return_in_memory (const_tree, const_tree fntype);
@@ -168,10 +168,10 @@ static bool visium_return_in_memory (const_tree, const_tree fntype);
static rtx visium_function_value (const_tree, const_tree fn_decl_or_type,
bool);
-static rtx visium_libcall_value (enum machine_mode, const_rtx);
+static rtx visium_libcall_value (machine_mode, const_rtx);
static void visium_setup_incoming_varargs (cumulative_args_t,
- enum machine_mode,
+ machine_mode,
tree, int *, int);
static void visium_va_start (tree valist, rtx nextarg);
@@ -188,9 +188,9 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
vec<const char *> &,
vec<rtx> &, HARD_REG_SET &);
-static bool visium_legitimate_constant_p (enum machine_mode, rtx);
+static bool visium_legitimate_constant_p (machine_mode, rtx);
-static bool visium_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool visium_legitimate_address_p (machine_mode, rtx, bool);
static bool visium_print_operand_punct_valid_p (unsigned char);
static void visium_print_operand (FILE *, rtx, int);
@@ -198,10 +198,10 @@ static void visium_print_operand_address (FILE *, machine_mode, rtx);
static void visium_conditional_register_usage (void);
-static rtx visium_legitimize_address (rtx, rtx, enum machine_mode);
+static rtx visium_legitimize_address (rtx, rtx, machine_mode);
static reg_class_t visium_secondary_reload (bool, rtx, reg_class_t,
- enum machine_mode,
+ machine_mode,
secondary_reload_info *);
static bool visium_class_likely_spilled_p (reg_class_t);
@@ -214,10 +214,10 @@ static int visium_adjust_priority (rtx_insn *, int);
static int visium_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
-static int visium_register_move_cost (enum machine_mode, reg_class_t,
+static int visium_register_move_cost (machine_mode, reg_class_t,
reg_class_t);
-static int visium_memory_move_cost (enum machine_mode, reg_class_t, bool);
+static int visium_memory_move_cost (machine_mode, reg_class_t, bool);
static bool visium_rtx_costs (rtx, machine_mode, int, int, int *, bool);
@@ -786,7 +786,7 @@ visium_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
X is guaranteed to satisfy the CONSTANT_P predicate. */
static bool
-visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+visium_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
rtx x ATTRIBUTE_UNUSED)
{
return true;
@@ -849,7 +849,7 @@ visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
/* Prepare operands for a move define_expand in MODE. */
void
-prepare_move_operands (rtx *operands, enum machine_mode mode)
+prepare_move_operands (rtx *operands, machine_mode mode)
{
/* If the output is not a register, the input must be. */
if (GET_CODE (operands[0]) == MEM && !reg_or_0_operand (operands[1], mode))
@@ -859,7 +859,7 @@ prepare_move_operands (rtx *operands, enum machine_mode mode)
/* Return true if the operands are valid for a simple move insn. */
bool
-ok_for_simple_move_operands (rtx *operands, enum machine_mode mode)
+ok_for_simple_move_operands (rtx *operands, machine_mode mode)
{
/* One of the operands must be a register. */
if (!register_operand (operands[0], mode)
@@ -878,7 +878,7 @@ ok_for_simple_move_operands (rtx *operands, enum machine_mode mode)
/* Return true if the operands are valid for a simple move strict insn. */
bool
-ok_for_simple_move_strict_operands (rtx *operands, enum machine_mode mode)
+ok_for_simple_move_strict_operands (rtx *operands, machine_mode mode)
{
/* Once the flags are exposed, no simple moves between integer registers.
Note that, in QImode only, a zero source counts as an integer register
@@ -896,7 +896,7 @@ ok_for_simple_move_strict_operands (rtx *operands, enum machine_mode mode)
insn. */
bool
-ok_for_simple_arith_logic_operands (rtx *, enum machine_mode)
+ok_for_simple_arith_logic_operands (rtx *, machine_mode)
{
/* Once the flags are exposed, no simple arithmetic or logical operations
between integer registers. */
@@ -1244,7 +1244,7 @@ visium_reorg (void)
static bool
visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
const_tree type,
bool named ATTRIBUTE_UNUSED)
{
@@ -1265,7 +1265,7 @@ visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
in general registers. */
static rtx
-visium_function_arg (cumulative_args_t pcum_v, enum machine_mode mode,
+visium_function_arg (cumulative_args_t pcum_v, machine_mode mode,
const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
@@ -1303,7 +1303,7 @@ visium_function_arg (cumulative_args_t pcum_v, enum machine_mode mode,
static void
visium_function_arg_advance (cumulative_args_t pcum_v,
- enum machine_mode mode,
+ machine_mode mode,
const_tree type ATTRIBUTE_UNUSED,
bool named)
{
@@ -1355,7 +1355,7 @@ visium_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
/* Define how scalar values are returned. */
static rtx
-visium_function_value_1 (enum machine_mode mode)
+visium_function_value_1 (machine_mode mode)
{
/* Scalar or complex single precision floating point values
are returned in floating register f1. */
@@ -1385,7 +1385,7 @@ visium_function_value (const_tree ret_type,
be returned. */
static rtx
-visium_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+visium_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
{
return visium_function_value_1 (mode);
}
@@ -1395,7 +1395,7 @@ visium_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
static void
visium_setup_incoming_varargs (cumulative_args_t pcum_v,
- enum machine_mode mode,
+ machine_mode mode,
tree type,
int *pretend_size ATTRIBUTE_UNUSED,
int no_rtl)
@@ -1711,7 +1711,7 @@ visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
address of a memory access in mode MODE. */
static bool
-rtx_ok_for_offset_p (enum machine_mode mode, rtx op)
+rtx_ok_for_offset_p (machine_mode mode, rtx op)
{
if (!CONST_INT_P (op) || INTVAL (op) < 0)
return false;
@@ -1759,7 +1759,7 @@ rtx_ok_for_offset_p (enum machine_mode mode, rtx op)
kind of register is required. */
static bool
-visium_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
{
rtx base;
unsigned int regno;
@@ -1832,7 +1832,7 @@ visium_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
static rtx
visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ machine_mode mode)
{
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -1866,7 +1866,7 @@ visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
that need reloading are indicated by calling push_reload. */
rtx
-visium_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum,
+visium_legitimize_reload_address (rtx x, machine_mode mode, int opnum,
int type, int ind ATTRIBUTE_UNUSED)
{
rtx newrtx, tem = NULL_RTX;
@@ -1915,7 +1915,7 @@ visium_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum,
relative to that. */
static int
-visium_register_move_cost (enum machine_mode mode, reg_class_t from,
+visium_register_move_cost (machine_mode mode, reg_class_t from,
reg_class_t to)
{
const int numwords = (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) ? 1 : 2;
@@ -1934,7 +1934,7 @@ visium_register_move_cost (enum machine_mode mode, reg_class_t from,
visium_register_move_cost. */
static int
-visium_memory_move_cost (enum machine_mode mode,
+visium_memory_move_cost (machine_mode mode,
reg_class_t to ATTRIBUTE_UNUSED,
bool in)
{
@@ -2042,7 +2042,7 @@ visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
/* Split a double move of OPERANDS in MODE. */
void
-visium_split_double_move (rtx *operands, enum machine_mode mode)
+visium_split_double_move (rtx *operands, machine_mode mode)
{
bool swap = false;
@@ -2152,7 +2152,7 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
/* Expand a copysign of OPERANDS in MODE. */
void
-visium_expand_copysign (rtx *operands, enum machine_mode mode)
+visium_expand_copysign (rtx *operands, machine_mode mode)
{
rtx op0 = operands[0];
rtx op1 = operands[1];
@@ -2206,7 +2206,7 @@ visium_expand_copysign (rtx *operands, enum machine_mode mode)
generated code. */
void
-visium_expand_int_cstore (rtx *operands, enum machine_mode mode)
+visium_expand_int_cstore (rtx *operands, machine_mode mode)
{
enum rtx_code code = GET_CODE (operands[1]);
rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], sltu;
@@ -2265,7 +2265,7 @@ visium_expand_int_cstore (rtx *operands, enum machine_mode mode)
void
visium_expand_fp_cstore (rtx *operands,
- enum machine_mode mode ATTRIBUTE_UNUSED)
+ machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (operands[1]);
rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], slt;
@@ -2314,7 +2314,7 @@ void
visium_split_cstore (enum rtx_code op_code, rtx op0, rtx op1,
enum rtx_code code, rtx op2, rtx op3)
{
- enum machine_mode cc_mode = visium_select_cc_mode (code, op2, op3);
+ machine_mode cc_mode = visium_select_cc_mode (code, op2, op3);
/* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
if (cc_mode == CCFPEmode && (op_code == NEG || op_code == MINUS))
@@ -2792,7 +2792,7 @@ visium_init_expanders (void)
/* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
return the mode to be used for the comparison. */
-enum machine_mode
+machine_mode
visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
{
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
@@ -2896,7 +2896,7 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
void
visium_split_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx label)
{
- enum machine_mode cc_mode = visium_select_cc_mode (code, op0, op1);
+ machine_mode cc_mode = visium_select_cc_mode (code, op0, op1);
rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM);
rtx x = gen_rtx_COMPARE (cc_mode, op0, op1);
@@ -3091,7 +3091,7 @@ output_ubranch (rtx label, rtx_insn *insn)
should reverse the sense of the comparison. INSN is the instruction. */
const char *
-output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
+output_cbranch (rtx label, enum rtx_code code, machine_mode cc_mode,
int reversed, rtx_insn *insn)
{
const char *cond;
@@ -3299,7 +3299,7 @@ visium_print_operand (FILE *file, rtx op, int letter)
whose address is ADDR. */
static void
-visium_print_operand_address (FILE *file, enum machine_mode mode, rtx addr)
+visium_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
switch (GET_CODE (addr))
{
@@ -4180,7 +4180,7 @@ visium_can_use_return_insn_p (void)
static reg_class_t
visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
reg_class_t rclass,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
secondary_reload_info *sri ATTRIBUTE_UNUSED)
{
int regno = true_regnum (x);
diff --git a/gcc/config/vxworks.c b/gcc/config/vxworks.c
index 547176bb0a7..944cc1d239b 100644
--- a/gcc/config/vxworks.c
+++ b/gcc/config/vxworks.c
@@ -80,8 +80,10 @@ vxworks_emutls_var_fields (tree type, tree *name)
DECL_CHAIN (field) = next_field;
next_field = field;
+ /* The offset field is declared as an unsigned int with pointer mode. */
field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- get_identifier ("offset"), unsigned_type_node);
+ get_identifier ("offset"), long_unsigned_type_node);
+
DECL_CONTEXT (field) = type;
DECL_CHAIN (field) = next_field;
@@ -123,20 +125,24 @@ vxworks_emutls_var_init (tree var, tree decl, tree tmpl_addr)
void
vxworks_override_options (void)
{
- /* We don't support __thread via target hooks. */
- targetm.have_tls = false;
-
- targetm.emutls.get_address = "__builtin___tls_lookup";
- targetm.emutls.register_common = NULL;
- targetm.emutls.var_section = ".tls_vars";
- targetm.emutls.tmpl_section = ".tls_data";
- targetm.emutls.var_prefix = "__tls__";
- targetm.emutls.tmpl_prefix = "";
- targetm.emutls.var_fields = vxworks_emutls_var_fields;
- targetm.emutls.var_init = vxworks_emutls_var_init;
- targetm.emutls.var_align_fixed = true;
- targetm.emutls.debug_form_tls_address = true;
-
+ /* Setup the tls emulation bits if the OS misses proper
+ tls support. */
+ targetm.have_tls = VXWORKS_HAVE_TLS;
+
+ if (!VXWORKS_HAVE_TLS)
+ {
+ targetm.emutls.get_address = "__builtin___tls_lookup";
+ targetm.emutls.register_common = NULL;
+ targetm.emutls.var_section = ".tls_vars";
+ targetm.emutls.tmpl_section = ".tls_data";
+ targetm.emutls.var_prefix = "__tls__";
+ targetm.emutls.tmpl_prefix = "";
+ targetm.emutls.var_fields = vxworks_emutls_var_fields;
+ targetm.emutls.var_init = vxworks_emutls_var_init;
+ targetm.emutls.var_align_fixed = true;
+ targetm.emutls.debug_form_tls_address = true;
+ }
+
/* We can use .ctors/.dtors sections only in RTP mode. */
targetm.have_ctors_dtors = TARGET_VXWORKS_RTP;
diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h
index 8a18aff4d78..62149d45e21 100644
--- a/gcc/config/vxworks.h
+++ b/gcc/config/vxworks.h
@@ -23,6 +23,11 @@ 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
@@ -36,6 +41,23 @@ along with GCC; see the file COPYING3. If not see
/* Since we provide a default -isystem, expand -isystem on the command
line early. */
+#if TARGET_VXWORKS7
+
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC \
+ "%{!nostdinc: \
+ %{isystem*} \
+ %{mrtp: -idirafter %:getenv(VSB_DIR /h) \
+ -idirafter %:getenv(VSB_DIR /share/h) \
+ -idirafter %:getenv(VSB_DIR /usr/h/public) \
+ -idirafter %:getenv(VSB_DIR /usr/h) \
+ ;: -idirafter %:getenv(VSB_DIR /h) \
+ -idirafter %:getenv(VSB_DIR /share/h) \
+ -idirafter %:getenv(VSB_DIR /krnl/h/system) \
+ -idirafter %:getenv(VSB_DIR /krnl/h/public)}}"
+
+#else /* TARGET_VXWORKS7 */
+
#undef VXWORKS_ADDITIONAL_CPP_SPEC
#define VXWORKS_ADDITIONAL_CPP_SPEC \
"%{!nostdinc: \
@@ -43,14 +65,40 @@ along with GCC; see the file COPYING3. If not see
%{mrtp: %:getenv(WIND_USR /h) \
;: %:getenv(WIND_BASE /target/h)}}"
+#endif
+
/* The references to __init and __fini will be satisfied by
- libc_internal.a. */
+ libc_internal.a, and 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"
+
+/* 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. */
+
+/* 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)"
+#define TLS_SYM "-u __tls__"
+#else
+#define VXWORKS_LIBS_DIR_RTP ""
+#define TLS_SYM ""
+#endif
+
#undef VXWORKS_LIB_SPEC
#define VXWORKS_LIB_SPEC \
"%{mrtp:%{shared:-u " USER_LABEL_PREFIX "__init -u " USER_LABEL_PREFIX "__fini} \
%{!shared:%{non-static:-u " USER_LABEL_PREFIX "_STI__6__rtld -ldl} \
- --start-group -lc -lgcc -lc_internal -lnet -ldsi \
- --end-group}}"
+ " TLS_SYM " \
+ --start-group " VXWORKS_LIBS_RTP " --end-group} \
+ " VXWORKS_LIBS_DIR_RTP "}"
/* The no-op spec for "-shared" below is present because otherwise GCC
will treat it as an unrecognized option. */
@@ -84,6 +132,9 @@ along with GCC; see the file COPYING3. If not see
#define VXWORKS_ENDFILE_SPEC ""
/* Do VxWorks-specific parts of TARGET_OPTION_OVERRIDE. */
+
+#define VXWORKS_HAVE_TLS (TARGET_VXWORKS7 && TARGET_VXWORKS_RTP)
+
#undef VXWORKS_OVERRIDE_OPTIONS
#define VXWORKS_OVERRIDE_OPTIONS vxworks_override_options ()
extern void vxworks_override_options (void);
@@ -131,6 +182,19 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority);
builtin_define ("__RTP__"); \
else \
builtin_define ("_WRS_KERNEL"); \
+ builtin_define ("_VX_TOOL_FAMILY=gnu"); \
+ builtin_define ("_VX_TOOL=gnu"); \
+ if (TARGET_VXWORKS7) \
+ { \
+ builtin_define ("_VSB_CONFIG_FILE=<config/vsbConfig.h>"); \
+ \
+ /* _ALLOW_KEYWORD_MACROS is needed on VxWorks 7 to \
+ prevent compilation failures triggered by our \
+ definition of "inline" in ansidecl when "inline" \
+ is not a keyword. */ \
+ if (!flag_isoc99 && !c_dialect_cxx()) \
+ builtin_define ("_ALLOW_KEYWORD_MACROS"); \
+ } \
} \
while (0)
diff --git a/gcc/configure b/gcc/configure
index 317517c1ab0..9cee6700a08 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -11489,15 +11489,15 @@ fi
# --------------------------------------------------------
# Collect build-machine-specific information.
-. ${srcdir}/config.build
+. ${srcdir}/config.build || exit 1
# Collect host-machine-specific information.
-. ${srcdir}/config.host
+. ${srcdir}/config.host || exit 1
target_gtfiles=
# Collect target-machine-specific information.
-. ${srcdir}/config.gcc
+. ${srcdir}/config.gcc || exit 1
extra_objs="${host_extra_objs} ${extra_objs}"
extra_gcc_objs="${host_extra_gcc_objs} ${extra_gcc_objs}"
@@ -24820,6 +24820,42 @@ $as_echo "#define HAVE_AS_AVR_MRMW_OPTION 1" >>confdefs.h
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for __gcc_isr pseudo instruction" >&5
+$as_echo_n "checking assembler for __gcc_isr pseudo instruction... " >&6; }
+if test "${gcc_cv_as_avr_mgccisr+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_avr_mgccisr=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ __gcc_isr 1
+ __gcc_isr 2
+ __gcc_isr 0,r24
+ ' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mgcc-isr -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_avr_mgccisr=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_avr_mgccisr" >&5
+$as_echo "$gcc_cv_as_avr_mgccisr" >&6; }
+if test $gcc_cv_as_avr_mgccisr = yes; then
+
+$as_echo "#define HAVE_AS_AVR_MGCCISR_OPTION 1" >>confdefs.h
+
+fi
+
+
# Check how default linker description file implements .rodata for
# avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to
# RAM so avr-gcc skips __do_copy_data for .rodata objects.
@@ -24851,29 +24887,32 @@ EOF
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
- if test -f conftest.nm
+ if test -s conftest.nm
then
if grep ' R xxvaryy' conftest.nm > /dev/null; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- rm -f conftest.s conftest.o conftest.elf conftest.nm
+
+$as_echo "#define HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH 1" >>confdefs.h
+
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no: avrxmega3 .rodata located in RAM" >&5
$as_echo "no: avrxmega3 .rodata located in RAM" >&6; }
echo "$as_me: nm output was" >&5
cat conftest.nm >&5
- rm -f conftest.s conftest.o conftest.elf conftest.nm
avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
- as_fn_error "support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)" "$LINENO" 5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&5
+$as_echo "$as_me: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&2;}
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: test failed" >&5
$as_echo "test failed" >&6; }
echo "$as_me: failed program was" >&5
cat conftest.s >&5
- rm -f conftest.s conftest.o conftest.elf
- as_fn_error "see \`config.log' for details" "$LINENO" 5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: see \`config.log' for details" >&5
+$as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
fi
+ rm -f conftest.s conftest.o conftest.elf conftest.nm
;;
cris-*-*)
@@ -25280,6 +25319,43 @@ $as_echo "#define HAVE_AS_SPARC5_VIS4 1" >>confdefs.h
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for SPARC6 instructions" >&5
+$as_echo_n "checking assembler for SPARC6 instructions... " >&6; }
+if test "${gcc_cv_as_sparc_sparc6+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_sparc6=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ rd %entropy, %g1
+ fpsll64x %f0, %f2, %f4' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=sparc6 -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_sparc_sparc6=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_sparc_sparc6" >&5
+$as_echo "$gcc_cv_as_sparc_sparc6" >&6; }
+if test $gcc_cv_as_sparc_sparc6 = yes; then
+
+$as_echo "#define HAVE_AS_SPARC6 1" >>confdefs.h
+
+fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for LEON instructions" >&5
$as_echo_n "checking assembler for LEON instructions... " >&6; }
if test "${gcc_cv_as_sparc_leon+set}" = set; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index e1b03a9ac96..0c0e3597cda 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1442,15 +1442,15 @@ fi
# --------------------------------------------------------
# Collect build-machine-specific information.
-. ${srcdir}/config.build
+. ${srcdir}/config.build || exit 1
# Collect host-machine-specific information.
-. ${srcdir}/config.host
+. ${srcdir}/config.host || exit 1
target_gtfiles=
# Collect target-machine-specific information.
-. ${srcdir}/config.gcc
+. ${srcdir}/config.gcc || exit 1
extra_objs="${host_extra_objs} ${extra_objs}"
extra_gcc_objs="${host_extra_gcc_objs} ${extra_gcc_objs}"
@@ -3817,6 +3817,16 @@ AS_HELP_STRING([--disable-fix-cortex-a53-843419],
[AC_DEFINE(HAVE_AS_AVR_MRMW_OPTION, 1,
[Define if your avr assembler supports -mrmw option.])])
+ gcc_GAS_CHECK_FEATURE([__gcc_isr pseudo instruction],
+ gcc_cv_as_avr_mgccisr,,
+ [-mgcc-isr], [.text
+ __gcc_isr 1
+ __gcc_isr 2
+ __gcc_isr 0,r24
+ ],,
+ [AC_DEFINE(HAVE_AS_AVR_MGCCISR_OPTION, 1,
+ [Define if your avr assembler supports -mgcc-isr option.])])
+
# Check how default linker description file implements .rodata for
# avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to
# RAM so avr-gcc skips __do_copy_data for .rodata objects.
@@ -3832,26 +3842,26 @@ EOF
AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o])
AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf])
AC_TRY_COMMAND([$gcc_cv_nm conftest.elf > conftest.nm])
- if test -f conftest.nm
+ if test -s conftest.nm
then
if grep ' R xxvaryy' conftest.nm > /dev/null; then
AC_MSG_RESULT(yes)
- rm -f conftest.s conftest.o conftest.elf conftest.nm
+ AC_DEFINE(HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH, 1,
+ [Define if your default avr linker script for avrxmega3 leaves .rodata in flash.])
else
AC_MSG_RESULT(no: avrxmega3 .rodata located in RAM)
echo "$as_me: nm output was" >&AS_MESSAGE_LOG_FD
cat conftest.nm >&AS_MESSAGE_LOG_FD
- rm -f conftest.s conftest.o conftest.elf conftest.nm
avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
- AC_MSG_ERROR([[support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)]])
+ AC_MSG_WARN([[support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)]])
fi
else
AC_MSG_RESULT(test failed)
echo "$as_me: failed program was" >&AS_MESSAGE_LOG_FD
cat conftest.s >&AS_MESSAGE_LOG_FD
- rm -f conftest.s conftest.o conftest.elf
- AC_MSG_ERROR([[see `config.log' for details]])
+ AC_MSG_WARN([[see `config.log' for details]])
fi
+ rm -f conftest.s conftest.o conftest.elf conftest.nm
;;
cris-*-*)
@@ -4003,6 +4013,18 @@ foo:
[AC_DEFINE(HAVE_AS_SPARC5_VIS4, 1,
[Define if your assembler supports SPARC5 and VIS 4.0 instructions.])])
+ gcc_GAS_CHECK_FEATURE([SPARC6 instructions],
+ gcc_cv_as_sparc_sparc6,,
+ [-xarch=sparc6],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ rd %entropy, %g1
+ fpsll64x %f0, %f2, %f4],,
+ [AC_DEFINE(HAVE_AS_SPARC6, 1,
+ [Define if your assembler supports SPARC6 instructions.])])
+
gcc_GAS_CHECK_FEATURE([LEON instructions],
gcc_cv_as_sparc_leon,,
[-Aleon],
diff --git a/gcc/convert.c b/gcc/convert.c
index 429f988cbde..58d8054a724 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -938,7 +938,8 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
return build1 (CONVERT_EXPR, type, expr);
case REAL_TYPE:
- if (sanitize_flags_p (SANITIZE_FLOAT_CAST))
+ if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
+ && current_function_decl != NULL_TREE)
{
expr = save_expr (expr);
tree check = ubsan_instrument_float_cast (loc, type, expr);
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index b7c3704eff8..9ceb5391b3c 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -358,12 +358,17 @@ typedef void (*gt_pointer_operator) (void *, void *);
typedef unsigned char uchar;
#endif
-/* Most host source files will require the following headers. */
-#if !defined (GENERATOR_FILE) && !defined (USED_FOR_TARGET)
-#include "machmode.h"
+/* Most source files will require the following headers. */
+#if !defined (USED_FOR_TARGET)
+#include "insn-modes.h"
#include "signop.h"
#include "wide-int.h"
+#include "wide-int-print.h"
+#include "insn-modes-inline.h"
+#include "machmode.h"
#include "double-int.h"
+/* Most host source files will require the following headers. */
+#if !defined (GENERATOR_FILE)
#include "real.h"
#include "fixed-value.h"
#include "hash-table.h"
@@ -372,6 +377,7 @@ typedef unsigned char uchar;
#include "is-a.h"
#include "memory-block.h"
#include "dumpfile.h"
+#endif
#endif /* GENERATOR_FILE && !USED_FOR_TARGET */
#endif /* coretypes.h */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a06de8ba8c7..76d1de09c4d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,483 @@
+2017-07-31 Jan Hubicka <hubicka@ucw.cz>
+ Martin Liska <mliska@suse.cz>
+
+ * pt.c (tsubst_copy): Copy PREDICT_EXPR.
+ * semantics.c (finish_goto_stmt): Build gimple predict
+ stament.
+ * constexpr.c (potential_constant_expression_1): Handle
+ PREDICT_EXPR.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81530
+ * cp-gimplify.c (cp_genericize): Guard condition with flag_sanitize_p
+ also with current_function_decl non-null equality.
+ * cp-ubsan.c (cp_ubsan_instrument_vptr_p): Likewise.
+ * decl.c (compute_array_index_type): Likewise.
+ * init.c (finish_length_check): Likewise.
+ * typeck.c (cp_build_binary_op): Likewise.
+
+2017-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-objcp-common.c (cp_decl_dwarf_attribute): Handle
+ DW_AT_export_symbols.
+ * name-lookup.c (emit_debug_info_using_namespace): Add IMPLICIT
+ argument, pass it through to the debug hook.
+ (finish_namespace_using_directive): Adjust
+ emit_debug_info_using_namespace caller.
+ (push_namespace): Likewise. Call it after setting
+ DECL_NAMESPACE_INLINE_P.
+ (cp_emit_debug_info_for_using): Pass false as new argument to
+ the imported_module_or_decl debug hook.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * lex.c (copy_decl): Adjust.
+ (copy_type): Likewise.
+
+2017-07-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/71570
+ * lambda.c (add_capture): Early return if we cannot capture by
+ reference.
+
+2017-07-26 Jason Merrill <jason@redhat.com>
+
+ P0702R1 - List deduction of vector.
+ * pt.c (do_class_deduction): Special-case deduction from a single
+ element of related type.
+
+2017-07-26 Leonid Koppel <lkoppel@uwaterloo.ca>
+
+ PR c++/67054 - Inherited ctor with non-default-constructible members
+ * method.c (walk_field_subobs) Consider member initializers (NSDMIs)
+ when deducing an inheriting constructor.
+
+2017-07-21 Nathan Sidwell <nathan@acm.org>
+
+ * search.c (lookup_conversion_operator): Return overloads.
+ (lookup_fnfields_idx_nolazy): Absorb into ...
+ (lookup_fnfields_slot_nolaxy): ... here.
+ (lookup_fnfields_1): Absorb into ...
+ (lookup_fnfields_slot): ... here.
+
+ Remove special CDtor METHOD_VEC slots.
+ * cp-tree.h (CLASSTYPE_CONSTRUCTOR_SLOT,
+ CLASSTYPE_DESTRUCTOR_SLOT): Delete.
+ (CLASSTYPE_CONSTRUCTORS): Use lookup_fnfields_slot_nolazy.
+ (CLASSTYPE_DESTRUCTOR): Likewise.
+ * class (add_method): Don't use special cdtor slots.
+ * search.c (lookup_fnfields_idx_nolazy): Likewise.
+ (look_for_overrides_here): Use lookup_fnfields_slot.
+ * semantics (classtype_has_nothrow_assign_or_copy_p): Likewise.
+
+ * call.c (add_candidates): Move decls to initialization. Don't
+ use !!.
+
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ Remove TYPE_METHODS.
+ * class.c (maybe_warn_about_overly_private_class,
+ finish_struct_methods, one_inheriting_sig, count_fields,
+ add_fields_to_record_type, check_field_decls, check_methods,
+ clone_function_decl, set_method_tm_attributes,
+ finalize_literal_type_property, check_bases_and_members,
+ create_vtable_ptr, determine_key_method,
+ unreverse_member_declarations, finish_struct,
+ add_vcall_offset_vtbl_entries_1): Member fns are on TYPE_FIELDS.
+ * decl.c (fixup_anonymous_aggr): Likewise.
+ * decl2.c (reset_type_linkage_2): Likewise.
+ * method.c (after_nsdmi_defaulted_late_checks,
+ lazily_declare_fn): Likewise.
+ * optimize.c (maybe_thunk_body, maybe_clone_body): Likewise.
+ * pt.c (instantiate_class_template_1, tsubst_expr,
+ do_type_instantiation, instantiate_pending_templates): Likewise.
+ * search.c (lookup_field_1): Likewise.
+ * semantics.c (finish_member_declaration,
+ finish_omp_declare_simd_methods): Likewise.
+
+2017-07-19 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (add_implicitly_declared_members): Use
+ classtype_has_move_assign_or_move_ctor_p.
+ (classtype_has_move_assign_or_move_ctor,
+ classtype_has_user_move_assign_or_move_ctor_p): Merge into ...
+ (classtype_has_move_assign_or_move_ctor_p): ... this new function.
+ * cp-tree.h (classtype_has_user_move_assign_or_move_ctor_p):
+ Replace with ...
+ (classtype_has_move_assign_or_move_ctor_p): ... this.
+ * method.c (maybe_explain_implicit_delete, lazily_declare_fn): Adjust.
+ * tree.c (type_has_nontrivial_copy_init): Adjust.
+
+ * cp-tree.h (PACK_EXPANSION_PARAMETER_PACKS,
+ PACK_EXPANSION_EXTRA_ARGS): Use TYPE_{MIN,MAX}_VALUE_RAW.
+
+2017-07-18 Nathan Sidwell <nathan@acm.org>
+
+ * cp-array-notation.c (build_array_notation_ref): Use
+ TYPE_{MIN,MAX}_VALUE.
+
+ * class.c (classtype_has_move_assign_or_move_ctor): Declare.
+ (add_implicitly_declared_members): Use it.
+ (type_has_move_constructor, type_has_move_assign): Merge into ...
+ (classtype_has_move_assign_or_move_ctor): ... this new function.
+ * cp-tree.h (type_has_move_constructor, type_has_move_assign): Delete.
+
+2017-07-17 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * parser.c (cp_parser_decl_specifier_seq): Add fix-it hints for
+ friend outside class and obsolete auto as storage-class-specifier.
+
+2017-07-17 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (maybe_warn_about_overly_private_class): Ignore public
+ copy ctors.
+
+ * class.c (type_has_user_declared_move_constructor,
+ type_has_user_declared_move_assign): Combine into ...
+ (classtype_has_user_move_assign_or_move_ctor_p): ... this new function.
+ * cp-tree.h (type_has_user_declared_move_constructor,
+ type_has_user_declared_move_assign): Combine into ...
+ (classtype_has_user_move_assign_or_move_ctor_p): ... this. Declare.
+ * method.c (maybe_explain_implicit_delete): Use it.
+ (lazily_declare_fn): Use it.
+ * tree.c (type_has_nontrivial_copy_init): Use it.
+
+ * semantics.c (classtype_has_nothrow_assign_or_copy_p): Clarify
+ semantics, simplify implementation.
+
+2017-07-16 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * parser.c (cp_parser_cast_expression): Use %q#T instead of %qT
+ in old-style cast diagnostic.
+ * typeck.c (maybe_warn_about_useless_cast): Use %q#T instead of %qT
+ in useless cast diagnostic.
+ * error.c (type_to_string): Remove enum special handling.
+
+2017-07-14 David Malcolm <dmalcolm@redhat.com>
+
+ * name-lookup.c (get_std_name_hint): Add '<' and '>' around
+ the header names.
+ (maybe_suggest_missing_header): Update for addition of '<' and '>'
+ to above. Provide a fix-it hint.
+ * pt.c: Include "gcc-rich-location.h"
+ (listify): Attempt to add fix-it hint for missing
+ #include <initializer_list>.
+ * rtti.c: Include "gcc-rich-location.h".
+ (typeid_ok_p): Attempt to add fix-it hint for missing
+ #include <typeinfo>.
+
+2017-07-12 Jason Merrill <jason@redhat.com>
+
+ P0512R0 - Deduction from an initializer list.
+ * pt.c (do_class_deduction): Do list deduction in two phases.
+
+2017-07-12 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_CONSTRUCTOR_P, DECL_MAYBE_IN_CHARGE_CONSTRUCTOR,
+ DECL_DESTRUCTOR_P, DECL_MAYBE_IN_CHARGE_DESTRCTOR): Look at
+ identifier flags.
+ * decl.c (grokfndecl): Set DECL_CXX_CONSTRUCTOR and
+ DECL_CXX_DESTRUCTOR explicitly.
+ * decl2.c (grokclassfn): Likewise.
+ * friend.c (do_friend): Likewise.
+ * method.c (make_thunk, make_alias_for,
+ implicitly_declare_fn): Likewise.
+
+2017-07-11 Jason Merrill <jason@redhat.com>
+
+ Core DR 393
+ * decl.c (grokparms): Downgrade error about array of unknown bound
+ to pedwarn and disable it for C++17.
+
+2017-07-11 Nathan Sidwell <nathan@acm.org>
+
+ * decl2.c (reset_type_linkage_2): Dont't change ctor name.
+
+2017-07-10 Martin Sebor <msebor@redhat.com>
+
+ * cp-tree.h (cp_operator_id, cp_assignment_operator_id): Document.
+
+2017-07-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/81204 - parse error with dependent template-name
+ * parser.c (cp_parser_lookup_name): Revert previous change.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_RUN_LANG_SELFTESTS): Define as
+ selftest::run_cp_tests.
+ (selftest::run_cp_tests): New function.
+ * cp-tree.h (selftest::run_cp_tests): New decl.
+
+2017-07-04 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_decomposition_declaration): Replace
+ decomposition declaration with structured binding in diagnostics.
+ * decl.c (cp_finish_decomp): Likewise.
+ (grokdeclarator): Likewise.
+
+ PR c++/81258
+ * parser.c (cp_parser_decomposition_declaration): Diagnose invalid
+ forms of structured binding initializers.
+
+2017-07-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/65775
+ * decl.c (grokdeclarator): Move checks on function return type after
+ the splice_late_return_type call; if declspecs->locations[ds_type_spec]
+ is UNKNOWN_LOCATION fall back to input_location.
+
+2017-07-03 David Malcolm <dmalcolm@redhat.com>
+
+ * parser.c (enum required_token): Fix spelling of
+ RT_INTERATION to RT_ITERATION.
+ (cp_parser_iteration_statement): Likewise.
+ (cp_parser_required_error): Likewise.
+
+2017-06-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/81257 - ICE with invalid ::template.
+ PR c++/54769 - wrong lookup of dependent template-name.
+ * parser.c (cp_parser_template_name): Revert part of last change.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * config-lang.in (gtfiles): Add cp/lex.c.
+ * cp-tree.h (mangle_convop_name_for_type): Rename ...
+ (make_conv_op_name): ... here. Move to lex.
+ * lambda.c (maybe_add_lambda_conv_op): Update.
+ * parser.c (cp_parser_conversion_function_id): Update.
+ * pt.c (tsubst_decl, tsubst_baselink, tsubst_copy,
+ tsubst_copy_and_build): Update.
+ * semantics.c (apply_deduced_return_type): Update.
+ * mangle.c (conv_type_hasher, conv_type_names,
+ mangle_conv_op_name_for_type): Move to ...
+ * lex.c (conv_type_hasher, conv_type_names, make_convop_name):
+ ... here. Rename.
+
+2017-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/80014
+ * parser.c (cp_parser_postfix_expression): Construct a location
+ for typeid expressions.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (lookup_fnfields_1, class_method_index_for_fn): Don't
+ declare.
+ (lookup_all_conversions): Declare.
+ * class.c (get_basefndecls): Use lookup_fnfields_slot.
+ * decl.c (register_dtor_fn): Use lookup_fnfields_slot.
+ * decl2.c (check_class_fn): Use lookup_fnfields_slot. Rework
+ diagnostics.
+ * pt.c (retrieve_specialization): Use lookup_fnfields_slot.
+ (check_explicit_specialization): Use lookup_fnfields_slot_nolazy,
+ lookup_all_conversions.
+ * search.c (lookup_fnfields_1): Make static.
+ (lookup_all_conversions): New.
+ (class_method_index_for_fn): Delete.
+ * semantics.c (classtype_has_nothrow_assign_or_copy_p): Use
+ lookup_fnfields_slot.
+
+ * call.c (build_new_method_call_1): Use constructo_name to get
+ ctor name. Move argument processing earlier to merge cdtor
+ handling blocks.
+ * decl.c (grokfndecl): Cdtors have special names.
+ * method.c (implicitly_declare_fn): Likewise. Simplify flag setting.
+ * pt.c (check_explicit_specialization): Cdtor name is already
+ special.
+ * search.c (class_method_index_for_fn): Likewise.
+
+ PR c++/81229
+ * name-lookup.c (do_pushdecl): Reset IDENTIFIER_TYPE when finding
+ a matching TYPE_DECL.
+
+2017-06-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * class.c (add_method): Change pair of errors to error + inform.
+ (handle_using_decl): Likewise.
+
+2017-06-29 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c, error.c, tree.c: Remove WITH_CLEANUP_EXPR handling.
+
+ PR c++/81180 - ICE with C++17 deduction of member class template.
+ * pt.c (build_deduction_guide): Correct member template handling.
+
+ PR c++/81188 - matching decltype of member function call.
+ * tree.c (cp_tree_equal): Remove COMPONENT_REF special case.
+
+2017-06-29 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/81247
+ * parser.c (cp_parser_namespace_definition): Immediately close the
+ namespace if there's no open-brace.
+ * name-lookup.c (do_pushdecl): Reset OLD when pushing into new
+ namespace.
+
+2017-06-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/81164 - ICE with invalid inherited constructor.
+ * search.c (binfo_direct_p): New.
+ * name-lookup.c (do_class_using_decl): Use it.
+
+2017-06-29 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (THIS_NAME, IN_CHARGE_NAME, VTBL_PTR_TYPE,
+ VTABLE_DELTA_NAME, VTABLE_PFN_NAME): Delete.
+ * decl.c (initialize_predefined_identifiers): Name cdtor special
+ names consistently. Use literals for above deleted defines.
+ (cxx_init_decl_processing): Use literal for vtbl_ptr_type name,
+
+ * lex.c (maybe_add_lang_type_raw): Exit early, rather than use a
+ flag.
+
+ * call.c (check_dtor_name): Use constructor_name for enums too.
+ (build_new_method_call_1): Use constructor_name for cdtors and
+ show ~ for dtor.
+ * class.c (build_self_reference): Use TYPE_NAME to get name of
+ self reference.
+ * name-lookup (constructor_name): Use DECL_NAME directly.
+ (constructor_name_p): Reimplement.
+ (push_class_level_binding_1): Use TYPE_NAME directly.
+
+ * class.c (finish_struct): Use OVL_P.
+ (get_vfield_name): Measure constructor_name length.
+ * cp-tree.h (SET_CLASS_TYPE_P): Add RECORD_OR_UNION_CHECK.
+ (NON_UNION_CLASS_TYPE_P): Check RECORD_TYPE up front.
+ * cxx-pretty-print.c (is_destructor_name): Delete.
+ (pp_cxx_unqualified_id): Remove bogus destructor name checking.
+ * decl.c (grokfndecl): Move cheap checks first when looking for
+ implicit extern cness.
+
+ * parser.c (cp_parser_direct_declarator): Reorder if to avoid
+ indentation. Remove unnecessary assignment of constructor name.
+
+ Whitespace cleanups.
+ * call.c (name_as_c_string): Move CONST_CAST to return.
+ (build_new_method_call_1): Remove unneeded bracing.
+ * class.c (include_empty_classes): Unbreak line.
+ * constraint.cc (tsubst_check_constraint): Add space.
+ * cp-tree.h (lang_decl_ns): Add comment.
+ (PTRMEM_CST_MEMBER): Break line.
+ * decl.c (grokfndecl): Add blank lines. Unbreak some others.
+ (grokdeclarator): Remove lines, move declaration to first use.
+ * decl2.c (decl_needed_p): Fix indentation.
+ (c_parse_final_cleanups): Remove blank line.
+ * method.c (implicitly_declare_fn): Move declaration to first use.
+ * search.c (current_scope): Add blank lines.
+
+2017-06-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/72764 - ICE with invalid template typename.
+ * decl.c (build_typename_type): No longer static.
+ * tree.c (strip_typedefs): Use it instead of make_typename_type.
+
+ PR c++/69300 - ICE with self-referential noexcept
+ * pt.c (maybe_instantiate_noexcept): Check for recursion.
+
+ PR c++/61022 - error with variadic template template parm
+ * pt.c (convert_template_argument): Keep the TYPE_PACK_EXPANSION.
+
+ PR c++/72801 - ICE with variadic partial specialization
+ * pt.c (unify_pack_expansion): Use PACK_EXPANSION_EXTRA_ARGS.
+
+ PR c++/55639 - partial specialization with ::template
+ * parser.c (cp_parser_class_head): Handle ::template.
+
+ PR c++/45976 - error with ::template in declarator.
+ * pt.c (resolve_typename_type): Fix TEMPLATE_ID_EXPR handling.
+
+ PR c++/54769 - wrong lookup of dependent template-name.
+ * parser.c (cp_parser_template_name): Handle dependent object type.
+ (cp_parser_nested_name_specifier_opt): Make template_keyword_p a
+ parameter.
+ (cp_parser_id_expression): Pass it.
+ (cp_parser_diagnose_invalid_type_name): Handle TEMPLATE_ID_EXPR.
+
+ * parser.c (cp_parser_template_id): Use the range location on the
+ TEMPLATE_ID_EXPR.
+
+ PR c++/81204 - parse error with dependent template-name
+ * parser.c (cp_parser_lookup_name): Disqualify function templates
+ after lookup.
+
+2017-06-27 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (tsubst_decl <FUNCTION_DECL>): Move var decls to
+ initialization point. Don't unnecessarily check for ctor name.
+
+ * cp-tree.h (CLASSTYPE_DESTRUCTORS): Rename to ...
+ (CLASSTYPE_DESTRUCTOR): ... this.
+ * class.c (accessible_nvdtor_p,
+ maybe_warn_about_overly_private_class,
+ add_implicitly_declared_members,
+ clone_constructors_and_destructors, type_has_virtual_destructor):
+ Adjust for CLASSTYPE_DESTRUCTOR.
+ (deduce_noexcept_on_destructors): Absorb into ...
+ (check_bases_and_members): ... here.
+ * except.c (dtor_nothrow): Adjust for CLASSTYPE_DESTRUCTOR.
+ * init.c (build_delete): Likewise.
+ * parser.c (cp_parser_lookup_name): Likewise.
+ * pt.c (check_explicit_specialization): Likewise.
+ * rtti.c (emit_support_tinfos): Likewise.
+ * search.c (lookup_fnfields_idx_nolazy): Likewise.
+
+ Kill IDENTIFIER_TEMPLATE.
+ * cp-tree.h (lang_identifier): Remove class_template_info field.
+ (IDENTIFIER_TEMPLATE): Delete.
+ * name-lookup.c (constructor_name_full): Subsume into ...
+ (constructor_name): ... here. Don't check IDENTIFIER_TEMPLATE.
+ (constructor_name_p): Likewise.
+ * mangle.c (write_source_name): Likewise.
+ * ptree.c (cxx_print_identifier): Likewise.
+
+2017-06-27 Marek Polacek <polacek@redhat.com>
+
+ PR bootstrap/81216
+ * parser.c (cp_parser_already_scoped_statement): Initialize
+ LOC_AFTER_LABELS.
+
+2017-06-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/81215 - deduction failure with variadic TTP.
+ * pt.c (unify_bound_ttp_args): Restore old logic for C++14 and down.
+
+2017-06-26 Martin Sebor <msebor@redhat.com>
+
+ PR c++/81169
+ * call.c (maybe_warn_class_memaccess): Preserve explicit conversions
+ to detect casting away cv-qualifiers.
+
+2017-06-26 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (lang_decl_fn): Remove assignment_operator_p field.
+ (DECL_COMPLETE_CONSTRUCTOR_P): Directly compare
+ identifier.
+ (DECL_BASE_CONSTRUCTOR_P, DECL_COMPLETE_DESTRUCTOR_P,
+ DECL_BASE_DESTRUCTOR_P, DECL_DELETING_DESTRUCTOR_P): Likewise.
+ (DECL_ASSIGNMENT_OPERATOR_P): Use IDENTIFIER_ASSIGN_OP_P.
+ * decl.c (grok_op_properties): Adjust identifier checking.
+ * init.c (expand_default_init): Adjust identifier descision.
+ * method.c (implicitly_declare_fn): Don't use
+ DECL_ASSIGNMENT_OPERATOR_P.
+ * search.c (lookup_fnfields_1): Use IDENTIFIER_CTOR_P,
+ IDENTIFIER_DTOR_P.
+ * call.c (in_charge_arg_for_name): Reimplement.
+ (build_special_member_call): Use IDENTIFIER_CDTOR_P,
+ IDENTIFIER_DTOR_P.
+
+2017-06-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/80116
+ * parser.c (cp_parser_statement): Add a default argument. Save the
+ location of the expression-statement after labels have been parsed.
+ (cp_parser_implicitly_scoped_statement): Set the location of the
+ body of the conditional after parsing all the labels. Call
+ warn_for_multistatement_macros.
+ (cp_parser_already_scoped_statement): Likewise.
+
2017-06-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/62315
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 2fc29da1c7a..e74d48daa8b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -231,9 +231,8 @@ check_dtor_name (tree basetype, tree name)
else if (identifier_p (name))
{
if ((MAYBE_CLASS_TYPE_P (basetype)
- && name == constructor_name (basetype))
- || (TREE_CODE (basetype) == ENUMERAL_TYPE
- && name == TYPE_IDENTIFIER (basetype)))
+ || TREE_CODE (basetype) == ENUMERAL_TYPE)
+ && name == constructor_name (basetype))
return true;
else
name = get_type_value (name);
@@ -5424,8 +5423,8 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
{
tree ctype;
const vec<tree, va_gc> *non_static_args;
- bool check_list_ctor;
- bool check_converting;
+ bool check_list_ctor = false;
+ bool check_converting = false;
unification_kind_t strict;
if (!fns)
@@ -5436,7 +5435,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
if (DECL_CONV_FN_P (fn))
{
check_list_ctor = false;
- check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ check_converting = (flags & LOOKUP_ONLYCONVERTING) != 0;
if (flags & LOOKUP_NO_CONVERSION)
/* We're doing return_type(x). */
strict = DEDUCE_CONV;
@@ -5453,18 +5452,13 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
{
if (DECL_CONSTRUCTOR_P (fn))
{
- check_list_ctor = !!(flags & LOOKUP_LIST_ONLY);
+ check_list_ctor = (flags & LOOKUP_LIST_ONLY) != 0;
/* For list-initialization we consider explicit constructors
and complain if one is chosen. */
check_converting
= ((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR))
== LOOKUP_ONLYCONVERTING);
}
- else
- {
- check_list_ctor = false;
- check_converting = false;
- }
strict = DEDUCE_CALL;
ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
}
@@ -5477,9 +5471,6 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
for (lkp_iterator iter (fns); iter; ++iter)
{
- tree fn_first_arg;
- const vec<tree, va_gc> *fn_args;
-
fn = *iter;
if (check_converting && DECL_NONCONVERTING_P (fn))
@@ -5487,10 +5478,13 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
if (check_list_ctor && !is_list_ctor (fn))
continue;
- /* Figure out which set of arguments to use. */
+ tree fn_first_arg = NULL_TREE;
+ const vec<tree, va_gc> *fn_args = args;
+
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{
- /* If this function is a non-static member and we didn't get an
+ /* Figure out where the object arg comes from. If this
+ function is a non-static member and we didn't get an
implicit object argument, move it out of args. */
if (first_arg == NULL_TREE)
{
@@ -5507,12 +5501,6 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
fn_first_arg = first_arg;
fn_args = non_static_args;
}
- else
- {
- /* Otherwise, just use the list of arguments provided. */
- fn_first_arg = NULL_TREE;
- fn_args = args;
- }
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (candidates,
@@ -8340,7 +8328,10 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
if (!dest || !TREE_TYPE (dest) || !POINTER_TYPE_P (TREE_TYPE (dest)))
return;
- STRIP_NOPS (dest);
+ /* Remove the outermost (usually implicit) conversion to the void*
+ argument type. */
+ if (TREE_CODE (dest) == NOP_EXPR)
+ dest = TREE_OPERAND (dest, 0);
tree srctype = NULL_TREE;
@@ -8357,7 +8348,7 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
if (current_function_decl
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl))
- && is_this_parameter (dest))
+ && is_this_parameter (tree_strip_nop_conversions (dest)))
{
tree ctx = DECL_CONTEXT (current_function_decl);
bool special = same_type_ignoring_top_level_qualifiers_p (ctx, desttype);
@@ -8677,20 +8668,22 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
tree
in_charge_arg_for_name (tree name)
{
- if (name == base_ctor_identifier
- || name == base_dtor_identifier)
- return integer_zero_node;
- else if (name == complete_ctor_identifier)
- return integer_one_node;
- else if (name == complete_dtor_identifier)
- return integer_two_node;
- else if (name == deleting_dtor_identifier)
- return integer_three_node;
-
- /* This function should only be called with one of the names listed
- above. */
- gcc_unreachable ();
- return NULL_TREE;
+ if (IDENTIFIER_CTOR_P (name))
+ {
+ if (name == complete_ctor_identifier)
+ return integer_one_node;
+ gcc_checking_assert (name == base_ctor_identifier);
+ }
+ else
+ {
+ if (name == complete_dtor_identifier)
+ return integer_two_node;
+ else if (name == deleting_dtor_identifier)
+ return integer_three_node;
+ gcc_checking_assert (name == base_dtor_identifier);
+ }
+
+ return integer_zero_node;
}
/* We've built up a constructor call RET. Complain if it delegates to the
@@ -8729,11 +8722,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
vec<tree, va_gc> *allocated = NULL;
tree ret;
- gcc_assert (name == complete_ctor_identifier
- || name == base_ctor_identifier
- || name == complete_dtor_identifier
- || name == base_dtor_identifier
- || name == deleting_dtor_identifier
+ gcc_assert (IDENTIFIER_CDTOR_P (name)
|| name == cp_assignment_operator_id (NOP_EXPR));
if (TYPE_P (binfo))
{
@@ -8753,9 +8742,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
instance = build_dummy_object (class_type);
else
{
- if (name == complete_dtor_identifier
- || name == base_dtor_identifier
- || name == deleting_dtor_identifier)
+ if (IDENTIFIER_DTOR_P (name))
gcc_assert (args == NULL || vec_safe_is_empty (*args));
/* Convert to the base class, if necessary. */
@@ -8879,7 +8866,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
static char *
name_as_c_string (tree name, tree type, bool *free_p)
{
- char *pretty_name;
+ const char *pretty_name;
/* Assume that we will not allocate memory. */
*free_p = false;
@@ -8887,7 +8874,7 @@ name_as_c_string (tree name, tree type, bool *free_p)
if (IDENTIFIER_CDTOR_P (name))
{
pretty_name
- = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type))));
+ = identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type)));
/* For a destructor, add the '~'. */
if (IDENTIFIER_DTOR_P (name))
{
@@ -8906,9 +8893,9 @@ name_as_c_string (tree name, tree type, bool *free_p)
*free_p = true;
}
else
- pretty_name = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (name)));
+ pretty_name = identifier_to_locale (IDENTIFIER_POINTER (name));
- return pretty_name;
+ return CONST_CAST (char *, pretty_name);
}
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
@@ -8996,6 +8983,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (! (complain & tf_error))
return error_mark_node;
+ name = constructor_name (basetype);
if (permerror (input_location,
"cannot call constructor %<%T::%D%> directly",
basetype, name))
@@ -9006,6 +8994,19 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
return call;
}
+ /* Process the argument list. */
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args, complain);
+ if (*args == NULL)
+ return error_mark_node;
+ }
+
+ /* Consider the object argument to be used even if we end up selecting a
+ static member function. */
+ instance = mark_type_use (instance);
+
+
/* Figure out whether to skip the first argument for the error
message we will display to users if an error occurs. We don't
want to display any compiler-generated arguments. The "this"
@@ -9015,35 +9016,18 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
skip_first_for_error = false;
if (IDENTIFIER_CDTOR_P (name))
{
- /* Callers should explicitly indicate whether they want to construct
+ /* Callers should explicitly indicate whether they want to ctor
the complete object or just the part without virtual bases. */
gcc_assert (name != ctor_identifier);
- /* Similarly for destructors. */
- gcc_assert (name != dtor_identifier);
+
/* Remove the VTT pointer, if present. */
if ((name == base_ctor_identifier || name == base_dtor_identifier)
&& CLASSTYPE_VBASECLASSES (basetype))
skip_first_for_error = true;
- }
- /* Process the argument list. */
- if (args != NULL && *args != NULL)
- {
- *args = resolve_args (*args, complain);
- if (*args == NULL)
- return error_mark_node;
- }
-
- /* Consider the object argument to be used even if we end up selecting a
- static member function. */
- instance = mark_type_use (instance);
-
- /* It's OK to call destructors and constructors on cv-qualified objects.
- Therefore, convert the INSTANCE to the unqualified type, if
- necessary. */
- if (DECL_DESTRUCTOR_P (fn)
- || DECL_CONSTRUCTOR_P (fn))
- {
+ /* It's OK to call destructors and constructors on cv-qualified
+ objects. Therefore, convert the INSTANCE to the unqualified
+ type, if necessary. */
if (!same_type_p (basetype, TREE_TYPE (instance)))
{
instance = build_this (instance);
@@ -9051,8 +9035,8 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
instance = build_fold_indirect_ref (instance);
}
}
- if (DECL_DESTRUCTOR_P (fn))
- name = complete_dtor_identifier;
+ else
+ gcc_assert (!DECL_DESTRUCTOR_P (fn) && !DECL_CONSTRUCTOR_P (fn));
/* For the overload resolution we need to find the actual `this`
that would be captured if the call turns out to be to a
@@ -9119,11 +9103,10 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
&candidates, complain);
}
else
- {
- add_candidates (fns, first_mem_arg, user_args, optype,
- explicit_targs, template_only, conversion_path,
- access_binfo, flags, &candidates, complain);
- }
+ add_candidates (fns, first_mem_arg, user_args, optype,
+ explicit_targs, template_only, conversion_path,
+ access_binfo, flags, &candidates, complain);
+
any_viable_p = false;
candidates = splice_viable (candidates, false, &any_viable_p);
@@ -9141,17 +9124,18 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
{
tree arglist = build_tree_list_vec (user_args);
tree errname = name;
+ bool twiddle = false;
if (IDENTIFIER_CDTOR_P (errname))
{
- tree fn = DECL_ORIGIN (OVL_FIRST (fns));
- errname = DECL_NAME (fn);
+ 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::%E(%A)%#V%>",
- basetype, errname, 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);
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1243f33605f..508570bdb04 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1039,50 +1039,39 @@ add_method (tree type, tree method, bool via_using)
we're going to end up with an assignment operator at some
point as well. */
vec_alloc (method_vec, 8);
- /* Create slots for constructors and destructors. */
- method_vec->quick_push (NULL_TREE);
- method_vec->quick_push (NULL_TREE);
CLASSTYPE_METHOD_VEC (type) = method_vec;
}
/* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
grok_special_member_properties (method);
- /* Constructors and destructors go in special slots. */
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
- slot = CLASSTYPE_CONSTRUCTOR_SLOT;
- else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
- slot = CLASSTYPE_DESTRUCTOR_SLOT;
- else
- {
- tree m;
+ tree m;
- insert_p = true;
- /* See if we already have an entry with this name. */
- for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
- vec_safe_iterate (method_vec, slot, &m);
- ++slot)
+ insert_p = true;
+ /* See if we already have an entry with this name. */
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ vec_safe_iterate (method_vec, slot, &m);
+ ++slot)
+ {
+ m = OVL_FIRST (m);
+ if (template_conv_p)
{
- m = OVL_FIRST (m);
- if (template_conv_p)
- {
- if (TREE_CODE (m) == TEMPLATE_DECL
- && DECL_TEMPLATE_CONV_FN_P (m))
- insert_p = false;
- break;
- }
- if (conv_p && !DECL_CONV_FN_P (m))
- break;
- if (DECL_NAME (m) == DECL_NAME (method))
- {
- insert_p = false;
- break;
- }
- if (complete_p
- && !DECL_CONV_FN_P (m)
- && DECL_NAME (m) > DECL_NAME (method))
- break;
+ if (TREE_CODE (m) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (m))
+ insert_p = false;
+ break;
}
+ if (conv_p && !DECL_CONV_FN_P (m))
+ break;
+ if (DECL_NAME (m) == DECL_NAME (method))
+ {
+ insert_p = false;
+ break;
+ }
+ if (complete_p
+ && !DECL_CONV_FN_P (m)
+ && DECL_NAME (m) > DECL_NAME (method))
+ break;
}
current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
@@ -1217,10 +1206,11 @@ add_method (tree type, tree method, bool via_using)
continue;
}
error_at (DECL_SOURCE_LOCATION (method),
- "%q#D", method);
- error_at (DECL_SOURCE_LOCATION (fn),
- "conflicts with version inherited from %qT",
- basef);
+ "%q#D conflicts with version inherited from %qT",
+ method, basef);
+ inform (DECL_SOURCE_LOCATION (fn),
+ "version inherited from %qT declared here",
+ basef);
}
/* Otherwise defer to the other function. */
return false;
@@ -1238,8 +1228,10 @@ add_method (tree type, tree method, bool via_using)
}
else
{
- error ("%q+#D cannot be overloaded", method);
- error ("with %q+#D", fn);
+ error_at (DECL_SOURCE_LOCATION (method),
+ "%q#D cannot be overloaded with %q#D", method, fn);
+ inform (DECL_SOURCE_LOCATION (fn),
+ "previous declaration %q#D", fn);
return false;
}
}
@@ -1253,7 +1245,7 @@ add_method (tree type, tree method, bool via_using)
if (conv_p)
TYPE_HAS_CONVERSION (type) = 1;
- else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+ else if (!complete_p && !IDENTIFIER_CDTOR_P (DECL_NAME (method)))
push_class_level_binding (DECL_NAME (method), current_fns);
if (insert_p)
@@ -1371,16 +1363,21 @@ handle_using_decl (tree using_decl, tree t)
the same name already present in the current class. */;
else
{
- error ("%q+D invalid in %q#T", using_decl, t);
- error (" because of local method %q+#D with same name",
- old_value);
+ error_at (DECL_SOURCE_LOCATION (using_decl), "%qD invalid in %q#T "
+ "because of local method %q#D with same name",
+ using_decl, t, old_value);
+ inform (DECL_SOURCE_LOCATION (old_value),
+ "local method %q#D declared here", old_value);
return;
}
}
else if (!DECL_ARTIFICIAL (old_value))
{
- error ("%q+D invalid in %q#T", using_decl, t);
- error (" because of local member %q+#D with same name", old_value);
+ error_at (DECL_SOURCE_LOCATION (using_decl), "%qD invalid in %q#T "
+ "because of local member %q#D with same name",
+ using_decl, t, old_value);
+ inform (DECL_SOURCE_LOCATION (old_value),
+ "local member %q#D declared here", old_value);
return;
}
@@ -1711,7 +1708,7 @@ inherit_targ_abi_tags (tree t)
static bool
accessible_nvdtor_p (tree t)
{
- tree dtor = CLASSTYPE_DESTRUCTORS (t);
+ tree dtor = CLASSTYPE_DESTRUCTOR (t);
/* An implicitly declared destructor is always public. And,
if it were virtual, we would have created it by now. */
@@ -2141,7 +2138,6 @@ maybe_warn_about_overly_private_class (tree t)
{
int has_member_fn = 0;
int has_nonprivate_method = 0;
- tree fn;
if (!warn_ctor_dtor_privacy
/* If the class has friends, those entities might create and
@@ -2171,26 +2167,26 @@ maybe_warn_about_overly_private_class (tree t)
functions are private. (Since there are no friends or
non-private statics, we can't ever call any of the private member
functions.) */
- for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
- /* We're not interested in compiler-generated methods; they don't
- provide any way to call private members. */
- if (!DECL_ARTIFICIAL (fn))
+ for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
+ if (!DECL_DECLARES_FUNCTION_P (fn))
+ /* Not a function. */;
+ else if (DECL_ARTIFICIAL (fn))
+ /* We're not interested in compiler-generated methods; they don't
+ provide any way to call private members. */;
+ else if (!TREE_PRIVATE (fn))
{
- if (!TREE_PRIVATE (fn))
- {
- if (DECL_STATIC_FUNCTION_P (fn))
- /* A non-private static member function is just like a
- friend; it can create and invoke private member
- functions, and be accessed without a class
- instance. */
- return;
+ if (DECL_STATIC_FUNCTION_P (fn))
+ /* A non-private static member function is just like a
+ friend; it can create and invoke private member
+ functions, and be accessed without a class
+ instance. */
+ return;
- has_nonprivate_method = 1;
- /* Keep searching for a static member function. */
- }
- else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
- has_member_fn = 1;
+ has_nonprivate_method = 1;
+ /* Keep searching for a static member function. */
}
+ else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
+ has_member_fn = 1;
if (!has_nonprivate_method && has_member_fn)
{
@@ -2220,22 +2216,22 @@ maybe_warn_about_overly_private_class (tree t)
/* Even if some of the member functions are non-private, the class
won't be useful for much if all the constructors or destructors
are private: such an object can never be created or destroyed. */
- fn = CLASSTYPE_DESTRUCTORS (t);
- if (fn && TREE_PRIVATE (fn))
- {
- warning (OPT_Wctor_dtor_privacy,
- "%q#T only defines a private destructor and has no friends",
- t);
- return;
- }
+ if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
+ if (TREE_PRIVATE (dtor))
+ {
+ warning (OPT_Wctor_dtor_privacy,
+ "%q#T only defines a private destructor and has no friends",
+ t);
+ return;
+ }
/* Warn about classes that have private constructors and no friends. */
if (TYPE_HAS_USER_CONSTRUCTOR (t)
/* Implicitly generated constructors are always public. */
- && (!CLASSTYPE_LAZY_DEFAULT_CTOR (t)
- || !CLASSTYPE_LAZY_COPY_CTOR (t)))
+ && !CLASSTYPE_LAZY_DEFAULT_CTOR (t))
{
bool nonprivate_ctor = false;
+ tree copy_or_move = NULL_TREE;
/* If a non-template class does not define a copy
constructor, one is defined for it, enabling it to avoid
@@ -2252,13 +2248,15 @@ maybe_warn_about_overly_private_class (tree t)
else
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t));
!nonprivate_ctor && iter; ++iter)
- /* Ideally, we wouldn't count copy constructors (or, in
- fact, any constructor that takes an argument of the class
- type as a parameter) because such things cannot be used
- to construct an instance of the class unless you already
- have one. But, for now at least, we're more
- generous. */
- if (! TREE_PRIVATE (*iter))
+ if (TREE_PRIVATE (*iter))
+ continue;
+ else if (copy_fn_p (*iter) || move_fn_p (*iter))
+ /* Ideally, we wouldn't count any constructor that takes
+ an argument of the class type as a parameter, because
+ such things cannot be used to construct an instance of
+ the class unless you already have one. */
+ copy_or_move = *iter;
+ else
nonprivate_ctor = true;
if (!nonprivate_ctor)
@@ -2266,6 +2264,10 @@ maybe_warn_about_overly_private_class (tree t)
warning (OPT_Wctor_dtor_privacy,
"%q#T only defines private constructors and has no friends",
t);
+ if (copy_or_move)
+ inform (DECL_SOURCE_LOCATION (copy_or_move),
+ "%q#D is public, but requires an existing %q#T object",
+ copy_or_move, t);
return;
}
}
@@ -2359,7 +2361,6 @@ resort_type_method_vec (void* obj,
static void
finish_struct_methods (tree t)
{
- tree fn_fields;
vec<tree, va_gc> *method_vec;
int slot, len;
@@ -2370,9 +2371,9 @@ finish_struct_methods (tree t)
len = method_vec->length ();
/* Clear DECL_IN_AGGR_P for all functions. */
- for (fn_fields = TYPE_METHODS (t); fn_fields;
- fn_fields = DECL_CHAIN (fn_fields))
- DECL_IN_AGGR_P (fn_fields) = 0;
+ for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
+ if (DECL_DECLARES_FUNCTION_P (fn))
+ DECL_IN_AGGR_P (fn) = false;
/* Issue warnings about private constructors and such. If there are
no methods, then some public defaults are generated. */
@@ -2380,6 +2381,7 @@ finish_struct_methods (tree t)
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
+ tree fn_fields;
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
method_vec->iterate (slot, &fn_fields);
++slot)
@@ -2958,29 +2960,25 @@ modify_all_vtables (tree t, tree virtuals)
static void
get_basefndecls (tree name, tree t, vec<tree> *base_fndecls)
{
- int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
- int i;
+ bool found_decls = false;
/* Find virtual functions in T with the indicated NAME. */
- i = lookup_fnfields_1 (t, name);
- bool found_decls = false;
- if (i != -1)
- for (ovl_iterator iter ((*CLASSTYPE_METHOD_VEC (t))[i]); iter; ++iter)
- {
- tree method = *iter;
+ for (ovl_iterator iter (lookup_fnfields_slot (t, name)); iter; ++iter)
+ {
+ tree method = *iter;
- if (TREE_CODE (method) == FUNCTION_DECL
- && DECL_VINDEX (method))
- {
- base_fndecls->safe_push (method);
- found_decls = true;
- }
- }
+ if (TREE_CODE (method) == FUNCTION_DECL && DECL_VINDEX (method))
+ {
+ base_fndecls->safe_push (method);
+ found_decls = true;
+ }
+ }
if (found_decls)
return;
- for (i = 0; i < n_baseclasses; i++)
+ int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
+ for (int i = 0; i < n_baseclasses; i++)
{
tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
get_basefndecls (name, basetype, base_fndecls);
@@ -3295,6 +3293,8 @@ declare_virt_assop_and_dtor (tree t)
static void
one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms)
{
+ gcc_assert (TYPE_MAIN_VARIANT (t) == t);
+
/* We don't declare an inheriting ctor that would be a default,
copy or move ctor for derived or base. */
if (nparms == 0)
@@ -3312,11 +3312,11 @@ one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms)
parmlist = tree_cons (NULL_TREE, parms[i], parmlist);
tree fn = implicitly_declare_fn (sfk_inheriting_constructor,
t, false, ctor, parmlist);
- gcc_assert (TYPE_MAIN_VARIANT (t) == t);
+
if (add_method (t, fn, false))
{
- DECL_CHAIN (fn) = TYPE_METHODS (t);
- TYPE_METHODS (t) = fn;
+ DECL_CHAIN (fn) = TYPE_FIELDS (t);
+ TYPE_FIELDS (t) = fn;
}
}
@@ -3366,18 +3366,17 @@ add_implicitly_declared_members (tree t, tree* access_decls,
int cant_have_const_cctor,
int cant_have_const_assignment)
{
- bool move_ok = false;
-
- if (cxx_dialect >= cxx11 && !CLASSTYPE_DESTRUCTORS (t)
- && !TYPE_HAS_COPY_CTOR (t) && !TYPE_HAS_COPY_ASSIGN (t)
- && !type_has_move_constructor (t) && !type_has_move_assign (t))
- move_ok = true;
-
/* Destructor. */
- if (!CLASSTYPE_DESTRUCTORS (t))
+ if (!CLASSTYPE_DESTRUCTOR (t))
/* In general, we create destructors lazily. */
CLASSTYPE_LAZY_DESTRUCTOR (t) = 1;
+ bool move_ok = false;
+ if (cxx_dialect >= cxx11 && CLASSTYPE_LAZY_DESTRUCTOR (t)
+ && !TYPE_HAS_COPY_CTOR (t) && !TYPE_HAS_COPY_ASSIGN (t)
+ && !classtype_has_move_assign_or_move_ctor_p (t, false))
+ move_ok = true;
+
/* [class.ctor]
If there is no user-declared constructor for a class, a default
@@ -3456,7 +3455,9 @@ count_fields (tree fields)
int n_fields = 0;
for (x = fields; x; x = DECL_CHAIN (x))
{
- if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+ if (DECL_DECLARES_FUNCTION_P (x))
+ /* Functions are dealt with separately. */;
+ else if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
n_fields += count_fields (TYPE_FIELDS (TREE_TYPE (x)));
else
n_fields += 1;
@@ -3474,7 +3475,9 @@ add_fields_to_record_type (tree fields, struct sorted_fields_type *field_vec, in
tree x;
for (x = fields; x; x = DECL_CHAIN (x))
{
- if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+ if (DECL_DECLARES_FUNCTION_P (x))
+ /* Functions are handled separately. */;
+ else if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
idx = add_fields_to_record_type (TYPE_FIELDS (TREE_TYPE (x)), field_vec, idx);
else
field_vec->elts[idx++] = x;
@@ -3731,6 +3734,10 @@ check_field_decls (tree t, tree *access_decls,
|| TREE_CODE (x) == TEMPLATE_DECL)
continue;
+ if (TREE_CODE (x) == FUNCTION_DECL)
+ /* FIXME: We should fold in the checking from check_methods. */
+ continue;
+
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
if (TREE_CODE (x) != CONST_DECL)
@@ -4655,39 +4662,42 @@ build_base_fields (record_layout_info rli,
}
}
-/* Go through the TYPE_METHODS of T issuing any appropriate
+/* Go through the TYPE_FIELDS of T issuing any appropriate
diagnostics, figuring out which methods override which other
methods, and so forth. */
static void
check_methods (tree t)
{
- tree x;
+ for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
+ if (DECL_DECLARES_FUNCTION_P (x))
+ {
+ check_for_override (x, t);
+
+ if (DECL_PURE_VIRTUAL_P (x)
+ && (TREE_CODE (x) != FUNCTION_DECL || ! DECL_VINDEX (x)))
+ error ("initializer specified for non-virtual method %q+D", x);
+ /* The name of the field is the original field name
+ Save this in auxiliary field for later overloading. */
+ if (TREE_CODE (x) == FUNCTION_DECL && DECL_VINDEX (x))
+ {
+ TYPE_POLYMORPHIC_P (t) = 1;
+ if (DECL_PURE_VIRTUAL_P (x))
+ vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x);
+ }
- for (x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
- {
- check_for_override (x, t);
- if (DECL_PURE_VIRTUAL_P (x) && (TREE_CODE (x) != FUNCTION_DECL || ! DECL_VINDEX (x)))
- error ("initializer specified for non-virtual method %q+D", x);
- /* The name of the field is the original field name
- Save this in auxiliary field for later overloading. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_VINDEX (x))
- {
- TYPE_POLYMORPHIC_P (t) = 1;
- if (DECL_PURE_VIRTUAL_P (x))
- vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x);
- }
- /* All user-provided destructors are non-trivial.
- Constructors and assignment ops are handled in
- grok_special_member_properties. */
- if (DECL_DESTRUCTOR_P (x) && user_provided_p (x))
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
- if (!DECL_VIRTUAL_P (x)
- && lookup_attribute ("transaction_safe_dynamic", DECL_ATTRIBUTES (x)))
- error_at (DECL_SOURCE_LOCATION (x),
- "%<transaction_safe_dynamic%> may only be specified for "
- "a virtual function");
- }
+ /* All user-provided destructors are non-trivial.
+ Constructors and assignment ops are handled in
+ grok_special_member_properties. */
+ if (DECL_DESTRUCTOR_P (x) && user_provided_p (x))
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
+ if (!DECL_VIRTUAL_P (x)
+ && lookup_attribute ("transaction_safe_dynamic",
+ DECL_ATTRIBUTES (x)))
+ error_at (DECL_SOURCE_LOCATION (x),
+ "%<transaction_safe_dynamic%> may only be specified for "
+ "a virtual function");
+ }
}
/* FN is a constructor or destructor. Clone the declaration to create
@@ -4893,7 +4903,7 @@ clone_function_decl (tree fn, bool update_methods)
/* For each destructor, we need three variants: an in-charge
version, a not-in-charge version, and an in-charge deleting
version. We clone the deleting version first because that
- means it will go second on the TYPE_METHODS list -- and that
+ means it will go second on the TYPE_FIELDS list -- and that
corresponds to the correct layout order in the virtual
function table.
@@ -5015,8 +5025,9 @@ clone_constructors_and_destructors (tree t)
we no longer need to know that. */
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
clone_function_decl (*iter, /*update_methods=*/true);
- for (ovl_iterator iter (CLASSTYPE_DESTRUCTORS (t)); iter; ++iter)
- clone_function_decl (*iter, /*update_methods=*/true);
+
+ if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
+ clone_function_decl (dtor, /*update_methods=*/true);
}
/* Deduce noexcept for a destructor DTOR. */
@@ -5029,24 +5040,6 @@ deduce_noexcept_on_destructor (tree dtor)
noexcept_deferred_spec);
}
-/* For each destructor in T, deduce noexcept:
-
- 12.4/3: A declaration of a destructor that does not have an
- exception-specification is implicitly considered to have the
- same exception-specification as an implicit declaration (15.4). */
-
-static void
-deduce_noexcept_on_destructors (tree t)
-{
- /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
- out now. */
- if (!CLASSTYPE_METHOD_VEC (t))
- return;
-
- for (ovl_iterator iter (CLASSTYPE_DESTRUCTORS (t)); iter; ++iter)
- deduce_noexcept_on_destructor (*iter);
-}
-
/* Subroutine of set_one_vmethod_tm_attributes. Search base classes
of TYPE for virtual functions which FNDECL overrides. Return a
mask of the tm attributes found therein. */
@@ -5182,11 +5175,10 @@ set_method_tm_attributes (tree t)
/* Any method that does not yet have a tm attribute inherits
the one from the class. */
- for (fndecl = TYPE_METHODS (t); fndecl; fndecl = TREE_CHAIN (fndecl))
- {
- if (!find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
- apply_tm_attr (fndecl, class_tm_attr);
- }
+ for (fndecl = TYPE_FIELDS (t); fndecl; fndecl = DECL_CHAIN (fndecl))
+ if (DECL_DECLARES_FUNCTION_P (fndecl)
+ && !find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
+ apply_tm_attr (fndecl, class_tm_attr);
}
/* Returns true if FN is a default constructor. */
@@ -5460,93 +5452,42 @@ type_has_virtual_destructor (tree type)
return false;
gcc_assert (COMPLETE_TYPE_P (type));
- dtor = CLASSTYPE_DESTRUCTORS (type);
+ dtor = CLASSTYPE_DESTRUCTOR (type);
return (dtor && DECL_VIRTUAL_P (dtor));
}
-/* Returns true iff class T has a move constructor. */
+/* Returns true iff T, a class, has a move-assignment or
+ move-constructor. Does not lazily declare either.
+ If USER_P is false, any move function will do. If it is true, the
+ move function must be user-declared.
-bool
-type_has_move_constructor (tree t)
-{
- if (CLASSTYPE_LAZY_MOVE_CTOR (t))
- {
- gcc_assert (COMPLETE_TYPE_P (t));
- lazily_declare_fn (sfk_move_constructor, t);
- }
-
- if (!CLASSTYPE_METHOD_VEC (t))
- return false;
-
- for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
- if (move_fn_p (*iter))
- return true;
-
- return false;
-}
-
-/* Returns true iff class T has a move assignment operator. */
+ Note that user-declared here is different from "user-provided",
+ which doesn't include functions that are defaulted in the
+ class. */
bool
-type_has_move_assign (tree t)
+classtype_has_move_assign_or_move_ctor_p (tree t, bool user_p)
{
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
- {
- gcc_assert (COMPLETE_TYPE_P (t));
- lazily_declare_fn (sfk_move_assignment, t);
- }
-
- for (ovl_iterator iter (lookup_fnfields_slot_nolazy
- (t, cp_assignment_operator_id (NOP_EXPR)));
- iter; ++iter)
- if (move_fn_p (*iter))
- return true;
-
- return false;
-}
-
-/* Returns true iff class T has a move constructor that was explicitly
- declared in the class body. Note that this is different from
- "user-provided", which doesn't include functions that are defaulted in
- the class. */
-
-bool
-type_has_user_declared_move_constructor (tree t)
-{
- if (CLASSTYPE_LAZY_MOVE_CTOR (t))
- return false;
+ gcc_assert (user_p
+ || (!CLASSTYPE_LAZY_MOVE_CTOR (t)
+ && !CLASSTYPE_LAZY_MOVE_ASSIGN (t)));
if (!CLASSTYPE_METHOD_VEC (t))
return false;
- for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
- {
- tree fn = *iter;
- if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ if (!CLASSTYPE_LAZY_MOVE_CTOR (t))
+ for (ovl_iterator iter (lookup_fnfields_slot_nolazy (t, ctor_identifier));
+ iter; ++iter)
+ if ((!user_p || !DECL_ARTIFICIAL (*iter)) && move_fn_p (*iter))
return true;
- }
-
- return false;
-}
-
-/* Returns true iff class T has a move assignment operator that was
- explicitly declared in the class body. */
-bool
-type_has_user_declared_move_assign (tree t)
-{
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
- return false;
-
- for (ovl_iterator iter (lookup_fnfields_slot_nolazy
- (t, cp_assignment_operator_id (NOP_EXPR)));
- iter; ++iter)
- {
- tree fn = *iter;
- if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ if (!CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+ for (ovl_iterator iter (lookup_fnfields_slot_nolazy
+ (t, cp_assignment_operator_id (NOP_EXPR)));
+ iter; ++iter)
+ if ((!user_p || !DECL_ARTIFICIAL (*iter)) && move_fn_p (*iter))
return true;
- }
-
+
return false;
}
@@ -5719,9 +5660,9 @@ finalize_literal_type_property (tree t)
/* C++14 DR 1684 removed this restriction. */
if (cxx_dialect < cxx14
&& !CLASSTYPE_LITERAL_P (t) && !LAMBDA_TYPE_P (t))
- for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
- if (DECL_DECLARED_CONSTEXPR_P (fn)
- && TREE_CODE (fn) != TEMPLATE_DECL
+ for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_DECLARED_CONSTEXPR_P (fn)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
&& !DECL_CONSTRUCTOR_P (fn))
{
@@ -5851,10 +5792,11 @@ check_bases_and_members (tree t)
of potential interest. */
check_bases (t, &cant_have_const_ctor, &no_const_asn_ref);
- /* Deduce noexcept on destructors. This needs to happen after we've set
+ /* Deduce noexcept on destructor. This needs to happen after we've set
triviality flags appropriately for our bases. */
if (cxx_dialect >= cxx11)
- deduce_noexcept_on_destructors (t);
+ if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
+ deduce_noexcept_on_destructor (dtor);
/* Check all the method declarations. */
check_methods (t);
@@ -5982,8 +5924,10 @@ check_bases_and_members (tree t)
/* Check defaulted declarations here so we have cant_have_const_ctor
and don't need to worry about clones. */
- for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
- if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn))
+ for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
+ if (DECL_DECLARES_FUNCTION_P (fn)
+ && !DECL_ARTIFICIAL (fn)
+ && DECL_DEFAULTED_IN_CLASS_P (fn))
{
int copy = copy_fn_p (fn);
if (copy > 0)
@@ -6042,7 +5986,7 @@ create_vtable_ptr (tree t, tree* virtuals_p)
tree fn;
/* Collect the virtual functions declared in T. */
- for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
+ for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
if (TREE_CODE (fn) == FUNCTION_DECL
&& DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
&& TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
@@ -6312,8 +6256,7 @@ include_empty_classes (record_layout_info rli)
because we are willing to overlay multiple bases at the same
offset. However, now we need to make sure that RLI is big enough
to reflect the entire class. */
- eoc = end_of_class (rli->t,
- CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+ eoc = end_of_class (rli->t, CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
rli_size = rli_size_unit_so_far (rli);
if (TREE_CODE (rli_size) == INTEGER_CST
&& tree_int_cst_lt (rli_size, eoc))
@@ -6702,8 +6645,7 @@ determine_key_method (tree type)
inline at the point of class definition. On some targets the
key function may not be inline; those targets should not call
this function until the end of the translation unit. */
- for (method = TYPE_METHODS (type); method != NULL_TREE;
- method = DECL_CHAIN (method))
+ for (method = TYPE_FIELDS (type); method; method = DECL_CHAIN (method))
if (TREE_CODE (method) == FUNCTION_DECL
&& DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method)
@@ -7395,11 +7337,11 @@ unreverse_member_declarations (tree t)
/* The following lists are all in reverse order. Put them in
declaration order now. */
- TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
- /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
- reverse order, so we can't just use nreverse. */
+ /* For the TYPE_FIELDS, only the non TYPE_DECLs are in reverse
+ order, so we can't just use nreverse. Due to stat_hack
+ chicanery in finish_member_declarations. */
prev = NULL_TREE;
for (x = TYPE_FIELDS (t);
x && TREE_CODE (x) != TYPE_DECL;
@@ -7409,6 +7351,7 @@ unreverse_member_declarations (tree t)
DECL_CHAIN (x) = prev;
prev = x;
}
+
if (prev)
{
DECL_CHAIN (TYPE_FIELDS (t)) = x;
@@ -7449,8 +7392,8 @@ finish_struct (tree t, tree attributes)
CLASSTYPE_PURE_VIRTUALS contains the list of the inline friends
(see CLASSTYPE_INLINE_FRIENDS) so we need to clear it. */
CLASSTYPE_PURE_VIRTUALS (t) = NULL;
- for (x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
- if (DECL_PURE_VIRTUAL_P (x))
+ for (x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
+ if (TREE_CODE (x) == FUNCTION_DECL && DECL_PURE_VIRTUAL_P (x))
vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x);
complete_vars (t);
/* We need to add the target functions to the CLASSTYPE_METHOD_VEC if
@@ -7461,7 +7404,7 @@ finish_struct (tree t, tree attributes)
if (TREE_CODE (x) == USING_DECL)
{
tree fn = strip_using_decl (x);
- if (is_overloaded_fn (fn))
+ if (OVL_P (fn))
for (lkp_iterator iter (fn); iter; ++iter)
add_method (t, *iter, true);
}
@@ -7475,7 +7418,6 @@ finish_struct (tree t, tree attributes)
TYPE_SIZE (x) = TYPE_SIZE (t);
TYPE_SIZE_UNIT (x) = TYPE_SIZE_UNIT (t);
TYPE_FIELDS (x) = TYPE_FIELDS (t);
- TYPE_METHODS (x) = TYPE_METHODS (t);
}
}
else
@@ -8522,7 +8464,6 @@ static tree
get_vfield_name (tree type)
{
tree binfo, base_binfo;
- char *buf;
for (binfo = TYPE_BINFO (type);
BINFO_N_BASE_BINFOS (binfo);
@@ -8536,10 +8477,10 @@ get_vfield_name (tree type)
}
type = BINFO_TYPE (binfo);
- buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT)
- + TYPE_NAME_LENGTH (type) + 2);
- sprintf (buf, VFIELD_NAME_FORMAT,
- IDENTIFIER_POINTER (constructor_name (type)));
+ tree ctor_name = constructor_name (type);
+ char *buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT)
+ + IDENTIFIER_LENGTH (ctor_name) + 2);
+ sprintf (buf, VFIELD_NAME_FORMAT, IDENTIFIER_POINTER (ctor_name));
return get_identifier (buf);
}
@@ -8569,9 +8510,8 @@ print_class_statistics (void)
void
build_self_reference (void)
{
- tree name = constructor_name (current_class_type);
+ tree name = DECL_NAME (TYPE_NAME (current_class_type));
tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
- tree saved_cas;
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
@@ -8582,7 +8522,7 @@ build_self_reference (void)
if (processing_template_decl)
value = push_template_decl (value);
- saved_cas = current_access_specifier;
+ tree saved_cas = current_access_specifier;
current_access_specifier = access_public_node;
finish_member_declaration (value);
current_access_specifier = saved_cas;
@@ -9983,7 +9923,7 @@ add_vcall_offset_vtbl_entries_1 (tree binfo, vtbl_init_data* vid)
/* The ABI requires that the methods be processed in declaration
order. */
- for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
+ for (orig_fn = TYPE_FIELDS (BINFO_TYPE (binfo));
orig_fn;
orig_fn = DECL_CHAIN (orig_fn))
if (TREE_CODE (orig_fn) == FUNCTION_DECL && DECL_VINDEX (orig_fn))
diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index d0a96a07b5a..c009570b63d 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -45,7 +45,7 @@ gtfiles="\
\$(srcdir)/cp/except.c \
\$(srcdir)/cp/friend.c \
\$(srcdir)/cp/init.c \
-\$(srcdir)/cp/lambda.c \
+\$(srcdir)/cp/lambda.c \$(srcdir)/cp/lex.c \
\$(srcdir)/cp/mangle.c \$(srcdir)/cp/method.c \
\$(srcdir)/cp/name-lookup.c \
\$(srcdir)/cp/parser.c \$(srcdir)/cp/pt.c \
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5a574524866..29ba2c3dac2 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4519,7 +4519,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
/* GCC internal stuff. */
case VA_ARG_EXPR:
case OBJ_TYPE_REF:
- case WITH_CLEANUP_EXPR:
case NON_DEPENDENT_EXPR:
case BASELINK:
case OFFSET_REF:
@@ -5533,7 +5532,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
case BIND_EXPR:
return RECUR (BIND_EXPR_BODY (t), want_rval);
- case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
case MUST_NOT_THROW_EXPR:
case TRY_CATCH_EXPR:
@@ -5784,6 +5782,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
case CLEANUP_STMT:
case EMPTY_CLASS_EXPR:
+ case PREDICT_EXPR:
return false;
case GOTO_EXPR:
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 6fd4bde22e5..64a8ea926d2 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1580,7 +1580,7 @@ tsubst_check_constraint (tree t, tree args,
/* Substitute through by building an template-id expression
and then substituting into that. */
- tree expr = build_nt(TEMPLATE_ID_EXPR, tmpl, targs);
+ tree expr = build_nt (TEMPLATE_ID_EXPR, tmpl, targs);
++processing_template_decl;
tree result = tsubst_expr (expr, args, complain, in_decl, false);
--processing_template_decl;
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index 36d66245224..31be7d685ba 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -1375,8 +1375,8 @@ build_array_notation_ref (location_t loc, tree array, tree start, tree length,
"using array notation with array of unknown bound");
return error_mark_node;
}
- start = cp_fold_convert (ptrdiff_type_node, TYPE_MINVAL (domain));
- length = size_binop (PLUS_EXPR, TYPE_MAXVAL (domain), size_one_node);
+ start = cp_fold_convert (ptrdiff_type_node, TYPE_MIN_VALUE (domain));
+ length = size_binop (PLUS_EXPR, TYPE_MAX_VALUE (domain), size_one_node);
length = cp_fold_convert (ptrdiff_type_node, length);
}
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index f010f6c63be..a9563b1a8cd 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1668,7 +1668,8 @@ cp_genericize (tree fndecl)
walk_tree's hash functionality. */
cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
- if (sanitize_flags_p (SANITIZE_RETURN))
+ if (sanitize_flags_p (SANITIZE_RETURN)
+ && current_function_decl != NULL_TREE)
cp_ubsan_maybe_instrument_return (fndecl);
/* Do everything else. */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index defcbdc79a9..805319a4185 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -79,6 +79,11 @@ static tree cxx_enum_underlying_base_type (const_tree);
#undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE cxx_enum_underlying_base_type
+#if CHECKING_P
+#undef LANG_HOOKS_RUN_LANG_SELFTESTS
+#define LANG_HOOKS_RUN_LANG_SELFTESTS selftest::run_cp_tests
+#endif /* #if CHECKING_P */
+
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -229,6 +234,25 @@ tree cxx_enum_underlying_base_type (const_tree type)
return underlying_type;
}
+#if CHECKING_P
+
+namespace selftest {
+
+/* Implementation of LANG_HOOKS_RUN_LANG_SELFTESTS for the C++ frontend. */
+
+void
+run_cp_tests (void)
+{
+ /* Run selftests shared within the C family. */
+ c_family_tests ();
+
+ /* Additional C++-specific tests. */
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
#include "gt-cp-cp-lang.h"
#include "gtype-cp.h"
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 5a7da5b4957..4475b6cb911 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -212,6 +212,13 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
}
break;
+ case DW_AT_export_symbols:
+ if (TREE_CODE (decl) == NAMESPACE_DECL
+ && (DECL_NAMESPACE_INLINE_P (decl)
+ || (DECL_NAME (decl) == NULL_TREE && dwarf_version >= 5)))
+ return 1;
+ break;
+
default:
break;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 33dde158dae..115cdaff61e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -206,8 +206,19 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
/* std::align_val_t */
#define align_type_node cp_global_trees[CPTI_ALIGN_TYPE]
-/* We cache these tree nodes so as to call get_identifier less
- frequently. */
+/* We cache these tree nodes so as to call get_identifier less frequently.
+ For identifiers for functions, including special member functions such
+ as ctors and assignment operators, the nodes can be used (among other
+ things) to iterate over their overloads defined by/for a type. For
+ example:
+
+ tree ovlid = cp_assignment_operator_id (NOP_EXPR);
+ tree overloads = lookup_fnfields_slot (type, ovlid);
+ for (ovl_iterator it (overloads); it; ++it) { ... }
+
+ iterates over the set of implicitly and explicitly defined overloads
+ of the assignment operator for type (including the copy and move
+ assignment operators, whether deleted or not). */
/* The name of a constructor that takes an in-charge parameter to
decide whether or not to construct virtual base classes. */
@@ -228,6 +239,18 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
/* The name of a destructor that destroys virtual base classes, and
then deletes the entire object. */
#define deleting_dtor_identifier cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
+
+/* The name of the identifier used internally to represent operator CODE. */
+#define cp_operator_id(CODE) \
+ (operator_name_info[(int) (CODE)].identifier)
+
+/* The name of the identifier used to represent assignment operator CODE,
+ both simple (i.e., operator= with CODE == NOP_EXPR) and compound (e.g.,
+ operator+= with CODE == PLUS_EXPR). Includes copy and move assignment.
+ Use copy_fn_p() to test specifically for copy assignment. */
+#define cp_assignment_operator_id(CODE) \
+ (assignment_operator_name_info[(int) (CODE)].identifier)
+
#define delta_identifier cp_global_trees[CPTI_DELTA_IDENTIFIER]
#define in_charge_identifier cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
/* The name of the parameter that contains a pointer to the VTT to use
@@ -527,7 +550,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
struct GTY(()) lang_identifier {
struct c_common_identifier c_common;
cxx_binding *bindings;
- tree class_template_info;
tree label_value;
};
@@ -954,9 +976,6 @@ enum GTY(()) abstract_class_use {
/* Macros for access to language-specific slots in an identifier. */
-#define IDENTIFIER_TEMPLATE(NODE) \
- (LANG_IDENTIFIER_CAST (NODE)->class_template_info)
-
/* The IDENTIFIER_BINDING is the innermost cxx_binding for the
identifier. Its PREVIOUS is the next outermost binding. Each
VALUE field is a DECL for the associated declaration. Thus,
@@ -1772,10 +1791,6 @@ struct GTY(()) language_function {
#define current_function_auto_return_pattern \
(cp_function_chain->x_auto_return_pattern)
-#define cp_operator_id(CODE) \
- (operator_name_info[(int) (CODE)].identifier)
-#define cp_assignment_operator_id(CODE) \
- (assignment_operator_name_info[(int) (CODE)].identifier)
/* In parser.c. */
extern tree cp_literal_operator_id (const char *);
@@ -1817,7 +1832,7 @@ enum languages { lang_c, lang_cplusplus };
/* Set CLASS_TYPE_P for T to VAL. T must be a class, struct, or
union type. */
#define SET_CLASS_TYPE_P(T, VAL) \
- (TYPE_LANG_FLAG_5 (T) = (VAL))
+ (TYPE_LANG_FLAG_5 (RECORD_OR_UNION_CHECK (T)) = (VAL))
/* Nonzero if T is a class type. Zero for template type parameters,
typename types, and so forth. */
@@ -1826,7 +1841,7 @@ enum languages { lang_c, lang_cplusplus };
/* Nonzero if T is a class type but not an union. */
#define NON_UNION_CLASS_TYPE_P(T) \
- (CLASS_TYPE_P (T) && TREE_CODE (T) != UNION_TYPE)
+ (TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T))
/* Keep these checks in ascending code order. */
#define RECORD_OR_UNION_CODE_P(T) \
@@ -2133,29 +2148,21 @@ struct GTY(()) lang_type {
and the RECORD_TYPE for the class template otherwise. */
#define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list)
-/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
-#define CLASSTYPE_CONSTRUCTOR_SLOT 0
-
-/* The slot in the CLASSTYPE_METHOD_VEC where destructors go. */
-#define CLASSTYPE_DESTRUCTOR_SLOT 1
-
/* The first slot in the CLASSTYPE_METHOD_VEC where conversion
operators can appear. */
-#define CLASSTYPE_FIRST_CONVERSION_SLOT 2
+#define CLASSTYPE_FIRST_CONVERSION_SLOT 0
/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These
are the constructors that take an in-charge parameter. */
#define CLASSTYPE_CONSTRUCTORS(NODE) \
- ((*CLASSTYPE_METHOD_VEC (NODE))[CLASSTYPE_CONSTRUCTOR_SLOT])
+ (lookup_fnfields_slot_nolazy (NODE, ctor_identifier))
-/* A FUNCTION_DECL for the destructor for NODE. These are the
+/* A FUNCTION_DECL for the destructor for NODE. This is the
destructors that take an in-charge parameter. If
CLASSTYPE_LAZY_DESTRUCTOR is true, then this entry will be NULL
until the destructor is created with lazily_declare_fn. */
-#define CLASSTYPE_DESTRUCTORS(NODE) \
- (CLASSTYPE_METHOD_VEC (NODE) \
- ? (*CLASSTYPE_METHOD_VEC (NODE))[CLASSTYPE_DESTRUCTOR_SLOT] \
- : NULL_TREE)
+#define CLASSTYPE_DESTRUCTOR(NODE) \
+ (lookup_fnfields_slot_nolazy (NODE, dtor_identifier))
/* A dictionary of the nested user-defined-types (class-types, or enums)
found within this class. This table includes nested member class
@@ -2182,11 +2189,9 @@ struct GTY(()) lang_type {
/* The type corresponding to NODE when NODE is used as a base class,
i.e., NODE without virtual base classes or tail padding. */
-
#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
/* True iff NODE is the CLASSTYPE_AS_BASE version of some type. */
-
#define IS_FAKE_BASE_TYPE(NODE) \
(TREE_CODE (NODE) == RECORD_TYPE \
&& TYPE_CONTEXT (NODE) && CLASS_TYPE_P (TYPE_CONTEXT (NODE)) \
@@ -2495,25 +2500,27 @@ struct GTY(()) lang_decl_fn {
struct lang_decl_min min;
/* In an overloaded operator, this is the value of
- DECL_OVERLOADED_OPERATOR_P. */
+ DECL_OVERLOADED_OPERATOR_P.
+ FIXME: We should really do better in compressing this. */
ENUM_BITFIELD (tree_code) operator_code : 16;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
- unsigned assignment_operator_p : 1;
unsigned static_function : 1;
unsigned pure_virtual : 1;
unsigned defaulted_p : 1;
unsigned has_in_charge_parm_p : 1;
unsigned has_vtt_parm_p : 1;
-
unsigned pending_inline_p : 1;
+
unsigned nonconverting : 1;
unsigned thunk_p : 1;
unsigned this_thunk_p : 1;
unsigned hidden_friend_p : 1;
unsigned omp_declare_reduction_p : 1;
- /* 2 spare bits on 32-bit hosts, 34 on 64-bit hosts. */
+ /* 3 spare bits. */
+
+ /* 32-bits padding on 64-bit host. */
/* For a non-thunk function decl, this is a tree list of
friendly classes. For a thunk function decl, it is the
@@ -2559,7 +2566,9 @@ struct GTY(()) lang_decl_ns {
vec<tree, va_gc> *usings;
vec<tree, va_gc> *inlinees;
- /* Map from IDENTIFIER nodes to DECLS. */
+ /* Map from IDENTIFIER nodes to DECLS. It'd be nice to have this
+ inline, but as the hash_map has a dtor, we can't then put this
+ struct into a union (until moving to c++11). */
hash_map<lang_identifier *, tree> *bindings;
};
@@ -2689,26 +2698,23 @@ struct GTY(()) lang_decl {
/* For FUNCTION_DECLs and TEMPLATE_DECLs: nonzero means that this function
is a constructor. */
#define DECL_CONSTRUCTOR_P(NODE) \
- DECL_CXX_CONSTRUCTOR_P (STRIP_TEMPLATE (NODE))
+ IDENTIFIER_CTOR_P (DECL_NAME (NODE))
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a complete
object. */
#define DECL_COMPLETE_CONSTRUCTOR_P(NODE) \
- (DECL_CONSTRUCTOR_P (NODE) \
- && DECL_NAME (NODE) == complete_ctor_identifier)
+ (DECL_NAME (NODE) == complete_ctor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a base
object. */
#define DECL_BASE_CONSTRUCTOR_P(NODE) \
- (DECL_CONSTRUCTOR_P (NODE) \
- && DECL_NAME (NODE) == base_ctor_identifier)
+ (DECL_NAME (NODE) == base_ctor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a constructor, but not either the
specialized in-charge constructor or the specialized not-in-charge
constructor. */
#define DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P(NODE) \
- (DECL_DECLARES_FUNCTION_P (NODE) && DECL_CONSTRUCTOR_P (NODE) \
- && !DECL_CLONED_FUNCTION_P (NODE))
+ (DECL_NAME (NODE) == ctor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a copy constructor. */
#define DECL_COPY_CONSTRUCTOR_P(NODE) \
@@ -2721,32 +2727,28 @@ struct GTY(()) lang_decl {
/* Nonzero if NODE (a FUNCTION_DECL or TEMPLATE_DECL)
is a destructor. */
#define DECL_DESTRUCTOR_P(NODE) \
- DECL_CXX_DESTRUCTOR_P (STRIP_TEMPLATE (NODE))
+ IDENTIFIER_DTOR_P (DECL_NAME (NODE))
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the
specialized in-charge constructor, in-charge deleting constructor,
or the base destructor. */
#define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \
- (DECL_DECLARES_FUNCTION_P (NODE) && DECL_DESTRUCTOR_P (NODE) \
- && !DECL_CLONED_FUNCTION_P (NODE))
+ (DECL_NAME (NODE) == dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a complete
object. */
#define DECL_COMPLETE_DESTRUCTOR_P(NODE) \
- (DECL_DESTRUCTOR_P (NODE) \
- && DECL_NAME (NODE) == complete_dtor_identifier)
+ (DECL_NAME (NODE) == complete_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a base
object. */
#define DECL_BASE_DESTRUCTOR_P(NODE) \
- (DECL_DESTRUCTOR_P (NODE) \
- && DECL_NAME (NODE) == base_dtor_identifier)
+ (DECL_NAME (NODE) == base_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a complete
object that deletes the object after it has been destroyed. */
#define DECL_DELETING_DESTRUCTOR_P(NODE) \
- (DECL_DESTRUCTOR_P (NODE) \
- && DECL_NAME (NODE) == deleting_dtor_identifier)
+ (DECL_NAME (NODE) == deleting_dtor_identifier)
/* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or
destructor. */
@@ -2836,9 +2838,7 @@ struct GTY(()) lang_decl {
(LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
/* If NODE is an overloaded operator, then this returns the TREE_CODE
- associated with the overloaded operator.
- DECL_ASSIGNMENT_OPERATOR_P must also be checked to determine
- whether or not NODE is an assignment operator. If NODE is not an
+ associated with the overloaded operator. If NODE is not an
overloaded operator, ERROR_MARK is returned. Since the numerical
value of ERROR_MARK is zero, this macro can be used as a predicate
to test whether or not NODE is an overloaded operator. */
@@ -2848,7 +2848,7 @@ struct GTY(()) lang_decl {
/* Nonzero if NODE is an assignment operator (including += and such). */
#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
- (LANG_DECL_FN_CHECK (NODE)->assignment_operator_p)
+ IDENTIFIER_ASSIGN_OP_P (DECL_NAME (NODE))
/* For FUNCTION_DECLs: nonzero means that this function is a
constructor or a destructor with an extra in-charge parameter to
@@ -3514,13 +3514,13 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define PACK_EXPANSION_PARAMETER_PACKS(NODE) \
*(TREE_CODE (NODE) == EXPR_PACK_EXPANSION \
? &TREE_OPERAND (NODE, 1) \
- : &TYPE_MINVAL (TYPE_PACK_EXPANSION_CHECK (NODE)))
+ : &TYPE_MIN_VALUE_RAW (TYPE_PACK_EXPANSION_CHECK (NODE)))
/* Any additional template args to be applied when substituting into
the pattern, set by tsubst_pack_expansion for partial instantiations. */
#define PACK_EXPANSION_EXTRA_ARGS(NODE) \
*(TREE_CODE (NODE) == TYPE_PACK_EXPANSION \
- ? &TYPE_MAXVAL (NODE) \
+ ? &TYPE_MAX_VALUE_RAW (NODE) \
: &TREE_OPERAND ((NODE), 2))
/* True iff this pack expansion is within a function context. */
@@ -4322,7 +4322,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* For a pointer-to-member constant `X::Y' this is the _DECL for
`Y'. */
-#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
+#define PTRMEM_CST_MEMBER(NODE) \
+ (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
/* The expression in question for a TYPEOF_TYPE. */
#define TYPEOF_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (TYPEOF_TYPE_CHECK (NODE)))
@@ -5202,14 +5203,6 @@ extern GTY(()) vec<tree, va_gc> *keyed_classes;
#endif /* NO_DOLLAR_IN_LABEL */
#endif /* NO_DOT_IN_LABEL */
-#define THIS_NAME "this"
-
-#define IN_CHARGE_NAME "__in_chrg"
-
-#define VTBL_PTR_TYPE "__vtbl_ptr_type"
-#define VTABLE_DELTA_NAME "__delta"
-#define VTABLE_PFN_NAME "__pfn"
-
#define LAMBDANAME_PREFIX "__lambda"
#define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
@@ -6022,10 +6015,7 @@ extern tree default_init_uninitialized_part (tree);
extern bool trivial_default_constructor_is_constexpr (tree);
extern bool type_has_constexpr_default_constructor (tree);
extern bool type_has_virtual_destructor (tree);
-extern bool type_has_move_constructor (tree);
-extern bool type_has_move_assign (tree);
-extern bool type_has_user_declared_move_constructor (tree);
-extern bool type_has_user_declared_move_assign(tree);
+extern bool classtype_has_move_assign_or_move_ctor_p (tree, bool user_declared);
extern bool type_build_ctor_call (tree);
extern bool type_build_dtor_call (tree);
extern void explain_non_literal_class (tree);
@@ -6097,6 +6087,7 @@ extern tree define_label (location_t, tree);
extern void check_goto (tree);
extern bool check_omp_return (void);
extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
+extern tree build_typename_type (tree, tree, tree, tag_types);
extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree build_library_fn_ptr (const char *, tree, int);
extern tree build_cp_library_fn_ptr (const char *, tree, int);
@@ -6340,6 +6331,7 @@ extern void yyungetc (int, int);
extern tree unqualified_name_lookup_error (tree,
location_t = UNKNOWN_LOCATION);
extern tree unqualified_fn_lookup_error (cp_expr);
+extern tree make_conv_op_name (tree);
extern tree build_lang_decl (enum tree_code, tree, tree);
extern tree build_lang_decl_loc (location_t, enum tree_code, tree, tree);
extern void retrofit_lang_decl (tree);
@@ -6581,10 +6573,9 @@ extern int accessible_p (tree, tree, bool);
extern int accessible_in_template_p (tree, tree);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
-extern int lookup_fnfields_1 (tree, tree);
extern tree lookup_fnfields_slot (tree, tree);
extern tree lookup_fnfields_slot_nolazy (tree, tree);
-extern int class_method_index_for_fn (tree, tree);
+extern tree lookup_all_conversions (tree);
extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool,
tsubst_flags_t,
@@ -6612,6 +6603,7 @@ extern tree dfs_walk_all (tree, tree (*) (tree, void *),
extern tree dfs_walk_once (tree, tree (*) (tree, void *),
tree (*) (tree, void *), void *);
extern tree binfo_via_virtual (tree, tree);
+extern bool binfo_direct_p (tree);
extern tree build_baselink (tree, tree, tree, tree);
extern tree adjust_result_of_qualified_name_lookup
(tree, tree, tree);
@@ -7194,7 +7186,6 @@ extern tree mangle_vtbl_for_type (tree);
extern tree mangle_vtt_for_type (tree);
extern tree mangle_ctor_vtbl_for_type (tree, tree);
extern tree mangle_thunk (tree, int, tree, tree, tree);
-extern tree mangle_conv_op_name_for_type (tree);
extern tree mangle_guard_variable (tree);
extern tree mangle_tls_init_fn (tree);
extern tree mangle_tls_wrapper_fn (tree);
@@ -7378,6 +7369,12 @@ extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree, tree);
extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
+#if CHECKING_P
+namespace selftest {
+ extern void run_cp_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
/* Inline bodies. */
inline tree
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index f00f870bd3e..3be607c0a42 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -36,6 +36,9 @@ cp_ubsan_instrument_vptr_p (tree type)
if (!sanitize_flags_p (SANITIZE_VPTR))
return false;
+ if (current_function_decl == NULL_TREE)
+ return false;
+
if (type)
{
type = TYPE_MAIN_VARIANT (type);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 5398e3dd87d..edaee04d7fb 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -88,14 +88,6 @@ pp_cxx_separate_with (cxx_pretty_printer *pp, int c)
/* Expressions. */
-static inline bool
-is_destructor_name (tree name)
-{
- return name == complete_dtor_identifier
- || name == base_dtor_identifier
- || name == deleting_dtor_identifier;
-}
-
/* conversion-function-id:
operator conversion-type-id
@@ -162,16 +154,7 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
else if (IDENTIFIER_CONV_OP_P (t))
pp_cxx_conversion_function_id (pp, t);
else
- {
- if (is_destructor_name (t))
- {
- pp_complement (pp);
- /* FIXME: Why is this necessary? */
- if (TREE_TYPE (t))
- t = constructor_name (TREE_TYPE (t));
- }
- pp_cxx_tree_identifier (pp, t);
- }
+ pp_cxx_tree_identifier (pp, t);
break;
case TEMPLATE_ID_EXPR:
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0361357a14e..4ec38b82aa9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
static GTY (()) hash_table<typename_hasher> *typename_htab;
-static tree
+tree
build_typename_type (tree context, tree name, tree fullname,
enum tag_types tag_type)
{
@@ -3955,16 +3955,16 @@ initialize_predefined_identifiers (void)
/* Some of these names have a trailing space so that it is
impossible for them to conflict with names written by users. */
{"__ct ", &ctor_identifier, cik_ctor},
- {"__base_ctor ", &base_ctor_identifier, cik_ctor},
- {"__comp_ctor ", &complete_ctor_identifier, cik_ctor},
+ {"__ct_base ", &base_ctor_identifier, cik_ctor},
+ {"__ct_comp ", &complete_ctor_identifier, cik_ctor},
{"__dt ", &dtor_identifier, cik_dtor},
- {"__comp_dtor ", &complete_dtor_identifier, cik_dtor},
- {"__base_dtor ", &base_dtor_identifier, cik_dtor},
- {"__deleting_dtor ", &deleting_dtor_identifier, cik_dtor},
- {IN_CHARGE_NAME, &in_charge_identifier, cik_normal},
- {THIS_NAME, &this_identifier, cik_normal},
- {VTABLE_DELTA_NAME, &delta_identifier, cik_normal},
- {VTABLE_PFN_NAME, &pfn_identifier, cik_normal},
+ {"__dt_base ", &base_dtor_identifier, cik_dtor},
+ {"__dt_comp ", &complete_dtor_identifier, cik_dtor},
+ {"__dt_del ", &deleting_dtor_identifier, cik_dtor},
+ {"__in_chrg", &in_charge_identifier, cik_normal},
+ {"this", &this_identifier, cik_normal},
+ {"__delta", &delta_identifier, cik_normal},
+ {"__pfn", &pfn_identifier, cik_normal},
{"_vptr", &vptr_identifier, cik_normal},
{"__vtt_parm", &vtt_parm_identifier, cik_normal},
{"::", &global_identifier, cik_normal},
@@ -4094,7 +4094,7 @@ cxx_init_decl_processing (void)
vtable_entry_type = build_pointer_type (vfunc_type);
}
- record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
+ record_builtin_type (RID_MAX, "__vtbl_ptr_type", vtable_entry_type);
vtbl_type_node
= build_cplus_array_type (vtable_entry_type, NULL_TREE);
@@ -4549,8 +4549,6 @@ push_throw_library_fn (tree name, tree type)
void
fixup_anonymous_aggr (tree t)
{
- tree *q;
-
/* Wipe out memory of synthesized methods. */
TYPE_HAS_USER_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
@@ -4559,29 +4557,12 @@ fixup_anonymous_aggr (tree t)
TYPE_HAS_COPY_ASSIGN (t) = 0;
TYPE_HAS_CONST_COPY_ASSIGN (t) = 0;
- /* Splice the implicitly generated functions out of the TYPE_METHODS
- list. */
- q = &TYPE_METHODS (t);
- while (*q)
- {
- if (DECL_ARTIFICIAL (*q))
- *q = TREE_CHAIN (*q);
- else
- q = &DECL_CHAIN (*q);
- }
-
- /* ISO C++ 9.5.3. Anonymous unions may not have function members. */
- if (TYPE_METHODS (t))
- {
- tree decl = TYPE_MAIN_DECL (t);
-
- if (TREE_CODE (t) != UNION_TYPE)
- error_at (DECL_SOURCE_LOCATION (decl),
- "an anonymous struct cannot have function members");
- else
- error_at (DECL_SOURCE_LOCATION (decl),
- "an anonymous union cannot have function members");
- }
+ /* Splice the implicitly generated functions out of TYPE_FIELDS. */
+ for (tree probe, *prev_p = &TYPE_FIELDS (t); (probe = *prev_p);)
+ if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe))
+ *prev_p = DECL_CHAIN (probe);
+ else
+ prev_p = &DECL_CHAIN (probe);
/* Anonymous aggregates cannot have fields with ctors, dtors or complex
assignment operators (because they cannot have these methods themselves).
@@ -7486,8 +7467,8 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
if (init == error_mark_node || eltype == error_mark_node)
{
- inform (dloc, "in initialization of decomposition variable %qD",
- v[i]);
+ inform (dloc, "in initialization of structured binding "
+ "variable %qD", v[i]);
goto error_out;
}
/* Save the decltype away before reference collapse. */
@@ -7849,12 +7830,8 @@ register_dtor_fn (tree decl)
use_dtor = ob_parm && CLASS_TYPE_P (type);
if (use_dtor)
{
- int idx;
+ cleanup = lookup_fnfields_slot (type, complete_dtor_identifier);
- /* Find the destructor. */
- idx = lookup_fnfields_1 (type, complete_dtor_identifier);
- gcc_assert (idx >= 0);
- cleanup = (*CLASSTYPE_METHOD_VEC (type))[idx];
/* Make sure it is accessible. */
perform_or_defer_access_check (TYPE_BINFO (type), cleanup, cleanup,
tf_warning_or_error);
@@ -8502,9 +8479,11 @@ grokfndecl (tree ctype,
/* Allocate space to hold the vptr bit if needed. */
SET_DECL_ALIGN (decl, MINIMUM_METHOD_BOUNDARY);
}
+
DECL_ARGUMENTS (decl) = parms;
for (t = parms; t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = decl;
+
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
@@ -8515,22 +8494,22 @@ grokfndecl (tree ctype,
case sfk_constructor:
case sfk_copy_constructor:
case sfk_move_constructor:
- DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_CXX_CONSTRUCTOR_P (decl) = 1;
+ DECL_NAME (decl) = ctor_identifier;
break;
case sfk_destructor:
- DECL_DESTRUCTOR_P (decl) = 1;
+ DECL_CXX_DESTRUCTOR_P (decl) = 1;
+ DECL_NAME (decl) = dtor_identifier;
break;
default:
break;
}
- if (friendp
- && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+ if (friendp && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
if (funcdef_flag)
- error
- ("defining explicit specialization %qD in friend declaration",
- orig_declarator);
+ error ("defining explicit specialization %qD in friend declaration",
+ orig_declarator);
else
{
tree fns = TREE_OPERAND (orig_declarator, 0);
@@ -8580,16 +8559,18 @@ grokfndecl (tree ctype,
DECL_CONTEXT (decl) = FROB_CONTEXT (current_decl_namespace ());
/* `main' and builtins have implicit 'C' linkage. */
- if ((MAIN_NAME_P (declarator)
- || (IDENTIFIER_LENGTH (declarator) > 10
- && IDENTIFIER_POINTER (declarator)[0] == '_'
- && IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0)
- || (targetcm.cxx_implicit_extern_c
- && targetcm.cxx_implicit_extern_c(IDENTIFIER_POINTER (declarator))))
+ if (ctype == NULL_TREE
+ && DECL_FILE_SCOPE_P (decl)
&& current_lang_name == lang_name_cplusplus
- && ctype == NULL_TREE
- && DECL_FILE_SCOPE_P (decl))
+ && (MAIN_NAME_P (declarator)
+ || (IDENTIFIER_LENGTH (declarator) > 10
+ && IDENTIFIER_POINTER (declarator)[0] == '_'
+ && IDENTIFIER_POINTER (declarator)[1] == '_'
+ && strncmp (IDENTIFIER_POINTER (declarator)+2,
+ "builtin_", 8) == 0)
+ || (targetcm.cxx_implicit_extern_c
+ && (targetcm.cxx_implicit_extern_c
+ (IDENTIFIER_POINTER (declarator))))))
SET_DECL_LANGUAGE (decl, lang_c);
/* Should probably propagate const out from type to decl I bet (mrs). */
@@ -9132,7 +9113,6 @@ build_ptrmemfunc_type (tree type)
this method instead of type_hash_canon, because it only does a
simple equality check on the list of field members. */
-
t = TYPE_PTRMEMFUNC_TYPE (type);
if (t)
return t;
@@ -9502,7 +9482,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
stabilize_vla_size (itype);
- if (sanitize_flags_p (SANITIZE_VLA))
+ if (sanitize_flags_p (SANITIZE_VLA)
+ && current_function_decl != NULL_TREE)
{
/* We have to add 1 -- in the ubsan routine we generate
LE_EXPR rather than LT_EXPR. */
@@ -9993,6 +9974,8 @@ grokdeclarator (const cp_declarator *declarator,
declspecs->locations);
if (typespec_loc == UNKNOWN_LOCATION)
typespec_loc = declspecs->locations[ds_type_spec];
+ if (typespec_loc == UNKNOWN_LOCATION)
+ typespec_loc = input_location;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
@@ -10068,8 +10051,6 @@ grokdeclarator (const cp_declarator *declarator,
{
case BIT_NOT_EXPR:
{
- tree type;
-
if (innermost_code != cdk_function)
{
error ("declaration of %qD as non-function", decl);
@@ -10082,7 +10063,7 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
}
- type = TREE_OPERAND (decl, 0);
+ tree type = TREE_OPERAND (decl, 0);
if (TYPE_P (type))
type = constructor_name (type);
name = identifier_to_locale (IDENTIFIER_POINTER (type));
@@ -10138,7 +10119,7 @@ grokdeclarator (const cp_declarator *declarator,
break;
case cdk_decomp:
- name = "decomposition";
+ name = "structured binding";
break;
case cdk_error:
@@ -10592,43 +10573,43 @@ grokdeclarator (const cp_declarator *declarator,
? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep)
error_at (declspecs->locations[ds_inline],
- "decomposition declaration cannot be declared %<inline%>");
+ "structured binding declaration cannot be %<inline%>");
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
- "decomposition declaration cannot be declared %<typedef%>");
+ "structured binding declaration cannot be %<typedef%>");
if (constexpr_p)
- error_at (declspecs->locations[ds_constexpr], "decomposition "
- "declaration cannot be declared %<constexpr%>");
+ error_at (declspecs->locations[ds_constexpr], "structured "
+ "binding declaration cannot be %<constexpr%>");
if (thread_p)
error_at (declspecs->locations[ds_thread],
- "decomposition declaration cannot be declared %qs",
+ "structured binding declaration cannot be %qs",
declspecs->gnu_thread_keyword_p
? "__thread" : "thread_local");
if (concept_p)
error_at (declspecs->locations[ds_concept],
- "decomposition declaration cannot be declared %<concept%>");
+ "structured binding declaration cannot be %<concept%>");
switch (storage_class)
{
case sc_none:
break;
case sc_register:
- error_at (loc, "decomposition declaration cannot be declared "
+ error_at (loc, "structured binding declaration cannot be "
"%<register%>");
break;
case sc_static:
- error_at (loc, "decomposition declaration cannot be declared "
+ error_at (loc, "structured binding declaration cannot be "
"%<static%>");
break;
case sc_extern:
- error_at (loc, "decomposition declaration cannot be declared "
+ error_at (loc, "structured binding declaration cannot be "
"%<extern%>");
break;
case sc_mutable:
- error_at (loc, "decomposition declaration cannot be declared "
+ error_at (loc, "structured binding declaration cannot be "
"%<mutable%>");
break;
case sc_auto:
- error_at (loc, "decomposition declaration cannot be declared "
+ error_at (loc, "structured binding declaration cannot be "
"C++98 %<auto%>");
break;
default:
@@ -10639,8 +10620,8 @@ grokdeclarator (const cp_declarator *declarator,
{
if (type != error_mark_node)
{
- error_at (loc, "decomposition declaration cannot be declared "
- "with type %qT", type);
+ error_at (loc, "structured binding declaration cannot have "
+ "type %qT", type);
inform (loc,
"type must be cv-qualified %<auto%> or reference to "
"cv-qualified %<auto%>");
@@ -10825,33 +10806,7 @@ grokdeclarator (const cp_declarator *declarator,
tree arg_types;
int funcdecl_p;
- /* Declaring a function type.
- Make sure we have a valid type for the function to return. */
-
- if (type_quals != TYPE_UNQUALIFIED)
- {
- if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
- {
- warning_at (typespec_loc, OPT_Wignored_qualifiers, "type "
- "qualifiers ignored on function return type");
- }
- /* We now know that the TYPE_QUALS don't apply to the
- decl, but to its return type. */
- type_quals = TYPE_UNQUALIFIED;
- }
-
- /* Error about some types functions can't return. */
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("%qs declared as function returning a function", name);
- return error_mark_node;
- }
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- error ("%qs declared as function returning an array", name);
- return error_mark_node;
- }
+ /* Declaring a function type. */
input_location = declspecs->locations[ds_type_spec];
abstract_virtuals_error (ACU_RETURN, type);
@@ -10959,7 +10914,35 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
if (late_return_type)
- late_return_type_p = true;
+ {
+ late_return_type_p = true;
+ type_quals = cp_type_quals (type);
+ }
+
+ if (type_quals != TYPE_UNQUALIFIED)
+ {
+ if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
+ warning_at (typespec_loc, OPT_Wignored_qualifiers, "type "
+ "qualifiers ignored on function return type");
+ /* We now know that the TYPE_QUALS don't apply to the
+ decl, but to its return type. */
+ type_quals = TYPE_UNQUALIFIED;
+ }
+
+ /* Error about some types functions can't return. */
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (typespec_loc, "%qs declared as function returning "
+ "a function", name);
+ return error_mark_node;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (typespec_loc, "%qs declared as function returning "
+ "an array", name);
+ return error_mark_node;
+ }
if (ctype == NULL_TREE
&& decl_context == FIELD
@@ -12590,9 +12573,11 @@ grokparms (tree parmlist, tree *parms)
}
else if (abstract_virtuals_error (decl, type))
any_error = 1; /* Seems like a good idea. */
- else if (POINTER_TYPE_P (type))
+ else if (cxx_dialect < cxx1z
+ && POINTER_TYPE_P (type))
{
- /* [dcl.fct]/6, parameter types cannot contain pointers
+ /* Before C++17 DR 393:
+ [dcl.fct]/6, parameter types cannot contain pointers
(references) to arrays of unknown bound. */
tree t = TREE_TYPE (type);
int ptr = TYPE_PTR_P (type);
@@ -12608,12 +12593,13 @@ grokparms (tree parmlist, tree *parms)
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
- error (ptr
- ? G_("parameter %qD includes pointer to array of "
- "unknown bound %qT")
- : G_("parameter %qD includes reference to array of "
- "unknown bound %qT"),
- decl, t);
+ pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+ ptr
+ ? G_("parameter %qD includes pointer to array of "
+ "unknown bound %qT")
+ : G_("parameter %qD includes reference to array of "
+ "unknown bound %qT"),
+ decl, t);
}
if (any_error)
@@ -12925,14 +12911,15 @@ grok_op_properties (tree decl, bool complain)
{
/* It'd be nice to hang something else of the identifier to
find CODE more directly. */
+ bool assign_op = IDENTIFIER_ASSIGN_OP_P (name);
const operator_name_info_t *oni
- = (IDENTIFIER_ASSIGN_OP_P (name)
- ? assignment_operator_name_info : operator_name_info);
- DECL_ASSIGNMENT_OPERATOR_P (decl) = IDENTIFIER_ASSIGN_OP_P (name);
+ = (assign_op ? assignment_operator_name_info : operator_name_info);
+
if (false)
;
#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \
- else if (oni[int (CODE)].identifier == name) \
+ else if (assign_op == (KIND == cik_assign_op) \
+ && oni[int (CODE)].identifier == name) \
operator_code = (CODE);
#include "operators.def"
#undef DEF_OPERATOR
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a4751460e06..2a52f8ca3e2 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -342,7 +342,7 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags)
DECL_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG)
- DECL_DESTRUCTOR_P (function) = 1;
+ DECL_CXX_DESTRUCTOR_P (function) = 1;
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
maybe_retrofit_in_chrg (function);
@@ -558,10 +558,6 @@ check_member_template (tree tmpl)
tree
check_classfn (tree ctype, tree function, tree template_parms)
{
- int ix;
- bool is_template;
- tree pushed_scope;
-
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
@@ -594,7 +590,7 @@ check_classfn (tree ctype, tree function, tree template_parms)
}
/* OK, is this a definition of a member template? */
- is_template = (template_parms != NULL_TREE);
+ bool is_template = (template_parms != NULL_TREE);
/* [temp.mem]
@@ -608,111 +604,88 @@ check_classfn (tree ctype, tree function, tree template_parms)
/* We must enter the scope here, because conversion operators are
named by target type, and type equivalence relies on typenames
resolving within the scope of CTYPE. */
- pushed_scope = push_scope (ctype);
- ix = class_method_index_for_fn (complete_type (ctype), function);
- if (ix >= 0)
- {
- vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (ctype);
-
- for (ovl_iterator iter ((*methods)[ix]); iter; ++iter)
- {
- tree fndecl = *iter;
- tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-
- /* We cannot simply call decls_match because this doesn't
- work for static member functions that are pretending to
- be methods, and because the name may have been changed by
- asm("new_name"). */
-
- /* Get rid of the this parameter on functions that become
- static. */
- if (DECL_STATIC_FUNCTION_P (fndecl)
- && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- p1 = TREE_CHAIN (p1);
-
- /* A member template definition only matches a member template
- declaration. */
- if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
- continue;
-
- /* ref-qualifier or absence of same must match. */
- if (type_memfn_rqual (TREE_TYPE (function))
- != type_memfn_rqual (TREE_TYPE (fndecl)))
- continue;
-
- // Include constraints in the match.
- tree c1 = get_constraints (function);
- tree c2 = get_constraints (fndecl);
-
- /* While finding a match, same types and params are not enough
- if the function is versioned. Also check version ("target")
- attributes. */
- if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
- TREE_TYPE (TREE_TYPE (fndecl)))
- && compparms (p1, p2)
- && !targetm.target_option.function_versions (function, fndecl)
- && (!is_template
- || comp_template_parms (template_parms,
- DECL_TEMPLATE_PARMS (fndecl)))
- && equivalent_constraints (c1, c2)
- && (DECL_TEMPLATE_SPECIALIZATION (function)
- == DECL_TEMPLATE_SPECIALIZATION (fndecl))
- && (!DECL_TEMPLATE_SPECIALIZATION (function)
- || (DECL_TI_TEMPLATE (function)
- == DECL_TI_TEMPLATE (fndecl))))
- {
- if (pushed_scope)
- pop_scope (pushed_scope);
- return fndecl;
- }
- }
-
- error_at (DECL_SOURCE_LOCATION (function),
- "prototype for %q#D does not match any in class %qT",
- function, ctype);
+ tree pushed_scope = push_scope (ctype);
+ tree matched = NULL_TREE;
+ tree fns = lookup_fnfields_slot (ctype, DECL_NAME (function));
+
+ for (ovl_iterator iter (fns); !matched && iter; ++iter)
+ {
+ tree fndecl = *iter;
+ tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
+ tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+
+ /* We cannot simply call decls_match because this doesn't work
+ for static member functions that are pretending to be
+ methods, and because the name may have been changed by
+ asm("new_name"). */
+
+ /* Get rid of the this parameter on functions that become
+ static. */
+ if (DECL_STATIC_FUNCTION_P (fndecl)
+ && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+ p1 = TREE_CHAIN (p1);
+
+ /* A member template definition only matches a member template
+ declaration. */
+ if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
+ continue;
- const char *format = NULL;
- tree first = OVL_FIRST ((*methods)[ix]);
- bool is_conv_op = DECL_CONV_FN_P (first);
- tree prev = NULL_TREE;
+ /* ref-qualifier or absence of same must match. */
+ if (type_memfn_rqual (TREE_TYPE (function))
+ != type_memfn_rqual (TREE_TYPE (fndecl)))
+ continue;
- if (is_conv_op)
- ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
- do
- {
- ovl_iterator iter ((*methods)[ix++]);
- if (is_conv_op && !DECL_CONV_FN_P (*iter))
- break;
- for (; iter; ++iter)
- {
- if (prev)
- {
- if (!format)
- format = N_("candidates are: %+#D");
- error (format, prev);
- format = " %+#D";
- }
- prev = *iter;
- }
- }
- while (is_conv_op && size_t (ix) < methods->length ());
- if (prev)
+ // Include constraints in the match.
+ tree c1 = get_constraints (function);
+ tree c2 = get_constraints (fndecl);
+
+ /* While finding a match, same types and params are not enough
+ if the function is versioned. Also check version ("target")
+ attributes. */
+ if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+ TREE_TYPE (TREE_TYPE (fndecl)))
+ && compparms (p1, p2)
+ && !targetm.target_option.function_versions (function, fndecl)
+ && (!is_template
+ || comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (fndecl)))
+ && equivalent_constraints (c1, c2)
+ && (DECL_TEMPLATE_SPECIALIZATION (function)
+ == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+ && (!DECL_TEMPLATE_SPECIALIZATION (function)
+ || (DECL_TI_TEMPLATE (function) == DECL_TI_TEMPLATE (fndecl))))
+ matched = fndecl;
+ }
+
+ if (!matched)
+ {
+ if (!COMPLETE_TYPE_P (ctype))
+ cxx_incomplete_type_error (function, ctype);
+ else
{
- if (!format)
- format = N_("candidate is: %+#D");
- error (format, prev);
+ if (DECL_CONV_FN_P (function))
+ fns = lookup_all_conversions (ctype);
+
+ error_at (DECL_SOURCE_LOCATION (function),
+ "no declaration matches %q#D", function);
+ if (fns)
+ print_candidates (fns);
+ else if (DECL_CONV_FN_P (function))
+ inform (DECL_SOURCE_LOCATION (function),
+ "no conversion operators declared");
+ else
+ inform (DECL_SOURCE_LOCATION (function),
+ "no functions named %qD", function);
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (ctype)),
+ "%#qT defined here", ctype);
}
+ matched = error_mark_node;
}
- else if (!COMPLETE_TYPE_P (ctype))
- cxx_incomplete_type_error (function, ctype);
- else
- error ("no %q#D member function declared in class %qT",
- function, ctype);
if (pushed_scope)
pop_scope (pushed_scope);
- return error_mark_node;
+
+ return matched;
}
/* DECL is a function with vague linkage. Remember it so that at the
@@ -1992,12 +1965,14 @@ decl_needed_p (tree decl)
/* If this entity was used, let the back end see it; it will decide
whether or not to emit it into the object file. */
if (TREE_USED (decl))
- return true;
+ return true;
+
/* Virtual functions might be needed for devirtualization. */
if (flag_devirtualize
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl))
return true;
+
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
return false;
@@ -2617,6 +2592,7 @@ reset_decl_linkage (tree decl)
determine_visibility (decl);
tentative_decl_linkage (decl);
}
+
static void
reset_type_linkage_2 (tree type)
{
@@ -2640,25 +2616,14 @@ reset_type_linkage_2 (tree type)
for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m))
{
tree mem = STRIP_TEMPLATE (m);
- if (VAR_P (mem))
+ if (TREE_CODE (mem) == VAR_DECL || TREE_CODE (mem) == FUNCTION_DECL)
reset_decl_linkage (mem);
}
- for (tree m = TYPE_METHODS (type); m; m = DECL_CHAIN (m))
- {
- tree mem = STRIP_TEMPLATE (m);
- reset_decl_linkage (mem);
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (mem))
- {
- /* Also update its name, for cxx_dwarf_name. */
- DECL_NAME (mem) = TYPE_IDENTIFIER (type);
- if (m != mem)
- DECL_NAME (m) = TYPE_IDENTIFIER (type);
- }
- }
binding_table_foreach (CLASSTYPE_NESTED_UTDS (type),
bt_reset_linkage_2, NULL);
}
}
+
static void
bt_reset_linkage_2 (binding_entry b, void */*data*/)
{
@@ -4803,7 +4768,6 @@ c_parse_final_cleanups (void)
perform_deferred_noexcept_checks ();
finish_repo ();
-
fini_constexpr ();
/* The entire file is now complete. If requested, dump everything
@@ -5030,19 +4994,13 @@ mark_used (tree decl, tsubst_flags_t complain)
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
- if (DECL_ARTIFICIAL (decl))
- {
- if (DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
- && LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
- {
- /* We mark a lambda conversion op as deleted if we can't
- generate it properly; see maybe_add_lambda_conv_op. */
- sorry ("converting lambda which uses %<...%> to "
- "function pointer");
- return false;
- }
- }
- if (complain & tf_error)
+ if (DECL_ARTIFICIAL (decl)
+ && DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
+ && LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
+ /* We mark a lambda conversion op as deleted if we can't
+ generate it properly; see maybe_add_lambda_conv_op. */
+ sorry ("converting lambda which uses %<...%> to function pointer");
+ else if (complain & tf_error)
{
error ("use of deleted function %qD", decl);
if (!maybe_explain_implicit_delete (decl))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 86fa804b317..2497c7f6d23 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2664,7 +2664,6 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
break;
case TRY_CATCH_EXPR:
- case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
dump_expr (pp, TREE_OPERAND (t, 0), flags);
break;
@@ -3173,10 +3172,6 @@ type_to_string (tree typ, int verbose)
if (len == aka_len && memcmp (p, p+aka_start, len) == 0)
p[len] = '\0';
}
-
- if (typ && TYPE_P (typ) && TREE_CODE (typ) == ENUMERAL_TYPE)
- pp_string (cxx_pp, M_(" {enum}"));
-
return pp_ggc_formatted_text (cxx_pp);
}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 9e41ec451af..208e52a405b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -218,7 +218,7 @@ dtor_nothrow (tree type)
if (CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
- return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
+ return TREE_NOTHROW (CLASSTYPE_DESTRUCTOR (type));
}
/* Build up a call to __cxa_end_catch, to destroy the exception object
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index a3c2ed09472..ef93bfe39ec 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -529,7 +529,7 @@ do_friend (tree ctype, tree declarator, tree decl,
/* A method friend. */
if (flags == NO_SPECIAL && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_CXX_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, decl, flags);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 90abd23a267..3fe8f18b2a9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1718,7 +1718,6 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
tsubst_flags_t complain)
{
tree type = TREE_TYPE (exp);
- tree ctor_name;
/* It fails because there may not be a constructor which takes
its own type as the first (or only parameter), but which does
@@ -1846,10 +1845,9 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
}
else
{
- if (true_exp == exp)
- ctor_name = complete_ctor_identifier;
- else
- ctor_name = base_ctor_identifier;
+ tree ctor_name = (true_exp == exp
+ ? complete_ctor_identifier : base_ctor_identifier);
+
rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
complain);
}
@@ -3912,7 +3910,8 @@ finish_length_check (tree atype, tree iterator, tree obase, unsigned n)
}
/* Don't check an array new when -fno-exceptions. */
}
- else if (sanitize_flags_p (SANITIZE_BOUNDS))
+ else if (sanitize_flags_p (SANITIZE_BOUNDS)
+ && current_function_decl != NULL_TREE)
{
/* Make sure the last element of the initializer is in bounds. */
finish_expr_stmt
@@ -4582,8 +4581,7 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
&& MAYBE_CLASS_TYPE_P (type) && !CLASSTYPE_FINAL (type)
&& TYPE_POLYMORPHIC_P (type))
{
- tree dtor;
- dtor = CLASSTYPE_DESTRUCTORS (type);
+ tree dtor = CLASSTYPE_DESTRUCTOR (type);
if (!dtor || !DECL_VINDEX (dtor))
{
if (CLASSTYPE_PURE_VIRTUALS (type))
@@ -4673,7 +4671,7 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
/* If the destructor is non-virtual, there is no deleting
variant. Instead, we must explicitly call the appropriate
`operator delete' here. */
- else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
+ else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTOR (type))
&& auto_delete == sfk_deleting_destructor)
{
/* We will use ADDR multiple times so we must save it. */
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 41d4921c1db..14ff6c2ae43 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -529,7 +529,10 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
else if (id != this_identifier && by_reference_p)
{
if (!lvalue_p (initializer))
- error ("cannot capture %qE by reference", initializer);
+ {
+ error ("cannot capture %qE by reference", initializer);
+ return error_mark_node;
+ }
}
else
{
@@ -1088,7 +1091,7 @@ maybe_add_lambda_conv_op (tree type)
/* First build up the conversion op. */
tree rettype = build_pointer_type (stattype);
- tree name = mangle_conv_op_name_for_type (rettype);
+ tree name = make_conv_op_name (rettype);
tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
tree fntype = build_method_type_directly (thistype, rettype, void_list_node);
tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 2fa26739c80..097fbb547d2 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -531,6 +531,74 @@ unqualified_fn_lookup_error (cp_expr name_expr)
return unqualified_name_lookup_error (name, loc);
}
+struct conv_type_hasher : ggc_ptr_hash<tree_node>
+{
+ static hashval_t hash (tree);
+ static bool equal (tree, tree);
+};
+
+/* This hash table maps TYPEs to the IDENTIFIER for a conversion
+ operator to TYPE. The nodes are IDENTIFIERs whose TREE_TYPE is the
+ TYPE. */
+
+static GTY (()) hash_table<conv_type_hasher> *conv_type_names;
+
+/* Hash a node (VAL1) in the table. */
+
+hashval_t
+conv_type_hasher::hash (tree val)
+{
+ return (hashval_t) TYPE_UID (TREE_TYPE (val));
+}
+
+/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
+
+bool
+conv_type_hasher::equal (tree val1, tree val2)
+{
+ return TREE_TYPE (val1) == val2;
+}
+
+/* Return an identifier for a conversion operator to TYPE. We can
+ get from the returned identifier to the type. */
+
+tree
+make_conv_op_name (tree type)
+{
+ tree *slot;
+ tree identifier;
+
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ if (conv_type_names == NULL)
+ conv_type_names = hash_table<conv_type_hasher>::create_ggc (31);
+
+ slot = conv_type_names->find_slot_with_hash (type,
+ (hashval_t) TYPE_UID (type),
+ INSERT);
+ identifier = *slot;
+ if (!identifier)
+ {
+ char buffer[64];
+
+ /* Create a unique name corresponding to TYPE. */
+ sprintf (buffer, "operator %lu",
+ (unsigned long) conv_type_names->elements ());
+ identifier = get_identifier (buffer);
+ *slot = identifier;
+
+ /* Hang TYPE off the identifier so it can be found easily later
+ when performing conversions. */
+ TREE_TYPE (identifier) = type;
+
+ /* Set the identifier kind so we know later it's a conversion. */
+ set_identifier_kind (identifier, cik_conv_op);
+ }
+
+ return identifier;
+}
+
/* Wrapper around build_lang_decl_loc(). Should gradually move to
build_lang_decl_loc() and then rename build_lang_decl_loc() back to
build_lang_decl(). */
@@ -698,7 +766,7 @@ copy_decl (tree decl MEM_STAT_DECL)
{
tree copy;
- copy = copy_node_stat (decl PASS_MEM_STAT);
+ copy = copy_node (decl PASS_MEM_STAT);
cxx_dup_lang_specific_decl (copy);
return copy;
}
@@ -731,7 +799,7 @@ copy_type (tree type MEM_STAT_DECL)
{
tree copy;
- copy = copy_node_stat (type PASS_MEM_STAT);
+ copy = copy_node (type PASS_MEM_STAT);
copy_lang_type (copy);
return copy;
}
@@ -741,21 +809,21 @@ copy_type (tree type MEM_STAT_DECL)
static bool
maybe_add_lang_type_raw (tree t)
{
- bool add = (RECORD_OR_UNION_CODE_P (TREE_CODE (t))
- || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM);
- if (add)
- {
- TYPE_LANG_SPECIFIC (t)
- = (struct lang_type *) (ggc_internal_cleared_alloc
- (sizeof (struct lang_type)));
+ if (!(RECORD_OR_UNION_CODE_P (TREE_CODE (t))
+ || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM))
+ return false;
+
+ TYPE_LANG_SPECIFIC (t)
+ = (struct lang_type *) (ggc_internal_cleared_alloc
+ (sizeof (struct lang_type)));
- if (GATHER_STATISTICS)
- {
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
- }
+ if (GATHER_STATISTICS)
+ {
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
}
- return add;
+
+ return true;
}
tree
@@ -799,3 +867,5 @@ in_main_input_context (void)
else
return filename_cmp (main_input_filename, LOCATION_FILE (input_location)) == 0;
}
+
+#include "gt-cp-lex.h"
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index e23591315c9..8bb26a9902b 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1460,11 +1460,6 @@ write_source_name (tree identifier)
{
MANGLE_TRACE_TREE ("source-name", identifier);
- /* Never write the whole template-id name including the template
- arguments; we only want the template name. */
- if (IDENTIFIER_TEMPLATE (identifier))
- identifier = IDENTIFIER_TEMPLATE (identifier);
-
write_unsigned_number (IDENTIFIER_LENGTH (identifier));
write_identifier (IDENTIFIER_POINTER (identifier));
}
@@ -4181,75 +4176,6 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
return result;
}
-struct conv_type_hasher : ggc_ptr_hash<tree_node>
-{
- static hashval_t hash (tree);
- static bool equal (tree, tree);
-};
-
-/* This hash table maps TYPEs to the IDENTIFIER for a conversion
- operator to TYPE. The nodes are IDENTIFIERs whose TREE_TYPE is the
- TYPE. */
-
-static GTY (()) hash_table<conv_type_hasher> *conv_type_names;
-
-/* Hash a node (VAL1) in the table. */
-
-hashval_t
-conv_type_hasher::hash (tree val)
-{
- return (hashval_t) TYPE_UID (TREE_TYPE (val));
-}
-
-/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
-
-bool
-conv_type_hasher::equal (tree val1, tree val2)
-{
- return TREE_TYPE (val1) == val2;
-}
-
-/* Return an identifier for the mangled unqualified name for a
- conversion operator to TYPE. This mangling is not specified by the
- ABI spec; it is only used internally. */
-
-tree
-mangle_conv_op_name_for_type (const tree type)
-{
- tree *slot;
- tree identifier;
-
- if (type == error_mark_node)
- return error_mark_node;
-
- if (conv_type_names == NULL)
- conv_type_names = hash_table<conv_type_hasher>::create_ggc (31);
-
- slot = conv_type_names->find_slot_with_hash (type,
- (hashval_t) TYPE_UID (type),
- INSERT);
- identifier = *slot;
- if (!identifier)
- {
- char buffer[64];
-
- /* Create a unique name corresponding to TYPE. */
- sprintf (buffer, "operator %lu",
- (unsigned long) conv_type_names->elements ());
- identifier = get_identifier (buffer);
- *slot = identifier;
-
- /* Hang TYPE off the identifier so it can be found easily later
- when performing conversions. */
- TREE_TYPE (identifier) = type;
-
- /* Set the identifier kind so we know later it's a conversion. */
- set_identifier_kind (identifier, cik_conv_op);
- }
-
- return identifier;
-}
-
/* Handle ABI backwards compatibility for past bugs where we didn't call
check_abi_tags in places where it's needed: call check_abi_tags and warn if
it makes a difference. If FOR_DECL is non-null, it's the declaration
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index fe4b2afe7db..8b07f526473 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -137,8 +137,8 @@ make_thunk (tree function, bool this_adjusting,
DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
/* The thunk itself is not a constructor or destructor, even if
the thing it is thunking to is. */
- DECL_DESTRUCTOR_P (thunk) = 0;
- DECL_CONSTRUCTOR_P (thunk) = 0;
+ DECL_CXX_DESTRUCTOR_P (thunk) = 0;
+ DECL_CXX_CONSTRUCTOR_P (thunk) = 0;
DECL_EXTERNAL (thunk) = 1;
DECL_ARTIFICIAL (thunk) = 1;
/* The THUNK is not a pending inline, even if the FUNCTION is. */
@@ -223,8 +223,8 @@ make_alias_for (tree target, tree newid)
if (TREE_CODE (alias) == FUNCTION_DECL)
{
DECL_SAVED_FUNCTION_DATA (alias) = NULL;
- DECL_DESTRUCTOR_P (alias) = 0;
- DECL_CONSTRUCTOR_P (alias) = 0;
+ DECL_CXX_DESTRUCTOR_P (alias) = 0;
+ DECL_CXX_CONSTRUCTOR_P (alias) = 0;
DECL_PENDING_INLINE_P (alias) = 0;
DECL_DECLARED_INLINE_P (alias) = 0;
DECL_INITIAL (alias) = error_mark_node;
@@ -1342,7 +1342,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
if (bad && deleted_p)
*deleted_p = true;
}
- else if (sfk == sfk_constructor)
+ else if (sfk == sfk_constructor || sfk == sfk_inheriting_constructor)
{
bool bad;
@@ -1808,10 +1808,8 @@ maybe_explain_implicit_delete (tree decl)
informed = false;
}
else if (DECL_ARTIFICIAL (decl)
- && (sfk == sfk_copy_assignment
- || sfk == sfk_copy_constructor)
- && (type_has_user_declared_move_constructor (ctype)
- || type_has_user_declared_move_assign (ctype)))
+ && (sfk == sfk_copy_assignment || sfk == sfk_copy_constructor)
+ && classtype_has_move_assign_or_move_ctor_p (ctype, true))
{
inform (DECL_SOURCE_LOCATION (decl),
"%q#D is implicitly declared as deleted because %qT "
@@ -1968,12 +1966,12 @@ implicitly_declare_fn (special_function_kind kind, tree type,
{
case sfk_destructor:
/* Destructor. */
- name = constructor_name (type);
+ name = dtor_identifier;
break;
case sfk_constructor:
/* Default constructor. */
- name = constructor_name (type);
+ name = ctor_identifier;
break;
case sfk_copy_constructor:
@@ -1982,7 +1980,6 @@ implicitly_declare_fn (special_function_kind kind, tree type,
case sfk_move_assignment:
case sfk_inheriting_constructor:
{
- bool move_p;
if (kind == sfk_copy_assignment
|| kind == sfk_move_assignment)
{
@@ -1990,7 +1987,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
name = cp_assignment_operator_id (NOP_EXPR);
}
else
- name = constructor_name (type);
+ name = ctor_identifier;
if (kind == sfk_inheriting_constructor)
parameter_types = inherited_parms;
@@ -2000,8 +1997,8 @@ implicitly_declare_fn (special_function_kind kind, tree type,
rhs_parm_type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
else
rhs_parm_type = type;
- move_p = (kind == sfk_move_assignment
- || kind == sfk_move_constructor);
+ bool move_p = (kind == sfk_move_assignment
+ || kind == sfk_move_constructor);
rhs_parm_type = cp_build_reference_type (rhs_parm_type, move_p);
parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
@@ -2054,16 +2051,14 @@ implicitly_declare_fn (special_function_kind kind, tree type,
fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
if (kind != sfk_inheriting_constructor)
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
- if (kind == sfk_constructor || kind == sfk_copy_constructor
- || kind == sfk_move_constructor || kind == sfk_inheriting_constructor)
- DECL_CONSTRUCTOR_P (fn) = 1;
- else if (kind == sfk_destructor)
- DECL_DESTRUCTOR_P (fn) = 1;
+
+ if (!IDENTIFIER_CDTOR_P (name))
+ /* Assignment operator. */
+ SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
+ else if (IDENTIFIER_CTOR_P (name))
+ DECL_CXX_CONSTRUCTOR_P (fn) = true;
else
- {
- DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
- SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
- }
+ DECL_CXX_DESTRUCTOR_P (fn) = true;
SET_DECL_ALIGN (fn, MINIMUM_METHOD_BOUNDARY);
@@ -2251,8 +2246,10 @@ after_nsdmi_defaulted_late_checks (tree t)
return;
if (t == error_mark_node)
return;
- for (tree fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
- if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn))
+ for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
+ if (!DECL_ARTIFICIAL (fn)
+ && DECL_DECLARES_FUNCTION_P (fn)
+ && DECL_DEFAULTED_IN_CLASS_P (fn))
{
tree fn_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec))
@@ -2375,31 +2372,34 @@ lazily_declare_fn (special_function_kind sfk, tree type)
/* [class.copy]/8 If the class definition declares a move constructor or
move assignment operator, the implicitly declared copy constructor is
defined as deleted.... */
- if ((sfk == sfk_copy_assignment
- || sfk == sfk_copy_constructor)
- && (type_has_user_declared_move_constructor (type)
- || type_has_user_declared_move_assign (type)))
+ if ((sfk == sfk_copy_assignment || sfk == sfk_copy_constructor)
+ && classtype_has_move_assign_or_move_ctor_p (type, true))
DECL_DELETED_FN (fn) = true;
- /* A destructor may be virtual. */
+ /* Destructors and assignment operators may be virtual. */
if (sfk == sfk_destructor
|| sfk == sfk_move_assignment
|| sfk == sfk_copy_assignment)
check_for_override (fn, type);
+
/* Add it to CLASSTYPE_METHOD_VEC. */
bool added = add_method (type, fn, false);
gcc_assert (added);
- /* Add it to TYPE_METHODS. */
+
+ /* Add it to TYPE_FIELDS. */
if (sfk == sfk_destructor
&& DECL_VIRTUAL_P (fn))
/* The ABI requires that a virtual destructor go at the end of the
vtable. */
- TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
+ TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), fn);
else
{
- DECL_CHAIN (fn) = TYPE_METHODS (type);
- TYPE_METHODS (type) = fn;
+ DECL_CHAIN (fn) = TYPE_FIELDS (type);
+ TYPE_FIELDS (type) = fn;
}
+ /* Propagate TYPE_FIELDS. */
+ fixup_type_variants (type);
+
maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 0df546a2e6a..4dc19da6ade 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2354,9 +2354,13 @@ do_pushdecl (tree decl, bool is_friend)
; /* Ignore using decls here. */
else if (tree match = duplicate_decls (decl, *iter, is_friend))
{
- if (iter.hidden_p ()
- && match != error_mark_node
- && !DECL_HIDDEN_P (match))
+ if (match == error_mark_node)
+ ;
+ else if (TREE_CODE (match) == TYPE_DECL)
+ /* The IDENTIFIER will have the type referring to the
+ now-smashed TYPE_DECL, because ...? Reset it. */
+ SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (match));
+ else if (iter.hidden_p () && !DECL_HIDDEN_P (match))
{
/* Unhiding a previously hidden decl. */
tree head = iter.reveal_node (old);
@@ -2422,6 +2426,9 @@ do_pushdecl (tree decl, bool is_friend)
{
ns = current_namespace;
slot = find_namespace_slot (ns, name, true);
+ /* Update OLD to reflect the namespace we're going to be
+ pushing into. */
+ old = MAYBE_STAT_DECL (*slot);
}
old = update_binding (level, binding, slot, old, decl, is_friend);
@@ -3183,27 +3190,14 @@ set_identifier_type_value (tree id, tree decl)
}
/* Return the name for the constructor (or destructor) for the
- specified class TYPE. When given a template, this routine doesn't
- lose the specialization. */
-
-static inline tree
-constructor_name_full (tree type)
-{
- return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
-}
-
-/* Return the name for the constructor (or destructor) for the
- specified class. When given a template, return the plain
- unspecialized name. */
+ specified class. */
tree
constructor_name (tree type)
{
- tree name;
- name = constructor_name_full (type);
- if (IDENTIFIER_TEMPLATE (name))
- name = IDENTIFIER_TEMPLATE (name);
- return name;
+ tree decl = TYPE_NAME (TYPE_MAIN_VARIANT (type));
+
+ return decl ? DECL_NAME (decl) : NULL_TREE;
}
/* Returns TRUE if NAME is the name for the constructor for TYPE,
@@ -3212,27 +3206,16 @@ constructor_name (tree type)
bool
constructor_name_p (tree name, tree type)
{
- tree ctor_name;
-
gcc_assert (MAYBE_CLASS_TYPE_P (type));
- if (!name)
- return false;
-
- if (!identifier_p (name))
- return false;
-
/* These don't have names. */
if (TREE_CODE (type) == DECLTYPE_TYPE
|| TREE_CODE (type) == TYPEOF_TYPE)
return false;
- ctor_name = constructor_name_full (type);
- if (name == ctor_name)
- return true;
- if (IDENTIFIER_TEMPLATE (ctor_name)
- && name == IDENTIFIER_TEMPLATE (ctor_name))
+ if (name && name == constructor_name (type))
return true;
+
return false;
}
@@ -3981,7 +3964,7 @@ push_class_level_binding_1 (tree name, tree x)
/* A data member of an anonymous union. */
|| (TREE_CODE (x) == FIELD_DECL
&& DECL_CONTEXT (x) != current_class_type))
- && DECL_NAME (x) == constructor_name (current_class_type))
+ && DECL_NAME (x) == DECL_NAME (TYPE_NAME (current_class_type)))
{
tree scope = context_for_name_lookup (x);
if (TYPE_P (scope) && same_type_p (scope, current_class_type))
@@ -4191,8 +4174,7 @@ do_class_using_decl (tree scope, tree name)
return NULL_TREE;
}
}
- else if (name == ctor_identifier
- && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo)))
+ else if (name == ctor_identifier && !binfo_direct_p (binfo))
{
error ("cannot inherit constructors from indirect base %qT", scope);
return NULL_TREE;
@@ -4778,7 +4760,7 @@ suggest_alternatives_for (location_t location, tree name,
/* Subroutine of maybe_suggest_missing_header for handling unrecognized names
for some of the most common names within "std::".
Given non-NULL NAME, a name for lookup within "std::", return the header
- name defining it within the C++ Standard Library (without '<' and '>'),
+ name defining it within the C++ Standard Library (with '<' and '>'),
or NULL. */
static const char *
@@ -4791,61 +4773,61 @@ get_std_name_hint (const char *name)
};
static const std_name_hint hints[] = {
/* <array>. */
- {"array", "array"}, // C++11
+ {"array", "<array>"}, // C++11
/* <deque>. */
- {"deque", "deque"},
+ {"deque", "<deque>"},
/* <forward_list>. */
- {"forward_list", "forward_list"}, // C++11
+ {"forward_list", "<forward_list>"}, // C++11
/* <fstream>. */
- {"basic_filebuf", "fstream"},
- {"basic_ifstream", "fstream"},
- {"basic_ofstream", "fstream"},
- {"basic_fstream", "fstream"},
+ {"basic_filebuf", "<fstream>"},
+ {"basic_ifstream", "<fstream>"},
+ {"basic_ofstream", "<fstream>"},
+ {"basic_fstream", "<fstream>"},
/* <iostream>. */
- {"cin", "iostream"},
- {"cout", "iostream"},
- {"cerr", "iostream"},
- {"clog", "iostream"},
- {"wcin", "iostream"},
- {"wcout", "iostream"},
- {"wclog", "iostream"},
+ {"cin", "<iostream>"},
+ {"cout", "<iostream>"},
+ {"cerr", "<iostream>"},
+ {"clog", "<iostream>"},
+ {"wcin", "<iostream>"},
+ {"wcout", "<iostream>"},
+ {"wclog", "<iostream>"},
/* <list>. */
- {"list", "list"},
+ {"list", "<list>"},
/* <map>. */
- {"map", "map"},
- {"multimap", "map"},
+ {"map", "<map>"},
+ {"multimap", "<map>"},
/* <queue>. */
- {"queue", "queue"},
- {"priority_queue", "queue"},
+ {"queue", "<queue>"},
+ {"priority_queue", "<queue>"},
/* <ostream>. */
- {"ostream", "ostream"},
- {"wostream", "ostream"},
- {"ends", "ostream"},
- {"flush", "ostream"},
- {"endl", "ostream"},
+ {"ostream", "<ostream>"},
+ {"wostream", "<ostream>"},
+ {"ends", "<ostream>"},
+ {"flush", "<ostream>"},
+ {"endl", "<ostream>"},
/* <set>. */
- {"set", "set"},
- {"multiset", "set"},
+ {"set", "<set>"},
+ {"multiset", "<set>"},
/* <sstream>. */
- {"basic_stringbuf", "sstream"},
- {"basic_istringstream", "sstream"},
- {"basic_ostringstream", "sstream"},
- {"basic_stringstream", "sstream"},
+ {"basic_stringbuf", "<sstream>"},
+ {"basic_istringstream", "<sstream>"},
+ {"basic_ostringstream", "<sstream>"},
+ {"basic_stringstream", "<sstream>"},
/* <stack>. */
- {"stack", "stack"},
+ {"stack", "<stack>"},
/* <string>. */
- {"string", "string"},
- {"wstring", "string"},
- {"u16string", "string"},
- {"u32string", "string"},
+ {"string", "<string>"},
+ {"wstring", "<string>"},
+ {"u16string", "<string>"},
+ {"u32string", "<string>"},
/* <unordered_map>. */
- {"unordered_map", "unordered_map"}, // C++11
- {"unordered_multimap", "unordered_map"}, // C++11
+ {"unordered_map", "<unordered_map>"}, // C++11
+ {"unordered_multimap", "<unordered_map>"}, // C++11
/* <unordered_set>. */
- {"unordered_set", "unordered_set"}, // C++11
- {"unordered_multiset", "unordered_set"}, // C++11
+ {"unordered_set", "<unordered_set>"}, // C++11
+ {"unordered_multiset", "<unordered_set>"}, // C++11
/* <vector>. */
- {"vector", "vector"},
+ {"vector", "<vector>"},
};
const size_t num_hints = sizeof (hints) / sizeof (hints[0]);
for (size_t i = 0; i < num_hints; i++)
@@ -4876,10 +4858,14 @@ maybe_suggest_missing_header (location_t location, tree name, tree scope)
const char *name_str = IDENTIFIER_POINTER (name);
const char *header_hint = get_std_name_hint (name_str);
if (header_hint)
- inform (location,
- "%<std::%s%> is defined in header %<<%s>%>;"
- " did you forget to %<#include <%s>%>?",
- name_str, header_hint, header_hint);
+ {
+ gcc_rich_location richloc (location);
+ maybe_add_include_fixit (&richloc, header_hint);
+ inform_at_rich_loc (&richloc,
+ "%<std::%s%> is defined in header %qs;"
+ " did you forget to %<#include %s%>?",
+ name_str, header_hint, header_hint);
+ }
}
/* Look for alternatives for NAME, an IDENTIFIER_NODE for which name
@@ -6059,11 +6045,12 @@ add_using_namespace (vec<tree, va_gc> *&usings, tree target)
/* Tell the debug system of a using directive. */
static void
-emit_debug_info_using_namespace (tree from, tree target)
+emit_debug_info_using_namespace (tree from, tree target, bool implicit)
{
/* Emit debugging info. */
tree context = from != global_namespace ? from : NULL_TREE;
- debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false);
+ debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false,
+ implicit);
}
/* Process a namespace-scope using directive. */
@@ -6078,7 +6065,7 @@ finish_namespace_using_directive (tree target, tree attribs)
add_using_namespace (DECL_NAMESPACE_USING (current_namespace),
ORIGINAL_NAMESPACE (target));
emit_debug_info_using_namespace (current_namespace,
- ORIGINAL_NAMESPACE (target));
+ ORIGINAL_NAMESPACE (target), false);
if (attribs == error_mark_node)
return;
@@ -6237,14 +6224,14 @@ push_namespace (tree name, bool make_inline)
else if (TREE_PUBLIC (current_namespace))
TREE_PUBLIC (ns) = 1;
- if (name == anon_identifier || make_inline)
- emit_debug_info_using_namespace (current_namespace, ns);
-
if (make_inline)
{
DECL_NAMESPACE_INLINE_P (ns) = true;
vec_safe_push (DECL_NAMESPACE_INLINEES (current_namespace), ns);
}
+
+ if (name == anon_identifier || make_inline)
+ emit_debug_info_using_namespace (current_namespace, ns, true);
}
}
@@ -6372,8 +6359,8 @@ cp_emit_debug_info_for_using (tree t, tree context)
if (building_stmt_list_p ())
add_stmt (build_stmt (input_location, USING_STMT, fn));
else
- debug_hooks->imported_module_or_decl (fn,
- NULL_TREE, context, false);
+ debug_hooks->imported_module_or_decl (fn, NULL_TREE, context,
+ false, false);
}
}
}
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index d646ef73803..a1c387092d4 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -326,7 +326,7 @@ maybe_thunk_body (tree fn, bool force)
}
args = XALLOCAVEC (tree, max_parms);
- /* We know that any clones immediately follow FN in TYPE_METHODS. */
+ /* We know that any clones immediately follow FN in TYPE_FIELDS. */
FOR_EACH_CLONE (clone, fn)
{
tree clone_parm;
@@ -447,7 +447,7 @@ maybe_clone_body (tree fn)
if (!tree_versionable_function_p (fn))
need_alias = true;
- /* We know that any clones immediately follow FN in the TYPE_METHODS
+ /* We know that any clones immediately follow FN in the TYPE_FIELDS
list. */
push_to_top_level ();
for (idx = 0; idx < 3; idx++)
@@ -516,7 +516,7 @@ maybe_clone_body (tree fn)
/* Emit the DWARF1 abstract instance. */
(*debug_hooks->deferred_inline_function) (fn);
- /* We know that any clones immediately follow FN in the TYPE_METHODS list. */
+ /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
for (idx = 0; idx < 3; idx++)
{
tree parm;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 634047e5d05..88d0b2b250d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -173,7 +173,7 @@ enum required_token {
RT_AT_THROW, /* @throw */
RT_SELECT, /* selection-statement */
- RT_INTERATION, /* iteration-statement */
+ RT_ITERATION, /* iteration-statement */
RT_JUMP, /* jump-statement */
RT_CLASS_KEY, /* class-key */
RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */
@@ -2039,7 +2039,7 @@ static cp_expr cp_parser_id_expression
static cp_expr cp_parser_unqualified_id
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
- (cp_parser *, bool, bool, bool, bool);
+ (cp_parser *, bool, bool, bool, bool, bool = false);
static tree cp_parser_nested_name_specifier
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_qualifying_entity
@@ -2102,7 +2102,7 @@ static void cp_parser_lambda_body
/* Statements [gram.stmt.stmt] */
static void cp_parser_statement
- (cp_parser *, tree, bool, bool *, vec<tree> * = NULL);
+ (cp_parser *, tree, bool, bool *, vec<tree> * = NULL, location_t * = NULL);
static void cp_parser_label_for_labeled_statement
(cp_parser *, tree);
static tree cp_parser_expression_statement
@@ -3253,6 +3253,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
error_at (location_of (id),
"%qE in namespace %qE does not name a template type",
id, parser->scope);
+ else if (TREE_CODE (id) == TEMPLATE_ID_EXPR)
+ error_at (location_of (id),
+ "%qE in namespace %qE does not name a template type",
+ TREE_OPERAND (id, 0), parser->scope);
else
error_at (location_of (id),
"%qE in namespace %qE does not name a type",
@@ -3296,6 +3300,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
error_at (location_of (id),
"%qE in %q#T does not name a template type",
id, parser->scope);
+ else if (TREE_CODE (id) == TEMPLATE_ID_EXPR)
+ error_at (location_of (id),
+ "%qE in %q#T does not name a template type",
+ TREE_OPERAND (id, 0), parser->scope);
else
error_at (location_of (id),
"%qE in %q#T does not name a type",
@@ -5420,16 +5428,21 @@ cp_parser_id_expression (cp_parser *parser,
/* Look for the optional `::' operator. */
global_scope_p
- = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
- != NULL_TREE);
+ = (!template_keyword_p
+ && (cp_parser_global_scope_opt (parser,
+ /*current_scope_valid_p=*/false)
+ != NULL_TREE));
+
/* Look for the optional nested-name-specifier. */
nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
check_dependency_p,
/*type_p=*/false,
- declarator_p)
+ declarator_p,
+ template_keyword_p)
!= NULL_TREE);
+
/* If there is a nested-name-specifier, then we are looking at
the first qualified-id production. */
if (nested_name_specifier_p)
@@ -5874,7 +5887,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
bool typename_keyword_p,
bool check_dependency_p,
bool type_p,
- bool is_declaration)
+ bool is_declaration,
+ bool template_keyword_p /* = false */)
{
bool success = false;
cp_token_position start = 0;
@@ -5892,7 +5906,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
tree new_scope;
tree old_scope;
tree saved_qualifying_scope;
- bool template_keyword_p;
/* Spot cases that cannot be the beginning of a
nested-name-specifier. */
@@ -5967,8 +5980,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
first time through the loop. */
if (success)
template_keyword_p = cp_parser_optional_template_keyword (parser);
- else
- template_keyword_p = false;
/* Save the old scope since the name lookup we are about to do
might destroy it. */
@@ -6531,7 +6542,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Look for the `)' token. Otherwise, we can't be sure that
we're not looking at an expression: consider `typeid (int
(3))', for example. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN,
+ RT_CLOSE_PAREN);
/* If all went well, simply lookup the type-id. */
if (cp_parser_parse_definitely (parser))
postfix_expression = get_typeid (type, tf_warning_or_error);
@@ -6545,13 +6557,26 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Compute its typeid. */
postfix_expression = build_typeid (expression, tf_warning_or_error);
/* Look for the `)' token. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ close_paren
+ = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
}
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* `typeid' may not appear in an integral constant expression. */
if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID))
postfix_expression = error_mark_node;
+
+ /* Construct a location e.g. :
+ typeid (expr)
+ ^~~~~~~~~~~~~
+ ranging from the start of the "typeid" token to the final closing
+ paren, with the caret at the start. */
+ if (close_paren)
+ {
+ location_t typeid_loc
+ = make_location (start_loc, start_loc, close_paren->location);
+ postfix_expression.set_location (typeid_loc);
+ }
}
break;
@@ -8865,7 +8890,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
maybe_add_cast_fixit (&rich_loc, open_paren_loc, close_paren_loc,
expr, type);
warning_at_rich_loc (&rich_loc, OPT_Wold_style_cast,
- "use of old-style cast to %qT", type);
+ "use of old-style cast to %q#T", type);
}
/* Only type conversions to integral or enumeration types
@@ -10637,7 +10662,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
static void
cp_parser_statement (cp_parser* parser, tree in_statement_expr,
- bool in_compound, bool *if_p, vec<tree> *chain)
+ bool in_compound, bool *if_p, vec<tree> *chain,
+ location_t *loc_after_labels)
{
tree statement, std_attrs = NULL_TREE;
cp_token *token;
@@ -10830,6 +10856,10 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
if (cp_parser_parse_definitely (parser))
return;
}
+ /* All preceding labels have been parsed at this point. */
+ if (loc_after_labels != NULL)
+ *loc_after_labels = statement_location;
+
/* Look for an expression-statement instead. */
statement = cp_parser_expression_statement (parser, in_statement_expr);
@@ -12031,7 +12061,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
token_indent_info guard_tinfo;
/* Peek at the next token. */
- token = cp_parser_require (parser, CPP_KEYWORD, RT_INTERATION);
+ token = cp_parser_require (parser, CPP_KEYWORD, RT_ITERATION);
if (!token)
return error_mark_node;
@@ -12370,6 +12400,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
{
tree statement;
location_t body_loc = cp_lexer_peek_token (parser->lexer)->location;
+ location_t body_loc_after_labels = UNKNOWN_LOCATION;
token_indent_info body_tinfo
= get_token_indent_info (cp_lexer_peek_token (parser->lexer));
@@ -12399,7 +12430,8 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
/* Create a compound-statement. */
statement = begin_compound_stmt (0);
/* Parse the dependent-statement. */
- cp_parser_statement (parser, NULL_TREE, false, if_p, chain);
+ cp_parser_statement (parser, NULL_TREE, false, if_p, chain,
+ &body_loc_after_labels);
/* Finish the dummy compound-statement. */
finish_compound_stmt (statement);
}
@@ -12408,6 +12440,11 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
= get_token_indent_info (cp_lexer_peek_token (parser->lexer));
warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo);
+ if (body_loc_after_labels != UNKNOWN_LOCATION
+ && next_tinfo.type != CPP_SEMICOLON)
+ warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
+ guard_tinfo.location, guard_tinfo.keyword);
+
/* Return the statement. */
return statement;
}
@@ -12426,11 +12463,19 @@ cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
{
token_indent_info body_tinfo
= get_token_indent_info (cp_lexer_peek_token (parser->lexer));
+ location_t loc_after_labels = UNKNOWN_LOCATION;
- cp_parser_statement (parser, NULL_TREE, false, if_p);
+ cp_parser_statement (parser, NULL_TREE, false, if_p, NULL,
+ &loc_after_labels);
token_indent_info next_tinfo
= get_token_indent_info (cp_lexer_peek_token (parser->lexer));
warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo);
+
+ if (loc_after_labels != UNKNOWN_LOCATION
+ && next_tinfo.type != CPP_SEMICOLON)
+ warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
+ guard_tinfo.location,
+ guard_tinfo.keyword);
}
else
{
@@ -13105,7 +13150,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
}
if (cxx_dialect < cxx1z)
- pedwarn (loc, 0, "decomposition declaration only available with "
+ pedwarn (loc, 0, "structured bindings only available with "
"-std=c++1z or -std=gnu++1z");
tree pushed_scope;
@@ -13154,7 +13199,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
if (v.is_empty ())
{
- error_at (loc, "empty decomposition declaration");
+ error_at (loc, "empty structured binding declaration");
decl = error_mark_node;
}
@@ -13165,6 +13210,16 @@ cp_parser_decomposition_declaration (cp_parser *parser,
*init_loc = cp_lexer_peek_token (parser->lexer)->location;
tree initializer = cp_parser_initializer (parser, &is_direct_init,
&non_constant_p);
+ if (initializer == NULL_TREE
+ || (TREE_CODE (initializer) == TREE_LIST
+ && TREE_CHAIN (initializer))
+ || (TREE_CODE (initializer) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (initializer) != 1))
+ {
+ error_at (loc, "invalid initializer for structured binding "
+ "declaration");
+ initializer = error_mark_node;
+ }
if (decl != error_mark_node)
{
@@ -13327,7 +13382,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
case RID_FRIEND:
if (!at_class_scope_p ())
{
- error_at (token->location, "%<friend%> used outside of class");
+ gcc_rich_location richloc (token->location);
+ richloc.add_fixit_remove ();
+ error_at_rich_loc (&richloc, "%<friend%> used outside of class");
cp_lexer_purge_token (parser->lexer);
}
else
@@ -13389,10 +13446,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
- /* Complain about `auto' as a storage specifier, if
- we're complaining about C++0x compatibility. */
- warning_at (token->location, OPT_Wc__11_compat, "%<auto%>"
- " changes meaning in C++11; please remove it");
+ /* Complain about `auto' as a storage specifier, if
+ we're complaining about C++0x compatibility. */
+ gcc_rich_location richloc (token->location);
+ richloc.add_fixit_remove ();
+ warning_at_rich_loc (&richloc, OPT_Wc__11_compat,
+ "%<auto%> changes meaning in C++11; "
+ "please remove it");
/* Set the storage class anyway. */
cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
@@ -14036,7 +14096,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
/* If the TYPE is invalid, indicate failure. */
if (type == error_mark_node)
return error_mark_node;
- return mangle_conv_op_name_for_type (type);
+ return make_conv_op_name (type);
}
/* Parse a conversion-type-id:
@@ -15502,17 +15562,17 @@ cp_parser_template_id (cp_parser *parser,
/* If the next token corresponds to a template-id, there is no need
to reparse it. */
- next_token = cp_lexer_peek_token (parser->lexer);
- if (next_token->type == CPP_TEMPLATE_ID)
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_TEMPLATE_ID)
{
cp_lexer_consume_token (parser->lexer);
- return saved_checks_value (next_token->u.tree_check_value);
+ return saved_checks_value (token->u.tree_check_value);
}
/* Avoid performing name lookup if there is no possibility of
finding a template-id. */
- if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR)
- || (next_token->type == CPP_NAME
+ if ((token->type != CPP_NAME && token->keyword != RID_OPERATOR)
+ || (token->type == CPP_NAME
&& !cp_parser_nth_token_starts_template_argument_list_p
(parser, 2)))
{
@@ -15603,9 +15663,19 @@ cp_parser_template_id (cp_parser *parser,
arguments = cp_parser_enclosed_template_argument_list (parser);
}
+ /* Set the location to be of the form:
+ template-name < template-argument-list [opt] >
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ with caret == start at the start of the template-name,
+ ranging until the closing '>'. */
+ location_t finish_loc
+ = get_finish (cp_lexer_previous_token (parser->lexer)->location);
+ location_t combined_loc
+ = make_location (token->location, token->location, finish_loc);
+
/* Build a representation of the specialization. */
if (identifier_p (templ))
- template_id = build_min_nt_loc (next_token->location,
+ template_id = build_min_nt_loc (combined_loc,
TEMPLATE_ID_EXPR,
templ, arguments);
else if (DECL_TYPE_TEMPLATE_P (templ)
@@ -15632,7 +15702,7 @@ cp_parser_template_id (cp_parser *parser,
{
template_id = lookup_template_variable (templ, arguments);
if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)
- SET_EXPR_LOCATION (template_id, next_token->location);
+ SET_EXPR_LOCATION (template_id, combined_loc);
}
else
{
@@ -15644,7 +15714,7 @@ cp_parser_template_id (cp_parser *parser,
template_id = lookup_template_function (templ, arguments);
if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)
- SET_EXPR_LOCATION (template_id, next_token->location);
+ SET_EXPR_LOCATION (template_id, combined_loc);
}
/* If parsing tentatively, replace the sequence of tokens that makes
@@ -15660,20 +15730,8 @@ cp_parser_template_id (cp_parser *parser,
&& cp_parser_parsing_tentatively (parser)
&& parser->in_declarator_p))
{
- cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
-
/* Reset the contents of the START_OF_ID token. */
token->type = CPP_TEMPLATE_ID;
-
- /* Update the location to be of the form:
- template-name < template-argument-list [opt] >
- ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- with caret == start at the start of the template-name,
- ranging until the closing '>'. */
- location_t finish_loc
- = get_finish (cp_lexer_previous_token (parser->lexer)->location);
- location_t combined_loc
- = make_location (token->location, token->location, finish_loc);
token->location = combined_loc;
/* We must mark the lookup as kept, so we don't throw it away on
@@ -15843,15 +15901,19 @@ cp_parser_template_name (cp_parser* parser,
no point in doing name-lookup, so we just return IDENTIFIER.
But, if the qualifying scope is non-dependent then we can
(and must) do name-lookup normally. */
- if (template_keyword_p
- && (!parser->scope
- || (TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))))
+ if (template_keyword_p)
{
- /* We're optimizing away the call to cp_parser_lookup_name, but we
- still need to do this. */
- parser->context->object_type = NULL_TREE;
- return identifier;
+ tree scope = (parser->scope ? parser->scope
+ : parser->context->object_type);
+ if (scope && TYPE_P (scope)
+ && (!CLASS_TYPE_P (scope)
+ || (check_dependency_p && dependent_type_p (scope))))
+ {
+ /* We're optimizing away the call to cp_parser_lookup_name, but
+ we still need to do this. */
+ parser->context->object_type = NULL_TREE;
+ return identifier;
+ }
}
}
@@ -18359,13 +18421,14 @@ cp_parser_namespace_definition (cp_parser* parser)
warning (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
/* Look for the `{' to validate starting the namespace. */
- cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
-
- /* Parse the body of the namespace. */
- cp_parser_namespace_body (parser);
+ if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+ {
+ /* Parse the body of the namespace. */
+ cp_parser_namespace_body (parser);
- /* Look for the final `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ /* Look for the final `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+ }
if (has_visibility)
pop_visibility (1);
@@ -20068,26 +20131,8 @@ cp_parser_direct_declarator (cp_parser* parser,
if (TREE_CODE (unqualified_name) == TYPE_DECL)
{
tree name_type = TREE_TYPE (unqualified_name);
- if (class_type && same_type_p (name_type, class_type))
- {
- if (qualifying_scope
- && CLASSTYPE_USE_TEMPLATE (name_type))
- {
- error_at (declarator_id_start_token->location,
- "invalid use of constructor as a template");
- inform (declarator_id_start_token->location,
- "use %<%T::%D%> instead of %<%T::%D%> to "
- "name the constructor in a qualified name",
- class_type,
- DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
- class_type, name_type);
- declarator = cp_error_declarator;
- break;
- }
- else
- unqualified_name = constructor_name (class_type);
- }
- else
+
+ if (!class_type || !same_type_p (name_type, class_type))
{
/* We do not attempt to print the declarator
here because we do not have enough
@@ -20097,6 +20142,21 @@ cp_parser_direct_declarator (cp_parser* parser,
declarator = cp_error_declarator;
break;
}
+ else if (qualifying_scope
+ && CLASSTYPE_USE_TEMPLATE (name_type))
+ {
+ error_at (declarator_id_start_token->location,
+ "invalid use of constructor as a template");
+ inform (declarator_id_start_token->location,
+ "use %<%T::%D%> instead of %<%T::%D%> to "
+ "name the constructor in a qualified name",
+ class_type,
+ DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+ class_type, name_type);
+ declarator = cp_error_declarator;
+ break;
+ }
+ unqualified_name = constructor_name (class_type);
}
if (class_type)
@@ -20126,14 +20186,10 @@ cp_parser_direct_declarator (cp_parser* parser,
struct S {
friend void N::S();
}; */
- && !(friend_p
- && class_type != qualifying_scope)
+ && (!friend_p || class_type == qualifying_scope)
&& constructor_name_p (unqualified_name,
class_type))
- {
- unqualified_name = constructor_name (class_type);
- sfk = sfk_constructor;
- }
+ sfk = sfk_constructor;
else if (is_overloaded_fn (unqualified_name)
&& DECL_CONSTRUCTOR_P (get_first_fn
(unqualified_name)))
@@ -22564,6 +22620,9 @@ cp_parser_class_head (cp_parser* parser,
/*is_declaration=*/false);
/* If there was a nested-name-specifier, then there *must* be an
identifier. */
+
+ cp_token *bad_template_keyword = NULL;
+
if (nested_name_specifier)
{
type_start_token = cp_lexer_peek_token (parser->lexer);
@@ -22585,6 +22644,8 @@ cp_parser_class_head (cp_parser* parser,
class-name is a template-id; if we looked for the
template-name first we would stop after the template-name. */
cp_parser_parse_tentatively (parser);
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
+ bad_template_keyword = cp_lexer_consume_token (parser->lexer);
type = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
@@ -22704,6 +22765,12 @@ cp_parser_class_head (cp_parser* parser,
{
tree scope;
+ if (bad_template_keyword)
+ /* [temp.names]: in a qualified-id formed by a class-head-name, the
+ keyword template shall not appear at the top level. */
+ pedwarn (bad_template_keyword->location, OPT_Wpedantic,
+ "keyword %<template%> not allowed in class-head-name");
+
/* Reject typedef-names in class heads. */
if (!DECL_IMPLICIT_TYPEDEF_P (type))
{
@@ -25659,12 +25726,14 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/* If that's not a class type, there is no destructor. */
if (!type || !CLASS_TYPE_P (type))
return error_mark_node;
+
if (CLASSTYPE_LAZY_DESTRUCTOR (type))
lazily_declare_fn (sfk_destructor, type);
- if (!CLASSTYPE_DESTRUCTORS (type))
- return error_mark_node;
- /* If it was a class type, return the destructor. */
- return CLASSTYPE_DESTRUCTORS (type);
+
+ if (tree dtor = CLASSTYPE_DESTRUCTOR (type))
+ return dtor;
+
+ return error_mark_node;
}
/* By this point, the NAME should be an ordinary identifier. If
@@ -28009,7 +28078,7 @@ cp_parser_required_error (cp_parser *parser,
case RT_SELECT:
cp_parser_error (parser, "expected selection-statement");
return;
- case RT_INTERATION:
+ case RT_ITERATION:
cp_parser_error (parser, "expected iteration-statement");
return;
case RT_JUMP:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 392fba07714..ee4e6b11334 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "type-utils.h"
#include "gimplify.h"
+#include "gcc-rich-location.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
@@ -1196,15 +1197,10 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
= retrieve_specialization (class_template, args, 0);
if (!class_specialization)
return NULL_TREE;
- /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
- for the specialization. */
- int idx = class_method_index_for_fn (class_specialization, tmpl);
- if (idx == -1)
- return NULL_TREE;
- /* Iterate through the methods with the indicated name, looking
- for the one that has an instance of TMPL. */
- vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_specialization);
- for (ovl_iterator iter ((*methods)[idx]); iter; ++iter)
+
+ /* Find the instance of TMPL. */
+ tree fns = lookup_fnfields_slot (class_specialization, DECL_NAME (tmpl));
+ for (ovl_iterator iter (fns); iter; ++iter)
{
tree fn = *iter;
if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl
@@ -2876,15 +2872,12 @@ check_explicit_specialization (tree declarator,
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
- tree fns = NULL_TREE;
- int idx;
if (constructor_name_p (name, ctype))
{
- int is_constructor = DECL_CONSTRUCTOR_P (decl);
-
- if (is_constructor ? !TYPE_HAS_USER_CONSTRUCTOR (ctype)
- : !CLASSTYPE_DESTRUCTORS (ctype))
+ if (DECL_CONSTRUCTOR_P (decl)
+ ? !TYPE_HAS_USER_CONSTRUCTOR (ctype)
+ : !CLASSTYPE_DESTRUCTOR (ctype))
{
/* From [temp.expl.spec]:
@@ -2898,42 +2891,19 @@ check_explicit_specialization (tree declarator,
return error_mark_node;
}
- name = is_constructor ? ctor_identifier : dtor_identifier;
+ name = DECL_NAME (decl);
}
- if (!DECL_CONV_FN_P (decl))
- {
- idx = lookup_fnfields_1 (ctype, name);
- if (idx >= 0)
- fns = (*CLASSTYPE_METHOD_VEC (ctype))[idx];
- }
+ tree fns = NULL_TREE;
+ if (DECL_CONV_FN_P (decl))
+ /* For a type-conversion operator, we cannot do a
+ name-based lookup. We might be looking for `operator
+ int' which will be a specialization of `operator T'.
+ Grab all the conversion operators, and then select from
+ them. */
+ fns = lookup_all_conversions (ctype);
else
- {
- vec<tree, va_gc> *methods;
- tree ovl;
-
- /* For a type-conversion operator, we cannot do a
- name-based lookup. We might be looking for `operator
- int' which will be a specialization of `operator T'.
- So, we find *all* the conversion operators, and then
- select from them. */
- fns = NULL_TREE;
-
- methods = CLASSTYPE_METHOD_VEC (ctype);
- if (methods)
- for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
- methods->iterate (idx, &ovl);
- ++idx)
- {
- if (!DECL_CONV_FN_P (OVL_FIRST (ovl)))
- /* There are no more conversion functions. */
- break;
-
- /* Glue all these conversion functions together
- with those we already have. */
- fns = lookup_add (ovl, fns);
- }
- }
+ fns = lookup_fnfields_slot_nolazy (ctype, name);
if (fns == NULL_TREE)
{
@@ -7170,26 +7140,68 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg,
parmvec = expand_template_argument_pack (parmvec);
argvec = expand_template_argument_pack (argvec);
- tree nparmvec = parmvec;
if (flag_new_ttp)
{
/* In keeping with P0522R0, adjust P's template arguments
to apply to A's template; then flatten it again. */
+ tree nparmvec = parmvec;
nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none);
nparmvec = expand_template_argument_pack (nparmvec);
- }
- if (unify (tparms, targs, nparmvec, argvec,
- UNIFY_ALLOW_NONE, explain_p))
- return 1;
+ if (unify (tparms, targs, nparmvec, argvec,
+ UNIFY_ALLOW_NONE, explain_p))
+ return 1;
- /* If the P0522 adjustment eliminated a pack expansion, deduce
- empty packs. */
- if (flag_new_ttp
- && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec)
- && unify_pack_expansion (tparms, targs, parmvec, argvec,
- DEDUCE_EXACT, /*sub*/true, explain_p))
- return 1;
+ /* If the P0522 adjustment eliminated a pack expansion, deduce
+ empty packs. */
+ if (flag_new_ttp
+ && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec)
+ && unify_pack_expansion (tparms, targs, parmvec, argvec,
+ DEDUCE_EXACT, /*sub*/true, explain_p))
+ return 1;
+ }
+ else
+ {
+ /* Deduce arguments T, i from TT<T> or TT<i>.
+ We check each element of PARMVEC and ARGVEC individually
+ rather than the whole TREE_VEC since they can have
+ different number of elements, which is allowed under N2555. */
+
+ int len = TREE_VEC_LENGTH (parmvec);
+
+ /* Check if the parameters end in a pack, making them
+ variadic. */
+ int parm_variadic_p = 0;
+ if (len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
+ parm_variadic_p = 1;
+
+ for (int i = 0; i < len - parm_variadic_p; ++i)
+ /* If the template argument list of P contains a pack
+ expansion that is not the last template argument, the
+ entire template argument list is a non-deduced
+ context. */
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, i)))
+ return unify_success (explain_p);
+
+ if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
+ return unify_too_few_arguments (explain_p,
+ TREE_VEC_LENGTH (argvec), len);
+
+ for (int i = 0; i < len - parm_variadic_p; ++i)
+ if (unify (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE, explain_p))
+ return 1;
+
+ if (parm_variadic_p
+ && unify_pack_expansion (tparms, targs,
+ parmvec, argvec,
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p))
+ return 1;
+ }
return 0;
}
@@ -7653,7 +7665,7 @@ convert_template_argument (tree parm,
if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
/* The number of argument required is not known yet.
Just accept it for now. */
- val = TREE_TYPE (arg);
+ val = orig_arg;
else
{
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
@@ -10539,7 +10551,6 @@ instantiate_class_template_1 (tree type)
}
else if (DECL_DECLARES_FUNCTION_P (t))
{
- /* Build new TYPE_METHODS. */
tree r;
if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -12235,22 +12246,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
case FUNCTION_DECL:
{
- tree ctx;
- tree argvec = NULL_TREE;
- tree *friends;
- tree gen_tmpl;
- tree type;
- int member;
- int args_depth;
- int parms_depth;
+ tree gen_tmpl, argvec;
/* Nobody should be tsubst'ing into non-template functions. */
gcc_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE);
if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
{
- tree spec;
-
/* If T is not dependent, just return it. */
if (!uses_template_parms (DECL_TI_ARGS (t)))
RETURN (t);
@@ -12268,9 +12270,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Check to see if we already have this specialization. */
hash = hash_tmpl_and_args (gen_tmpl, argvec);
- spec = retrieve_specialization (gen_tmpl, argvec, hash);
-
- if (spec)
+ if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash))
{
r = spec;
break;
@@ -12308,11 +12308,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
which we can spot because the pattern will be a
specialization in this case. */
- args_depth = TMPL_ARGS_DEPTH (args);
- parms_depth =
+ int args_depth = TMPL_ARGS_DEPTH (args);
+ int parms_depth =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
- if (args_depth > parms_depth
- && !DECL_TEMPLATE_SPECIALIZATION (t))
+
+ if (args_depth > parms_depth && !DECL_TEMPLATE_SPECIALIZATION (t))
args = get_innermost_template_args (args, parms_depth);
}
else
@@ -12329,23 +12329,18 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
new decl (R) with appropriate types so that we can call
determine_specialization. */
gen_tmpl = NULL_TREE;
+ argvec = NULL_TREE;
}
- if (DECL_CLASS_SCOPE_P (t))
- {
- if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))
- member = 2;
- else
- member = 1;
- ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
- complain, t, /*entering_scope=*/1);
- }
- else
- {
- member = 0;
- ctx = DECL_CONTEXT (t);
- }
- type = tsubst (TREE_TYPE (t), args, complain|tf_fndecl_type, in_decl);
+ tree ctx = DECL_CONTEXT (t);
+ bool member = ctx && TYPE_P (ctx);
+
+ if (member)
+ ctx = tsubst_aggr_type (ctx, args,
+ complain, t, /*entering_scope=*/1);
+
+ tree type = tsubst (TREE_TYPE (t), args,
+ complain | tf_fndecl_type, in_decl);
if (type == error_mark_node)
RETURN (error_mark_node);
@@ -12390,7 +12385,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
case it's the name of one of the template's parameters. */
- DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
+ DECL_NAME (r) = make_conv_op_name (TREE_TYPE (type));
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
complain, t);
@@ -12465,14 +12460,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_TEMPLATE_INFO (r) = NULL_TREE;
/* Copy the list of befriending classes. */
- for (friends = &DECL_BEFRIENDING_CLASSES (r);
+ for (tree *friends = &DECL_BEFRIENDING_CLASSES (r);
*friends;
friends = &TREE_CHAIN (*friends))
{
*friends = copy_node (*friends);
- TREE_VALUE (*friends) = tsubst (TREE_VALUE (*friends),
- args, complain,
- in_decl);
+ TREE_VALUE (*friends)
+ = tsubst (TREE_VALUE (*friends), args, complain, in_decl);
}
if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
@@ -14248,7 +14242,7 @@ tsubst_baselink (tree baselink, tree object_type,
tree name = OVL_NAME (fns);
if (IDENTIFIER_CONV_OP_P (name))
- name = mangle_conv_op_name_for_type (optype);
+ name = make_conv_op_name (optype);
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
if (!baselink)
@@ -15038,7 +15032,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (IDENTIFIER_CONV_OP_P (t))
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- return mangle_conv_op_name_for_type (new_type);
+ return make_conv_op_name (new_type);
}
else
return t;
@@ -15111,6 +15105,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return tsubst_binary_left_fold (t, args, complain, in_decl);
case BINARY_RIGHT_FOLD_EXPR:
return tsubst_binary_right_fold (t, args, complain, in_decl);
+ case PREDICT_EXPR:
+ return t;
default:
/* We shouldn't get here, but keep going if !flag_checking. */
@@ -16142,13 +16138,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
instantiated along with their containing function. And this
way we don't have to deal with pushing out of one local class
to instantiate a member of another local class. */
- tree fn;
/* Closures are handled by the LAMBDA_EXPR. */
gcc_assert (!LAMBDA_TYPE_P (TREE_TYPE (t)));
complete_type (tmp);
- for (fn = TYPE_METHODS (tmp); fn; fn = DECL_CHAIN (fn))
- if (!DECL_ARTIFICIAL (fn))
- instantiate_decl (fn, /*defer_ok=*/false,
+ for (tree fld = TYPE_FIELDS (tmp); fld; fld = DECL_CHAIN (fld))
+ if ((VAR_P (fld)
+ || (TREE_CODE (fld) == FUNCTION_DECL
+ && !DECL_ARTIFICIAL (fld)))
+ && DECL_TEMPLATE_INSTANTIATION (fld))
+ instantiate_decl (fld, /*defer_ok=*/false,
/*expl_inst_class=*/false);
}
break;
@@ -16671,7 +16669,7 @@ tsubst_copy_and_build (tree t,
if (IDENTIFIER_CONV_OP_P (t))
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- t = mangle_conv_op_name_for_type (new_type);
+ t = make_conv_op_name (new_type);
}
/* Look up the name. */
@@ -20019,6 +20017,9 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
tree pack, packs = NULL_TREE;
int i, start = TREE_VEC_LENGTH (packed_parms) - 1;
+ /* Add in any args remembered from an earlier partial instantiation. */
+ targs = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (parm), targs);
+
packed_args = expand_template_argument_pack (packed_args);
int len = TREE_VEC_LENGTH (packed_args);
@@ -22135,18 +22136,6 @@ bt_instantiate_type_proc (binding_entry entry, void *data)
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
-/* Called from do_type_instantiation to instantiate a member
- (a member function or a static member variable) of an
- explicitly instantiated class template. */
-static void
-instantiate_class_member (tree decl, int extern_p)
-{
- mark_decl_instantiated (decl, extern_p);
- if (! extern_p)
- instantiate_decl (decl, /*defer_ok=*/true,
- /*expl_inst_class_mem_p=*/true);
-}
-
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
@@ -22256,12 +22245,9 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
if (nomem_p)
return;
- {
- tree tmp;
-
- /* In contrast to implicit instantiation, where only the
- declarations, and not the definitions, of members are
- instantiated, we have here:
+ /* In contrast to implicit instantiation, where only the
+ declarations, and not the definitions, of members are
+ instantiated, we have here:
[temp.explicit]
@@ -22270,27 +22256,28 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
previously explicitly specialized in the translation unit
containing the explicit instantiation.
- Of course, we can't instantiate member template classes, since
- we don't have any arguments for them. Note that the standard
- is unclear on whether the instantiation of the members are
- *explicit* instantiations or not. However, the most natural
- interpretation is that it should be an explicit instantiation. */
-
- if (! static_p)
- for (tmp = TYPE_METHODS (t); tmp; tmp = DECL_CHAIN (tmp))
- if (TREE_CODE (tmp) == FUNCTION_DECL
- && DECL_TEMPLATE_INSTANTIATION (tmp)
- && user_provided_p (tmp))
- instantiate_class_member (tmp, extern_p);
-
- for (tmp = TYPE_FIELDS (t); tmp; tmp = DECL_CHAIN (tmp))
- if (VAR_P (tmp) && DECL_TEMPLATE_INSTANTIATION (tmp))
- instantiate_class_member (tmp, extern_p);
-
- if (CLASSTYPE_NESTED_UTDS (t))
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
- bt_instantiate_type_proc, &storage);
- }
+ Of course, we can't instantiate member template classes, since we
+ don't have any arguments for them. Note that the standard is
+ unclear on whether the instantiation of the members are
+ *explicit* instantiations or not. However, the most natural
+ interpretation is that it should be an explicit
+ instantiation. */
+ for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld))
+ if ((VAR_P (fld)
+ || (TREE_CODE (fld) == FUNCTION_DECL
+ && !static_p
+ && user_provided_p (fld)))
+ && DECL_TEMPLATE_INSTANTIATION (fld))
+ {
+ mark_decl_instantiated (fld, extern_p);
+ if (! extern_p)
+ instantiate_decl (fld, /*defer_ok=*/true,
+ /*expl_inst_class_mem_p=*/true);
+ }
+
+ if (CLASSTYPE_NESTED_UTDS (t))
+ binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
+ bt_instantiate_type_proc, &storage);
}
/* Given a function DECL, which is a specialization of TMPL, modify
@@ -22529,8 +22516,20 @@ maybe_instantiate_noexcept (tree fn)
if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
{
+ static hash_set<tree>* fns = new hash_set<tree>;
+ bool added = false;
if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE)
spec = get_defaulted_eh_spec (fn);
+ else if (!(added = !fns->add (fn)))
+ {
+ /* If hash_set::add returns true, the element was already there. */
+ location_t loc = EXPR_LOC_OR_LOC (DEFERRED_NOEXCEPT_PATTERN (noex),
+ DECL_SOURCE_LOCATION (fn));
+ error_at (loc,
+ "exception specification of %qD depends on itself",
+ fn);
+ spec = noexcept_false_spec;
+ }
else if (push_tinst_level (fn))
{
push_access_scope (fn);
@@ -22551,6 +22550,9 @@ maybe_instantiate_noexcept (tree fn)
else
spec = noexcept_false_spec;
+ if (added)
+ fns->remove (fn);
+
TREE_TYPE (fn) = build_exception_variant (fntype, spec);
}
@@ -23067,19 +23069,20 @@ instantiate_pending_templates (int retries)
if (TYPE_P (instantiation))
{
- tree fn;
-
if (!COMPLETE_TYPE_P (instantiation))
{
instantiate_class_template (instantiation);
if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
- for (fn = TYPE_METHODS (instantiation);
- fn;
- fn = TREE_CHAIN (fn))
- if (! DECL_ARTIFICIAL (fn))
- instantiate_decl (fn,
+ for (tree fld = TYPE_FIELDS (instantiation);
+ fld; fld = TREE_CHAIN (fld))
+ if ((VAR_P (fld)
+ || (TREE_CODE (fld) == FUNCTION_DECL
+ && !DECL_ARTIFICIAL (fld)))
+ && DECL_TEMPLATE_INSTANTIATION (fld))
+ instantiate_decl (fld,
/*defer_ok=*/false,
/*expl_inst_class_mem_p=*/false);
+
if (COMPLETE_TYPE_P (instantiation))
reconsider = 1;
}
@@ -24599,26 +24602,38 @@ resolve_typename_type (tree type, bool only_current_p)
/* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */
+ tree fullname = TYPENAME_TYPE_FULLNAME (type);
if (!decl)
/*nop*/;
- else if (identifier_p (TYPENAME_TYPE_FULLNAME (type))
+ else if (identifier_p (fullname)
&& TREE_CODE (decl) == TYPE_DECL)
{
result = TREE_TYPE (decl);
if (result == error_mark_node)
result = NULL_TREE;
}
- else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
+ else if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR
&& DECL_CLASS_TEMPLATE_P (decl))
{
- tree tmpl;
- tree args;
/* Obtain the template and the arguments. */
- tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
- args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
+ tree tmpl = TREE_OPERAND (fullname, 0);
+ if (TREE_CODE (tmpl) == IDENTIFIER_NODE)
+ {
+ /* We get here with a plain identifier because a previous tentative
+ parse of the nested-name-specifier as part of a ptr-operator saw
+ ::template X<A>. The use of ::template is necessary in a
+ ptr-operator, but wrong in a declarator-id.
+
+ [temp.names]: In a qualified-id of a declarator-id, the keyword
+ template shall not appear at the top level. */
+ pedwarn (EXPR_LOC_OR_LOC (fullname, input_location), OPT_Wpedantic,
+ "keyword %<template%> not allowed in declarator-id");
+ tmpl = decl;
+ }
+ tree args = TREE_OPERAND (fullname, 1);
/* Instantiate the template. */
result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
- /*entering_scope=*/0,
+ /*entering_scope=*/true,
tf_error | tf_user);
if (result == error_mark_node)
result = NULL_TREE;
@@ -24843,8 +24858,12 @@ listify (tree arg)
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
{
- error ("deducing from brace-enclosed initializer list requires "
- "#include <initializer_list>");
+ gcc_rich_location richloc (input_location);
+ maybe_add_include_fixit (&richloc, "<initializer_list>");
+ error_at_rich_loc (&richloc,
+ "deducing from brace-enclosed initializer list"
+ " requires #include <initializer_list>");
+
return error_mark_node;
}
tree argvec = make_tree_vec (1);
@@ -25161,17 +25180,16 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
}
else
{
+ ++processing_template_decl;
+
+ tree fn_tmpl
+ = (TREE_CODE (ctor) == TEMPLATE_DECL ? ctor
+ : DECL_TI_TEMPLATE (ctor));
if (outer_args)
- ctor = tsubst (ctor, outer_args, complain, ctor);
+ fn_tmpl = tsubst (fn_tmpl, outer_args, complain, ctor);
+ ctor = DECL_TEMPLATE_RESULT (fn_tmpl);
+
type = DECL_CONTEXT (ctor);
- tree fn_tmpl;
- if (TREE_CODE (ctor) == TEMPLATE_DECL)
- {
- fn_tmpl = ctor;
- ctor = DECL_TEMPLATE_RESULT (fn_tmpl);
- }
- else
- fn_tmpl = DECL_TI_TEMPLATE (ctor);
tparms = DECL_TEMPLATE_PARMS (fn_tmpl);
/* If type is a member class template, DECL_TI_ARGS (ctor) will have
@@ -25193,7 +25211,6 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
/* For a member template constructor, we need to flatten the two
template parameter lists into one, and then adjust the function
signature accordingly. This gets...complicated. */
- ++processing_template_decl;
tree save_parms = current_template_parms;
/* For a member template we should have two levels of parms/args, one
@@ -25254,8 +25271,8 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
ci = tsubst_constraint_info (ci, tsubst_args, complain, ctor);
current_template_parms = save_parms;
- --processing_template_decl;
}
+ --processing_template_decl;
}
if (!memtmpl)
@@ -25307,14 +25324,38 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
tree type = TREE_TYPE (tmpl);
+ bool try_list_ctor = false;
+
vec<tree,va_gc> *args;
if (init == NULL_TREE
|| TREE_CODE (init) == TREE_LIST)
args = make_tree_vector_from_list (init);
- else if (BRACE_ENCLOSED_INITIALIZER_P (init)
- && !TYPE_HAS_LIST_CTOR (type)
- && !is_std_init_list (type))
- args = make_tree_vector_from_ctor (init);
+ else if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ {
+ try_list_ctor = TYPE_HAS_LIST_CTOR (type);
+ if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
+ {
+ /* As an exception, the first phase in 16.3.1.7 (considering the
+ initializer list as a single argument) is omitted if the
+ initializer list consists of a single expression of type cv U,
+ where U is a specialization of C or a class derived from a
+ specialization of C. */
+ tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+ tree etype = TREE_TYPE (elt);
+
+ tree tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+ tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
+ int err = unify (tparms, targs, type, etype,
+ UNIFY_ALLOW_DERIVED, /*explain*/false);
+ if (err == 0)
+ try_list_ctor = false;
+ ggc_free (targs);
+ }
+ if (try_list_ctor || is_std_init_list (type))
+ args = make_tree_vector_single (init);
+ else
+ args = make_tree_vector_from_ctor (init);
+ }
else
args = make_tree_vector_single (init);
@@ -25369,13 +25410,43 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
saw_ctor = true;
}
- if (args->length () < 2)
+ tree call = error_mark_node;
+
+ /* If this is list-initialization and the class has a list constructor, first
+ try deducing from the list as a single argument, as [over.match.list]. */
+ tree list_cands = NULL_TREE;
+ if (try_list_ctor && cands)
+ for (lkp_iterator iter (cands); iter; ++iter)
+ {
+ tree dg = *iter;
+ if (is_list_ctor (dg))
+ list_cands = lookup_add (dg, list_cands);
+ }
+ if (list_cands)
+ {
+ ++cp_unevaluated_operand;
+ call = build_new_function_call (list_cands, &args, tf_decltype);
+ --cp_unevaluated_operand;
+
+ if (call == error_mark_node)
+ {
+ /* That didn't work, now try treating the list as a sequence of
+ arguments. */
+ release_tree_vector (args);
+ args = make_tree_vector_from_ctor (init);
+ }
+ }
+
+ /* Maybe generate an implicit deduction guide. */
+ if (call == error_mark_node && args->length () < 2)
{
tree gtype = NULL_TREE;
if (args->length () == 1)
+ /* Generate a copy guide. */
gtype = build_reference_type (type);
else if (!saw_ctor)
+ /* Generate a default guide. */
gtype = type;
if (gtype)
@@ -25397,22 +25468,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
return error_mark_node;
}
- ++cp_unevaluated_operand;
- tree t = build_new_function_call (cands, &args, tf_decltype);
+ if (call == error_mark_node)
+ {
+ ++cp_unevaluated_operand;
+ call = build_new_function_call (cands, &args, tf_decltype);
+ --cp_unevaluated_operand;
+ }
- if (t == error_mark_node && (complain & tf_warning_or_error))
+ if (call == error_mark_node && (complain & tf_warning_or_error))
{
error ("class template argument deduction failed:");
- t = build_new_function_call (cands, &args, complain | tf_decltype);
+
+ ++cp_unevaluated_operand;
+ call = build_new_function_call (cands, &args, complain | tf_decltype);
+ --cp_unevaluated_operand;
+
if (elided)
inform (input_location, "explicit deduction guides not considered "
"for copy-initialization");
}
- --cp_unevaluated_operand;
release_tree_vector (args);
- return cp_build_qualified_type (TREE_TYPE (t), cp_type_quals (ptype));
+ return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
}
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 7b69dbe2b89..d377efc8cc5 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -181,7 +181,6 @@ cxx_print_identifier (FILE *file, tree node, int indent)
fprintf (file, "%s local bindings <%p>", get_identifier_kind_name (node),
(void *) IDENTIFIER_BINDING (node));
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
- print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
}
void
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index ff72ce538b2..a660cdd9413 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "stor-layout.h"
#include "c-family/c-pragma.h"
+#include "gcc-rich-location.h"
/* C++ returns type information to the user in struct type_info
objects. We also use type information to implement dynamic_cast and
@@ -316,7 +317,12 @@ typeid_ok_p (void)
if (!COMPLETE_TYPE_P (const_type_info_type_node))
{
- error ("must %<#include <typeinfo>%> before using %<typeid%>");
+ gcc_rich_location richloc (input_location);
+ maybe_add_include_fixit (&richloc, "<typeinfo>");
+ error_at_rich_loc (&richloc,
+ "must %<#include <typeinfo>%> before using"
+ " %<typeid%>");
+
return false;
}
@@ -1556,7 +1562,7 @@ emit_support_tinfos (void)
bltn_type = TREE_TYPE (bltn_type);
if (!COMPLETE_TYPE_P (bltn_type))
return;
- tree dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
+ tree dtor = CLASSTYPE_DESTRUCTOR (bltn_type);
if (!dtor || DECL_EXTERNAL (dtor))
return;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 00f895c5d7d..469a88b4c6f 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -444,6 +444,10 @@ lookup_field_1 (tree type, tree name, bool want_type)
{
tree decl = field;
+ if (DECL_DECLARES_FUNCTION_P (decl))
+ /* Functions are kep separately, at the moment. */
+ continue;
+
if (GATHER_STATISTICS)
n_fields_searched++;
@@ -507,10 +511,13 @@ current_scope (void)
&& same_type_p (DECL_FRIEND_CONTEXT (current_function_decl),
current_class_type))))
return current_function_decl;
+
if (current_class_type)
return current_class_type;
+
if (current_function_decl)
return current_function_decl;
+
return current_namespace;
}
@@ -1523,86 +1530,67 @@ lookup_fnfields (tree xbasetype, tree name, int protect)
return rval;
}
-/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
- corresponding to "operator TYPE ()", or -1 if there is no such
- operator. Only CLASS_TYPE itself is searched; this routine does
- not scan the base classes of CLASS_TYPE. */
+/* Return the conversion operators in CLASS_TYPE corresponding to
+ "operator TYPE ()". Only CLASS_TYPE itself is searched; this
+ routine does not scan the base classes of CLASS_TYPE. */
-static int
+static tree
lookup_conversion_operator (tree class_type, tree type)
{
- int tpl_slot = -1;
+ tree tpls = NULL_TREE;
if (TYPE_HAS_CONVERSION (class_type))
{
- int i;
- tree fn;
+ tree fns;
vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type);
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- vec_safe_iterate (methods, i, &fn); ++i)
+ for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ vec_safe_iterate (methods, i, &fns); ++i)
{
/* All the conversion operators come near the beginning of
the class. Therefore, if FN is not a conversion
operator, there is no matching conversion operator in
CLASS_TYPE. */
- fn = OVL_FIRST (fn);
+ tree fn = OVL_FIRST (fns);
if (!DECL_CONV_FN_P (fn))
break;
if (TREE_CODE (fn) == TEMPLATE_DECL)
/* All the templated conversion functions are on the same
slot, so remember it. */
- tpl_slot = i;
+ tpls = fns;
else if (same_type_p (DECL_CONV_FN_TYPE (fn), type))
- return i;
+ return fns;
}
}
- return tpl_slot;
+ return tpls;
}
-/* TYPE is a class type. Return the index of the fields within
- the method vector with name NAME, or -1 if no such field exists.
- Does not lazily declare implicitly-declared member functions. */
+/* TYPE is a class type. Return the member functions in the method
+ vector with name NAME. Does not lazily declare implicitly-declared
+ member functions. */
-static int
-lookup_fnfields_idx_nolazy (tree type, tree name)
+tree
+lookup_fnfields_slot_nolazy (tree type, tree name)
{
- vec<tree, va_gc> *method_vec;
- tree fn;
- size_t i;
-
- if (!CLASS_TYPE_P (type))
- return -1;
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
+ vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
- return -1;
+ return NULL_TREE;
if (GATHER_STATISTICS)
n_calls_lookup_fnfields_1++;
- /* Constructors are first... */
- if (name == ctor_identifier)
- {
- fn = CLASSTYPE_CONSTRUCTORS (type);
- return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
- }
- /* and destructors are second. */
- if (name == dtor_identifier)
- {
- fn = CLASSTYPE_DESTRUCTORS (type);
- return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1;
- }
if (IDENTIFIER_CONV_OP_P (name))
return lookup_conversion_operator (type, TREE_TYPE (name));
/* Skip the conversion operators. */
+ int i;
+ tree fns;
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- vec_safe_iterate (method_vec, i, &fn);
+ vec_safe_iterate (method_vec, i, &fns);
++i)
- if (!DECL_CONV_FN_P (OVL_FIRST (fn)))
+ if (!DECL_CONV_FN_P (OVL_FIRST (fns)))
break;
/* If the type is complete, use binary search. */
@@ -1620,42 +1608,39 @@ lookup_fnfields_idx_nolazy (tree type, tree name)
if (GATHER_STATISTICS)
n_outer_fields_searched++;
- tree tmp = (*method_vec)[i];
- tmp = OVL_NAME (tmp);
- if (tmp > name)
+ fns = (*method_vec)[i];
+ tree fn_name = OVL_NAME (fns);
+ if (fn_name > name)
hi = i;
- else if (tmp < name)
+ else if (fn_name < name)
lo = i + 1;
else
- return i;
+ return fns;
}
}
else
- for (; vec_safe_iterate (method_vec, i, &fn); ++i)
+ for (; vec_safe_iterate (method_vec, i, &fns); ++i)
{
if (GATHER_STATISTICS)
n_outer_fields_searched++;
- if (OVL_NAME (fn) == name)
- return i;
+ if (OVL_NAME (fns) == name)
+ return fns;
}
- return -1;
+ return NULL_TREE;
}
-/* TYPE is a class type. Return the index of the fields within
- the method vector with name NAME, or -1 if no such field exists. */
+/* TYPE is a class type. Return the overloads in
+ the method vector with name NAME. Lazily create ctors etc. */
-int
-lookup_fnfields_1 (tree type, tree name)
+tree
+lookup_fnfields_slot (tree type, tree name)
{
- if (!CLASS_TYPE_P (type))
- return -1;
+ type = complete_type (type);
if (COMPLETE_TYPE_P (type))
{
- if ((name == ctor_identifier
- || name == base_ctor_identifier
- || name == complete_ctor_identifier))
+ if (IDENTIFIER_CTOR_P (name))
{
if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
lazily_declare_fn (sfk_constructor, type);
@@ -1671,55 +1656,40 @@ lookup_fnfields_1 (tree type, tree name)
if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
lazily_declare_fn (sfk_move_assignment, type);
}
- else if ((name == dtor_identifier
- || name == base_dtor_identifier
- || name == complete_dtor_identifier
- || name == deleting_dtor_identifier)
- && CLASSTYPE_LAZY_DESTRUCTOR (type))
- lazily_declare_fn (sfk_destructor, type);
+ else if (IDENTIFIER_DTOR_P (name))
+ {
+ if (CLASSTYPE_LAZY_DESTRUCTOR (type))
+ lazily_declare_fn (sfk_destructor, type);
+ }
}
- return lookup_fnfields_idx_nolazy (type, name);
+ return lookup_fnfields_slot_nolazy (type, name);
}
-/* TYPE is a class type. Return the field within the method vector with
- name NAME, or NULL_TREE if no such field exists. */
+/* Collect all the conversion operators of KLASS. */
tree
-lookup_fnfields_slot (tree type, tree name)
+lookup_all_conversions (tree klass)
{
- int ix = lookup_fnfields_1 (complete_type (type), name);
- if (ix < 0)
- return NULL_TREE;
- return (*CLASSTYPE_METHOD_VEC (type))[ix];
-}
+ tree lkp = NULL_TREE;
-/* As above, but avoid lazily declaring functions. */
-
-tree
-lookup_fnfields_slot_nolazy (tree type, tree name)
-{
- int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
- if (ix < 0)
- return NULL_TREE;
- return (*CLASSTYPE_METHOD_VEC (type))[ix];
-}
-
-/* Like lookup_fnfields_1, except that the name is extracted from
- FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */
+ if (vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (klass))
+ {
+ tree ovl;
+ for (int idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ methods->iterate (idx, &ovl); ++idx)
+ {
+ if (!DECL_CONV_FN_P (OVL_FIRST (ovl)))
+ /* There are no more conversion functions. */
+ break;
-int
-class_method_index_for_fn (tree class_type, tree function)
-{
- gcc_assert (DECL_DECLARES_FUNCTION_P (function));
+ lkp = lookup_add (ovl, lkp);
+ }
+ }
- return lookup_fnfields_1 (class_type,
- DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
- DECL_DESTRUCTOR_P (function) ? dtor_identifier :
- DECL_NAME (function));
+ return lkp;
}
-
/* DECL is the result of a qualified name lookup. QUALIFYING_SCOPE is
the class or namespace used to qualify the name. CONTEXT_CLASS is
the class corresponding to the object in which DECL will be used.
@@ -2415,37 +2385,26 @@ look_for_overrides (tree type, tree fndecl)
tree
look_for_overrides_here (tree type, tree fndecl)
{
- int ix;
+ tree ovl = lookup_fnfields_slot (type, DECL_NAME (fndecl));
- /* If there are no methods in TYPE (meaning that only implicitly
- declared methods will ever be provided for TYPE), then there are
- no virtual functions. */
- if (!CLASSTYPE_METHOD_VEC (type))
- return NULL_TREE;
-
- if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
- ix = CLASSTYPE_DESTRUCTOR_SLOT;
- else
- ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
- if (ix >= 0)
- for (ovl_iterator iter ((*CLASSTYPE_METHOD_VEC (type))[ix]); iter; ++iter)
- {
- tree fn = *iter;
+ for (ovl_iterator iter (ovl); iter; ++iter)
+ {
+ tree fn = *iter;
- if (!DECL_VIRTUAL_P (fn))
- /* Not a virtual. */;
- else if (DECL_CONTEXT (fn) != type)
- /* Introduced with a using declaration. */;
- else if (DECL_STATIC_FUNCTION_P (fndecl))
- {
- tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
- tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- if (compparms (TREE_CHAIN (btypes), dtypes))
- return fn;
- }
- else if (same_signature_p (fndecl, fn))
- return fn;
- }
+ if (!DECL_VIRTUAL_P (fn))
+ /* Not a virtual. */;
+ else if (DECL_CONTEXT (fn) != type)
+ /* Introduced with a using declaration. */;
+ else if (DECL_STATIC_FUNCTION_P (fndecl))
+ {
+ tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ if (compparms (TREE_CHAIN (btypes), dtypes))
+ return fn;
+ }
+ else if (same_signature_p (fndecl, fn))
+ return fn;
+ }
return NULL_TREE;
}
@@ -2976,6 +2935,28 @@ binfo_via_virtual (tree binfo, tree limit)
return NULL_TREE;
}
+/* BINFO is for a base class in some hierarchy. Return true iff it is a
+ direct base. */
+
+bool
+binfo_direct_p (tree binfo)
+{
+ tree d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
+ if (BINFO_INHERITANCE_CHAIN (d_binfo))
+ /* A second inheritance chain means indirect. */
+ return false;
+ if (!BINFO_VIRTUAL_P (binfo))
+ /* Non-virtual, so only one inheritance chain means direct. */
+ return true;
+ /* A virtual base looks like a direct base, so we need to look through the
+ direct bases to see if it's there. */
+ tree b_binfo;
+ for (int i = 0; BINFO_BASE_ITERATE (d_binfo, i, b_binfo); ++i)
+ if (b_binfo == binfo)
+ return true;
+ return false;
+}
+
/* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
Find the equivalent binfo within whatever graph HERE is located.
This is the inverse of original_binfo. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9589b47dd64..f56d00fd8f3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "omp-general.h"
#include "convert.h"
#include "gomp-constants.h"
+#include "predict.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
@@ -630,6 +631,7 @@ finish_goto_stmt (tree destination)
check_goto (destination);
+ add_stmt (build_predict_expr (PRED_GOTO, NOT_TAKEN));
return add_stmt (build_stmt (input_location, GOTO_EXPR, destination));
}
@@ -3037,9 +3039,9 @@ finish_member_declaration (tree decl)
if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
SET_DECL_LANGUAGE (decl, lang_cplusplus);
- /* Put functions on the TYPE_METHODS list and everything else on the
- TYPE_FIELDS list. Note that these are built up in reverse order.
- We reverse them (to obtain declaration order) in finish_struct. */
+ /* Put the decl on the TYPE_FIELDS list. Note that this is built up
+ in reverse order. We reverse it (to obtain declaration order) in
+ finish_struct. */
if (DECL_DECLARES_FUNCTION_P (decl))
{
/* We also need to add this function to the
@@ -3047,8 +3049,8 @@ finish_member_declaration (tree decl)
if (add_method (current_class_type, decl, false))
{
gcc_assert (TYPE_MAIN_VARIANT (current_class_type) == current_class_type);
- DECL_CHAIN (decl) = TYPE_METHODS (current_class_type);
- TYPE_METHODS (current_class_type) = decl;
+ DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type);
+ TYPE_FIELDS (current_class_type) = decl;
maybe_add_class_template_decl_list (current_class_type, decl,
/*friend_p=*/0);
@@ -5794,7 +5796,7 @@ finish_omp_declare_simd_methods (tree t)
if (processing_template_decl)
return;
- for (tree x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
+ for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
{
if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
continue;
@@ -9072,52 +9074,34 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
}
/* Called from trait_expr_value to evaluate either __has_nothrow_assign or
- __has_nothrow_copy, depending on assign_p. */
+ __has_nothrow_copy, depending on assign_p. Returns true iff all
+ the copy {ctor,assign} fns are nothrow. */
static bool
classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
{
- tree fns;
+ tree fns = NULL_TREE;
if (assign_p)
- {
- int ix;
- ix = lookup_fnfields_1 (type, cp_assignment_operator_id (NOP_EXPR));
- if (ix < 0)
- return false;
- fns = (*CLASSTYPE_METHOD_VEC (type))[ix];
- }
+ fns = lookup_fnfields_slot (type, cp_assignment_operator_id (NOP_EXPR));
else if (TYPE_HAS_COPY_CTOR (type))
- {
- /* If construction of the copy constructor was postponed, create
- it now. */
- if (CLASSTYPE_LAZY_COPY_CTOR (type))
- lazily_declare_fn (sfk_copy_constructor, type);
- if (CLASSTYPE_LAZY_MOVE_CTOR (type))
- lazily_declare_fn (sfk_move_constructor, type);
- fns = CLASSTYPE_CONSTRUCTORS (type);
- }
- else
- return false;
+ fns = lookup_fnfields_slot (type, ctor_identifier);
+ bool saw_copy = false;
for (ovl_iterator iter (fns); iter; ++iter)
{
tree fn = *iter;
-
- if (assign_p)
+
+ if (copy_fn_p (fn) > 0)
{
- if (copy_fn_p (fn) == 0)
- continue;
+ saw_copy = true;
+ maybe_instantiate_noexcept (fn);
+ if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
+ return false;
}
- else if (copy_fn_p (fn) <= 0)
- continue;
-
- maybe_instantiate_noexcept (fn);
- if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
- return false;
}
- return true;
+ return saw_copy;
}
/* Actually evaluates the trait. */
@@ -9401,7 +9385,7 @@ apply_deduced_return_type (tree fco, tree return_type)
}
if (DECL_CONV_FN_P (fco))
- DECL_NAME (fco) = mangle_conv_op_name_for_type (return_type);
+ DECL_NAME (fco) = make_conv_op_name (return_type);
TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index bb17278c611..2122450c653 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -90,7 +90,6 @@ lvalue_kind (const_tree ref)
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case TRY_CATCH_EXPR:
- case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
return lvalue_kind (TREE_OPERAND (ref, 0));
@@ -1503,13 +1502,13 @@ strip_typedefs (tree t, bool *remove_attributes)
break;
case TYPENAME_TYPE:
{
+ bool changed = false;
tree fullname = TYPENAME_TYPE_FULLNAME (t);
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR
&& TREE_OPERAND (fullname, 1))
{
tree args = TREE_OPERAND (fullname, 1);
tree new_args = copy_node (args);
- bool changed = false;
for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
{
tree arg = TREE_VEC_ELT (args, i);
@@ -1533,12 +1532,15 @@ strip_typedefs (tree t, bool *remove_attributes)
else
ggc_free (new_args);
}
- result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t),
- remove_attributes),
- fullname, typename_type, tf_none);
- /* Handle 'typedef typename A::N N;' */
- if (typedef_variant_p (result))
- result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (result)));
+ tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes);
+ if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t))
+ return t;
+ tree name = fullname;
+ if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (fullname, 0);
+ /* Use build_typename_type rather than make_typename_type because we
+ don't want to resolve it here, just strip typedefs. */
+ result = build_typename_type (ctx, name, fullname, typename_type);
}
break;
case DECLTYPE_TYPE:
@@ -3581,16 +3583,6 @@ cp_tree_equal (tree t1, tree t2)
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
}
- case WITH_CLEANUP_EXPR:
- if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
- return false;
- return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
-
- case COMPONENT_REF:
- if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
- return false;
- return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-
case PARM_DECL:
/* For comparing uses of parameters in late-specified return types
with an out-of-class definition of the function, but can also come
@@ -3984,8 +3976,7 @@ type_has_nontrivial_copy_init (const_tree type)
else if (CLASSTYPE_LAZY_COPY_CTOR (t))
{
saw_copy = true;
- if (type_has_user_declared_move_constructor (t)
- || type_has_user_declared_move_assign (t))
+ if (classtype_has_move_assign_or_move_ctor_p (t, true))
/* [class.copy]/8 If the class definition declares a move
constructor or move assignment operator, the implicitly declared
copy constructor is defined as deleted.... */;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1c15f29eb3d..3dc64045e1a 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5256,6 +5256,7 @@ cp_build_binary_op (location_t location,
if (sanitize_flags_p ((SANITIZE_SHIFT
| SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+ && current_function_decl != NULL_TREE
&& !processing_template_decl
&& (doing_div_or_mod || doing_shift))
{
@@ -6681,7 +6682,7 @@ maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain)
? xvalue_p (expr) : lvalue_p (expr))
&& same_type_p (TREE_TYPE (expr), TREE_TYPE (type)))
|| same_type_p (TREE_TYPE (expr), type))
- warning (OPT_Wuseless_cast, "useless cast to type %qT", type);
+ warning (OPT_Wuseless_cast, "useless cast to type %q#T", type);
}
}
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index bb8ca3254c0..3d9268c3d1d 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -371,7 +371,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_early_global_decl, /* early_global_decl */
dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@@ -411,7 +411,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
dbxout_early_global_decl, /* early_global_decl */
dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@@ -952,8 +952,6 @@ get_lang_number (void)
return N_SO_FORTRAN;
else if (lang_GNU_Fortran ())
return N_SO_FORTRAN90; /* CHECKME */
- else if (strcmp (language_string, "GNU Pascal") == 0)
- return N_SO_PASCAL;
else if (strcmp (language_string, "GNU Objective-C") == 0)
return N_SO_OBJC;
else if (strcmp (language_string, "GNU Objective-C++") == 0)
@@ -1483,6 +1481,8 @@ dbxout_type_fields (tree type)
/* Omit here local type decls until we know how to support them. */
if (TREE_CODE (tem) == TYPE_DECL
|| TREE_CODE (tem) == TEMPLATE_DECL
+ /* Member functions emitted after fields. */
+ || TREE_CODE (tem) == FUNCTION_DECL
/* Omit here the nameless fields that are used to skip bits. */
|| DECL_IGNORED_P (tem)
/* Omit fields whose position or size are variable or too large to
@@ -1588,55 +1588,38 @@ dbxout_type_method_1 (tree decl)
}
}
-/* Subroutine of `dbxout_type'. Output debug info about the methods defined
- in TYPE. */
+/* Subroutine of `dbxout_type'. Output debug info about the member
+ functions defined in TYPE. */
static void
dbxout_type_methods (tree type)
{
- /* C++: put out the method names and their parameter lists */
- tree methods = TYPE_METHODS (type);
- tree fndecl;
- tree last;
-
- if (methods == NULL_TREE)
- return;
-
- if (TREE_CODE (methods) != TREE_VEC)
- fndecl = methods;
- else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
- fndecl = TREE_VEC_ELT (methods, 0);
- else
- fndecl = TREE_VEC_ELT (methods, 1);
-
- while (fndecl)
+ for (tree fndecl = TYPE_FIELDS (type); fndecl;)
{
int need_prefix = 1;
/* Group together all the methods for the same operation.
These differ in the types of the arguments. */
- for (last = NULL_TREE;
+ for (tree last = NULL_TREE;
fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last));
fndecl = DECL_CHAIN (fndecl))
/* Output the name of the field (after overloading), as
well as the name of the field before overloading, along
with its parameter list */
{
- /* Skip methods that aren't FUNCTION_DECLs. (In C++, these
- include TEMPLATE_DECLs.) The debugger doesn't know what
- to do with such entities anyhow. */
+ /* Skip non-functions. */
if (TREE_CODE (fndecl) != FUNCTION_DECL)
continue;
- CONTIN;
-
- last = fndecl;
-
/* Also ignore abstract methods; those are only interesting to
the DWARF backends. */
if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT_P (fndecl))
continue;
+ CONTIN;
+
+ last = fndecl;
+
/* Redundantly output the plain name, since that's what gdb
expects. */
if (need_prefix)
@@ -2211,10 +2194,8 @@ dbxout_type (tree type, int full)
/* Write out the field declarations. */
dbxout_type_fields (type);
- if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
- {
- dbxout_type_methods (type);
- }
+ if (use_gnu_debug_info_extensions)
+ dbxout_type_methods (type);
stabstr_C (';');
diff --git a/gcc/dbxout.h b/gcc/dbxout.h
index ee6a08d2deb..c3582603253 100644
--- a/gcc/dbxout.h
+++ b/gcc/dbxout.h
@@ -53,7 +53,6 @@ extern void dbxout_stab_value_internal_label_diff (const char *, int *,
#define N_SO_ANSI_C 3
#define N_SO_CC 4 /* c++*/
#define N_SO_FORTRAN 5
-#define N_SO_PASCAL 6
#define N_SO_FORTRAN90 7
#define N_SO_OBJC 50
#define N_SO_OBJCPLUS 51
diff --git a/gcc/debug.c b/gcc/debug.c
index 860f1e312b9..d68c30ff2b9 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -47,7 +47,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
debug_nothing_tree, /* early_global_decl */
debug_nothing_tree, /* late_global_decl */
debug_nothing_tree_int, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@@ -80,10 +80,11 @@ debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED,
}
void
-debug_nothing_tree_tree_tree_bool (tree t1 ATTRIBUTE_UNUSED,
- tree t2 ATTRIBUTE_UNUSED,
- tree t3 ATTRIBUTE_UNUSED,
- bool b1 ATTRIBUTE_UNUSED)
+debug_nothing_tree_tree_tree_bool_bool (tree t1 ATTRIBUTE_UNUSED,
+ tree t2 ATTRIBUTE_UNUSED,
+ tree t3 ATTRIBUTE_UNUSED,
+ bool b1 ATTRIBUTE_UNUSED,
+ bool b2 ATTRIBUTE_UNUSED)
{
}
diff --git a/gcc/debug.h b/gcc/debug.h
index 395365861f7..bfb72213631 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -145,7 +145,8 @@ struct gcc_debug_hooks
/* Debug information for imported modules and declarations. */
void (* imported_module_or_decl) (tree decl, tree name,
- tree context, bool child);
+ tree context, bool child,
+ bool implicit);
/* DECL is an inline function, whose body is present, but which is
not being output at this point. */
@@ -206,7 +207,8 @@ extern void debug_nothing_int_int (unsigned int, unsigned int);
extern void debug_nothing_tree (tree);
extern void debug_nothing_tree_tree (tree, tree);
extern void debug_nothing_tree_int (tree, int);
-extern void debug_nothing_tree_tree_tree_bool (tree, tree, tree, bool);
+extern void debug_nothing_tree_tree_tree_bool_bool (tree, tree, tree,
+ bool, bool);
extern bool debug_true_const_tree (const_tree);
extern void debug_nothing_rtx_insn (rtx_insn *);
extern void debug_nothing_rtx_code_label (rtx_code_label *);
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 8bf4d9e2c85..b0e72e735bf 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "backtrace.h"
#include "diagnostic.h"
#include "diagnostic-color.h"
+#include "gcc-rich-location.h"
#include "selftest.h"
#ifdef HAVE_TERMIOS_H
@@ -196,6 +197,9 @@ class layout
rich_location *richloc,
diagnostic_t diagnostic_kind);
+ bool maybe_add_location_range (const location_range *loc_range,
+ 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]; }
@@ -206,6 +210,7 @@ class layout
void print_line (int row);
private:
+ bool will_show_line_p (int row) const;
void print_leading_fixits (int row);
void print_source_line (int row, const char *line, int line_width,
line_bounds *lbounds_out);
@@ -241,6 +246,7 @@ class layout
diagnostic_context *m_context;
pretty_printer *m_pp;
diagnostic_t m_diagnostic_kind;
+ location_t m_primary_loc;
expanded_location m_exploc;
colorizer m_colorizer;
bool m_colorize_source_p;
@@ -750,6 +756,16 @@ compatible_locations_p (location_t loc_a, location_t loc_b)
}
}
+/* Comparator for sorting fix-it hints. */
+
+static int
+fixit_cmp (const void *p_a, const void *p_b)
+{
+ const fixit_hint * hint_a = *static_cast<const fixit_hint * const *> (p_a);
+ const fixit_hint * hint_b = *static_cast<const fixit_hint * const *> (p_b);
+ return hint_a->get_start_loc () - hint_b->get_start_loc ();
+}
+
/* Implementation of class layout. */
/* Constructor for class layout.
@@ -767,6 +783,7 @@ layout::layout (diagnostic_context * context,
: m_context (context),
m_pp (context->printer),
m_diagnostic_kind (diagnostic_kind),
+ m_primary_loc (richloc->get_range (0)->m_loc),
m_exploc (richloc->get_expanded_location (0)),
m_colorizer (context, diagnostic_kind),
m_colorize_source_p (context->colorize_source_p),
@@ -775,74 +792,12 @@ layout::layout (diagnostic_context * context,
m_line_spans (1 + richloc->get_num_locations ()),
m_x_offset (0)
{
- source_location primary_loc = richloc->get_range (0)->m_loc;
-
for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
{
/* 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);
-
- /* Split the "range" into caret and range information. */
- source_range src_range = get_range_from_loc (line_table, loc_range->m_loc);
-
- /* Expand the various locations. */
- expanded_location start
- = linemap_client_expand_location_to_spelling_point (src_range.m_start);
- expanded_location finish
- = linemap_client_expand_location_to_spelling_point (src_range.m_finish);
- expanded_location caret
- = linemap_client_expand_location_to_spelling_point (loc_range->m_loc);
-
- /* If any part of the range isn't in the same file as the primary
- location of this diagnostic, ignore the range. */
- if (start.file != m_exploc.file)
- continue;
- if (finish.file != m_exploc.file)
- continue;
- if (loc_range->m_show_caret_p)
- if (caret.file != m_exploc.file)
- continue;
-
- /* Sanitize the caret location for non-primary ranges. */
- if (m_layout_ranges.length () > 0)
- if (loc_range->m_show_caret_p)
- if (!compatible_locations_p (loc_range->m_loc, primary_loc))
- /* Discard any non-primary ranges that can't be printed
- sanely relative to the primary location. */
- continue;
-
- /* 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);
-
- /* If we have a range that finishes before it starts (perhaps
- from something built via macro expansion), printing the
- range is likely to be nonsensical. Also, attempting to do so
- breaks assumptions within the printing code (PR c/68473).
- Similarly, don't attempt to print ranges if one or both ends
- of the range aren't sane to print relative to the
- primary location (PR c++/70105). */
- if (start.line > finish.line
- || !compatible_locations_p (src_range.m_start, primary_loc)
- || !compatible_locations_p (src_range.m_finish, primary_loc))
- {
- /* Is this the primary location? */
- if (m_layout_ranges.length () == 0)
- {
- /* We want to print the caret for the primary location, but
- we must sanitize away m_start and m_finish. */
- ri.m_start = ri.m_caret;
- ri.m_finish = ri.m_caret;
- }
- else
- /* This is a non-primary range; ignore it. */
- continue;
- }
-
- /* Passed all the tests; add the range to m_layout_ranges so that
- it will be printed. */
- m_layout_ranges.safe_push (ri);
+ maybe_add_location_range (loc_range, false);
}
/* Populate m_fixit_hints, filtering to only those that are in the
@@ -854,6 +809,9 @@ layout::layout (diagnostic_context * context,
m_fixit_hints.safe_push (hint);
}
+ /* Sort m_fixit_hints. */
+ m_fixit_hints.qsort (fixit_cmp);
+
/* Populate m_line_spans. */
calculate_line_spans ();
@@ -879,6 +837,118 @@ layout::layout (diagnostic_context * context,
show_ruler (m_x_offset + max_width);
}
+/* Attempt to add LOC_RANGE to m_layout_ranges, filtering them to
+ those that we can sanely print.
+
+ 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
+ already specified by other locations.
+
+ Return true iff LOC_RANGE was added. */
+
+bool
+layout::maybe_add_location_range (const location_range *loc_range,
+ bool restrict_to_current_line_spans)
+{
+ gcc_assert (loc_range);
+
+ /* Split the "range" into caret and range information. */
+ source_range src_range = get_range_from_loc (line_table, loc_range->m_loc);
+
+ /* Expand the various locations. */
+ expanded_location start
+ = linemap_client_expand_location_to_spelling_point
+ (src_range.m_start, LOCATION_ASPECT_START);
+ expanded_location finish
+ = linemap_client_expand_location_to_spelling_point
+ (src_range.m_finish, LOCATION_ASPECT_FINISH);
+ expanded_location caret
+ = linemap_client_expand_location_to_spelling_point
+ (loc_range->m_loc, LOCATION_ASPECT_CARET);
+
+ /* If any part of the range isn't in the same file as the primary
+ location of this diagnostic, ignore the range. */
+ if (start.file != m_exploc.file)
+ return false;
+ if (finish.file != m_exploc.file)
+ return false;
+ if (loc_range->m_show_caret_p)
+ 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 (!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. */
+ return false;
+
+ /* 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);
+
+ /* If we have a range that finishes before it starts (perhaps
+ from something built via macro expansion), printing the
+ range is likely to be nonsensical. Also, attempting to do so
+ breaks assumptions within the printing code (PR c/68473).
+ Similarly, don't attempt to print ranges if one or both ends
+ of the range aren't sane to print relative to the
+ primary location (PR c++/70105). */
+ if (start.line > finish.line
+ || !compatible_locations_p (src_range.m_start, m_primary_loc)
+ || !compatible_locations_p (src_range.m_finish, m_primary_loc))
+ {
+ /* Is this the primary location? */
+ if (m_layout_ranges.length () == 0)
+ {
+ /* We want to print the caret for the primary location, but
+ we must sanitize away m_start and m_finish. */
+ ri.m_start = ri.m_caret;
+ ri.m_finish = ri.m_caret;
+ }
+ else
+ /* This is a non-primary range; ignore it. */
+ return false;
+ }
+
+ /* Potentially filter to just the lines already specified by other
+ locations. This is for use by gcc_rich_location::add_location_if_nearby.
+ The layout ctor doesn't use it, and can't because m_line_spans
+ hasn't been set up at that point. */
+ if (restrict_to_current_line_spans)
+ {
+ if (!will_show_line_p (start.line))
+ return false;
+ if (!will_show_line_p (finish.line))
+ return false;
+ if (loc_range->m_show_caret_p)
+ if (!will_show_line_p (caret.line))
+ return false;
+ }
+
+ /* Passed all the tests; add the range to m_layout_ranges so that
+ it will be printed. */
+ m_layout_ranges.safe_push (ri);
+ return true;
+}
+
+/* Return true iff ROW is within one of the line spans for this layout. */
+
+bool
+layout::will_show_line_p (int row) const
+{
+ for (int line_span_idx = 0; line_span_idx < get_num_line_spans ();
+ line_span_idx++)
+ {
+ const line_span *line_span = get_line_span (line_span_idx);
+ if (line_span->contains_line_p (row))
+ return true;
+ }
+ return false;
+}
+
/* Return true iff we should print a heading when starting the
line span with the given index. */
@@ -1328,7 +1398,11 @@ layout::annotation_line_showed_range_p (int line, int start_column,
struct column_range
{
- column_range (int start_, int finish_) : start (start_), finish (finish_) {}
+ column_range (int start_, int finish_) : start (start_), finish (finish_)
+ {
+ /* We must have either a range, or an insertion. */
+ gcc_assert (start <= finish || finish == start - 1);
+ }
bool operator== (const column_range &other) const
{
@@ -1370,6 +1444,26 @@ get_printed_columns (const fixit_hint *hint)
}
}
+/* A struct capturing the bounds of a buffer, to allow for run-time
+ bounds-checking in a checked build. */
+
+struct char_span
+{
+ char_span (const char *ptr, size_t n_elts) : m_ptr (ptr), m_n_elts (n_elts) {}
+
+ char_span subspan (int offset, int n_elts)
+ {
+ gcc_assert (offset >= 0);
+ gcc_assert (offset < (int)m_n_elts);
+ gcc_assert (n_elts >= 0);
+ gcc_assert (offset + n_elts <= (int)m_n_elts);
+ return char_span (m_ptr + offset, n_elts);
+ }
+
+ const char *m_ptr;
+ size_t m_n_elts;
+};
+
/* A correction on a particular line.
This describes a plan for how to print one or more fixit_hint
instances that affected the line, potentially consolidating hints
@@ -1398,6 +1492,14 @@ struct correction
void ensure_capacity (size_t len);
void ensure_terminated ();
+ void overwrite (int dst_offset, const char_span &src_span)
+ {
+ gcc_assert (dst_offset >= 0);
+ gcc_assert (dst_offset + src_span.m_n_elts < m_alloc_sz);
+ memcpy (m_text + dst_offset, src_span.m_ptr,
+ src_span.m_n_elts);
+ }
+
/* If insert, then start: the column before which the text
is to be inserted, and finish is offset by the length of
the replacement.
@@ -1469,6 +1571,26 @@ line_corrections::~line_corrections ()
delete c;
}
+/* A struct wrapping a particular source line, allowing
+ run-time bounds-checking of accesses in a checked build. */
+
+struct source_line
+{
+ source_line (const char *filename, int line);
+
+ char_span as_span () { return char_span (chars, width); }
+
+ const char *chars;
+ int width;
+};
+
+/* source_line's ctor. */
+
+source_line::source_line (const char *filename, int line)
+{
+ chars = location_get_source_line (filename, line, &width);
+}
+
/* Add HINT to the corrections for this line.
Attempt to consolidate nearby hints so that they will not
overlap with printed. */
@@ -1484,6 +1606,14 @@ line_corrections::add_hint (const fixit_hint *hint)
{
correction *last_correction
= m_corrections[m_corrections.length () - 1];
+
+ /* The following consolidation code assumes that the fix-it hints
+ have been sorted by start (done within layout's ctor). */
+ gcc_assert (affected_columns.start
+ >= last_correction->m_affected_columns.start);
+ gcc_assert (printed_columns.start
+ >= last_correction->m_printed_columns.start);
+
if (printed_columns.start <= last_correction->m_printed_columns.finish)
{
/* We have two hints for which the printed forms of the hints
@@ -1496,23 +1626,26 @@ line_corrections::add_hint (const fixit_hint *hint)
printed_columns.start - 1);
/* Try to read the source. */
- int line_width;
- const char *line = location_get_source_line (m_filename, m_row,
- &line_width);
- if (line && between.finish < line_width)
+ source_line line (m_filename, m_row);
+ if (line.chars && between.finish < line.width)
{
/* Consolidate into the last correction:
add a no-op "replace" of the "between" text, and
add the text from the new hint. */
- size_t old_len = last_correction->m_len;
- size_t between_len = between.finish + 1 - between.start;
- size_t new_len = old_len + between_len + hint->get_length ();
+ int old_len = last_correction->m_len;
+ gcc_assert (old_len >= 0);
+ int between_len = between.finish + 1 - between.start;
+ gcc_assert (between_len >= 0);
+ int new_len = old_len + between_len + hint->get_length ();
+ gcc_assert (new_len >= 0);
last_correction->ensure_capacity (new_len);
- memcpy (last_correction->m_text + old_len,
- line + between.start - 1,
- between.finish + 1 - between.start);
- memcpy (last_correction->m_text + old_len + between_len,
- hint->get_string (), hint->get_length ());
+ last_correction->overwrite
+ (old_len,
+ line.as_span ().subspan (between.start - 1,
+ between.finish + 1 - between.start));
+ last_correction->overwrite (old_len + between_len,
+ char_span (hint->get_string (),
+ hint->get_length ()));
last_correction->m_len = new_len;
last_correction->ensure_terminated ();
last_correction->m_affected_columns.finish
@@ -1779,6 +1912,28 @@ layout::print_line (int row)
} /* End of anonymous namespace. */
+/* If LOC is within the spans of lines that will already be printed for
+ this gcc_rich_location, then add it as a secondary location and return true.
+
+ Otherwise return false. */
+
+bool
+gcc_rich_location::add_location_if_nearby (location_t loc)
+{
+ /* Use the layout location-handling logic to sanitize LOC,
+ filtering it to the current line spans within a temporary
+ layout instance. */
+ 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))
+ return false;
+
+ add_range (loc, false);
+ return true;
+}
+
/* Print the physical source code corresponding to the location of
this diagnostic, with additional annotations. */
@@ -2223,6 +2378,70 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
test_one_liner_many_fixits_2 ();
}
+/* Verify that gcc_rich_location::add_location_if_nearby works. */
+
+static void
+test_add_location_if_nearby (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = ("struct same_line { double x; double y; ;\n" /* line 1. */
+ "struct different_line\n" /* line 2. */
+ "{\n" /* line 3. */
+ " double x;\n" /* line 4. */
+ " double y;\n" /* line 5. */
+ ";\n"); /* line 6. */
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ 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);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 7);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Test of add_location_if_nearby on the same line as the
+ primary location. */
+ {
+ const location_t missing_close_brace_1_39
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 39);
+ const location_t matching_open_brace_1_18
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
+ gcc_rich_location richloc (missing_close_brace_1_39);
+ bool added = richloc.add_location_if_nearby (matching_open_brace_1_18);
+ ASSERT_TRUE (added);
+ ASSERT_EQ (2, richloc.get_num_locations ());
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " struct same_line { double x; double y; ;\n"
+ " ~ ^\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Test of add_location_if_nearby on a different line to the
+ primary location. */
+ {
+ const location_t missing_close_brace_6_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 1);
+ const location_t matching_open_brace_3_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 1);
+ gcc_rich_location richloc (missing_close_brace_6_1);
+ bool added = richloc.add_location_if_nearby (matching_open_brace_3_1);
+ ASSERT_FALSE (added);
+ ASSERT_EQ (1, richloc.get_num_locations ());
+ }
+}
+
/* Verify that we print fixits even if they only affect lines
outside those covered by the ranges in the rich_location. */
@@ -2648,6 +2867,96 @@ test_overlapped_fixit_printing (const line_table_case &case_)
}
}
+/* Verify that the line_corrections machinery correctly prints
+ overlapping fixit-hints that have been added in the wrong
+ order.
+ Adapted from PR c/81405 seen on gcc.dg/init-excess-1.c*/
+
+static void
+test_overlapped_fixit_printing_2 (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = ("int a5[][0][0] = { 1, 2 };\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ 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);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 100);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ const location_t col_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+ const location_t col_20
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 20);
+ const location_t col_21
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 21);
+ const location_t col_23
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
+ const location_t col_25
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 25);
+
+ /* Two insertions, in the wrong order. */
+ {
+ rich_location richloc (line_table, col_20);
+ richloc.add_fixit_insert_before (col_23, "{");
+ richloc.add_fixit_insert_before (col_21, "}");
+
+ /* These fixits should be accepted; they can't be consolidated. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+ ASSERT_EQ (column_range (23, 22), get_affected_columns (hint_0));
+ ASSERT_EQ (column_range (23, 23), get_printed_columns (hint_0));
+ const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+ ASSERT_EQ (column_range (21, 20), get_affected_columns (hint_1));
+ ASSERT_EQ (column_range (21, 21), get_printed_columns (hint_1));
+
+ /* Verify that they're printed correctly. */
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " int a5[][0][0] = { 1, 2 };\n"
+ " ^\n"
+ " } {\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Various overlapping insertions, some occurring "out of order"
+ (reproducing the fix-it hints from PR c/81405). */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, col_20);
+
+ richloc.add_fixit_insert_before (col_20, "{{");
+ richloc.add_fixit_insert_before (col_21, "}}");
+ richloc.add_fixit_insert_before (col_23, "{");
+ richloc.add_fixit_insert_before (col_21, "}");
+ richloc.add_fixit_insert_before (col_23, "{{");
+ richloc.add_fixit_insert_before (col_25, "}");
+ richloc.add_fixit_insert_before (col_21, "}");
+ richloc.add_fixit_insert_before (col_1, "{");
+ richloc.add_fixit_insert_before (col_25, "}");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " int a5[][0][0] = { 1, 2 };\n"
+ " ^\n"
+ " { -----\n"
+ " {{1}}}}, {{{2 }}\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
/* Insertion fix-it hint: adding a "break;" on a line by itself. */
static void
@@ -2854,9 +3163,11 @@ diagnostic_show_locus_c_tests ()
test_diagnostic_show_locus_unknown_location ();
for_each_line_table_case (test_diagnostic_show_locus_one_liner);
+ for_each_line_table_case (test_add_location_if_nearby);
for_each_line_table_case (test_diagnostic_show_locus_fixit_lines);
for_each_line_table_case (test_fixit_consolidation);
for_each_line_table_case (test_overlapped_fixit_printing);
+ for_each_line_table_case (test_overlapped_fixit_printing_2);
for_each_line_table_case (test_fixit_insert_containing_newline);
for_each_line_table_case (test_fixit_insert_containing_newline_2);
for_each_line_table_case (test_fixit_replace_containing_newline);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 43f9ecf2466..34cb7d3dd22 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988-2017 Free Software Foundation, Inc.
+c Copyright (C) 1988-2017 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -2984,6 +2984,19 @@ asm ("");
(@pxref{Extended Asm}) in the called function, to serve as a special
side-effect.
+@item noipa
+@cindex @code{noipa} function attribute
+Disable interprocedural optimizations between the function with this
+attribute and its callers, as if the body of the function is not available
+when optimizing callers and the callers are unavailable when optimizing
+the body. This attribute implies @code{noinline}, @code{noclone} and
+@code{no_icf} attributes. However, this attribute is not equivalent
+to a combination of other attributes, because its purpose is to suppress
+existing and future optimizations employing interprocedural analysis,
+including those that do not have an attribute suitable for disabling
+them individually. This attribute is supported mainly for the purpose
+of testing the compiler.
+
@item nonnull (@var{arg-index}, @dots{})
@cindex @code{nonnull} function attribute
@cindex functions with non-null pointer arguments
@@ -3105,6 +3118,27 @@ that affect more than one function.
This attribute should be used for debugging purposes only. It is not
suitable in production code.
+@item patchable_function_entry
+@cindex @code{patchable_function_entry} function attribute
+@cindex extra NOP instructions at the function entry point
+In case the target's text segment can be made writable at run time by
+any means, padding the function entry with a number of NOPs can be
+used to provide a universal tool for instrumentation.
+
+The @code{patchable_function_entry} function attribute can be used to
+change the number of NOPs to any desired value. The two-value syntax
+is the same as for the command-line switch
+@option{-fpatchable-function-entry=N,M}, generating @var{N} NOPs, with
+the function entry point before the @var{M}th NOP instruction.
+@var{M} defaults to 0 if omitted e.g. function entry point is before
+the first NOP.
+
+If patchable function entries are enabled globally using the command-line
+option @option{-fpatchable-function-entry=N,M}, then you must disable
+instrumentation on all functions that are part of the instrumentation
+framework with the attribute @code{patchable_function_entry (0)}
+to prevent recursion.
+
@item pure
@cindex @code{pure} function attribute
@cindex functions that have no side effects
@@ -3278,16 +3312,17 @@ are the same as for @code{target} attribute.
For instance, on an x86, you could compile a function with
@code{target_clones("sse4.1,avx")}. GCC creates two function clones,
one compiled with @option{-msse4.1} and another with @option{-mavx}.
-It also creates a resolver function (see the @code{ifunc} attribute
-above) that dynamically selects a clone suitable for current
-architecture.
On a PowerPC, you can compile a function with
@code{target_clones("cpu=power9,default")}. GCC will create two
function clones, one compiled with @option{-mcpu=power9} and another
-with the default options. It also creates a resolver function (see
+with the default options. GCC must be configured to use GLIBC 2.23 or
+newer in order to use the @code{target_clones} attribute.
+
+It also creates a resolver function (see
the @code{ifunc} attribute above) that dynamically selects a clone
-suitable for current architecture.
+suitable for current architecture. The resolver is created only if there
+is a usage of a function with @code{target_clones} attribute.
@item unused
@cindex @code{unused} function attribute
@@ -3815,6 +3850,33 @@ prologue/epilogue sequences generated by the compiler. Only basic
basic @code{asm} and C code may appear to work, they cannot be
depended upon to work reliably and are not supported.
+@item no_gccisr
+@cindex @code{no_gccisr} function attribute, AVR
+Do not use @code{__gcc_isr} pseudo instructions in a function with
+the @code{interrupt} or @code{signal} attribute aka. interrupt
+service routine (ISR).
+Use this attribute if the preamble of the ISR prologue should always read
+@example
+push __zero_reg__
+push __tmp_reg__
+in __tmp_reg__, __SREG__
+push __tmp_reg__
+clr __zero_reg__
+@end example
+and accordingly for the postamble of the epilogue --- no matter whether
+the mentioned registers are actually used in the ISR or not.
+Situations where you might want to use this attribute include:
+@itemize @bullet
+@item
+Code that (effectively) clobbers bits of @code{SREG} other than the
+@code{I}-flag by writing to the memory location of @code{SREG}.
+@item
+Code that uses inline assembler to jump to a different function which
+expects (parts of) the prologue code as outlined above to be present.
+@end itemize
+To disable @code{__gcc_isr} generation for the whole compilation unit,
+there is option @option{-mno-gas-isr-prologues}, @pxref{AVR Options}.
+
@item OS_main
@itemx OS_task
@cindex @code{OS_main} function attribute, AVR
@@ -5308,6 +5370,17 @@ this function attribute to make GCC generate the ``hot-patching'' function
prologue used in Win32 API functions in Microsoft Windows XP Service Pack 2
and newer.
+@item naked
+@cindex @code{naked} function attribute, x86
+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.
+
@item regparm (@var{number})
@cindex @code{regparm} function attribute, x86
@cindex functions that are passed arguments in registers on x86-32
@@ -12720,54 +12793,37 @@ or if not a specific built-in is implemented or not. For example, if
@code{__builtin_avr_nop} is available the macro
@code{__BUILTIN_AVR_NOP} is defined to @code{1} and undefined otherwise.
-The following built-in functions map to the respective machine
+@table @code
+
+@item void __builtin_avr_nop (void)
+@itemx void __builtin_avr_sei (void)
+@itemx void __builtin_avr_cli (void)
+@itemx void __builtin_avr_sleep (void)
+@itemx void __builtin_avr_wdr (void)
+@itemx unsigned char __builtin_avr_swap (unsigned char)
+@itemx unsigned int __builtin_avr_fmul (unsigned char, unsigned char)
+@itemx int __builtin_avr_fmuls (char, char)
+@itemx int __builtin_avr_fmulsu (char, unsigned char)
+These built-in functions map to the respective machine
instruction, i.e.@: @code{nop}, @code{sei}, @code{cli}, @code{sleep},
@code{wdr}, @code{swap}, @code{fmul}, @code{fmuls}
resp. @code{fmulsu}. The three @code{fmul*} built-ins are implemented
as library call if no hardware multiplier is available.
-@smallexample
-void __builtin_avr_nop (void)
-void __builtin_avr_sei (void)
-void __builtin_avr_cli (void)
-void __builtin_avr_sleep (void)
-void __builtin_avr_wdr (void)
-unsigned char __builtin_avr_swap (unsigned char)
-unsigned int __builtin_avr_fmul (unsigned char, unsigned char)
-int __builtin_avr_fmuls (char, char)
-int __builtin_avr_fmulsu (char, unsigned char)
-@end smallexample
-
-In order to delay execution for a specific number of cycles, GCC
-implements
-@smallexample
-void __builtin_avr_delay_cycles (unsigned long ticks)
-@end smallexample
-
-@noindent
-@code{ticks} is the number of ticks to delay execution. Note that this
+@item void __builtin_avr_delay_cycles (unsigned long ticks)
+Delay execution for @var{ticks} cycles. Note that this
built-in does not take into account the effect of interrupts that
-might increase delay time. @code{ticks} must be a compile-time
+might increase delay time. @var{ticks} must be a compile-time
integer constant; delays with a variable number of cycles are not supported.
-@smallexample
-char __builtin_avr_flash_segment (const __memx void*)
-@end smallexample
-
-@noindent
+@item char __builtin_avr_flash_segment (const __memx void*)
This built-in takes a byte address to the 24-bit
@ref{AVR Named Address Spaces,address space} @code{__memx} and returns
the number of the flash segment (the 64 KiB chunk) where the address
points to. Counting starts at @code{0}.
If the address does not point to flash memory, return @code{-1}.
-@smallexample
-unsigned char __builtin_avr_insert_bits (unsigned long map,
- unsigned char bits,
- unsigned char val)
-@end smallexample
-
-@noindent
+@item uint8_t __builtin_avr_insert_bits (uint32_t map, uint8_t bits, uint8_t val)
Insert bits from @var{bits} into @var{val} and return the resulting
value. The nibbles of @var{map} determine how the insertion is
performed: Let @var{X} be the @var{n}-th nibble of @var{map}
@@ -12812,13 +12868,29 @@ __builtin_avr_insert_bits (0xffff3210, bits, val)
__builtin_avr_insert_bits (0x01234567, bits, 0)
@end smallexample
-@smallexample
-void __builtin_avr_nops (unsigned count)
-@end smallexample
+@item void __builtin_avr_nops (unsigned count)
+Insert @var{count} @code{NOP} instructions.
+The number of instructions must be a compile-time integer constant.
+
+@end table
@noindent
-Insert @code{count} @code{NOP} instructions.
-The number of instructions must be a compile-time integer constant.
+There are many more AVR-specific built-in functions that are used to
+implement the ISO/IEC TR 18037 ``Embedded C'' fixed-point functions of
+section 7.18a.6. You don't need to use these built-ins directly.
+Instead, use the declarations as supplied by the @code{stdfix.h} header
+with GNU-C99:
+
+@smallexample
+#include <stdfix.h>
+
+// Re-interpret the bit representation of unsigned 16-bit
+// integer @var{uval} as Q-format 0.16 value.
+unsigned fract get_bits (uint_ur_t uval)
+@{
+ return urbits (uval);
+@}
+@end smallexample
@node Blackfin Built-in Functions
@subsection Blackfin Built-in Functions
@@ -14918,8 +14990,18 @@ to maintain API compatibility with the x86 builtins.
@deftypefn {Built-in Function} int __builtin_cpu_is (const char *@var{cpuname})
This function returns a value of @code{1} if the run-time CPU is of type
-@var{cpuname} and returns @code{0} otherwise. The following CPU names can be
-detected:
+@var{cpuname} and returns @code{0} otherwise
+
+The @code{__builtin_cpu_is} function requires GLIBC 2.23 or newer
+which exports the hardware capability bits. GCC defines the macro
+@code{__BUILTIN_CPU_SUPPORTS__} if the @code{__builtin_cpu_supports}
+built-in function is fully supported.
+
+If GCC was configured to use a GLIBC before 2.23, the built-in
+function @code{__builtin_cpu_is} always returns a 0 and the compiler
+issues a warning.
+
+The following CPU names can be detected:
@table @samp
@item power9
@@ -14956,20 +15038,33 @@ IBM PowerPC Cell Broadband Engine Architecture CPU.
Here is an example:
@smallexample
-if (__builtin_cpu_is ("power8"))
- @{
- do_power8 (); // POWER8 specific implementation.
- @}
-else
- @{
- do_generic (); // Generic implementation.
- @}
+#ifdef __BUILTIN_CPU_SUPPORTS__
+ if (__builtin_cpu_is ("power8"))
+ @{
+ do_power8 (); // POWER8 specific implementation.
+ @}
+ else
+#endif
+ @{
+ do_generic (); // Generic implementation.
+ @}
@end smallexample
@end deftypefn
@deftypefn {Built-in Function} int __builtin_cpu_supports (const char *@var{feature})
This function returns a value of @code{1} if the run-time CPU supports the HWCAP
-feature @var{feature} and returns @code{0} otherwise. The following features can be
+feature @var{feature} and returns @code{0} otherwise.
+
+The @code{__builtin_cpu_supports} function requires GLIBC 2.23 or
+newer which exports the hardware capability bits. GCC defines the
+macro @code{__BUILTIN_CPU_SUPPORTS__} if the
+@code{__builtin_cpu_supports} built-in function is fully supported.
+
+If GCC was configured to use a GLIBC before 2.23, the built-in
+function @code{__builtin_cpu_suports} always returns a 0 and the
+compiler issues a warning.
+
+The following features can be
detected:
@table @samp
@@ -15053,14 +15148,16 @@ CPU supports the vector-scalar extension.
Here is an example:
@smallexample
-if (__builtin_cpu_supports ("fpu"))
- @{
- asm("fadd %0,%1,%2" : "=d"(dst) : "d"(src1), "d"(src2));
- @}
-else
- @{
- dst = __fadd (src1, src2); // Software FP addition function.
- @}
+#ifdef __BUILTIN_CPU_SUPPORTS__
+ if (__builtin_cpu_supports ("fpu"))
+ @{
+ asm("fadd %0,%1,%2" : "=d"(dst) : "d"(src1), "d"(src2));
+ @}
+ else
+#endif
+ @{
+ dst = __fadd (src1, src2); // Software FP addition function.
+ @}
@end smallexample
@end deftypefn
@@ -15176,13 +15273,21 @@ long long __builtin_darn_raw (void);
int __builtin_darn_32 (void);
unsigned int scalar_extract_exp (double source);
+unsigned long long int scalar_extract_exp (__ieee128 source);
+
unsigned long long int scalar_extract_sig (double source);
+unsigned __int128 scalar_extract_sig (__ieee128 source);
double
scalar_insert_exp (unsigned long long int significand, unsigned long long int exponent);
double
scalar_insert_exp (double significand, unsigned long long int exponent);
+ieee_128
+scalar_insert_exp (unsigned __int128 significand, unsigned long long int exponent);
+ieee_128
+scalar_insert_exp (ieee_128 significand, unsigned long long int exponent);
+
int scalar_cmp_exp_gt (double arg1, double arg2);
int scalar_cmp_exp_lt (double arg1, double arg2);
int scalar_cmp_exp_eq (double arg1, double arg2);
@@ -15190,9 +15295,11 @@ int scalar_cmp_exp_unordered (double arg1, double arg2);
bool scalar_test_data_class (float source, const int condition);
bool scalar_test_data_class (double source, const int condition);
+bool scalar_test_data_class (__ieee128 source, const int condition);
bool scalar_test_neg (float source);
bool scalar_test_neg (double source);
+bool scalar_test_neg (__ieee128 source);
int __builtin_byte_in_set (unsigned char u, unsigned long long set);
int __builtin_byte_in_range (unsigned char u, unsigned int range);
@@ -15232,25 +15339,38 @@ functions require a 64-bit environment supporting ISA 3.0 or later.
The @code{scalar_extract_exp} and @code{scalar_extract_sig} built-in
functions return the significand and the biased exponent value
respectively of their @code{source} arguments.
-Within the result returned by @code{scalar_extract_sig},
-the @code{0x10000000000000} bit is set if the
+When supplied with a 64-bit @code{source} argument, the
+result returned by @code{scalar_extract_sig} has
+the @code{0x0010000000000000} bit set if the
function's @code{source} argument is in normalized form.
Otherwise, this bit is set to 0.
+When supplied with a 128-bit @code{source} argument, the
+@code{0x00010000000000000000000000000000} bit of the result is
+treated similarly.
Note that the sign of the significand is not represented in the result
returned from the @code{scalar_extract_sig} function. Use the
@code{scalar_test_neg} function to test the sign of its @code{double}
argument.
-The @code{scalar_insert_exp}
-function requires a 64-bit environment supporting ISA 3.0 or later.
-The @code{scalar_insert_exp} built-in function returns a double-precision
+The @code{scalar_insert_exp}
+functions require a 64-bit environment supporting ISA 3.0 or later.
+When supplied with a 64-bit first argument, the
+@code{scalar_insert_exp} built-in function returns a double-precision
floating point value that is constructed by assembling the values of its
@code{significand} and @code{exponent} arguments. The sign of the
result is copied from the most significant bit of the
@code{significand} argument. The significand and exponent components
of the result are composed of the least significant 11 bits of the
@code{exponent} argument and the least significant 52 bits of the
-@code{significand} argument.
+@code{significand} argument respectively.
+
+When supplied with a 128-bit first argument, the
+@code{scalar_insert_exp} built-in function returns a quad-precision
+ieee floating point value. The sign bit of the result is copied from
+the most significant bit of the @code{significand} argument.
+The significand and exponent components of the result are composed of
+the least significant 15 bits of the @code{exponent} argument and the
+least significant 112 bits of the @code{significand} argument respectively.
The @code{scalar_cmp_exp_gt}, @code{scalar_cmp_exp_lt},
@code{scalar_cmp_exp_eq}, and @code{scalar_cmp_exp_unordered} built-in
@@ -15357,12 +15477,23 @@ vector bool short vec_cmpnez (vector unsigned short arg1, vector unsigned short
vector bool int vec_cmpnez (vector signed int arg1, vector signed int arg2);
vector bool int vec_cmpnez (vector unsigned int, vector unsigned int);
+vector signed char vec_cnttz (vector signed char);
+vector unsigned char vec_cnttz (vector unsigned char);
+vector signed short vec_cnttz (vector signed short);
+vector unsigned short vec_cnttz (vector unsigned short);
+vector signed int vec_cnttz (vector signed int);
+vector unsigned int vec_cnttz (vector unsigned int);
+vector signed long long vec_cnttz (vector signed long long);
+vector unsigned long long vec_cnttz (vector unsigned long long);
+
signed int vec_cntlz_lsbb (vector signed char);
signed int vec_cntlz_lsbb (vector unsigned char);
signed int vec_cnttz_lsbb (vector signed char);
signed int vec_cnttz_lsbb (vector unsigned char);
+vector unsigned short vec_pack_to_short_fp32 (vector float, vector float);
+
vector signed char vec_xl_len (signed char *addr, size_t len);
vector unsigned char vec_xl_len (unsigned char *addr, size_t len);
vector signed int vec_xl_len (signed int *addr, size_t len);
@@ -16558,6 +16689,19 @@ vector bool char vec_perm (vector bool char,
vector float vec_re (vector float);
+vector bool char vec_reve (vector bool char);
+vector signed char vec_reve (vector signed char);
+vector unsigned char vec_reve (vector unsigned char);
+vector bool int vec_reve (vector bool int);
+vector signed int vec_reve (vector signed int);
+vector unsigned int vec_reve (vector unsigned int);
+vector bool long long vec_reve (vector bool long long);
+vector signed long long vec_reve (vector signed long long);
+vector unsigned long long vec_reve (vector unsigned long long);
+vector bool short vec_reve (vector bool short);
+vector signed short vec_reve (vector signed short);
+vector unsigned short vec_reve (vector unsigned short);
+
vector signed char vec_rl (vector signed char,
vector unsigned char);
vector unsigned char vec_rl (vector unsigned char,
@@ -16645,6 +16789,13 @@ vector bool char vec_sel (vector bool char,
vector bool char,
vector unsigned char);
+vector signed long long vec_signed (vector double);
+vector signed int vec_signed (vector float);
+
+vector signed int vec_signede (vector double);
+vector signed int vec_signedo (vector double);
+vector signed int vec_signed2 (vector double, vector double);
+
vector signed char vec_sl (vector signed char,
vector unsigned char);
vector unsigned char vec_sl (vector unsigned char,
@@ -17096,7 +17247,34 @@ vector unsigned char vec_vsububm (vector unsigned char,
vector unsigned char vec_vsububm (vector unsigned char,
vector unsigned char);
+vector signed int vec_subc (vector signed int, vector signed int);
vector unsigned int vec_subc (vector unsigned int, vector unsigned int);
+vector signed __int128 vec_subc (vector signed __int128,
+ vector signed __int128);
+vector unsigned __int128 vec_subc (vector unsigned __int128,
+ vector unsigned __int128);
+
+vector signed int vec_sube (vector signed int, vector signed int,
+ vector signed int);
+vector unsigned int vec_sube (vector unsigned int, vector unsigned int,
+ vector unsigned int);
+vector signed __int128 vec_sube (vector signed __int128,
+ vector signed __int128,
+ vector signed __int128);
+vector unsigned __int128 vec_sube (vector unsigned __int128,
+ vector unsigned __int128,
+ vector unsigned __int128);
+
+vector signed int vec_subec (vector signed int, vector signed int,
+ vector signed int);
+vector unsigned int vec_subec (vector unsigned int, vector unsigned int,
+ vector unsigned int);
+vector signed __int128 vec_subec (vector signed __int128,
+ vector signed __int128,
+ vector signed __int128);
+vector unsigned __int128 vec_subec (vector unsigned __int128,
+ vector unsigned __int128,
+ vector unsigned __int128);
vector unsigned char vec_subs (vector bool char, vector unsigned char);
vector unsigned char vec_subs (vector unsigned char, vector bool char);
@@ -17173,6 +17351,13 @@ vector signed int vec_sums (vector signed int, vector signed int);
vector float vec_trunc (vector float);
+vector signed long long vec_unsigned (vector double);
+vector signed int vec_unsigned (vector float);
+
+vector signed int vec_unsignede (vector double);
+vector signed int vec_unsignedo (vector double);
+vector signed int vec_unsigned2 (vector double, vector double);
+
vector signed short vec_unpackh (vector signed char);
vector bool short vec_unpackh (vector bool char);
vector signed int vec_unpackh (vector signed short);
@@ -18175,6 +18360,9 @@ vector bool short vec_cmpne (vector bool short, vector bool short);
vector bool int vec_cmpne (vector bool int, vector bool int);
vector bool long long vec_cmpne (vector bool long long, vector bool long long);
+vector float vec_extract_fp32_from_shorth (vector unsigned short);
+vector float vec_extract_fp32_from_shortl (vector unsigned short);
+
vector long long vec_vctz (vector long long);
vector unsigned long long vec_vctz (vector unsigned long long);
vector int vec_vctz (vector int);
@@ -18205,6 +18393,13 @@ vector unsigned char vec_insert4b (vector unsigned int, vector unsigned char,
vector signed char vec_insert4b (long long, vector signed char, const int);
vector unsigned char vec_insert4b (long long, vector unsigned char, const int);
+vector unsigned int vec_parity_lsbb (vector signed int);
+vector unsigned int vec_parity_lsbb (vector unsigned int);
+vector unsigned __int128 vec_parity_lsbb (vector signed __int128);
+vector unsigned __int128 vec_parity_lsbb (vector unsigned __int128);
+vector unsigned long long vec_parity_lsbb (vector signed long long);
+vector unsigned long long vec_parity_lsbb (vector unsigned long long);
+
vector int vec_vprtyb (vector int);
vector unsigned int vec_vprtyb (vector unsigned int);
vector long long vec_vprtyb (vector long long);
@@ -18420,13 +18615,17 @@ of each element.
If the ISA 3.0 instruction set additions (@option{-mcpu=power9})
are available:
@smallexample
+vector signed bool char vec_revb (vector signed char);
vector signed char vec_revb (vector signed char);
vector unsigned char vec_revb (vector unsigned char);
+vector bool short vec_revb (vector bool short);
vector short vec_revb (vector short);
vector unsigned short vec_revb (vector unsigned short);
+vector bool int vec_revb (vector bool int);
vector int vec_revb (vector int);
vector unsigned int vec_revb (vector unsigned int);
vector float vec_revb (vector float);
+vector bool long long vec_revb (vector bool long long);
vector long long vec_revb (vector long long);
vector unsigned long long vec_revb (vector unsigned long long);
vector double vec_revb (vector double);
@@ -19199,6 +19398,45 @@ v4hi __builtin_vis_fpminu16 (v4hi, v4hi);
v2si __builtin_vis_fpminu32 (v2si, v2si);
@end smallexample
+When you use the @option{-mvis4b} switch, the VIS version 4.0B
+built-in functions also become available:
+
+@smallexample
+v8qi __builtin_vis_dictunpack8 (double, int);
+v4hi __builtin_vis_dictunpack16 (double, int);
+v2si __builtin_vis_dictunpack32 (double, int);
+
+long __builtin_vis_fpcmple8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpgt8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpeq8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpne8shl (v8qi, v8qi, int);
+
+long __builtin_vis_fpcmple16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpgt16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpeq16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpne16shl (v4hi, v4hi, int);
+
+long __builtin_vis_fpcmple32shl (v2si, v2si, int);
+long __builtin_vis_fpcmpgt32shl (v2si, v2si, int);
+long __builtin_vis_fpcmpeq32shl (v2si, v2si, int);
+long __builtin_vis_fpcmpne32shl (v2si, v2si, int);
+
+long __builtin_vis_fpcmpule8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpugt8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpule16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpugt16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpule32shl (v2si, v2si, int);
+long __builtin_vis_fpcmpugt32shl (v2si, v2si, int);
+
+long __builtin_vis_fpcmpde8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpde16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpde32shl (v2si, v2si, int);
+
+long __builtin_vis_fpcmpur8shl (v8qi, v8qi, int);
+long __builtin_vis_fpcmpur16shl (v4hi, v4hi, int);
+long __builtin_vis_fpcmpur32shl (v2si, v2si, int);
+@end smallexample
+
@node SPU Built-in Functions
@subsection SPU Built-in Functions
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index 858521688b4..874d46440f4 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -2820,7 +2820,6 @@ This function cannot be used with namespaces that have
@findex BINFO_TYPE
@findex TYPE_FIELDS
@findex TYPE_VFIELD
-@findex TYPE_METHODS
Besides namespaces, the other high-level scoping construct in C++ is the
class. (Throughout this manual the term @dfn{class} is used to mean the
@@ -2837,7 +2836,7 @@ macro to discern whether or not a particular type is a @code{class} as
opposed to a @code{struct}. This macro will be true only for classes
declared with the @code{class} tag.
-Almost all non-function members are available on the @code{TYPE_FIELDS}
+Almost all members are available on the @code{TYPE_FIELDS}
list. Given one member, the next can be found by following the
@code{TREE_CHAIN}. You should not depend in any way on the order in
which fields appear on this list. All nodes on this list will be
@@ -2849,7 +2848,11 @@ list, if the enumeration type was declared in the class. (Of course,
the @code{TYPE_DECL} for the enumeration type will appear here as well.)
There are no entries for base classes on this list. In particular,
there is no @code{FIELD_DECL} for the ``base-class portion'' of an
-object.
+object. If a function member is overloaded, each of the overloaded
+functions appears; no @code{OVERLOAD} nodes appear on the @code{TYPE_FIELDS}
+list. Implicitly declared functions (including default constructors,
+copy constructors, assignment operators, and destructors) will appear on
+this list as well.
The @code{TYPE_VFIELD} is a compiler-generated field used to point to
virtual function tables. It may or may not appear on the
@@ -2857,14 +2860,6 @@ virtual function tables. It may or may not appear on the
@code{TYPE_VFIELD} just like all the entries on the @code{TYPE_FIELDS}
list.
-The function members are available on the @code{TYPE_METHODS} list.
-Again, subsequent members are found by following the @code{TREE_CHAIN}
-field. If a function is overloaded, each of the overloaded functions
-appears; no @code{OVERLOAD} nodes appear on the @code{TYPE_METHODS}
-list. Implicitly declared functions (including default constructors,
-copy constructors, assignment operators, and destructors) will appear on
-this list as well.
-
Every class has an associated @dfn{binfo}, which can be obtained with
@code{TYPE_BINFO}. Binfos are used to represent base-classes. The
binfo given by @code{TYPE_BINFO} is the degenerate case, whereby every
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e4ca1b4b4fc..5ae9dc4128d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -294,7 +294,7 @@ Objective-C and Objective-C++ Dialects}.
-Wmain -Wmaybe-uninitialized -Wmemset-elt-size -Wmemset-transposed-args @gol
-Wmisleading-indentation -Wmissing-braces @gol
-Wmissing-field-initializers -Wmissing-include-dirs @gol
--Wno-multichar -Wnonnull -Wnonnull-compare @gol
+-Wno-multichar -Wmultistatement-macros -Wnonnull -Wnonnull-compare @gol
-Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} @gol
-Wnull-dereference -Wodr -Wno-overflow -Wopenmp-simd @gol
-Woverride-init-side-effects -Woverlength-strings @gol
@@ -587,15 +587,14 @@ Objective-C and Objective-C++ Dialects}.
-mgeneral-regs-only @gol
-mcmodel=tiny -mcmodel=small -mcmodel=large @gol
-mstrict-align @gol
--momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol
+-momit-leaf-frame-pointer @gol
-mtls-dialect=desc -mtls-dialect=traditional @gol
-mtls-size=@var{size} @gol
--mfix-cortex-a53-835769 -mno-fix-cortex-a53-835769 @gol
--mfix-cortex-a53-843419 -mno-fix-cortex-a53-843419 @gol
--mlow-precision-recip-sqrt -mno-low-precision-recip-sqrt@gol
--mlow-precision-sqrt -mno-low-precision-sqrt@gol
--mlow-precision-div -mno-low-precision-div @gol
--march=@var{name} -mcpu=@var{name} -mtune=@var{name}}
+-mfix-cortex-a53-835769 -mfix-cortex-a53-843419 @gol
+-mlow-precision-recip-sqrt -mlow-precision-sqrt -mlow-precision-div @gol
+-mpc-relative-literal-loads @gol
+-msign-return-address=@var{scope} @gol
+-march=@var{name} -mcpu=@var{name} -mtune=@var{name} -moverride=@var{string}}
@emph{Adapteva Epiphany Options}
@gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol
@@ -632,6 +631,7 @@ Objective-C and Objective-C++ Dialects}.
-mapcs-reentrant -mno-apcs-reentrant @gol
-msched-prolog -mno-sched-prolog @gol
-mlittle-endian -mbig-endian @gol
+-mbe8 -mbe32 @gol
-mfloat-abi=@var{name} @gol
-mfp16-format=@var{name}
-mthumb-interwork -mno-thumb-interwork @gol
@@ -661,7 +661,8 @@ Objective-C and Objective-C++ Dialects}.
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -mabsdata -maccumulate-args @gol
-mbranch-cost=@var{cost} @gol
--mcall-prologues -mint8 -mn_flash=@var{size} -mno-interrupts @gol
+-mcall-prologues -mgas-isr-prologues -mint8 @gol
+-mn_flash=@var{size} -mno-interrupts @gol
-mrelax -mrmw -mstrict-X -mtiny-stack -mfract-convert-truncate @gol
-mshort-calls -nodevicelib @gol
-Waddr-space-convert -Wmisspelled-isr}
@@ -1044,14 +1045,10 @@ See RS/6000 and PowerPC Options.
-mquad-memory -mno-quad-memory @gol
-mquad-memory-atomic -mno-quad-memory-atomic @gol
-mcompat-align-parm -mno-compat-align-parm @gol
--mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs-di -mno-upper-regs-di @gol
--mupper-regs -mno-upper-regs @gol
-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
-mgnu-attribute -mno-gnu-attribute @gol
-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol
--mstack-protector-guard-offset=@var{offset} @gol
--mlra -mno-lra}
+-mstack-protector-guard-offset=@var{offset}}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
@@ -1125,9 +1122,10 @@ See RS/6000 and PowerPC Options.
-muser-mode -mno-user-mode @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
--mcbcond -mno-cbcond -mfmaf -mno-fmaf @gol
--mpopc -mno-popc -msubxc -mno-subxc@gol
--mfix-at697f -mfix-ut699 @gol
+-mvis4 -mno-vis4 -mvis4b -mno-vis4b @gol
+-mcbcond -mno-cbcond -mfmaf -mno-fmaf -mfsmuld -mno-fsmuld @gol
+-mpopc -mno-popc -msubxc -mno-subxc @gol
+-mfix-at697f -mfix-ut699 -mfix-ut700 -mfix-gr712rc @gol
-mlra -mno-lra}
@emph{SPU Options}
@@ -3842,6 +3840,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wmemset-transposed-args @gol
-Wmisleading-indentation @r{(only for C/C++)} @gol
-Wmissing-braces @r{(only for C/ObjC)} @gol
+-Wmultistatement-macros @gol
-Wnarrowing @r{(only for C++)} @gol
-Wnonnull @gol
-Wnonnull-compare @gol
@@ -4514,6 +4513,32 @@ This warning is enabled by @option{-Wall}.
@opindex Wno-missing-include-dirs
Warn if a user-supplied include directory does not exist.
+@item -Wmultistatement-macros
+@opindex Wmultistatement-macros
+@opindex Wno-multistatement-macros
+Warn about unsafe multiple statement macros that appear to be guarded
+by a clause such as @code{if}, @code{else}, @code{for}, @code{switch}, or
+@code{while}, in which only the first statement is actually guarded after
+the macro is expanded.
+
+For example:
+
+@smallexample
+#define DOIT x++; y++
+if (c)
+ DOIT;
+@end smallexample
+
+will increment @code{y} unconditionally, not just when @code{c} holds.
+The can usually be fixed by wrapping the macro in a do-while loop:
+@smallexample
+#define DOIT do @{ x++; y++; @} while (0)
+if (c)
+ DOIT;
+@end smallexample
+
+This warning is enabled by @option{-Wall} in C and C++.
+
@item -Wparentheses
@opindex Wparentheses
@opindex Wno-parentheses
@@ -8672,7 +8697,7 @@ into separate sections of the assembly and @file{.o} files, to improve
paging and cache locality performance.
This optimization is automatically turned off in the presence of
-exception handling, for linkonce sections, for functions with a user-defined
+exception handling or unwind tables (on targets using setjump/longjump or target specific scheme), for linkonce sections, for functions with a user-defined
section attribute and on any architecture that does not support named
sections. When @option{-fsplit-stack} is used this option is not
enabled by default (to avoid linker errors), but may be enabled
@@ -11493,6 +11518,34 @@ of the function name, it is considered to be a match. For C99 and C++
extended identifiers, the function name must be given in UTF-8, not
using universal character names.
+@item -fpatchable-function-entry=@var{N}[,@var{M}]
+@opindex fpatchable-function-entry
+Generate @var{N} NOPs right at the beginning
+of each function, with the function entry point before the @var{M}th NOP.
+If @var{M} is omitted, it defaults to @code{0} so the
+function entry points to the address just at the first NOP.
+The NOP instructions reserve extra space which can be used to patch in
+any desired instrumentation at run time, provided that the code segment
+is writable. The amount of space is controllable indirectly via
+the number of NOPs; the NOP instruction used corresponds to the instruction
+emitted by the internal GCC back-end interface @code{gen_nop}. This behavior
+is target-specific and may also depend on the architecture variant and/or
+other compilation options.
+
+For run-time identification, the starting addresses of these areas,
+which correspond to their respective function entries minus @var{M},
+are additionally collected in the @code{__patchable_function_entries}
+section of the resulting binary.
+
+Note that the value of @code{__attribute__ ((patchable_function_entry
+(N,M)))} takes precedence over command-line option
+@option{-fpatchable-function-entry=N,M}. This can be used to increase
+the area size or to remove it completely on a single function.
+If @code{N=0}, no pad location is recorded.
+
+The NOP instructions are inserted at---and maybe before, depending on
+@var{M}---the function entry address, even before the prologue.
+
@end table
@@ -14055,7 +14108,7 @@ support for the ARMv8.2-A architecture extensions.
The value @samp{armv8.1-a} implies @samp{armv8-a} and enables compiler
support for the ARMv8.1-A architecture extension. In particular, it
-enables the @samp{+crc} and @samp{+lse} features.
+enables the @samp{+crc}, @samp{+lse}, and @samp{+rdma} features.
The value @samp{native} is available on native AArch64 GNU/Linux and
causes the compiler to pick the architecture of the host system. This
@@ -14131,8 +14184,10 @@ across releases.
This option is only intended to be useful when developing GCC.
@item -mpc-relative-literal-loads
+@itemx -mno-pc-relative-literal-loads
@opindex mpc-relative-literal-loads
-Enable PC-relative literal loads. With this option literal pools are
+@opindex mno-pc-relative-literal-loads
+Enable or disable PC-relative literal loads. With this option literal pools are
accessed using a single instruction and emitted after each function. This
limits the maximum size of functions to 1MB. This is enabled by default for
@option{-mcmodel=tiny}.
@@ -14171,8 +14226,15 @@ instructions. This is on by default for all possible values for options
@item lse
Enable Large System Extension instructions. This is on by default for
@option{-march=armv8.1-a}.
+@item rdma
+Enable Round Double Multiply Accumulate instructions. This is on by default
+for @option{-march=armv8.1-a}.
@item fp16
Enable FP16 extension. This also enables floating-point instructions.
+@item rcpc
+Enable the RcPc extension. This does not change code generation from GCC,
+but is passed on to the assembler, enabling inline asm statements to use
+instructions from the RcPc extension.
@end table
@@ -14871,7 +14933,7 @@ Enable pre-reload use of the @code{cbranchsi} pattern.
@item -mexpand-adddi
@opindex mexpand-adddi
Expand @code{adddi3} and @code{subdi3} at RTL generation time into
-@code{add.f}, @code{adc} etc.
+@code{add.f}, @code{adc} etc. This option is deprecated.
@item -mindexed-loads
@opindex mindexed-loads
@@ -15161,7 +15223,16 @@ the default for all standard configurations.
Generate code for a processor running in big-endian mode; the default is
to compile code for a little-endian processor.
-@item -march=@var{name@r{[}+extension@dots{}@r{]}}
+@item -mbe8
+@itemx -mbe32
+@opindex mbe8
+When linking a big-endian image select between BE8 and BE32 formats.
+The option has no effect for little-endian images and is ignored. The
+default is dependent on the selected target architecture. For ARMv6
+and later architectures the default is BE8, for older architectures
+the default is BE32. BE32 format has been deprecated by ARM.
+
+@item -march=@var{name}@r{[}+extension@dots{}@r{]}
@opindex march
This specifies the name of the target ARM architecture. GCC uses this
name to determine what kind of instructions it can emit when generating
@@ -15176,6 +15247,7 @@ Permissible names are:
@samp{armv7}, @samp{armv7-a}, @samp{armv7ve},
@samp{armv8-a}, @samp{armv8.1-a}, @samp{armv8.2-a},
@samp{armv7-r},
+@samp{armv8-r},
@samp{armv6-m}, @samp{armv6s-m},
@samp{armv7-m}, @samp{armv7e-m},
@samp{armv8-m.base}, @samp{armv8-m.main},
@@ -15442,7 +15514,22 @@ The single- and double-precision floating-point instructions.
@item +nofp
Disable the floating-point extension.
+@end table
+@item armv8-r
+@table @samp
+@item +crc
+The Cyclic Redundancy Check (CRC) instructions.
+@item +fp.sp
+The single-precision FPv5 floating-point instructions.
+@item +simd
+The ARMv8 Advanced SIMD and floating-point instructions.
+@item +crypto
+The cryptographic instructions.
+@item +nocrypto
+Disable the cryptographic isntructions.
+@item +nofp
+Disable the floating-point, Advanced SIMD and cryptographic instructions.
@end table
@end table
@@ -15477,9 +15564,10 @@ Permissible names are: @samp{arm2}, @samp{arm250},
@samp{arm1156t2-s}, @samp{arm1156t2f-s}, @samp{arm1176jz-s}, @samp{arm1176jzf-s},
@samp{generic-armv7-a}, @samp{cortex-a5}, @samp{cortex-a7}, @samp{cortex-a8},
@samp{cortex-a9}, @samp{cortex-a12}, @samp{cortex-a15}, @samp{cortex-a17},
-@samp{cortex-a32}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a57},
-@samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-r4},
-@samp{cortex-r4f}, @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8},
+@samp{cortex-a32}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55},
+@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
+@samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-r5}, @samp{cortex-r7},
+@samp{cortex-r8}, @samp{cortex-r52},
@samp{cortex-m33},
@samp{cortex-m23},
@samp{cortex-m7},
@@ -15502,7 +15590,8 @@ Additionally, this option can specify that GCC should tune the performance
of the code for a big.LITTLE system. Permissible names are:
@samp{cortex-a15.cortex-a7}, @samp{cortex-a17.cortex-a7},
@samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
-@samp{cortex-a72.cortex-a35}, @samp{cortex-a73.cortex-a53}.
+@samp{cortex-a72.cortex-a35}, @samp{cortex-a73.cortex-a53},
+@samp{cortex-a75.cortex-a55}.
@option{-mtune=generic-@var{arch}} specifies that GCC should tune the
performance for a blend of processors within architecture @var{arch}.
@@ -15519,7 +15608,7 @@ of the build computer. At present, this feature is only supported on
GNU/Linux, and not all architectures are recognized. If the auto-detect is
unsuccessful the option has no effect.
-@item -mcpu=@var{name@r{[}+extension@dots{}@r{]}}
+@item -mcpu=@var{name}@r{[}+extension@dots{}@r{]}
@opindex mcpu
This specifies the name of the target ARM processor. GCC uses this name
to derive the name of the target ARM architecture (as if specified
@@ -15563,17 +15652,25 @@ Disables the floating-point and SIMD instructions on
@samp{generic-armv7-a}, @samp{cortex-a5}, @samp{cortex-a7},
@samp{cortex-a8}, @samp{cortex-a9}, @samp{cortex-a12},
@samp{cortex-a15}, @samp{cortex-a17}, @samp{cortex-a15.cortex-a7},
-@samp{cortex-a17.cortex-a7}, @samp{cortex-a32}, @samp{cortex-a35}
-and @samp{cortex-a53}.
+@samp{cortex-a17.cortex-a7}, @samp{cortex-a32}, @samp{cortex-a35},
+@samp{cortex-a53} and @samp{cortex-a55}.
@item +nofp.dp
Disables the double-precision component of the floating-point instructions
-on @samp{cortex-r5} and @samp{cortex-m7}.
+on @samp{cortex-r5}, @samp{cortex-r52} and @samp{cortex-m7}.
@item +nosimd
Disables the SIMD (but not floating-point) instructions on
@samp{generic-armv7-a}, @samp{cortex-a5}, @samp{cortex-a7}
and @samp{cortex-a9}.
+
+@item +crypto
+Enables the cryptographic instructions on @samp{cortex-a32},
+@samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55}, @samp{cortex-a57},
+@samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75}, @samp{exynos-m1},
+@samp{xgene1}, @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
+@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53} and
+@samp{cortex-a75.cortex-a55}.
@end table
Additionally the @samp{generic-armv7-a} pseudo target defaults to
@@ -15641,6 +15738,8 @@ incompatible. Code compiled with one value cannot necessarily expect to
work with code or libraries compiled with another value, if they exchange
information using structures or unions.
+This option is deprecated.
+
@item -mabort-on-noreturn
@opindex mabort-on-noreturn
Generate a call to the function @code{abort} at the end of a
@@ -15918,6 +16017,16 @@ integers. The default branch cost is 0.
Functions prologues/epilogues are expanded as calls to appropriate
subroutines. Code size is smaller.
+@item -mgas-isr-prologues
+@opindex mgas-isr-prologues
+Interrupt service routines (ISRs) may use the @code{__gcc_isr} pseudo
+instruction supported by GNU Binutils.
+If this option is on, the feature can still be disabled for individual
+ISRs by means of the @ref{AVR Function Attributes,,@code{no_gccisr}}
+function attribute. This feature is activated per default
+if optimization is on (but not with @option{-Og}, @pxref{Optimize Options}),
+and if GNU Binutils support @w{@uref{https://sourceware.org/PR21683,PR21683}}.
+
@item -mint8
@opindex mint8
Assume @code{int} to be 8-bit integer. This affects the sizes of all types: a
@@ -21731,11 +21840,6 @@ This switch enables or disables the generation of ISEL instructions.
This switch has been deprecated. Use @option{-misel} and
@option{-mno-isel} instead.
-@item -mlra
-@opindex mlra
-Enable Local Register Allocation. By default the port uses LRA.
-(i.e. @option{-mno-lra}).
-
@item -mspe
@itemx -mno-spe
@opindex mspe
@@ -21819,50 +21923,6 @@ Generate code that uses (does not use) the atomic quad word memory
instructions. The @option{-mquad-memory-atomic} option requires use of
64-bit mode.
-@item -mupper-regs-di
-@itemx -mno-upper-regs-di
-@opindex mupper-regs-di
-@opindex mno-upper-regs-di
-Generate code that uses (does not use) the scalar instructions that
-target all 64 registers in the vector/scalar floating point register
-set that were added in version 2.06 of the PowerPC ISA when processing
-integers. @option{-mupper-regs-di} is turned on by default if you use
-any of the @option{-mcpu=power7}, @option{-mcpu=power8},
-@option{-mcpu=power9}, or @option{-mvsx} options.
-
-@item -mupper-regs-df
-@itemx -mno-upper-regs-df
-@opindex mupper-regs-df
-@opindex mno-upper-regs-df
-Generate code that uses (does not use) the scalar double precision
-instructions that target all 64 registers in the vector/scalar
-floating point register set that were added in version 2.06 of the
-PowerPC ISA. @option{-mupper-regs-df} is turned on by default if you
-use any of the @option{-mcpu=power7}, @option{-mcpu=power8},
-@option{-mcpu=power9}, or @option{-mvsx} options.
-
-@item -mupper-regs-sf
-@itemx -mno-upper-regs-sf
-@opindex mupper-regs-sf
-@opindex mno-upper-regs-sf
-Generate code that uses (does not use) the scalar single precision
-instructions that target all 64 registers in the vector/scalar
-floating point register set that were added in version 2.07 of the
-PowerPC ISA. @option{-mupper-regs-sf} is turned on by default if you
-use either of the @option{-mcpu=power8}, @option{-mpower8-vector}, or
-@option{-mcpu=power9} options.
-
-@item -mupper-regs
-@itemx -mno-upper-regs
-@opindex mupper-regs
-@opindex mno-upper-regs
-Generate code that uses (does not use) the scalar
-instructions that target all 64 registers in the vector/scalar
-floating point register set, depending on the model of the machine.
-
-If the @option{-mno-upper-regs} option is used, it turns off both
-@option{-mupper-regs-sf} and @option{-mupper-regs-df} options.
-
@item -mfloat128
@itemx -mno-float128
@opindex mfloat128
@@ -23835,7 +23895,7 @@ for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{leon}, @samp{leon3}, @samp{leon3v7}, @samp{sparclite}, @samp{f930},
@samp{f934}, @samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9},
@samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2},
-@samp{niagara3}, @samp{niagara4} and @samp{niagara7}.
+@samp{niagara3}, @samp{niagara4}, @samp{niagara7} and @samp{m8}.
Native Solaris and GNU/Linux toolchains also support the value @samp{native},
which selects the best architecture option for the host processor.
@@ -23863,7 +23923,8 @@ f930, f934, sparclite86x
tsc701
@item v9
-ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7
+ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4,
+niagara7, m8
@end table
By default (unless configured otherwise), GCC generates code for the V7
@@ -23907,7 +23968,8 @@ additionally optimizes it for Sun UltraSPARC T2 chips. With
UltraSPARC T3 chips. With @option{-mcpu=niagara4}, the compiler
additionally optimizes it for Sun UltraSPARC T4 chips. With
@option{-mcpu=niagara7}, the compiler additionally optimizes it for
-Oracle SPARC M7 chips.
+Oracle SPARC M7 chips. With @option{-mcpu=m8}, the compiler
+additionally optimizes it for Oracle M8 chips.
@item -mtune=@var{cpu_type}
@opindex mtune
@@ -23922,8 +23984,8 @@ that select a particular CPU implementation. Those are
@samp{leon3}, @samp{leon3v7}, @samp{f930}, @samp{f934},
@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc},
@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3},
-@samp{niagara4} and @samp{niagara7}. With native Solaris and
-GNU/Linux toolchains, @samp{native} can also be used.
+@samp{niagara4}, @samp{niagara7} and @samp{m8}. With native Solaris
+and GNU/Linux toolchains, @samp{native} can also be used.
@item -mv8plus
@itemx -mno-v8plus
@@ -23971,6 +24033,18 @@ default is @option{-mvis4} when targeting a cpu that supports such
instructions, such as niagara-7 and later. Setting @option{-mvis4}
also sets @option{-mvis3}, @option{-mvis2} and @option{-mvis}.
+@item -mvis4b
+@itemx -mno-vis4b
+@opindex mvis4b
+@opindex mno-vis4b
+With @option{-mvis4b}, GCC generates code that takes advantage of
+version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus
+the additional VIS instructions introduced in the Oracle SPARC
+Architecture 2017. The default is @option{-mvis4b} when targeting a
+cpu that supports such instructions, such as m8 and later. Setting
+@option{-mvis4b} also sets @option{-mvis4}, @option{-mvis3},
+@option{-mvis2} and @option{-mvis}.
+
@item -mcbcond
@itemx -mno-cbcond
@opindex mcbcond
@@ -23989,6 +24063,15 @@ Fused Multiply-Add Floating-point instructions. The default is @option{-mfmaf}
when targeting a CPU that supports such instructions, such as Niagara-3 and
later.
+@item -mfsmuld
+@itemx -mno-fsmuld
+@opindex mfsmuld
+@opindex mno-fsmuld
+With @option{-mfsmuld}, GCC generates code that takes advantage of the
+Floating-point Multiply Single to Double (FsMULd) instruction. The default is
+@option{-mfsmuld} when targeting a CPU supporting the architecture versions V8
+or V9 with FPU except @option{-mcpu=leon}.
+
@item -mpopc
@itemx -mno-popc
@opindex mpopc
@@ -24016,6 +24099,16 @@ processor (which corresponds to erratum #13 of the AT697E processor).
@opindex mfix-ut699
Enable the documented workarounds for the floating-point errata and the data
cache nullify errata of the UT699 processor.
+
+@item -mfix-ut700
+@opindex mfix-ut700
+Enable the documented workaround for the back-to-back store errata of
+the UT699E/UT700 processor.
+
+@item -mfix-gr712rc
+@opindex mfix-gr712rc
+Enable the documented workaround for the back-to-back store errata of
+the GR712RC processor.
@end table
These @samp{-m} options are supported in addition to the above
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index b02e5a16bfe..6e2799a1ce9 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -4022,9 +4022,10 @@ are stored in the @code{REG_NOTES} field of an insn.
@item REG_BR_PROB
This is used to specify the ratio of branches to non-branches of a
branch insn according to the profile data. The note is represented
-as an @code{int_list} expression whose integer value is between 0 and
-REG_BR_PROB_BASE. Larger values indicate a higher probability that
-the branch will be taken.
+as an @code{int_list} expression whose integer value is an encoding
+of @code{profile_probability} type. @code{profile_probability} provide
+member function @code{from_reg_br_prob_note} and @code{to_reg_br_prob_note}
+to extract and store the probability into the RTL encoding.
@findex REG_BR_PRED
@item REG_BR_PRED
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 7f5c2cf58c4..85af8778167 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1582,6 +1582,12 @@ Test system supports executing NEON v2 instructions.
ARM Target supports @code{-mfpu=neon -mfloat-abi=softfp} or compatible
options. Some multilibs may be incompatible with these options.
+@item arm_neon_ok_no_float_abi
+@anchor{arm_neon_ok_no_float_abi}
+ARM Target supports NEON with @code{-mfpu=neon}, but without any
+-mfloat-abi= option. Some multilibs may be incompatible with this
+option.
+
@item arm_neonv2_ok
@anchor{arm_neonv2_ok}
ARM Target supports @code{-mfpu=neon-vfpv4 -mfloat-abi=softfp} or compatible
@@ -2305,6 +2311,11 @@ the codeset to convert to.
Skip the test if the target does not support profiling with option
@var{profopt}.
+@item dg-require-stack-check @var{check}
+Skip the test if the target does not support the @code{-fstack-check}
+option. If @var{check} is @code{""}, support for @code{-fstack-check}
+is checked, for @code{-fstack-check=("@var{check}")} otherwise.
+
@item dg-require-visibility @var{vis}
Skip the test if the target does not support the @code{visibility} attribute.
If @var{vis} is @code{""}, support for @code{visibility("hidden")} is
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 39302f3e883..23e85c7afea 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4573,6 +4573,15 @@ will select the smallest suitable mode.
This section describes the macros that output function entry
(@dfn{prologue}) and exit (@dfn{epilogue}) code.
+@deftypefn {Target Hook} void TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY (FILE *@var{file}, unsigned HOST_WIDE_INT @var{patch_area_size}, bool @var{record_p})
+Generate a patchable area at the function start, consisting of
+@var{patch_area_size} NOP instructions. If the target supports named
+sections and if @var{record_p} is true, insert a pointer to the current
+location in the table of patchable functions. The default implementation
+of the hook places the table of pointers in the special section named
+@code{__patchable_function_entries}.
+@end deftypefn
+
@deftypefn {Target Hook} void TARGET_ASM_FUNCTION_PROLOGUE (FILE *@var{file}, HOST_WIDE_INT @var{size})
If defined, a function that outputs the assembler code for entry to a
function. The prologue is responsible for setting up the stack frame,
@@ -5172,7 +5181,7 @@ returns bounds for returned pointers. Arguments meaning is similar to
@code{TARGET_FUNCTION_VALUE}.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARG_BOUNDS (cumulative_args_t @var{args_so_far}, enum machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
+@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARG_BOUNDS (cumulative_args_t @var{args_so_far}, machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
Use it to store bounds for anonymous register arguments stored
into the stack. Arguments meaning is similar to
@code{TARGET_SETUP_INCOMING_VARARGS}.
@@ -11346,7 +11355,7 @@ returns upper bound of bounds @var{b}.
@deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void)
Return type to be used for bounds
@end deftypefn
-@deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void)
+@deftypefn {Target Hook} machine_mode TARGET_CHKP_BOUND_MODE (void)
Return mode to be used for bounds.
@end deftypefn
@deftypefn {Target Hook} tree TARGET_CHKP_MAKE_BOUNDS_CONSTANT (HOST_WIDE_INT @var{lb}, HOST_WIDE_INT @var{ub})
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 98f2e6bce5f..6df08a2c477 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3650,6 +3650,8 @@ will select the smallest suitable mode.
This section describes the macros that output function entry
(@dfn{prologue}) and exit (@dfn{epilogue}) code.
+@hook TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY
+
@hook TARGET_ASM_FUNCTION_PROLOGUE
@hook TARGET_ASM_FUNCTION_END_PROLOGUE
diff --git a/gcc/dojump.c b/gcc/dojump.c
index b45bba3ac37..7a389663ab4 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -39,19 +39,13 @@ along with GCC; see the file COPYING3. If not see
static bool prefer_and_bit_test (machine_mode, int);
static void do_jump_by_parts_greater (tree, tree, int,
- rtx_code_label *, rtx_code_label *, int);
+ rtx_code_label *, rtx_code_label *,
+ profile_probability);
static void do_jump_by_parts_equality (tree, tree, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
static void do_compare_and_jump (tree, tree, enum rtx_code, enum rtx_code,
- rtx_code_label *, rtx_code_label *, int);
-
-/* Invert probability if there is any. -1 stands for unknown. */
-
-static inline int
-inv (int prob)
-{
- return prob == -1 ? -1 : REG_BR_PROB_BASE - prob;
-}
+ rtx_code_label *, rtx_code_label *,
+ profile_probability);
/* At the start of a function, record that we have no previously-pushed
arguments waiting to be popped. */
@@ -128,29 +122,29 @@ restore_pending_stack_adjust (saved_pending_stack_adjust *save)
/* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
void
-jumpifnot (tree exp, rtx_code_label *label, int prob)
+jumpifnot (tree exp, rtx_code_label *label, profile_probability prob)
{
- do_jump (exp, label, NULL, inv (prob));
+ do_jump (exp, label, NULL, prob.invert ());
}
void
jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx_code_label *label,
- int prob)
+ profile_probability prob)
{
- do_jump_1 (code, op0, op1, label, NULL, inv (prob));
+ do_jump_1 (code, op0, op1, label, NULL, prob.invert ());
}
/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
void
-jumpif (tree exp, rtx_code_label *label, int prob)
+jumpif (tree exp, rtx_code_label *label, profile_probability prob)
{
do_jump (exp, NULL, label, prob);
}
void
jumpif_1 (enum tree_code code, tree op0, tree op1,
- rtx_code_label *label, int prob)
+ rtx_code_label *label, profile_probability prob)
{
do_jump_1 (code, op0, op1, NULL, label, prob);
}
@@ -200,12 +194,12 @@ prefer_and_bit_test (machine_mode mode, int bitnum)
/* Subroutine of do_jump, dealing with exploded comparisons of the type
OP0 CODE OP1 . IF_FALSE_LABEL and IF_TRUE_LABEL like in do_jump.
- PROB is probability of jump to if_true_label, or -1 if unknown. */
+ PROB is probability of jump to if_true_label. */
void
do_jump_1 (enum tree_code code, tree op0, tree op1,
rtx_code_label *if_false_label, rtx_code_label *if_true_label,
- int prob)
+ profile_probability prob)
{
machine_mode mode;
rtx_code_label *drop_through_label = 0;
@@ -222,7 +216,8 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
!= MODE_COMPLEX_INT);
if (integer_zerop (op1))
- do_jump (op0, if_true_label, if_false_label, inv (prob));
+ do_jump (op0, if_true_label, if_false_label,
+ prob.invert ());
else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
&& !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
do_jump_by_parts_equality (op0, op1, if_false_label, if_true_label,
@@ -247,7 +242,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
&& !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
do_jump_by_parts_equality (op0, op1, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, NE, NE, if_false_label, if_true_label,
prob);
@@ -270,7 +265,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
if (GET_MODE_CLASS (mode) == MODE_INT
&& ! can_compare_p (LE, mode, ccp_jump))
do_jump_by_parts_greater (op0, op1, 0, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, LE, LEU, if_false_label, if_true_label,
prob);
@@ -292,7 +287,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
if (GET_MODE_CLASS (mode) == MODE_INT
&& ! can_compare_p (GE, mode, ccp_jump))
do_jump_by_parts_greater (op0, op1, 1, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, GE, GEU, if_false_label, if_true_label,
prob);
@@ -346,17 +341,17 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
half of the total probability of being false, so its jump has a false
probability of half the total, relative to the probability we
reached it (i.e. the first condition was true). */
- int op0_prob = -1;
- int op1_prob = -1;
- if (prob != -1)
+ profile_probability op0_prob = profile_probability::uninitialized ();
+ profile_probability op1_prob = profile_probability::uninitialized ();
+ if (prob.initialized_p ())
{
- int false_prob = inv (prob);
- int op0_false_prob = false_prob / 2;
- int op1_false_prob = GCOV_COMPUTE_SCALE ((false_prob / 2),
- inv (op0_false_prob));
+ profile_probability false_prob = prob.invert ();
+ profile_probability op0_false_prob = false_prob.apply_scale (1, 2);
+ profile_probability op1_false_prob = false_prob.apply_scale (1, 2)
+ / op0_false_prob.invert ();
/* Get the probability that each jump below is true. */
- op0_prob = inv (op0_false_prob);
- op1_prob = inv (op1_false_prob);
+ op0_prob = op0_false_prob.invert ();
+ op1_prob = op1_false_prob.invert ();
}
if (if_false_label == NULL)
{
@@ -379,12 +374,12 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
The second condition has the other half of the total probability,
so its jump has a probability of half the total, relative to
the probability we reached it (i.e. the first condition was false). */
- int op0_prob = -1;
- int op1_prob = -1;
- if (prob != -1)
+ profile_probability op0_prob = profile_probability::uninitialized ();
+ profile_probability op1_prob = profile_probability::uninitialized ();
+ if (prob.initialized_p ())
{
- op0_prob = prob / 2;
- op1_prob = GCOV_COMPUTE_SCALE ((prob / 2), inv (op0_prob));
+ op0_prob = prob.apply_scale (1, 2);
+ op1_prob = prob.apply_scale (1, 2) / op0_prob.invert ();
}
if (if_true_label == NULL)
{
@@ -420,11 +415,11 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
actually perform a jump. An example where there is no jump
is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
- PROB is probability of jump to if_true_label, or -1 if unknown. */
+ PROB is probability of jump to if_true_label. */
void
do_jump (tree exp, rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label, profile_probability prob)
{
enum tree_code code = TREE_CODE (exp);
rtx temp;
@@ -481,7 +476,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
case TRUTH_NOT_EXPR:
do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case COND_EXPR:
@@ -497,7 +492,8 @@ do_jump (tree exp, rtx_code_label *if_false_label,
}
do_pending_stack_adjust ();
- do_jump (TREE_OPERAND (exp, 0), label1, NULL, -1);
+ do_jump (TREE_OPERAND (exp, 0), label1, NULL,
+ profile_probability::uninitialized ());
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
emit_label (label1);
do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
@@ -542,7 +538,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
{
tree exp0 = TREE_OPERAND (exp, 0);
rtx_code_label *set_label, *clr_label;
- int setclr_prob = prob;
+ profile_probability setclr_prob = prob;
/* Strip narrowing integral type conversions. */
while (CONVERT_EXPR_P (exp0)
@@ -558,7 +554,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
exp0 = TREE_OPERAND (exp0, 0);
clr_label = if_true_label;
set_label = if_false_label;
- setclr_prob = inv (prob);
+ setclr_prob = prob.invert ();
}
else
{
@@ -673,7 +669,7 @@ static void
do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
rtx op1, rtx_code_label *if_false_label,
rtx_code_label *if_true_label,
- int prob)
+ profile_probability prob)
{
int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
rtx_code_label *drop_through_label = 0;
@@ -703,7 +699,7 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
if_false_label = drop_through_label;
drop_through_if_true = false;
drop_through_if_false = true;
- prob = inv (prob);
+ prob = prob.invert ();
}
/* Compare a word at a time, high order first. */
@@ -733,7 +729,8 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
/* Consider lower words only if these are equal. */
do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
- NULL_RTX, NULL, if_false_label, inv (prob));
+ NULL_RTX, NULL, if_false_label,
+ prob.invert ());
}
if (!drop_through_if_false)
@@ -750,7 +747,8 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
static void
do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx op0 = expand_normal (swap ? treeop1 : treeop0);
rtx op1 = expand_normal (swap ? treeop0 : treeop1);
@@ -769,7 +767,8 @@ do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
static void
do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
rtx part;
@@ -819,7 +818,8 @@ do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
static void
do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
rtx_code_label *drop_through_label = NULL;
@@ -859,7 +859,8 @@ do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
static void
do_jump_by_parts_equality (tree treeop0, tree treeop1,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx op0 = expand_normal (treeop0);
rtx op1 = expand_normal (treeop1);
@@ -956,7 +957,8 @@ void
do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
machine_mode mode, rtx size,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx tem;
rtx_code_label *dummy_label = NULL;
@@ -983,7 +985,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
{
std::swap (if_true_label, if_false_label);
code = rcode;
- prob = inv (prob);
+ prob = prob.invert ();
}
}
@@ -1035,7 +1037,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
case LEU:
do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case GTU:
@@ -1046,7 +1048,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
case GEU:
do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case LT:
@@ -1057,7 +1059,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
case LE:
do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case GT:
@@ -1068,7 +1070,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
case GE:
do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case EQ:
@@ -1078,7 +1080,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
case NE:
do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
- if_false_label, inv (prob));
+ if_false_label,
+ prob.invert ());
break;
default:
@@ -1115,11 +1118,13 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
else
{
- int first_prob = prob;
+ profile_probability first_prob = prob;
if (first_code == UNORDERED)
- first_prob = REG_BR_PROB_BASE / 100;
+ first_prob = profile_probability::guessed_always ().apply_scale
+ (1, 100);
else if (first_code == ORDERED)
- first_prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100;
+ first_prob = profile_probability::guessed_always ().apply_scale
+ (99, 100);
if (and_them)
{
rtx_code_label *dest_label;
@@ -1165,7 +1170,7 @@ static void
do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
enum rtx_code unsigned_code,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label, profile_probability prob)
{
rtx op0, op1;
tree type;
diff --git a/gcc/dojump.h b/gcc/dojump.h
index 00d66a7239d..ca6df449f74 100644
--- a/gcc/dojump.h
+++ b/gcc/dojump.h
@@ -57,23 +57,26 @@ extern void save_pending_stack_adjust (saved_pending_stack_adjust *);
extern void restore_pending_stack_adjust (saved_pending_stack_adjust *);
/* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
-extern void jumpifnot (tree exp, rtx_code_label *label, int prob);
-extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *, int);
+extern void jumpifnot (tree exp, rtx_code_label *label,
+ profile_probability prob);
+extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *,
+ profile_probability);
/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
-extern void jumpif (tree exp, rtx_code_label *label, int prob);
-extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *, int);
+extern void jumpif (tree exp, rtx_code_label *label, profile_probability prob);
+extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *,
+ profile_probability);
/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
the result is zero, or IF_TRUE_LABEL if the result is one. */
extern void do_jump (tree exp, rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob);
+ rtx_code_label *if_true_label, profile_probability prob);
extern void do_jump_1 (enum tree_code, tree, tree, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
machine_mode, rtx, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
extern bool split_comparison (enum rtx_code, machine_mode,
enum rtx_code *, enum rtx_code *);
diff --git a/gcc/domwalk.c b/gcc/domwalk.c
index a0daae6b2d8..ff6604e5686 100644
--- a/gcc/domwalk.c
+++ b/gcc/domwalk.c
@@ -128,19 +128,45 @@ along with GCC; see the file COPYING3. If not see
which is currently an abstraction over walking tree statements. Thus
the dominator walker is currently only useful for trees. */
+/* Reverse postorder index of each basic block. */
static int *bb_postorder;
static int
cmp_bb_postorder (const void *a, const void *b)
{
- basic_block bb1 = *(basic_block *)const_cast<void *>(a);
- basic_block bb2 = *(basic_block *)const_cast<void *>(b);
- if (bb1->index == bb2->index)
- return 0;
+ basic_block bb1 = *(const basic_block *)(a);
+ basic_block bb2 = *(const basic_block *)(b);
/* Place higher completion number first (pop off lower number first). */
- if (bb_postorder[bb1->index] > bb_postorder[bb2->index])
- return -1;
- return 1;
+ return bb_postorder[bb2->index] - bb_postorder[bb1->index];
+}
+
+/* Permute array BBS of N basic blocks in postorder,
+ i.e. by descending number in BB_POSTORDER array. */
+
+static void
+sort_bbs_postorder (basic_block *bbs, int n)
+{
+ if (__builtin_expect (n == 2, true))
+ {
+ basic_block bb0 = bbs[0], bb1 = bbs[1];
+ if (bb_postorder[bb0->index] < bb_postorder[bb1->index])
+ bbs[0] = bb1, bbs[1] = bb0;
+ }
+ else if (__builtin_expect (n == 3, true))
+ {
+ basic_block bb0 = bbs[0], bb1 = bbs[1], bb2 = bbs[2];
+ if (bb_postorder[bb0->index] < bb_postorder[bb1->index])
+ std::swap (bb0, bb1);
+ if (bb_postorder[bb1->index] < bb_postorder[bb2->index])
+ {
+ std::swap (bb1, bb2);
+ if (bb_postorder[bb0->index] < bb_postorder[bb1->index])
+ std::swap (bb0, bb1);
+ }
+ bbs[0] = bb0, bbs[1] = bb1, bbs[2] = bb2;
+ }
+ else
+ qsort (bbs, n, sizeof *bbs, cmp_bb_postorder);
}
/* Constructor for a dom walker.
@@ -284,16 +310,8 @@ dom_walker::walk (basic_block bb)
for (dest = first_dom_son (m_dom_direction, bb);
dest; dest = next_dom_son (m_dom_direction, dest))
worklist[sp++] = dest;
- if (m_dom_direction == CDI_DOMINATORS)
- switch (sp - saved_sp)
- {
- case 0:
- case 1:
- break;
- default:
- qsort (&worklist[saved_sp], sp - saved_sp,
- sizeof (basic_block), cmp_bb_postorder);
- }
+ if (sp - saved_sp > 1 && m_dom_direction == CDI_DOMINATORS)
+ sort_bbs_postorder (&worklist[saved_sp], sp - saved_sp);
}
/* NULL is used to mark pop operations in the recursion stack. */
while (sp > 0 && !worklist[sp - 1])
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 6c55f05b677..658500b6103 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "dumpfile.h"
#include "context.h"
+#include "profile-count.h"
#include "tree-cfg.h"
#include "langhooks.h"
@@ -110,9 +111,9 @@ static const struct dump_option_value_info dump_options[] =
{"missed", MSG_MISSED_OPTIMIZATION},
{"note", MSG_NOTE},
{"optall", MSG_ALL},
- {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH | TDF_STMTADDR
- | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV
- | TDF_GIMPLE)},
+ {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
+ | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
+ | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
{NULL, 0}
};
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 3f420405038..8e3e86f224c 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -345,7 +345,9 @@ dw2_asm_output_nstring (const char *str, size_t orig_len,
for (i = 0; i < len; i++)
{
int c = str[i];
- if (c == '\"' || c == '\\')
+ if (c == '\"')
+ fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file);
+ else if (c == '\\')
fputc ('\\', asm_out_file);
if (ISPRINT (c))
fputc (c, asm_out_file);
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 2a527c9feca..a5f9832fc4a 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "common/common-target.h"
#include "except.h" /* expand_builtin_dwarf_sp_column */
+#include "profile-count.h" /* For expr.h */
#include "expr.h" /* init_return_column_size */
#include "output.h" /* asm_out_file */
#include "debug.h" /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c277d27e8e8..4a3b3c1d0f4 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2680,7 +2680,7 @@ static bool dwarf2out_ignore_block (const_tree);
static void dwarf2out_early_global_decl (tree);
static void dwarf2out_late_global_decl (tree);
static void dwarf2out_type_decl (tree, int);
-static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
+static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool, bool);
static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
dw_die_ref);
static void dwarf2out_abstract_function (tree);
@@ -2764,7 +2764,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
debug_nothing_tree, /* early_global_decl */
debug_nothing_tree, /* late_global_decl */
debug_nothing_tree_int, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@@ -5049,16 +5049,6 @@ is_cxx (const_tree decl)
return is_cxx ();
}
-/* Return TRUE if the language is Java. */
-
-static inline bool
-is_java (void)
-{
- unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
-
- return lang == DW_LANG_Java;
-}
-
/* Return TRUE if the language is Fortran. */
static inline bool
@@ -10756,8 +10746,8 @@ output_pubname (dw_offset die_offset, pubname_entry *entry)
case DW_TAG_enumerator:
GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
GDB_INDEX_SYMBOL_KIND_VARIABLE);
- if (!is_cxx () && !is_java ())
- GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+ if (!is_cxx ())
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
break;
case DW_TAG_subprogram:
GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
@@ -10785,7 +10775,7 @@ output_pubname (dw_offset die_offset, pubname_entry *entry)
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
- if (!is_cxx () && !is_java ())
+ if (!is_cxx ())
GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
break;
default:
@@ -11707,7 +11697,7 @@ output_file_names (void)
output_line_string (str_form, filename0, "File Entry", 0);
/* Include directory index. */
- if (dwarf_version >= 5 && idx_form != DW_FORM_udata)
+ if (idx_form != DW_FORM_udata)
dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2,
0, NULL);
else
@@ -19830,7 +19820,6 @@ lower_bound_default (void)
case DW_LANG_C_plus_plus_14:
case DW_LANG_ObjC:
case DW_LANG_ObjC_plus_plus:
- case DW_LANG_Java:
return 0;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
@@ -19846,7 +19835,6 @@ lower_bound_default (void)
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
- case DW_LANG_Pascal83:
case DW_LANG_Modula2:
case DW_LANG_PLI:
return dwarf_version >= 4 ? 1 : -1;
@@ -23305,46 +23293,6 @@ gen_field_die (tree decl, struct vlr_context *ctx, dw_die_ref context_die)
equate_decl_number_to_die (decl, decl_die);
}
-#if 0
-/* Don't generate either pointer_type DIEs or reference_type DIEs here.
- Use modified_type_die instead.
- We keep this code here just in case these types of DIEs may be needed to
- represent certain things in other languages (e.g. Pascal) someday. */
-
-static void
-gen_pointer_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref ptr_die
- = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
-
- equate_type_number_to_die (type, ptr_die);
- add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
- context_die);
- add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
-}
-
-/* Don't generate either pointer_type DIEs or reference_type DIEs here.
- Use modified_type_die instead.
- We keep this code here just in case these types of DIEs may be needed to
- represent certain things in other languages (e.g. Pascal) someday. */
-
-static void
-gen_reference_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref ref_die, scope_die = scope_die_for (type, context_die);
-
- if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
- ref_die = new_die (DW_TAG_rvalue_reference_type, scope_die, type);
- else
- ref_die = new_die (DW_TAG_reference_type, scope_die, type);
-
- equate_type_number_to_die (type, ref_die);
- add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
- context_die);
- add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
-}
-#endif
-
/* Generate a DIE for a pointer to a member type. TYPE can be an
OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
pointer to member function. */
@@ -23576,8 +23524,6 @@ gen_compile_unit_die (const char *filename)
}
else if (strcmp (language_string, "GNU F77") == 0)
language = DW_LANG_Fortran77;
- else if (strcmp (language_string, "GNU Pascal") == 0)
- language = DW_LANG_Pascal83;
else if (dwarf_version >= 3 || !dwarf_strict)
{
if (strcmp (language_string, "GNU Ada") == 0)
@@ -23593,8 +23539,6 @@ gen_compile_unit_die (const char *filename)
language = DW_LANG_Fortran08;
}
}
- else if (strcmp (language_string, "GNU Java") == 0)
- language = DW_LANG_Java;
else if (strcmp (language_string, "GNU Objective-C") == 0)
language = DW_LANG_ObjC;
else if (strcmp (language_string, "GNU Objective-C++") == 0)
@@ -24088,7 +24032,8 @@ gen_member_die (tree type, dw_die_ref context_die)
{
tree member;
tree binfo = TYPE_BINFO (type);
- dw_die_ref child;
+
+ gcc_assert (TYPE_MAIN_VARIANT (type) == type);
/* If this is not an incomplete type, output descriptions of each of its
members. Note that as we output the DIEs necessary to represent the
@@ -24125,13 +24070,16 @@ gen_member_die (tree type, dw_die_ref context_die)
&& (lang_hooks.decls.decl_dwarf_attribute (member, DW_AT_inline)
!= -1));
+ /* Ignore clones. */
+ if (DECL_ABSTRACT_ORIGIN (member))
+ continue;
+
/* If we thought we were generating minimal debug info for TYPE
and then changed our minds, some of the member declarations
may have already been defined. Don't define them again, but
do put them in the right order. */
- child = lookup_decl_die (member);
- if (child)
+ if (dw_die_ref child = lookup_decl_die (member))
{
/* Handle inline static data members, which only have in-class
declarations. */
@@ -24159,6 +24107,7 @@ gen_member_die (tree type, dw_die_ref context_die)
static_inline_p = false;
}
}
+
if (child->die_tag == DW_TAG_variable
&& child->die_parent == comp_unit_die ()
&& ref == NULL)
@@ -24197,27 +24146,6 @@ gen_member_die (tree type, dw_die_ref context_die)
DECL_EXTERNAL (member) = old_extern;
}
}
-
- /* We do not keep type methods in type variants. */
- gcc_assert (TYPE_MAIN_VARIANT (type) == type);
- /* Now output info about the function members (if any). */
- if (TYPE_METHODS (type) != error_mark_node)
- for (member = TYPE_METHODS (type); member; member = DECL_CHAIN (member))
- {
- /* Don't include clones in the member list. */
- if (DECL_ABSTRACT_ORIGIN (member))
- continue;
- /* Nor constructors for anonymous classes. */
- if (DECL_ARTIFICIAL (member)
- && dwarf2_name (member, 0) == NULL)
- continue;
-
- child = lookup_decl_die (member);
- if (child)
- splice_child_die (context_die, child);
- else
- gen_decl_die (member, NULL, NULL, context_die);
- }
}
/* Generate a DIE for a structure or union type. If TYPE_DECL_SUPPRESS_DEBUG
@@ -25238,6 +25166,11 @@ gen_namespace_die (tree decl, dw_die_ref context_die)
add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
equate_decl_number_to_die (decl, namespace_die);
}
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.decls.decl_dwarf_attribute (decl,
+ DW_AT_export_symbols) == 1)
+ add_AT_flag (namespace_die, DW_AT_export_symbols, 1);
+
/* Bypass dwarf2_name's check for DECL_NAMELESS. */
if (want_pubnames ())
add_pubname_string (lang_hooks.dwarf_name (decl, 1), namespace_die);
@@ -25651,11 +25584,13 @@ dwarf2out_imported_module_or_decl_1 (tree decl,
/* Output debug information for imported module or decl DECL.
NAME is non-NULL name in context if the decl has been renamed.
CHILD is true if decl is one of the renamed decls as part of
- importing whole module. */
+ importing whole module.
+ IMPLICIT is set if this hook is called for an implicit import
+ such as inline namespace. */
static void
dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
- bool child)
+ bool child, bool implicit)
{
/* dw_die_ref at_import_die; */
dw_die_ref scope_die;
@@ -25665,6 +25600,16 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
gcc_assert (decl);
+ /* For DWARF5, just DW_AT_export_symbols on the DW_TAG_namespace
+ should be enough, for DWARF4 and older even if we emit as extension
+ DW_AT_export_symbols add the implicit DW_TAG_imported_module anyway
+ for the benefit of consumers unaware of DW_AT_export_symbols. */
+ if (implicit
+ && dwarf_version >= 5
+ && lang_hooks.decls.decl_dwarf_attribute (decl,
+ DW_AT_export_symbols) == 1)
+ return;
+
set_early_dwarf s;
/* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
@@ -27047,6 +26992,7 @@ output_macinfo (void)
macinfo_entry *ref;
vec<macinfo_entry, va_gc> *files = NULL;
macinfo_hash_type *macinfo_htab = NULL;
+ char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES];
if (! length)
return;
@@ -27057,6 +27003,12 @@ output_macinfo (void)
&& (int) DW_MACINFO_start_file == (int) DW_MACRO_start_file
&& (int) DW_MACINFO_end_file == (int) DW_MACRO_end_file);
+ /* AIX Assembler inserts the length, so adjust the reference to match the
+ offset expected by debuggers. */
+ strcpy (dl_section_ref, debug_line_section_label);
+ if (XCOFF_DEBUGGING_INFO)
+ strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
+
/* For .debug_macro emit the section header. */
if (!dwarf_strict || dwarf_version >= 5)
{
@@ -27067,7 +27019,7 @@ output_macinfo (void)
else
dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
dw2_asm_output_offset (DWARF_OFFSET_SIZE,
- (!dwarf_split_debug_info ? debug_line_section_label
+ (!dwarf_split_debug_info ? dl_section_ref
: debug_skeleton_line_section_label),
debug_line_section, NULL);
}
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 980a8be3c41..e86c7ba4f4b 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "stor-layout.h"
#include "opts.h"
+#include "predict.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -190,9 +191,8 @@ static reg_attrs *get_reg_attrs (tree, int);
static rtx gen_const_vector (machine_mode, int);
static void copy_rtx_if_shared_1 (rtx *orig);
-/* Probability of the conditional branch currently proceeded by try_split.
- Set to -1 otherwise. */
-int split_branch_probability = -1;
+/* Probability of the conditional branch currently proceeded by try_split. */
+profile_probability split_branch_probability;
/* Returns a hash code for X (which is a really a CONST_INT). */
@@ -433,7 +433,7 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
rtx
gen_raw_REG (machine_mode mode, unsigned int regno)
{
- rtx x = rtx_alloc_stat (REG MEM_STAT_INFO);
+ rtx x = rtx_alloc (REG MEM_STAT_INFO);
set_mode_and_regno (x, mode, regno);
REG_ATTRS (x) = NULL;
ORIGINAL_REGNO (x) = regno;
@@ -3665,7 +3665,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
rtx_insn *before, *after;
rtx note;
rtx_insn *seq, *tem;
- int probability;
+ profile_probability probability;
rtx_insn *insn_last, *insn;
int njumps = 0;
rtx_insn *call_insn = NULL;
@@ -3676,12 +3676,16 @@ try_split (rtx pat, rtx_insn *trial, int last)
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
- split_branch_probability = XINT (note, 0);
+ split_branch_probability
+ = profile_probability::from_reg_br_prob_note (XINT (note, 0));
+ else
+ split_branch_probability = profile_probability::uninitialized ();
+
probability = split_branch_probability;
seq = split_insns (pat, trial);
- split_branch_probability = -1;
+ split_branch_probability = profile_probability::uninitialized ();
if (!seq)
return trial;
@@ -3712,7 +3716,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
CROSSING_JUMP_P (insn) = CROSSING_JUMP_P (trial);
mark_jump_label (PATTERN (insn), insn, 0);
njumps++;
- if (probability != -1
+ if (probability.initialized_p ()
&& any_condjump_p (insn)
&& !find_reg_note (insn, REG_BR_PROB, 0))
{
@@ -3721,7 +3725,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
is responsible for this step using
split_branch_probability variable. */
gcc_assert (njumps == 1);
- add_int_reg_note (insn, REG_BR_PROB, probability);
+ add_reg_br_prob_note (insn, probability);
}
}
}
diff --git a/gcc/except.c b/gcc/except.c
index 0bf2c2eac0e..4068b68f31f 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -974,7 +974,6 @@ dw2_build_landing_pads (void)
{
basic_block bb;
rtx_insn *seq;
- edge e;
if (lp == NULL || lp->post_landing_pad == NULL)
continue;
@@ -991,9 +990,9 @@ dw2_build_landing_pads (void)
end_sequence ();
bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
- e = make_edge (bb, bb->next_bb, e_flags);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ bb->count = bb->next_bb->count;
+ bb->frequency = bb->next_bb->frequency;
+ make_single_succ_edge (bb, bb->next_bb, e_flags);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
@@ -1183,7 +1182,8 @@ sjlj_emit_function_enter (rtx_code_label *dispatch_label)
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0,
- dispatch_label, REG_BR_PROB_BASE / 100);
+ dispatch_label,
+ profile_probability::unlikely ());
#else
expand_builtin_setjmp_setup (addr, dispatch_label);
#endif
@@ -1258,7 +1258,6 @@ sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
rtx_insn *seq;
basic_block bb;
eh_region r;
- edge e;
int i, disp_index;
vec<tree> dispatch_labels = vNULL;
@@ -1346,9 +1345,7 @@ sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
rtx_insn *before = label_rtx (lp->post_landing_pad);
bb = emit_to_new_bb_before (seq2, before);
- e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
@@ -1386,9 +1383,7 @@ sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
bb = emit_to_new_bb_before (seq, first_reachable_label);
if (num_dispatch == 1)
{
- e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
@@ -2449,6 +2444,61 @@ emit_note_eh_region_end (rtx_insn *insn)
return emit_note_after (NOTE_INSN_EH_REGION_END, insn);
}
+/* Add NOP after NOTE_INSN_SWITCH_TEXT_SECTIONS when the cold section starts
+ with landing pad.
+ With landing pad being at offset 0 from the start label of the section
+ we would miss EH delivery because 0 is special and means no landing pad. */
+
+static bool
+maybe_add_nop_after_section_switch (void)
+{
+ if (!crtl->uses_eh_lsda
+ || !crtl->eh.call_site_record_v[1])
+ return false;
+ int n = vec_safe_length (crtl->eh.call_site_record_v[1]);
+ hash_set<rtx_insn *> visited;
+
+ for (int i = 0; i < n; ++i)
+ {
+ struct call_site_record_d *cs
+ = (*crtl->eh.call_site_record_v[1])[i];
+ if (cs->landing_pad)
+ {
+ rtx_insn *insn = as_a <rtx_insn *> (cs->landing_pad);
+ while (true)
+ {
+ /* Landing pads have LABEL_PRESERVE_P flag set. This check make
+ sure that we do not walk past landing pad visited earlier
+ which would result in possible quadratic behaviour. */
+ if (LABEL_P (insn) && LABEL_PRESERVE_P (insn)
+ && visited.add (insn))
+ break;
+
+ /* Conservatively assume that ASM insn may be empty. We have
+ now way to tell what they contain. */
+ if (active_insn_p (insn)
+ && GET_CODE (PATTERN (insn)) != ASM_INPUT
+ && GET_CODE (PATTERN (insn)) != ASM_OPERANDS)
+ break;
+
+ /* If we reached the start of hot section, then NOP will be
+ needed. */
+ if (GET_CODE (insn) == NOTE
+ && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ {
+ emit_insn_after (gen_nop (), insn);
+ break;
+ }
+
+ /* We visit only labels from cold section. We should never hit
+ begining of the insn stream here. */
+ insn = PREV_INSN (insn);
+ }
+ }
+ }
+ return false;
+}
+
/* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
The new note numbers will not refer to region numbers, but
instead to call site entries. */
@@ -2636,7 +2686,9 @@ public:
virtual bool gate (function *);
virtual unsigned int execute (function *)
{
- return convert_to_eh_region_ranges ();
+ int ret = convert_to_eh_region_ranges ();
+ maybe_add_nop_after_section_switch ();
+ return ret;
}
}; // class pass_convert_to_eh_region_ranges
diff --git a/gcc/explow.c b/gcc/explow.c
index 6884224570b..b38664c0e36 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "tm_p.h"
#include "expmed.h"
+#include "profile-count.h"
#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 0c812806f9b..9026472724c 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -363,9 +363,9 @@ check_reverse_float_storage_order_support (void)
useful if X is a CONST_INT. */
rtx
-flip_storage_order (enum machine_mode mode, rtx x)
+flip_storage_order (machine_mode mode, rtx x)
{
- enum machine_mode int_mode;
+ machine_mode int_mode;
rtx result;
if (mode == QImode)
@@ -5905,7 +5905,8 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
{
label = gen_label_rtx ();
do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, mode,
- NULL_RTX, NULL, label, -1);
+ NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
emit_move_insn (target, trueval);
emit_label (label);
return target;
@@ -5943,7 +5944,7 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
emit_move_insn (target, trueval);
label = gen_label_rtx ();
do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, NULL,
- label, -1);
+ label, profile_probability::uninitialized ());
emit_move_insn (target, falseval);
emit_label (label);
@@ -5961,5 +5962,5 @@ do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, machine_mode mode,
{
int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU);
do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, NULL_RTX,
- NULL, label, -1);
+ NULL, label, profile_probability::uninitialized ());
}
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 64476c3b4b2..985becb22c1 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -679,9 +679,9 @@ convert_cost (machine_mode to_mode, machine_mode from_mode,
extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
- enum machine_mode mode, enum machine_mode compare_mode,
+ machine_mode mode, machine_mode compare_mode,
int unsignedp, rtx x, rtx y, int normalizep,
- enum machine_mode target_mode);
+ machine_mode target_mode);
/* Arguments MODE, RTX: return an rtx for the negation of that value.
May emit insns. */
@@ -689,7 +689,7 @@ extern rtx negate_rtx (machine_mode, rtx);
/* Arguments MODE, RTX: return an rtx for the flipping of that value.
May emit insns. */
-extern rtx flip_storage_order (enum machine_mode, rtx);
+extern rtx flip_storage_order (machine_mode, rtx);
/* Expand a logical AND operation. */
extern rtx expand_and (machine_mode, rtx, rtx, rtx);
diff --git a/gcc/expr.c b/gcc/expr.c
index 792bc5ad868..8abee9434bd 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -96,7 +96,8 @@ static rtx do_store_flag (sepops, rtx, machine_mode);
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (machine_mode, rtx, tree);
#endif
-static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
+static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx,
+ profile_probability);
static rtx const_vector_from_tree (tree);
static rtx const_scalar_mask_from_tree (tree);
static tree tree_expr_size (const_tree);
@@ -1452,7 +1453,7 @@ compare_by_pieces_d::generate (rtx op0, rtx op1, machine_mode mode)
m_accumulator = NULL_RTX;
}
do_compare_rtx_and_jump (op0, op1, NE, true, mode, NULL_RTX, NULL,
- m_fail_label, -1);
+ m_fail_label, profile_probability::uninitialized ());
}
/* Return true if MODE can be used for a set of moves and comparisons,
@@ -1484,7 +1485,8 @@ compare_by_pieces_d::finish_mode (machine_mode mode)
{
if (m_accumulator != NULL_RTX)
do_compare_rtx_and_jump (m_accumulator, const0_rtx, NE, true, mode,
- NULL_RTX, NULL, m_fail_label, -1);
+ NULL_RTX, NULL, m_fail_label,
+ profile_probability::uninitialized ());
}
/* Generate several move instructions to compare LEN bytes from blocks
@@ -1845,7 +1847,9 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
emit_label (cmp_label);
emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
- true, top_label, REG_BR_PROB_BASE * 90 / 100);
+ true, top_label,
+ profile_probability::guessed_always ()
+ .apply_scale (9, 10));
}
/* Expand a call to memcpy or memmove or memcmp, and return the result.
@@ -5402,7 +5406,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
do_pending_stack_adjust ();
NO_DEFER_POP;
- jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
+ jumpifnot (TREE_OPERAND (exp, 0), lab1,
+ profile_probability::uninitialized ());
store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
nontemporal, reverse, btarget);
emit_jump_insn (targetm.gen_jump (lab2));
@@ -6504,7 +6509,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size,
/* Generate a conditional jump to exit the loop. */
exit_cond = build2 (LT_EXPR, integer_type_node,
index, hi_index);
- jumpif (exit_cond, loop_end, -1);
+ jumpif (exit_cond, loop_end,
+ profile_probability::uninitialized ());
/* Update the loop counter, and jump to the head of
the loop. */
@@ -9043,7 +9049,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
lab = gen_label_rtx ();
do_compare_rtx_and_jump (target, cmpop1, comparison_code,
unsignedp, mode, NULL_RTX, NULL, lab,
- -1);
+ profile_probability::uninitialized ());
}
emit_move_insn (target, op1);
emit_label (lab);
@@ -9272,7 +9278,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
emit_move_insn (target, const0_rtx);
rtx_code_label *lab1 = gen_label_rtx ();
- jumpifnot_1 (code, treeop0, treeop1, lab1, -1);
+ jumpifnot_1 (code, treeop0, treeop1, lab1,
+ profile_probability::uninitialized ());
if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
emit_move_insn (target, constm1_rtx);
@@ -9523,7 +9530,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
NO_DEFER_POP;
rtx_code_label *lab0 = gen_label_rtx ();
rtx_code_label *lab1 = gen_label_rtx ();
- jumpifnot (treeop0, lab0, -1);
+ jumpifnot (treeop0, lab0,
+ profile_probability::uninitialized ());
store_expr (treeop1, temp,
modifier == EXPAND_STACK_PARM,
false, false);
@@ -9768,7 +9776,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (targetm.gen_ccmp_first)
{
gcc_checking_assert (targetm.gen_ccmp_next != NULL);
- r = expand_ccmp_expr (g);
+ r = expand_ccmp_expr (g, mode);
if (r)
break;
}
@@ -10634,11 +10642,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
|| (mode1 != BLKmode
- && (((TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode)
- || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)
- || (MEM_P (op0)
- && (MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1)
- || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0))))
+ && (((MEM_P (op0)
+ ? MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1)
+ || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0)
+ : TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode)
+ || (bitpos % GET_MODE_ALIGNMENT (mode) != 0))
&& modifier != EXPAND_MEMORY
&& ((modifier == EXPAND_CONST_ADDRESS
|| modifier == EXPAND_INITIALIZER)
@@ -11045,7 +11053,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
do_jump (TREE_OPERAND (rhs, 1),
value ? label : 0,
- value ? 0 : label, -1);
+ value ? 0 : label,
+ profile_probability::uninitialized ());
expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
false);
do_pending_stack_adjust ();
@@ -11515,7 +11524,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
int
try_casesi (tree index_type, tree index_expr, tree minval, tree range,
rtx table_label, rtx default_label, rtx fallback_label,
- int default_probability)
+ profile_probability default_probability)
{
struct expand_operand ops[5];
machine_mode index_mode = SImode;
@@ -11585,7 +11594,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
static void
do_tablejump (rtx index, machine_mode mode, rtx range, rtx table_label,
- rtx default_label, int default_probability)
+ rtx default_label, profile_probability default_probability)
{
rtx temp, vector;
@@ -11648,7 +11657,8 @@ do_tablejump (rtx index, machine_mode mode, rtx range, rtx table_label,
int
try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
- rtx table_label, rtx default_label, int default_probability)
+ rtx table_label, rtx default_label,
+ profile_probability default_probability)
{
rtx index;
diff --git a/gcc/expr.h b/gcc/expr.h
index 84002abb025..b92ff3ce8a6 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -288,8 +288,8 @@ expand_normal (tree exp)
extern tree string_constant (tree, tree *);
/* Two different ways of generating switch statements. */
-extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
-extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, int);
+extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
+extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, profile_probability);
extern int safe_from_p (const_rtx, tree, int);
diff --git a/gcc/final.c b/gcc/final.c
index 356c923c4cd..2a24f4fe102 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -4492,7 +4492,8 @@ rest_of_handle_final (void)
assemble_start_function (current_function_decl, fnname);
final_start_function (get_insns (), asm_out_file, optimize);
final (get_insns (), asm_out_file, optimize);
- if (flag_ipa_ra)
+ if (flag_ipa_ra
+ && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)))
collect_fn_hard_reg_usage ();
final_end_function ();
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 5faade53975..6372d3cb178 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -238,6 +238,7 @@ enum sanitize_code {
SANITIZE_OBJECT_SIZE = 1UL << 21,
SANITIZE_VPTR = 1UL << 22,
SANITIZE_BOUNDS_STRICT = 1UL << 23,
+ SANITIZE_POINTER_OVERFLOW = 1UL << 24,
SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
@@ -245,7 +246,8 @@ enum sanitize_code {
| SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
| SANITIZE_NONNULL_ATTRIBUTE
| SANITIZE_RETURNS_NONNULL_ATTRIBUTE
- | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR,
+ | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR
+ | SANITIZE_POINTER_OVERFLOW,
SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
| SANITIZE_BOUNDS_STRICT
};
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 379a30ea285..524208ae564 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -132,7 +132,6 @@ static tree fold_binary_op_with_conditional_arg (location_t,
enum tree_code, tree,
tree, tree,
tree, tree, int);
-static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
static tree fold_negate_const (tree, tree);
static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree);
@@ -383,7 +382,7 @@ negate_expr_p (tree t)
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
+ if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
return true;
/* Check that -CST will not overflow type. */
@@ -3185,9 +3184,18 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
flags &= ~OEP_ADDRESS_OF;
return OP_SAME (0);
+ case BIT_INSERT_EXPR:
+ /* BIT_INSERT_EXPR has an implict operand as the type precision
+ of op1. Need to check to make sure they are the same. */
+ if (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 1)))
+ != TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 1))))
+ return false;
+ /* FALLTHRU */
+
case VEC_COND_EXPR:
case DOT_PROD_EXPR:
- case BIT_INSERT_EXPR:
return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
case MODIFY_EXPR:
@@ -3928,7 +3936,7 @@ make_bit_field_ref (location_t loc, tree inner, tree orig_inner, tree type,
bftype = build_nonstandard_integer_type (bitsize, 0);
result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
- size_int (bitsize), bitsize_int (bitpos));
+ bitsize_int (bitsize), bitsize_int (bitpos));
REF_REVERSE_STORAGE_ORDER (result) = reversep;
if (bftype != type)
@@ -4787,6 +4795,39 @@ maskable_range_p (const_tree low, const_tree high, tree type, tree *mask,
return true;
}
+/* Helper routine for build_range_check and match.pd. Return the type to
+ perform the check or NULL if it shouldn't be optimized. */
+
+tree
+range_check_type (tree etype)
+{
+ /* First make sure that arithmetics in this type is valid, then make sure
+ that it wraps around. */
+ if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
+ etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+ TYPE_UNSIGNED (etype));
+
+ if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
+ {
+ tree utype, minv, maxv;
+
+ /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
+ for the type in question, as we rely on this here. */
+ utype = unsigned_type_for (etype);
+ maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
+ maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
+ build_int_cst (TREE_TYPE (maxv), 1), 1);
+ minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
+
+ if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
+ minv, 1, maxv, 1)))
+ etype = utype;
+ else
+ return NULL_TREE;
+ }
+ return etype;
+}
+
/* Given a range, LOW, HIGH, and IN_P, an expression, EXP, and a result
type, TYPE, return an expression to test if EXP is in (or out of, depending
on IN_P) the range. Return 0 if the test couldn't be created. */
@@ -4818,21 +4859,21 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
if (low == 0)
return fold_build2_loc (loc, LE_EXPR, type, exp,
- fold_convert_loc (loc, etype, high));
+ fold_convert_loc (loc, etype, high));
if (high == 0)
return fold_build2_loc (loc, GE_EXPR, type, exp,
- fold_convert_loc (loc, etype, low));
+ fold_convert_loc (loc, etype, low));
if (operand_equal_p (low, high, 0))
return fold_build2_loc (loc, EQ_EXPR, type, exp,
- fold_convert_loc (loc, etype, low));
+ fold_convert_loc (loc, etype, low));
if (TREE_CODE (exp) == BIT_AND_EXPR
&& maskable_range_p (low, high, etype, &mask, &value))
return fold_build2_loc (loc, EQ_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, etype,
- exp, mask),
+ exp, mask),
value);
if (integer_zerop (low))
@@ -4864,36 +4905,18 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
exp = fold_convert_loc (loc, etype, exp);
}
return fold_build2_loc (loc, GT_EXPR, type, exp,
- build_int_cst (etype, 0));
+ build_int_cst (etype, 0));
}
}
/* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
- This requires wrap-around arithmetics for the type of the expression.
- First make sure that arithmetics in this type is valid, then make sure
- that it wraps around. */
- if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
- etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
- TYPE_UNSIGNED (etype));
-
- if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
- {
- tree utype, minv, maxv;
-
- /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
- for the type in question, as we rely on this here. */
- utype = unsigned_type_for (etype);
- maxv = fold_convert_loc (loc, utype, TYPE_MAX_VALUE (etype));
- maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
- build_int_cst (TREE_TYPE (maxv), 1), 1);
- minv = fold_convert_loc (loc, utype, TYPE_MIN_VALUE (etype));
+ This requires wrap-around arithmetics for the type of the expression. */
+ etype = range_check_type (etype);
+ if (etype == NULL_TREE)
+ return NULL_TREE;
- if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
- minv, 1, maxv, 1)))
- etype = utype;
- else
- return 0;
- }
+ if (POINTER_TYPE_P (etype))
+ etype = unsigned_type_for (etype);
high = fold_convert_loc (loc, etype, high);
low = fold_convert_loc (loc, etype, low);
@@ -4901,19 +4924,6 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
value = const_binop (MINUS_EXPR, high, low);
-
- if (POINTER_TYPE_P (etype))
- {
- if (value != 0 && !TREE_OVERFLOW (value))
- {
- low = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (low), low);
- return build_range_check (loc, type,
- fold_build_pointer_plus_loc (loc, exp, low),
- 1, build_int_cst (etype, 0), value);
- }
- return 0;
- }
-
if (value != 0 && !TREE_OVERFLOW (value))
return build_range_check (loc, type,
fold_build2_loc (loc, MINUS_EXPR, etype, exp, low),
@@ -6548,65 +6558,55 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
}
-/* Subroutine of fold() that optimizes comparisons of a division by
+/* Subroutine of match.pd that optimizes comparisons of a division by
a nonzero integer constant against an integer constant, i.e.
X/C1 op C2.
CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR,
- GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1
- are the operands of the comparison. ARG1 must be a TREE_REAL_CST.
-
- The function returns the constant folded tree if a simplification
- can be made, and NULL_TREE otherwise. */
+ GE_EXPR or LE_EXPR. ARG01 and ARG1 must be a INTEGER_CST. */
-static tree
-fold_div_compare (location_t loc,
- enum tree_code code, tree type, tree arg0, tree arg1)
+enum tree_code
+fold_div_compare (enum tree_code code, tree c1, tree c2, tree *lo,
+ tree *hi, bool *neg_overflow)
{
- tree prod, tmp, hi, lo;
- tree arg00 = TREE_OPERAND (arg0, 0);
- tree arg01 = TREE_OPERAND (arg0, 1);
- signop sign = TYPE_SIGN (TREE_TYPE (arg0));
- bool neg_overflow = false;
+ tree prod, tmp, type = TREE_TYPE (c1);
+ signop sign = TYPE_SIGN (type);
bool overflow;
/* We have to do this the hard way to detect unsigned overflow.
- prod = int_const_binop (MULT_EXPR, arg01, arg1); */
- wide_int val = wi::mul (arg01, arg1, sign, &overflow);
- prod = force_fit_type (TREE_TYPE (arg00), val, -1, overflow);
- neg_overflow = false;
+ prod = int_const_binop (MULT_EXPR, c1, c2); */
+ wide_int val = wi::mul (c1, c2, sign, &overflow);
+ prod = force_fit_type (type, val, -1, overflow);
+ *neg_overflow = false;
if (sign == UNSIGNED)
{
- tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1));
- lo = prod;
+ tmp = int_const_binop (MINUS_EXPR, c1, build_int_cst (type, 1));
+ *lo = prod;
- /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp). */
+ /* Likewise *hi = int_const_binop (PLUS_EXPR, prod, tmp). */
val = wi::add (prod, tmp, sign, &overflow);
- hi = force_fit_type (TREE_TYPE (arg00), val,
- -1, overflow | TREE_OVERFLOW (prod));
+ *hi = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (prod));
}
- else if (tree_int_cst_sgn (arg01) >= 0)
+ else if (tree_int_cst_sgn (c1) >= 0)
{
- tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1));
- switch (tree_int_cst_sgn (arg1))
+ tmp = int_const_binop (MINUS_EXPR, c1, build_int_cst (type, 1));
+ switch (tree_int_cst_sgn (c2))
{
case -1:
- neg_overflow = true;
- lo = int_const_binop (MINUS_EXPR, prod, tmp);
- hi = prod;
+ *neg_overflow = true;
+ *lo = int_const_binop (MINUS_EXPR, prod, tmp);
+ *hi = prod;
break;
- case 0:
- lo = fold_negate_const (tmp, TREE_TYPE (arg0));
- hi = tmp;
+ case 0:
+ *lo = fold_negate_const (tmp, type);
+ *hi = tmp;
break;
- case 1:
- hi = int_const_binop (PLUS_EXPR, prod, tmp);
- lo = prod;
+ case 1:
+ *hi = int_const_binop (PLUS_EXPR, prod, tmp);
+ *lo = prod;
break;
default:
@@ -6618,24 +6618,23 @@ fold_div_compare (location_t loc,
/* A negative divisor reverses the relational operators. */
code = swap_tree_comparison (code);
- tmp = int_const_binop (PLUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1));
- switch (tree_int_cst_sgn (arg1))
+ tmp = int_const_binop (PLUS_EXPR, c1, build_int_cst (type, 1));
+ switch (tree_int_cst_sgn (c2))
{
case -1:
- hi = int_const_binop (MINUS_EXPR, prod, tmp);
- lo = prod;
+ *hi = int_const_binop (MINUS_EXPR, prod, tmp);
+ *lo = prod;
break;
- case 0:
- hi = fold_negate_const (tmp, TREE_TYPE (arg0));
- lo = tmp;
+ case 0:
+ *hi = fold_negate_const (tmp, type);
+ *lo = tmp;
break;
- case 1:
- neg_overflow = true;
- lo = int_const_binop (PLUS_EXPR, prod, tmp);
- hi = prod;
+ case 1:
+ *neg_overflow = true;
+ *lo = int_const_binop (PLUS_EXPR, prod, tmp);
+ *hi = prod;
break;
default:
@@ -6643,63 +6642,17 @@ fold_div_compare (location_t loc,
}
}
- switch (code)
- {
- case EQ_EXPR:
- if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
- return omit_one_operand_loc (loc, type, integer_zero_node, arg00);
- if (TREE_OVERFLOW (hi))
- return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
- if (TREE_OVERFLOW (lo))
- return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
- return build_range_check (loc, type, arg00, 1, lo, hi);
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return code;
- case NE_EXPR:
- if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
- return omit_one_operand_loc (loc, type, integer_one_node, arg00);
- if (TREE_OVERFLOW (hi))
- return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
- if (TREE_OVERFLOW (lo))
- return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
- return build_range_check (loc, type, arg00, 0, lo, hi);
+ if (TREE_OVERFLOW (*lo)
+ || operand_equal_p (*lo, TYPE_MIN_VALUE (type), 0))
+ *lo = NULL_TREE;
+ if (TREE_OVERFLOW (*hi)
+ || operand_equal_p (*hi, TYPE_MAX_VALUE (type), 0))
+ *hi = NULL_TREE;
- case LT_EXPR:
- if (TREE_OVERFLOW (lo))
- {
- tmp = neg_overflow ? integer_zero_node : integer_one_node;
- return omit_one_operand_loc (loc, type, tmp, arg00);
- }
- return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
-
- case LE_EXPR:
- if (TREE_OVERFLOW (hi))
- {
- tmp = neg_overflow ? integer_zero_node : integer_one_node;
- return omit_one_operand_loc (loc, type, tmp, arg00);
- }
- return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
-
- case GT_EXPR:
- if (TREE_OVERFLOW (hi))
- {
- tmp = neg_overflow ? integer_one_node : integer_zero_node;
- return omit_one_operand_loc (loc, type, tmp, arg00);
- }
- return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
-
- case GE_EXPR:
- if (TREE_OVERFLOW (lo))
- {
- tmp = neg_overflow ? integer_one_node : integer_zero_node;
- return omit_one_operand_loc (loc, type, tmp, arg00);
- }
- return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
-
- default:
- break;
- }
-
- return NULL_TREE;
+ return code;
}
@@ -8793,20 +8746,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
}
}
- /* We can fold X/C1 op C2 where C1 and C2 are integer constants
- into a single range test. */
- if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !integer_zerop (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (arg1))
- {
- tem = fold_div_compare (loc, code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
-
return NULL_TREE;
}
@@ -12256,8 +12195,8 @@ debug_fold_checksum (const_tree t)
expression with code CODE of type TYPE with an operand OP0. */
tree
-fold_build1_stat_loc (location_t loc,
- enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
+fold_build1_loc (location_t loc,
+ enum tree_code code, tree type, tree op0 MEM_STAT_DECL)
{
tree tem;
#ifdef ENABLE_FOLD_CHECKING
@@ -12273,7 +12212,7 @@ fold_build1_stat_loc (location_t loc,
tem = fold_unary_loc (loc, code, type, op0);
if (!tem)
- tem = build1_stat_loc (loc, code, type, op0 PASS_MEM_STAT);
+ tem = build1_loc (loc, code, type, op0 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
@@ -12293,7 +12232,7 @@ fold_build1_stat_loc (location_t loc,
OP0 and OP1. */
tree
-fold_build2_stat_loc (location_t loc,
+fold_build2_loc (location_t loc,
enum tree_code code, tree type, tree op0, tree op1
MEM_STAT_DECL)
{
@@ -12319,7 +12258,7 @@ fold_build2_stat_loc (location_t loc,
tem = fold_binary_loc (loc, code, type, op0, op1);
if (!tem)
- tem = build2_stat_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
+ tem = build2_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
@@ -12346,7 +12285,7 @@ fold_build2_stat_loc (location_t loc,
type TYPE with operands OP0, OP1, and OP2. */
tree
-fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
+fold_build3_loc (location_t loc, enum tree_code code, tree type,
tree op0, tree op1, tree op2 MEM_STAT_DECL)
{
tree tem;
@@ -12379,7 +12318,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
if (!tem)
- tem = build3_stat_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
+ tem = build3_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
@@ -13753,8 +13692,8 @@ fold_negate_const (tree arg0, tree type)
bool overflow;
wide_int val = wi::neg (arg0, &overflow);
t = force_fit_type (type, val, 1,
- (overflow | TREE_OVERFLOW (arg0))
- && !TYPE_UNSIGNED (type));
+ (overflow && ! TYPE_UNSIGNED (type))
+ || TREE_OVERFLOW (arg0));
break;
}
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 7abf4d1bc06..8380d420ddb 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -49,23 +49,17 @@ extern tree fold_binary_loc (location_t, enum tree_code, tree, tree, tree);
fold_ternary_loc (UNKNOWN_LOCATION, CODE, T1, T2, T3, T4)
extern tree fold_ternary_loc (location_t, enum tree_code, tree, tree, tree, tree);
#define fold_build1(c,t1,t2)\
- fold_build1_stat_loc (UNKNOWN_LOCATION, c, t1, t2 MEM_STAT_INFO)
-#define fold_build1_loc(l,c,t1,t2)\
- fold_build1_stat_loc (l, c, t1, t2 MEM_STAT_INFO)
-extern tree fold_build1_stat_loc (location_t, enum tree_code, tree,
- tree MEM_STAT_DECL);
+ fold_build1_loc (UNKNOWN_LOCATION, c, t1, t2 MEM_STAT_INFO)
+extern tree fold_build1_loc (location_t, enum tree_code, tree,
+ tree CXX_MEM_STAT_INFO);
#define fold_build2(c,t1,t2,t3)\
- fold_build2_stat_loc (UNKNOWN_LOCATION, c, t1, t2, t3 MEM_STAT_INFO)
-#define fold_build2_loc(l,c,t1,t2,t3)\
- fold_build2_stat_loc (l, c, t1, t2, t3 MEM_STAT_INFO)
-extern tree fold_build2_stat_loc (location_t, enum tree_code, tree, tree,
- tree MEM_STAT_DECL);
+ fold_build2_loc (UNKNOWN_LOCATION, c, t1, t2, t3 MEM_STAT_INFO)
+extern tree fold_build2_loc (location_t, enum tree_code, tree, tree,
+ tree CXX_MEM_STAT_INFO);
#define fold_build3(c,t1,t2,t3,t4)\
- fold_build3_stat_loc (UNKNOWN_LOCATION, c, t1, t2, t3, t4 MEM_STAT_INFO)
-#define fold_build3_loc(l,c,t1,t2,t3,t4)\
- fold_build3_stat_loc (l, c, t1, t2, t3, t4 MEM_STAT_INFO)
-extern tree fold_build3_stat_loc (location_t, enum tree_code, tree, tree, tree,
- tree MEM_STAT_DECL);
+ fold_build3_loc (UNKNOWN_LOCATION, c, t1, t2, t3, t4 MEM_STAT_INFO)
+extern tree fold_build3_loc (location_t, enum tree_code, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
extern tree fold_build1_initializer_loc (location_t, enum tree_code, tree, tree);
extern tree fold_build2_initializer_loc (location_t, enum tree_code, tree, tree, tree);
#define fold_build_call_array(T1,T2,N,T4)\
@@ -88,6 +82,8 @@ extern void fold_undefer_overflow_warnings (bool, const gimple *, int);
extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (void);
extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code);
+extern enum tree_code fold_div_compare (enum tree_code, tree, tree,
+ tree *, tree *, bool *);
extern int operand_equal_p (const_tree, const_tree, unsigned int);
extern int multiple_of_p (tree, const_tree, const_tree);
#define omit_one_operand(T1,T2,T3)\
@@ -175,6 +171,7 @@ extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
extern tree make_range (tree, int *, tree *, tree *, bool *);
extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
tree *, tree *, int *, bool *);
+extern tree range_check_type (tree);
extern tree build_range_check (location_t, tree, tree, int, tree, tree);
extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
tree, tree);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 88fd0b327d7..dc0495af964 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,72 @@
+2017-07-31 Jakub Jelinek <jakub@redhat.com>
+
+ * check.c (gfc_check_num_images): Fix a pasto.
+
+2017-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ * trans-decl.c (gfc_trans_use_stmts): Pass false as new argument to
+ the imported_module_or_decl debug hook.
+
+2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * resolve.c (find_reachable_labels): Adjust.
+
+2017-07-25 Jakub Jelinek <jakub@redhat.com>
+
+ * ioparm.def: Use 1U << 31 instead of 1 << 31 as flags2 mask.
+
+2017-07-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * dump-parse-tree.c (show_symbol): Show binding label if present.
+
+2017-07-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+ Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/66102
+ * fortran/trans-array.c (gfc_conv_resolve_dependencies):
+ Break if dependency has been found.
+
+2017-07-23 Alexander Monakov <amonakov@ispras.ru>
+
+ * interface.c (pair_cmp): Fix gfc_symbol comparison. Adjust comment.
+
+2017-07-18 Nathan Sidwell <nathan@acm.org>
+
+ * trans.c (gfc_build_array_ref): Use TYPE_MAX_VALUE.
+
+2017-07-09 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/81341
+ * class.c (class_array_ref_detected): Remove a redundant
+ condition.
+
+2017-07-06 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/70071
+ * array.c (gfc_ref_dimen_size): Handle bad subscript triplets.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/79866
+ * resolve.c (resolve_symbol): Fix typo.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/79843
+ * symbol.c (check_conflict): Add missing "conflicts".
+
+2017-06-29 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR fortran/77765
+ * openmp.c (gfc_match_oacc_routine): Check if proc_name exist before
+ comparing the routine name against it.
+
+2017-06-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/80164
+ * trans-stmt.c (gfc_trans_call): If no code expr, use code->loc
+ as warning/error locus.
+
2017-06-24 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/81160
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index 30656c197d0..46642bb5d97 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -2203,9 +2203,15 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
bool t;
gfc_expr *stride_expr = NULL;
- if (dimen < 0 || ar == NULL || dimen > ar->dimen - 1)
+ if (dimen < 0 || ar == NULL)
gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");
+ if (dimen > ar->dimen - 1)
+ {
+ gfc_error ("Bad array dimension at %L", &ar->c_where[dimen]);
+ return false;
+ }
+
switch (ar->dimen_type[dimen])
{
case DIMEN_ELEMENT:
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 45bc68ef7ad..e85e398cd43 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -5149,7 +5149,7 @@ gfc_check_num_images (gfc_expr *distance, gfc_expr *failed)
return false;
if (!gfc_notify_std (GFC_STD_F2008_TS, "FAILED= argument to "
- "NUM_IMAGES at %L", &distance->where))
+ "NUM_IMAGES at %L", &failed->where))
return false;
}
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 2d72e9570da..a345d131442 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -310,7 +310,6 @@ class_array_ref_detected (gfc_ref *ref, bool *full_array)
else if (ref->next && ref->next->type == REF_ARRAY
&& !ref->next->next
&& ref->type == REF_COMPONENT
- && ref->next->type == REF_ARRAY
&& ref->next->u.ar.type != AR_ELEMENT)
{
with_data = true;
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 5b692e1ea9c..46b3705f4f8 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -857,6 +857,9 @@ show_symbol (gfc_symbol *sym)
for (i=len; i<12; i++)
fputc(' ', dumpfile);
+ if (sym->binding_label)
+ fprintf (dumpfile,"|| binding_label: '%s' ", sym->binding_label);
+
++show_level;
show_indent ();
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 6fe0647ecfe..13e2bdd6c7e 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -3294,7 +3294,7 @@ argpair;
order:
- p->a->expr == NULL
- p->a->expr->expr_type != EXPR_VARIABLE
- - growing p->a->expr->symbol. */
+ - by gfc_symbol pointer value (larger first). */
static int
pair_cmp (const void *p1, const void *p2)
@@ -3320,6 +3320,8 @@ pair_cmp (const void *p1, const void *p2)
}
if (a2->expr->expr_type != EXPR_VARIABLE)
return 1;
+ if (a1->expr->symtree->n.sym > a2->expr->symtree->n.sym)
+ return -1;
return a1->expr->symtree->n.sym < a2->expr->symtree->n.sym;
}
diff --git a/gcc/fortran/ioparm.def b/gcc/fortran/ioparm.def
index 9789dd164ae..ca5631b9cd9 100644
--- a/gcc/fortran/ioparm.def
+++ b/gcc/fortran/ioparm.def
@@ -82,7 +82,7 @@ IOPARM (inquire, read, 1 << 27, char2)
IOPARM (inquire, write, 1 << 28, char1)
IOPARM (inquire, readwrite, 1 << 29, char2)
IOPARM (inquire, convert, 1 << 30, char1)
-IOPARM (inquire, flags2, 1 << 31, int4)
+IOPARM (inquire, flags2, 1U << 31, int4)
IOPARM (inquire, asynchronous, 1 << 0, char1)
IOPARM (inquire, decimal, 1 << 1, char2)
IOPARM (inquire, encoding, 1 << 2, char1)
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 2b56558b7c1..8400354181c 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -2295,7 +2295,8 @@ gfc_match_oacc_routine (void)
if (st)
{
sym = st->n.sym;
- if (strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
+ if (gfc_current_ns->proc_name != NULL
+ && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
sym = NULL;
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index a5f4874d513..5caf76761ee 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -9098,7 +9098,7 @@ find_reachable_labels (gfc_code *block)
if (!block)
return;
- cs_base->reachable_labels = bitmap_obstack_alloc (&labels_obstack);
+ cs_base->reachable_labels = bitmap_alloc (&labels_obstack);
/* Collect labels in this block. We don't keep those corresponding
to END {IF|SELECT}, these are checked in resolve_branch by going
@@ -14525,7 +14525,7 @@ resolve_symbol (gfc_symbol *sym)
&& !sym->attr.codimension && !sym->ts.u.derived->attr.coarray_comp)
{
gfc_error ("Variable %s at %L of type EVENT_TYPE or with subcomponent of "
- "type LOCK_TYPE must be a coarray", sym->name,
+ "type EVENT_TYPE must be a coarray", sym->name,
&sym->declared_at);
return;
}
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index ec43e635bf3..3bc2b34768f 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -845,13 +845,13 @@ conflict:
conflict_std:
if (name == NULL)
{
- return gfc_notify_std (standard, "%s attribute "
+ return gfc_notify_std (standard, "%s attribute conflicts "
"with %s attribute at %L", a1, a2,
where);
}
else
{
- return gfc_notify_std (standard, "%s attribute "
+ return gfc_notify_std (standard, "%s attribute conflicts "
"with %s attribute in %qs at %L",
a1, a2, name, where);
}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 47e8c091a9b..9efb531a722 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -4577,7 +4577,10 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
&& gfc_check_dependency (dest_expr, ss_expr, false))
ss_info->data.scalar.needs_temporary = 1;
- continue;
+ if (nDepend)
+ break;
+ else
+ continue;
}
if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index b2f73b78466..74d860689ee 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4875,7 +4875,7 @@ gfc_trans_use_stmts (gfc_namespace * ns)
(*debug_hooks->imported_module_or_decl) (entry->namespace_decl,
NULL_TREE,
ns->proc_name->backend_decl,
- false);
+ false, false);
for (rent = use_stmt->rename; rent; rent = rent->next)
{
tree decl, local_name;
@@ -4952,7 +4952,8 @@ gfc_trans_use_stmts (gfc_namespace * ns)
gfc_set_backend_locus (&rent->where);
(*debug_hooks->imported_module_or_decl) (decl, local_name,
ns->proc_name->backend_decl,
- !use_stmt->only_flag);
+ !use_stmt->only_flag,
+ false);
}
}
}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index e4f1da54ac7..a1e1dff72e0 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -452,7 +452,11 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
subscripts. This could be prevented in the elemental case
as temporaries are handled separatedly
(below in gfc_conv_elemental_dependencies). */
- gfc_conv_loop_setup (&loop, &code->expr1->where);
+ if (code->expr1)
+ gfc_conv_loop_setup (&loop, &code->expr1->where);
+ else
+ gfc_conv_loop_setup (&loop, &code->loc);
+
gfc_mark_ss_chain_used (ss, 1);
/* Convert the arguments, checking for dependencies. */
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 2323e0abe3d..8f0adde77e0 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -334,15 +334,15 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
/* Use pointer arithmetic for deferred character length array
references. */
if (type && TREE_CODE (type) == ARRAY_TYPE
- && TYPE_MAXVAL (TYPE_DOMAIN (type)) != NULL_TREE
- && (VAR_P (TYPE_MAXVAL (TYPE_DOMAIN (type)))
- || TREE_CODE (TYPE_MAXVAL (TYPE_DOMAIN (type))) == INDIRECT_REF)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
+ && (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ || TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INDIRECT_REF)
&& decl
- && (TREE_CODE (TYPE_MAXVAL (TYPE_DOMAIN (type))) == INDIRECT_REF
+ && (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INDIRECT_REF
|| TREE_CODE (decl) == FUNCTION_DECL
- || DECL_CONTEXT (TYPE_MAXVAL (TYPE_DOMAIN (type)))
- == DECL_CONTEXT (decl)))
- span = TYPE_MAXVAL (TYPE_DOMAIN (type));
+ || (DECL_CONTEXT (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ == DECL_CONTEXT (decl))))
+ span = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
else
span = NULL_TREE;
diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index ca30028143b..9e6e0116077 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
-#include "signop.h"
#include "hash-set.h"
#include "fixed-value.h"
#include "alias.h"
@@ -38,7 +37,6 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h"
#include "hashtab.h"
#include "hash-set.h"
-#include "machmode.h"
#include "hard-reg-set.h"
#include "input.h"
#include "function.h"
@@ -56,10 +54,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "tree-cfg.h"
#include "basic-block.h"
-#include "double-int.h"
#include "alias.h"
#include "symtab.h"
-#include "wide-int.h"
#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
diff --git a/gcc/function.c b/gcc/function.c
index f625489205b..62e72eb2a9f 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2218,20 +2218,11 @@ use_register_for_decl (const_tree decl)
if (!DECL_REGISTER (decl))
return false;
- switch (TREE_CODE (TREE_TYPE (decl)))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- /* When not optimizing, disregard register keyword for variables with
- types containing methods, otherwise the methods won't be callable
- from the debugger. */
- if (TYPE_METHODS (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
- return false;
- break;
- default:
- break;
- }
+ /* When not optimizing, disregard register keyword for types that
+ could have methods, otherwise the methods won't be callable from
+ the debugger. */
+ if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
+ return false;
return true;
}
@@ -5263,6 +5254,16 @@ expand_function_start (tree subr)
}
}
+ /* The following was moved from init_function_start.
+ The move is supposed to make sdb output more accurate. */
+ /* Indicate the beginning of the function body,
+ as opposed to parm setup. */
+ emit_note (NOTE_INSN_FUNCTION_BEG);
+
+ gcc_assert (NOTE_P (get_last_insn ()));
+
+ parm_birth_insn = get_last_insn ();
+
/* If the function receives a non-local goto, then store the
bits we need to restore the frame pointer. */
if (cfun->nonlocal_goto_save_area)
@@ -5284,16 +5285,6 @@ expand_function_start (tree subr)
update_nonlocal_goto_save_area ();
}
- /* The following was moved from init_function_start.
- The move is supposed to make sdb output more accurate. */
- /* Indicate the beginning of the function body,
- as opposed to parm setup. */
- emit_note (NOTE_INSN_FUNCTION_BEG);
-
- gcc_assert (NOTE_P (get_last_insn ()));
-
- parm_birth_insn = get_last_insn ();
-
if (crtl->profile)
{
#ifdef PROFILE_HOOK
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 68bcb7d24f1..09f3081dd15 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -23,13 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "rtl.h"
#include "hash-set.h"
-#include "machmode.h"
#include "vec.h"
-#include "double-int.h"
#include "input.h"
#include "alias.h"
#include "symtab.h"
-#include "wide-int.h"
#include "inchash.h"
#include "tree-core.h"
#include "tree.h"
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 49708cabf17..2720f38d0eb 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -40,6 +40,27 @@ class gcc_rich_location : public rich_location
void add_fixit_misspelled_id (location_t misspelled_token_loc,
tree hint_id);
+
+ /* If LOC is within the spans of lines that will already be printed for
+ this gcc_rich_location, then add it as a secondary location
+ and return true.
+
+ Otherwise return false.
+
+ This allows for a diagnostic to compactly print secondary locations
+ in one diagnostic when these are near enough the primary locations for
+ diagnostics-show-locus.c to cope with them, and to fall back to
+ printing them via a note otherwise e.g.:
+
+ gcc_rich_location richloc (primary_loc);
+ bool added secondary = richloc.add_location_if_nearby (secondary_loc);
+ error_at_rich_loc (&richloc, "main message");
+ if (!added secondary)
+ inform (secondary_loc, "message for secondary");
+
+ Implemented in diagnostic-show-locus.c. */
+
+ bool add_location_if_nearby (location_t loc);
};
#endif /* GCC_RICH_LOCATION_H */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 6d724b25423..d8c5260e36b 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1305,9 +1305,6 @@ static const struct compiler default_compilers[] =
{".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
{".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
{".r", "#Ratfor", 0, 0, 0},
- {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
- {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
- {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
{".go", "#Go", 0, 1, 0},
/* Next come the entries for C. */
{".c", "@c", 0, 0, 1},
@@ -4615,23 +4612,23 @@ process_command (unsigned int decoded_options_count,
/* Decide if undefined variable references are allowed in specs. */
- /* --version and --help alone or together are safe. Note that -v would
- make them unsafe, as they'd then be run for subprocesses as well, the
- location of which might depend on variables possibly coming from
- self-specs.
+ /* -v alone is safe. --version and --help alone or together are safe. Note
+ that -v would make them unsafe, as they'd then be run for subprocesses as
+ well, the location of which might depend on variables possibly coming
+ from self-specs. Note also that the command name is counted in
+ decoded_options_count. */
- Count the number of options we have for which undefined variables
- are harmless for sure, and check that nothing else is set. */
-
- unsigned n_varsafe_options = 0;
+ unsigned help_version_count = 0;
if (print_version)
- n_varsafe_options++;
-
+ help_version_count++;
+
if (print_help_list)
- n_varsafe_options++;
-
- spec_undefvar_allowed = (n_varsafe_options == decoded_options_count - 1);
+ help_version_count++;
+
+ spec_undefvar_allowed =
+ ((verbose_flag && decoded_options_count == 2)
+ || help_version_count == decoded_options_count - 1);
alloc_switch ();
switches[n_switches].part1 = 0;
diff --git a/gcc/gencheck.c b/gcc/gencheck.c
index f541d1c5389..7d71a62db2c 100644
--- a/gcc/gencheck.c
+++ b/gcc/gencheck.c
@@ -17,9 +17,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/>. */
-/* We don't have insn-modes.h, but we include tm.h. */
-#define BITS_PER_UNIT 8
-
#include "bconfig.h"
#include "system.h"
#include "coretypes.h"
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index 19381be38d2..e23327b5cfc 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -250,7 +250,7 @@ gendef (const char *format)
the memory and initializes it. */
puts ("{");
puts (" rtx rt;");
- puts (" rt = rtx_alloc_stat (code PASS_MEM_STAT);\n");
+ puts (" rt = rtx_alloc (code PASS_MEM_STAT);\n");
puts (" PUT_MODE_RAW (rt, mode);");
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index f20e39f9158..9da911a3695 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -61,7 +61,8 @@ static struct line_maps *line_table;
This is the implementation for genmatch. */
expanded_location
-linemap_client_expand_location_to_spelling_point (source_location loc)
+linemap_client_expand_location_to_spelling_point (source_location loc,
+ enum location_aspect)
{
const struct line_map_ordinary *map;
loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION, &map);
@@ -792,13 +793,17 @@ struct simplify
{
enum simplify_kind { SIMPLIFY, MATCH };
- simplify (simplify_kind kind_, operand *match_, operand *result_,
- vec<vec<user_id *> > for_vec_, cid_map_t *capture_ids_)
- : kind (kind_), match (match_), result (result_),
+ simplify (simplify_kind kind_, unsigned id_, operand *match_,
+ operand *result_, vec<vec<user_id *> > for_vec_,
+ cid_map_t *capture_ids_)
+ : kind (kind_), id (id_), match (match_), result (result_),
for_vec (for_vec_), for_subst_vec (vNULL),
capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1) {}
simplify_kind kind;
+ /* ID. This is kept to easily associate related simplifies expanded
+ from the same original one. */
+ unsigned id;
/* The expression that is matched against the GENERIC or GIMPLE IL. */
operand *match;
/* For a (simplify ...) an expression with ifs and withs with the expression
@@ -1007,7 +1012,7 @@ lower_commutative (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = commutate (s->match, s->for_vec);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1136,7 +1141,7 @@ lower_opt_convert (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = lower_opt_convert (s->match);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1237,7 +1242,7 @@ lower_cond (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = lower_cond (s->match);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1452,7 +1457,7 @@ lower_for (simplify *sin, vec<simplify *>& simplifiers)
if (skip)
continue;
- simplify *ns = new simplify (s->kind, match_op, result_op,
+ simplify *ns = new simplify (s->kind, s->id, match_op, result_op,
vNULL, s->capture_ids);
ns->for_subst_vec.safe_splice (s->for_subst_vec);
if (result_op
@@ -1526,8 +1531,11 @@ struct sinfo_hashmap_traits : simple_hashmap_traits<pointer_hash<dt_simplify>,
typedef hash_map<void * /* unused */, sinfo *, sinfo_hashmap_traits>
sinfo_map_t;
+/* Current simplifier ID we are processing during insertion into the
+ decision tree. */
+static unsigned current_id;
-/* Decision tree base class, used for DT_TRUE and DT_NODE. */
+/* Decision tree base class, used for DT_NODE. */
struct dt_node
{
@@ -1535,6 +1543,7 @@ struct dt_node
enum dt_type type;
unsigned level;
+ dt_node *parent;
vec<dt_node *> kids;
/* Statistics. */
@@ -1542,12 +1551,14 @@ struct dt_node
unsigned total_size;
unsigned max_level;
- dt_node (enum dt_type type_): type (type_), level (0), kids (vNULL) {}
+ dt_node (enum dt_type type_, dt_node *parent_)
+ : type (type_), level (0), parent (parent_), kids (vNULL) {}
dt_node *append_node (dt_node *);
- dt_node *append_op (operand *, dt_node *parent = 0, unsigned pos = 0);
- dt_node *append_true_op (dt_node *parent = 0, unsigned pos = 0);
- dt_node *append_match_op (dt_operand *, dt_node *parent = 0, unsigned pos = 0);
+ dt_node *append_op (operand *, dt_node *parent, unsigned pos);
+ dt_node *append_true_op (operand *, dt_node *parent, unsigned pos);
+ dt_node *append_match_op (operand *, dt_operand *, dt_node *parent,
+ unsigned pos);
dt_node *append_simplify (simplify *, unsigned, dt_operand **);
virtual void gen (FILE *, int, bool) {}
@@ -1560,20 +1571,20 @@ struct dt_node
void analyze (sinfo_map_t &);
};
-/* Generic decision tree node used for DT_OPERAND and DT_MATCH. */
+/* Generic decision tree node used for DT_OPERAND, DT_MATCH and DT_TRUE. */
struct dt_operand : public dt_node
{
operand *op;
dt_operand *match_dop;
- dt_operand *parent;
unsigned pos;
bool value_match;
+ unsigned for_id;
dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_,
- dt_operand *parent_ = 0, unsigned pos_ = 0)
- : dt_node (type), op (op_), match_dop (match_dop_),
- parent (parent_), pos (pos_), value_match (false) {}
+ dt_operand *parent_, unsigned pos_)
+ : dt_node (type, parent_), op (op_), match_dop (match_dop_),
+ pos (pos_), value_match (false), for_id (current_id) {}
void gen (FILE *, int, bool);
unsigned gen_predicate (FILE *, int, const char *, bool);
@@ -1596,7 +1607,7 @@ struct dt_simplify : public dt_node
sinfo *info;
dt_simplify (simplify *s_, unsigned pattern_no_, dt_operand **indexes_)
- : dt_node (DT_SIMPLIFY), s (s_), pattern_no (pattern_no_),
+ : dt_node (DT_SIMPLIFY, NULL), s (s_), pattern_no (pattern_no_),
indexes (indexes_), info (NULL) {}
void gen_1 (FILE *, int, bool, operand *);
@@ -1609,7 +1620,8 @@ inline bool
is_a_helper <dt_operand *>::test (dt_node *n)
{
return (n->type == dt_node::DT_OPERAND
- || n->type == dt_node::DT_MATCH);
+ || n->type == dt_node::DT_MATCH
+ || n->type == dt_node::DT_TRUE);
}
template<>
@@ -1632,7 +1644,7 @@ struct decision_tree
void gen (FILE *f, bool gimple);
void print (FILE *f = stderr);
- decision_tree () { root = new dt_node (dt_node::DT_NODE); }
+ decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); }
static dt_node *insert_operand (dt_node *, operand *, dt_operand **indexes,
unsigned pos = 0, dt_node *parent = 0);
@@ -1702,15 +1714,48 @@ decision_tree::find_node (vec<dt_node *>& ops, dt_node *p)
&& !ops.is_empty ()
&& ops.last ()->type == dt_node::DT_TRUE)
return ops.last ();
+ dt_operand *true_node = NULL;
for (int i = ops.length () - 1; i >= 0; --i)
{
/* But we can't merge across DT_TRUE nodes as they serve as
pattern order barriers to make sure that patterns apply
in order of appearance in case multiple matches are possible. */
if (ops[i]->type == dt_node::DT_TRUE)
- return NULL;
+ {
+ if (! true_node
+ || as_a <dt_operand *> (ops[i])->for_id > true_node->for_id)
+ true_node = as_a <dt_operand *> (ops[i]);
+ }
if (decision_tree::cmp_node (ops[i], p))
- return ops[i];
+ {
+ /* Unless we are processing the same pattern or the blocking
+ pattern is before the one we are going to merge with. */
+ if (true_node
+ && true_node->for_id != current_id
+ && true_node->for_id > as_a <dt_operand *> (ops[i])->for_id)
+ {
+ if (verbose >= 1)
+ {
+ source_location p_loc = 0;
+ if (p->type == dt_node::DT_OPERAND)
+ p_loc = as_a <dt_operand *> (p)->op->location;
+ source_location op_loc = 0;
+ if (ops[i]->type == dt_node::DT_OPERAND)
+ op_loc = as_a <dt_operand *> (ops[i])->op->location;
+ source_location true_loc = 0;
+ true_loc = true_node->op->location;
+ warning_at (p_loc,
+ "failed to merge decision tree node");
+ warning_at (op_loc,
+ "with the following");
+ warning_at (true_loc,
+ "because of the following which serves as ordering "
+ "barrier");
+ }
+ return NULL;
+ }
+ return ops[i];
+ }
}
return NULL;
}
@@ -1746,20 +1791,21 @@ dt_node::append_op (operand *op, dt_node *parent, unsigned pos)
/* Append a DT_TRUE decision tree node. */
dt_node *
-dt_node::append_true_op (dt_node *parent, unsigned pos)
+dt_node::append_true_op (operand *op, dt_node *parent, unsigned pos)
{
dt_operand *parent_ = safe_as_a<dt_operand *> (parent);
- dt_operand *n = new dt_operand (DT_TRUE, 0, 0, parent_, pos);
+ dt_operand *n = new dt_operand (DT_TRUE, op, 0, parent_, pos);
return append_node (n);
}
/* Append a DT_MATCH decision tree node. */
dt_node *
-dt_node::append_match_op (dt_operand *match_dop, dt_node *parent, unsigned pos)
+dt_node::append_match_op (operand *op, dt_operand *match_dop,
+ dt_node *parent, unsigned pos)
{
dt_operand *parent_ = as_a<dt_operand *> (parent);
- dt_operand *n = new dt_operand (DT_MATCH, 0, match_dop, parent_, pos);
+ dt_operand *n = new dt_operand (DT_MATCH, op, match_dop, parent_, pos);
return append_node (n);
}
@@ -1838,7 +1884,7 @@ decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes,
q = insert_operand (p, c->what, indexes, pos, parent);
else
{
- q = elm = p->append_true_op (parent, pos);
+ q = elm = p->append_true_op (o, parent, pos);
goto at_assert_elm;
}
// get to the last capture
@@ -1852,19 +1898,19 @@ decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes,
unsigned cc_index = c->where;
dt_operand *match_op = indexes[cc_index];
- dt_operand temp (dt_node::DT_TRUE, 0, 0);
+ dt_operand temp (dt_node::DT_TRUE, 0, 0, 0, 0);
elm = decision_tree::find_node (p->kids, &temp);
if (elm == 0)
{
- dt_operand temp (dt_node::DT_MATCH, 0, match_op);
+ dt_operand temp (dt_node::DT_MATCH, 0, match_op, 0, 0);
temp.value_match = c->value_match;
elm = decision_tree::find_node (p->kids, &temp);
}
}
else
{
- dt_operand temp (dt_node::DT_OPERAND, c->what, 0);
+ dt_operand temp (dt_node::DT_OPERAND, c->what, 0, 0, 0);
elm = decision_tree::find_node (p->kids, &temp);
}
@@ -1877,7 +1923,7 @@ at_assert_elm:
}
else
{
- p = p->append_match_op (indexes[capt_index], parent, pos);
+ p = p->append_match_op (o, indexes[capt_index], parent, pos);
as_a <dt_operand *>(p)->value_match = c->value_match;
if (c->what)
return insert_operand (p, c->what, indexes, 0, p);
@@ -1902,6 +1948,7 @@ at_assert_elm:
void
decision_tree::insert (struct simplify *s, unsigned pattern_no)
{
+ current_id = s->id;
dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1);
dt_node *p = decision_tree::insert_operand (root, s->match, indexes);
p->append_simplify (s, pattern_no, indexes);
@@ -1937,9 +1984,12 @@ decision_tree::print_node (dt_node *p, FILE *f, unsigned indent)
fprintf (f, "%p, ", (void *) s->indexes[i]);
fprintf (f, " } ");
}
+ if (is_a <dt_operand *> (p))
+ fprintf (f, " [%u]", as_a <dt_operand *> (p)->for_id);
}
- fprintf (stderr, " (%p), %u, %u\n", (void *) p, p->level, p->kids.length ());
+ fprintf (stderr, " (%p, %p), %u, %u\n",
+ (void *) p, (void *) p->parent, p->level, p->kids.length ());
for (unsigned i = 0; i < p->kids.length (); ++i)
decision_tree::print_node (p->kids[i], f, indent + 2);
@@ -2571,12 +2621,12 @@ capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
char *
dt_operand::get_name (char *name)
{
- if (!parent)
+ if (! parent)
sprintf (name, "t");
else if (parent->level == 1)
sprintf (name, "op%u", pos);
else if (parent->type == dt_node::DT_MATCH)
- return parent->get_name (name);
+ return as_a <dt_operand *> (parent)->get_name (name);
else
sprintf (name, "o%u%u", parent->level, pos);
return name;
@@ -2587,7 +2637,7 @@ dt_operand::get_name (char *name)
void
dt_operand::gen_opname (char *name, unsigned pos)
{
- if (!parent)
+ if (! parent)
sprintf (name, "op%u", pos);
else
sprintf (name, "o%u%u", level, pos);
@@ -2645,6 +2695,7 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
expr *e = static_cast<expr *> (op);
id_base *id = e->operation;
unsigned n_ops = e->ops.length ();
+ unsigned n_braces = 0;
for (unsigned i = 0; i < n_ops; ++i)
{
@@ -2677,14 +2728,15 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
"if ((TREE_CODE (%s) == SSA_NAME\n",
child_opname);
fprintf_indent (f, indent,
- " || is_gimple_min_invariant (%s))\n",
+ " || is_gimple_min_invariant (%s)))\n",
child_opname);
fprintf_indent (f, indent,
- " && (%s = do_valueize (valueize, %s)))\n",
- child_opname, child_opname);
- fprintf_indent (f, indent,
" {\n");
indent += 4;
+ n_braces++;
+ fprintf_indent (f, indent,
+ "%s = do_valueize (valueize, %s);\n",
+ child_opname, child_opname);
continue;
}
else
@@ -2697,10 +2749,8 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
"tree %s = gimple_call_arg (def, %u);\n",
child_opname, i);
fprintf_indent (f, indent,
- "if ((%s = do_valueize (valueize, %s)))\n",
+ "%s = do_valueize (valueize, %s);\n",
child_opname, child_opname);
- fprintf_indent (f, indent, " {\n");
- indent += 4;
}
/* While the toplevel operands are canonicalized by the caller
after valueizing operands of sub-expressions we have to
@@ -2725,7 +2775,7 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
}
}
- return n_ops;
+ return n_braces;
}
/* Generate GENERIC matching code for the decision tree operand. */
@@ -2866,14 +2916,10 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
fprintf_indent (f, indent,
"case SSA_NAME:\n");
fprintf_indent (f, indent,
- " if (do_valueize (valueize, %s) != NULL_TREE)\n",
+ " if (gimple *def_stmt = get_def (valueize, %s))\n",
kid_opname);
fprintf_indent (f, indent,
" {\n");
- fprintf_indent (f, indent,
- " gimple *def_stmt = SSA_NAME_DEF_STMT (%s);\n",
- kid_opname);
-
indent += 6;
if (exprs_len)
{
@@ -3460,11 +3506,11 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
if (! s->for_subst_vec[i].first->used)
continue;
if (is_a <operator_id *> (s->for_subst_vec[i].second))
- fprintf_indent (f, indent, "enum tree_code %s = %s;\n",
+ fprintf_indent (f, indent, "const enum tree_code %s = %s;\n",
s->for_subst_vec[i].first->id,
s->for_subst_vec[i].second->id);
else if (is_a <fn_id *> (s->for_subst_vec[i].second))
- fprintf_indent (f, indent, "combined_fn %s = %s;\n",
+ fprintf_indent (f, indent, "const combined_fn %s = %s;\n",
s->for_subst_vec[i].first->id,
s->for_subst_vec[i].second->id);
else
@@ -3600,13 +3646,13 @@ decision_tree::gen (FILE *f, bool gimple)
"%s (code_helper *res_code, tree *res_ops,\n"
" gimple_seq *seq, tree (*valueize)(tree) "
"ATTRIBUTE_UNUSED,\n"
- " tree ARG_UNUSED (type), tree *ARG_UNUSED "
+ " const tree ARG_UNUSED (type), tree *ARG_UNUSED "
"(captures)\n",
s->fname);
else
{
fprintf (f, "\nstatic tree\n"
- "%s (location_t ARG_UNUSED (loc), tree ARG_UNUSED (type),\n",
+ "%s (location_t ARG_UNUSED (loc), const tree ARG_UNUSED (type),\n",
(*iter).second->fname);
for (unsigned i = 0;
i < as_a <expr *>(s->s->s->match)->ops.length (); ++i)
@@ -3618,10 +3664,10 @@ decision_tree::gen (FILE *f, bool gimple)
if (! s->s->s->for_subst_vec[i].first->used)
continue;
if (is_a <operator_id *> (s->s->s->for_subst_vec[i].second))
- fprintf (f, ", enum tree_code ARG_UNUSED (%s)",
+ fprintf (f, ", const enum tree_code ARG_UNUSED (%s)",
s->s->s->for_subst_vec[i].first->id);
else if (is_a <fn_id *> (s->s->s->for_subst_vec[i].second))
- fprintf (f, ", combined_fn ARG_UNUSED (%s)",
+ fprintf (f, ", const combined_fn ARG_UNUSED (%s)",
s->s->s->for_subst_vec[i].first->id);
}
@@ -3662,7 +3708,7 @@ decision_tree::gen (FILE *f, bool gimple)
else
fprintf (f, "\nstatic tree\n"
"generic_simplify_%s (location_t ARG_UNUSED (loc), enum "
- "tree_code ARG_UNUSED (code), tree ARG_UNUSED (type)",
+ "tree_code ARG_UNUSED (code), const tree ARG_UNUSED (type)",
e->operation->id);
for (unsigned i = 0; i < n; ++i)
fprintf (f, ", tree op%d", i);
@@ -3682,11 +3728,11 @@ decision_tree::gen (FILE *f, bool gimple)
fprintf (f, "\nstatic bool\n"
"gimple_simplify (code_helper *res_code, tree *res_ops,\n"
" gimple_seq *seq, tree (*valueize)(tree),\n"
- " code_helper code, tree type");
+ " code_helper code, const tree type");
else
fprintf (f, "\ntree\n"
"generic_simplify (location_t loc, enum tree_code code, "
- "tree type ATTRIBUTE_UNUSED");
+ "const tree type ATTRIBUTE_UNUSED");
for (unsigned i = 0; i < n; ++i)
fprintf (f, ", tree op%d", i);
fprintf (f, ")\n");
@@ -3750,7 +3796,7 @@ write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
p->nargs > 0 ? ", tree *res_ops" : "",
gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
/* Conveniently make 'type' available. */
- fprintf_indent (f, 2, "tree type = TREE_TYPE (t);\n");
+ fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n");
if (!gimple)
fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
@@ -3822,6 +3868,7 @@ private:
vec<user_id *> oper_lists;
cid_map_t *capture_ids;
+ unsigned last_id;
public:
vec<simplify *> simplifiers;
@@ -4317,7 +4364,7 @@ parser::push_simplify (simplify::simplify_kind kind,
active_fors.safe_push (oper_lists);
simplifiers.safe_push
- (new simplify (kind, match, result,
+ (new simplify (kind, last_id++, match, result,
active_fors.copy (), capture_ids));
if (!oper_lists.is_empty ())
@@ -4882,6 +4929,7 @@ parser::parser (cpp_reader *r_)
capture_ids = NULL;
user_predicates = vNULL;
parsing_match_operand = false;
+ last_id = 0;
const cpp_token *token = next ();
while (token->type != CPP_EOF)
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index e56c08b4d30..f7eaeef2fe6 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1204,6 +1204,24 @@ enum machine_mode\n{");
printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+ puts ("\
+\n\
+#endif /* insn-modes.h */");
+}
+
+static void
+emit_insn_modes_inline_h (void)
+{
+ printf ("/* Generated automatically from machmode.def%s%s\n",
+ HAVE_EXTRA_MODES ? " and " : "",
+ EXTRA_MODES_FILE);
+
+ puts ("\
+ by genmodes. */\n\
+\n\
+#ifndef GCC_INSN_MODES_INLINE_H\n\
+#define GCC_INSN_MODES_INLINE_H");
+
puts ("\n#if !defined (USED_FOR_TARGET) && GCC_VERSION >= 4001\n");
emit_mode_size_inline ();
emit_mode_nunits_inline ();
@@ -1214,7 +1232,7 @@ enum machine_mode\n{");
puts ("\
\n\
-#endif /* insn-modes.h */");
+#endif /* insn-modes-inline.h */");
}
static void
@@ -1231,7 +1249,6 @@ emit_insn_modes_c_header (void)
#include \"system.h\"\n\
#include \"coretypes.h\"\n\
#include \"tm.h\"\n\
-#include \"machmode.h\"\n\
#include \"real.h\"");
}
@@ -1247,7 +1264,7 @@ emit_min_insn_modes_c_header (void)
\n\
#include \"bconfig.h\"\n\
#include \"system.h\"\n\
-#include \"machmode.h\"");
+#include \"coretypes.h\"");
}
static void
@@ -1799,18 +1816,20 @@ emit_min_insn_modes_c (void)
int
main (int argc, char **argv)
{
- bool gen_header = false, gen_min = false;
+ bool gen_header = false, gen_inlines = false, gen_min = false;
progname = argv[0];
if (argc == 1)
;
else if (argc == 2 && !strcmp (argv[1], "-h"))
gen_header = true;
+ else if (argc == 2 && !strcmp (argv[1], "-i"))
+ gen_inlines = true;
else if (argc == 2 && !strcmp (argv[1], "-m"))
gen_min = true;
else
{
- error ("usage: %s [-h|-m] > file", progname);
+ error ("usage: %s [-h|-i|-m] > file", progname);
return FATAL_EXIT_CODE;
}
@@ -1826,6 +1845,8 @@ main (int argc, char **argv)
if (gen_header)
emit_insn_modes_h ();
+ else if (gen_inlines)
+ emit_insn_modes_inline_h ();
else if (gen_min)
emit_min_insn_modes_c ();
else
diff --git a/gcc/genmultilib b/gcc/genmultilib
index c8bcdf3935d..1da3a6ed79c 100644
--- a/gcc/genmultilib
+++ b/gcc/genmultilib
@@ -186,8 +186,7 @@ fi
EOF
chmod +x tmpmultilib
-combination_space=`initial=/ ./tmpmultilib ${options}`
-combinations="$combination_space"
+combinations=`initial=/ ./tmpmultilib ${options}`
# If there exceptions, weed them out now
if [ -n "${exceptions}" ]; then
@@ -460,6 +459,15 @@ done
echo "NULL"
echo "};"
+# Generate a regular expression to validate option combinations.
+options_re=
+for set in ${options}; do
+ for opt in `echo ${set} | sed -e 's_[/|]_ _g' -e 's/+/./g' `; do
+ options_re="${options_re}${options_re:+|}${opt}"
+ done
+done
+options_re="^/((${options_re})/)*\$"
+
# Output rules used for multilib reuse.
echo ""
echo "static const char *const multilib_reuse_raw[] = {"
@@ -473,7 +481,7 @@ for rrule in ${multilib_reuse}; do
# in this variable, it means no multilib will be built for current reuse
# rule. Thus the reuse purpose specified by current rule is meaningless.
if expr "${combinations} " : ".*/${combo}/.*" > /dev/null; then
- if expr "${combination_space} " : ".*/${copts}/.*" > /dev/null; then
+ if echo "/${copts}/" | grep -E "${options_re}" > /dev/null; then
combo="/${combo}/"
dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"`
copts="/${copts}/"
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index b69043f0d02..966405038d1 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -740,9 +740,9 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
case VEC_SELECT:
if (GET_MODE (pattern) != VOIDmode)
{
- enum machine_mode mode = GET_MODE (pattern);
- enum machine_mode imode = GET_MODE (XEXP (pattern, 0));
- enum machine_mode emode
+ machine_mode mode = GET_MODE (pattern);
+ machine_mode imode = GET_MODE (XEXP (pattern, 0));
+ machine_mode emode
= VECTOR_MODE_P (mode) ? GET_MODE_INNER (mode) : mode;
if (GET_CODE (XEXP (pattern, 1)) == PARALLEL)
{
diff --git a/gcc/ggc.h b/gcc/ggc.h
index d100a535e0a..9b5eb456779 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -24,9 +24,6 @@ along with GCC; see the file COPYING3. If not see
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
-/* Constants for general use. */
-extern const char empty_string[]; /* empty string */
-
/* Internal functions and data structures used by the GTY
machinery, including the generated gt*.[hc] files. */
@@ -127,9 +124,8 @@ extern void *ggc_internal_alloc (size_t, void (*)(void *), size_t,
size_t CXX_MEM_STAT_INFO)
ATTRIBUTE_MALLOC;
- static inline
- void *
- ggc_internal_alloc (size_t s CXX_MEM_STAT_INFO)
+inline void *
+ggc_internal_alloc (size_t s CXX_MEM_STAT_INFO)
{
return ggc_internal_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
}
@@ -141,8 +137,7 @@ extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *),
size_t, size_t
CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
-static inline
-void *
+inline void *
ggc_internal_cleared_alloc (size_t s CXX_MEM_STAT_INFO)
{
return ggc_internal_cleared_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
@@ -168,7 +163,7 @@ finalize (void *p)
}
template<typename T>
-static inline bool
+inline bool
need_finalization_p ()
{
#if GCC_VERSION >= 4003
@@ -179,7 +174,7 @@ need_finalization_p ()
}
template<typename T>
-static inline T *
+inline T *
ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
{
if (need_finalization_p<T> ())
@@ -191,7 +186,7 @@ ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
}
template<typename T>
-static inline T *
+inline T *
ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
{
if (need_finalization_p<T> ())
@@ -204,7 +199,7 @@ ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
}
template<typename T>
-static inline T *
+inline T *
ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
{
if (need_finalization_p<T> ())
@@ -216,7 +211,7 @@ ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
}
template<typename T>
-static inline T *
+inline T *
ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
{
if (need_finalization_p<T> ())
@@ -229,7 +224,7 @@ ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
0, 0 PASS_MEM_STAT));
}
-static inline void *
+inline void *
ggc_alloc_atomic (size_t s CXX_MEM_STAT_INFO)
{
return ggc_internal_alloc (s PASS_MEM_STAT);
@@ -274,52 +269,52 @@ extern void init_ggc_heuristics (void);
/* Memory statistics passing versions of some allocators. Too few of them to
make gengtype produce them, so just define the needed ones here. */
-static inline struct rtx_def *
+inline struct rtx_def *
ggc_alloc_rtx_def_stat (size_t s CXX_MEM_STAT_INFO)
{
return (struct rtx_def *) ggc_internal_alloc (s PASS_MEM_STAT);
}
-static inline union tree_node *
+inline union tree_node *
ggc_alloc_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
{
return (union tree_node *) ggc_internal_alloc (s PASS_MEM_STAT);
}
-static inline union tree_node *
+inline union tree_node *
ggc_alloc_cleared_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
{
return (union tree_node *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
}
-static inline gimple *
+inline gimple *
ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
{
return (gimple *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
}
-static inline void
+inline void
gt_ggc_mx (const char *s)
{
ggc_test_and_set_mark (const_cast<char *> (s));
}
-static inline void
+inline void
gt_pch_nx (const char *)
{
}
-static inline void
+inline void
gt_ggc_mx (int)
{
}
-static inline void
+inline void
gt_pch_nx (int)
{
}
-static inline void
+inline void
gt_pch_nx (unsigned int)
{
}
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index 9d8034c3192..13e55ef55fe 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -388,14 +388,14 @@ copy_var_decl (tree var, tree name, tree type)
/* Strip off a legitimate source ending from the input string NAME of
length LEN. Rather than having to know the names used by all of
our front ends, we strip off an ending of a period followed by
- up to five characters. (Java uses ".class".) */
+ up to four characters. (like ".cpp".) */
static inline void
remove_suffix (char *name, int len)
{
int i;
- for (i = 2; i < 8 && len > i; i++)
+ for (i = 2; i < 7 && len > i; i++)
{
if (name[len - i] == '.')
{
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index a00c2c88713..d82d0606cbe 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -571,7 +571,7 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
/* Replace the call at *GSI with the gimple value VAL. */
-static void
+void
replace_call_with_value (gimple_stmt_iterator *gsi, tree val)
{
gimple *stmt = gsi_stmt (*gsi);
@@ -607,9 +607,10 @@ replace_call_with_call_and_fold (gimple_stmt_iterator *gsi, gimple *repl)
&& TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
{
gimple_set_vdef (repl, gimple_vdef (stmt));
- gimple_set_vuse (repl, gimple_vuse (stmt));
SSA_NAME_DEF_STMT (gimple_vdef (repl)) = repl;
}
+ if (gimple_vuse (stmt))
+ gimple_set_vuse (repl, gimple_vuse (stmt));
gsi_replace (gsi, repl, false);
fold_stmt (gsi);
}
@@ -4244,7 +4245,7 @@ maybe_canonicalize_mem_ref_addr (tree *t)
TREE_TYPE (*t),
TREE_OPERAND (TREE_OPERAND (*t, 0), 0),
TYPE_SIZE (TREE_TYPE (*t)),
- wide_int_to_tree (sizetype, idx));
+ wide_int_to_tree (bitsizetype, idx));
res = true;
}
}
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index ad0b00dccad..2cee38508fc 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -58,6 +58,7 @@ extern bool gimple_fold_builtin_sprintf (gimple_stmt_iterator *);
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);
/* gimple_build, functionally matching fold_buildN, outputs stmts
int the provided sequence, matching and simplifying them on-the-fly.
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index 5f6aa273b96..8ad1f8c5eae 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -779,10 +779,25 @@ inline tree
do_valueize (tree (*valueize)(tree), tree op)
{
if (valueize && TREE_CODE (op) == SSA_NAME)
- return valueize (op);
+ {
+ tree tem = valueize (op);
+ if (tem)
+ return tem;
+ }
return op;
}
+/* Helper for the autogenerated code, get at the definition of NAME when
+ VALUEIZE allows that. */
+
+inline gimple *
+get_def (tree (*valueize)(tree), tree name)
+{
+ if (valueize && ! valueize (name))
+ return NULL;
+ return SSA_NAME_DEF_STMT (name);
+}
+
/* Routine to determine if the types T1 and T2 are effectively
the same for GIMPLE. If T1 or T2 is not a type, the test
applies to their TREE_TYPE. */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 447921be036..8b69b72e9e2 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -80,7 +80,7 @@ debug_gimple_stmt (gimple *gs)
by xstrdup_for_dump. */
static const char *
-dump_probability (int frequency, profile_count &count)
+dump_profile (int frequency, profile_count &count)
{
float minimum = 0.01f;
@@ -91,10 +91,42 @@ dump_probability (int frequency, profile_count &count)
char *buf;
if (count.initialized_p ())
- asprintf (&buf, "[%.2f%%] [count: %" PRId64 "]", fvalue,
- count.to_gcov_type ());
+ buf = xasprintf ("[%.2f%%] [count: %" PRId64 "]", fvalue,
+ count.to_gcov_type ());
else
- asprintf (&buf, "[%.2f%%] [count: INV]", fvalue);
+ buf = xasprintf ("[%.2f%%] [count: INV]", fvalue);
+
+ const char *ret = xstrdup_for_dump (buf);
+ free (buf);
+
+ return ret;
+}
+
+/* Return formatted string of a VALUE probability
+ (biased by REG_BR_PROB_BASE). Returned string is allocated
+ by xstrdup_for_dump. */
+
+static const char *
+dump_probability (profile_probability probability, profile_count &count)
+{
+ float minimum = 0.01f;
+ float fvalue = -1;
+
+ if (probability.initialized_p ())
+ {
+ fvalue = probability.to_reg_br_prob_base () * 100.0f / REG_BR_PROB_BASE;
+ if (fvalue < minimum && probability.to_reg_br_prob_base ())
+ fvalue = minimum;
+ }
+
+ char *buf;
+ if (count.initialized_p ())
+ buf = xasprintf ("[%.2f%%] [count: %" PRId64 "]", fvalue,
+ count.to_gcov_type ());
+ else if (probability.initialized_p ())
+ buf = xasprintf ("[%.2f%%] [count: INV]", fvalue);
+ else
+ buf = xasprintf ("[INV] [count: INV]");
const char *ret = xstrdup_for_dump (buf);
free (buf);
@@ -1088,9 +1120,6 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc,
else
{
dump_generic_node (buffer, label, spc, flags, false);
- basic_block bb = gimple_bb (gs);
- if (bb && !(flags & TDF_GIMPLE))
- pp_scalar (buffer, " %s", dump_probability (bb->frequency, bb->count));
pp_colon (buffer);
}
if (flags & TDF_GIMPLE)
@@ -2663,16 +2692,12 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent,
}
else
{
- gimple *stmt = first_stmt (bb);
- if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
- {
- if (flags & TDF_GIMPLE)
- fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
- else
- fprintf (outf, "%*s<bb %d> %s:\n",
- indent, "", bb->index, dump_probability (bb->frequency,
- bb->count));
- }
+ if (flags & TDF_GIMPLE)
+ fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
+ else
+ fprintf (outf, "%*s<bb %d> %s:\n",
+ indent, "", bb->index, dump_profile (bb->frequency,
+ bb->count));
}
}
@@ -2728,22 +2753,10 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t flags)
}
else
{
- gimple *stmt = first_stmt (e->dest);
-
pp_string (buffer, "goto <bb ");
pp_decimal_int (buffer, e->dest->index);
pp_greater (buffer);
- if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
- {
- pp_string (buffer, " (");
- dump_generic_node (buffer,
- gimple_label_label (as_a <glabel *> (stmt)),
- 0, 0, false);
- pp_right_paren (buffer);
- pp_semicolon (buffer);
- }
- else
- pp_semicolon (buffer);
+ pp_semicolon (buffer);
dump_edge_probability (buffer, e);
}
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
index 7ad39b4e09b..fbc41057463 100644
--- a/gcc/gimple-ssa-isolate-paths.c
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -442,6 +442,8 @@ find_implicit_erroneous_behavior (void)
if (!integer_zerop (op))
continue;
+ location_t phi_arg_loc = gimple_phi_arg_location (phi, i);
+
/* We've got a NULL PHI argument. Now see if the
PHI's result is dereferenced within BB. */
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
@@ -454,7 +456,7 @@ find_implicit_erroneous_behavior (void)
location_t loc = gimple_location (use_stmt)
? gimple_location (use_stmt)
- : gimple_phi_arg_location (phi, i);
+ : phi_arg_loc;
if (stmt_uses_name_in_undefined_way (use_stmt, lhs, loc))
{
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index f43778bbcfc..644cf7e33b1 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -1407,7 +1407,7 @@ format_integer (const directive &dir, tree arg)
return res;
}
- else if (TREE_CODE (TREE_TYPE (arg)) == INTEGER_TYPE
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
|| TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE)
/* Determine the type of the provided non-constant argument. */
argtype = TREE_TYPE (arg);
@@ -1427,7 +1427,7 @@ format_integer (const directive &dir, tree arg)
if (arg
&& TREE_CODE (arg) == SSA_NAME
- && TREE_CODE (argtype) == INTEGER_TYPE)
+ && INTEGRAL_TYPE_P (argtype))
{
/* Try to determine the range of values of the integer argument
(range information is not available for pointers). */
@@ -1472,7 +1472,7 @@ format_integer (const directive &dir, tree arg)
if (code == NOP_EXPR)
{
tree type = TREE_TYPE (gimple_assign_rhs1 (def));
- if (TREE_CODE (type) == INTEGER_TYPE
+ if (INTEGRAL_TYPE_P (type)
|| TREE_CODE (type) == POINTER_TYPE)
argtype = type;
}
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 64b83517c7a..ea7dc846c43 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -331,8 +331,8 @@ clear_bit_region (unsigned char *ptr, unsigned int start,
else if (start == 0 && len > BITS_PER_UNIT)
{
unsigned int nbytes = len / BITS_PER_UNIT;
- /* We could recurse on each byte but do the loop here to avoid
- recursing too deep. */
+ /* We could recurse on each byte but we clear whole bytes, so a simple
+ memset will do. */
memset (ptr, '\0', nbytes);
/* Clear the remaining sub-byte region if there is one. */
if (len % BITS_PER_UNIT != 0)
@@ -516,12 +516,12 @@ sort_by_bitpos (const void *x, const void *y)
store_immediate_info *const *tmp = (store_immediate_info * const *) x;
store_immediate_info *const *tmp2 = (store_immediate_info * const *) y;
- if ((*tmp)->bitpos <= (*tmp2)->bitpos)
+ if ((*tmp)->bitpos < (*tmp2)->bitpos)
return -1;
else if ((*tmp)->bitpos > (*tmp2)->bitpos)
return 1;
-
- gcc_unreachable ();
+ else
+ return 0;
}
/* Sorting function for store_immediate_info objects.
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 25f751a60ba..00c30444700 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -482,6 +482,36 @@ find_phi_def (tree base)
return c->cand_num;
}
+/* Determine whether all uses of NAME are directly or indirectly
+ used by STMT. That is, we want to know whether if STMT goes
+ dead, the definition of NAME also goes dead. */
+static bool
+uses_consumed_by_stmt (tree name, gimple *stmt, unsigned recurse = 0)
+{
+ gimple *use_stmt;
+ imm_use_iterator iter;
+ bool retval = true;
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
+ {
+ if (use_stmt == stmt || is_gimple_debug (use_stmt))
+ continue;
+
+ if (!is_gimple_assign (use_stmt)
+ || !gimple_get_lhs (use_stmt)
+ || !is_gimple_reg (gimple_get_lhs (use_stmt))
+ || recurse >= 10
+ || !uses_consumed_by_stmt (gimple_get_lhs (use_stmt), stmt,
+ recurse + 1))
+ {
+ retval = false;
+ BREAK_FROM_IMM_USE_STMT (iter);
+ }
+ }
+
+ return retval;
+}
+
/* Helper routine for find_basis_for_candidate. May be called twice:
once for the candidate's base expr, and optionally again either for
the candidate's phi definition or for a CAND_REF's alternative base
@@ -558,7 +588,8 @@ find_basis_for_candidate (slsr_cand_t c)
/* If we found a hidden basis, estimate additional dead-code
savings if the phi and its feeding statements can be removed. */
- if (basis && has_single_use (gimple_phi_result (phi_cand->cand_stmt)))
+ tree feeding_var = gimple_phi_result (phi_cand->cand_stmt);
+ if (basis && uses_consumed_by_stmt (feeding_var, c->cand_stmt))
c->dead_savings += phi_cand->dead_savings;
}
}
@@ -789,7 +820,7 @@ slsr_process_phi (gphi *phi, bool speed)
/* Gather potential dead code savings if the phi statement
can be removed later on. */
- if (has_single_use (arg))
+ if (uses_consumed_by_stmt (arg, phi))
{
if (gimple_code (arg_stmt) == GIMPLE_PHI)
savings += arg_cand->dead_savings;
@@ -2051,13 +2082,14 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
types but allows for safe negation without twisted logic. */
if (wi::fits_shwi_p (bump)
&& bump.to_shwi () != HOST_WIDE_INT_MIN
- /* It is not useful to replace casts, copies, or adds of
+ /* It is not useful to replace casts, copies, negates, or adds of
an SSA name and a constant. */
&& cand_code != SSA_NAME
&& !CONVERT_EXPR_CODE_P (cand_code)
&& cand_code != PLUS_EXPR
&& cand_code != POINTER_PLUS_EXPR
- && cand_code != MINUS_EXPR)
+ && cand_code != MINUS_EXPR
+ && cand_code != NEGATE_EXPR)
{
enum tree_code code = PLUS_EXPR;
tree bump_tree;
@@ -2479,7 +2511,9 @@ replace_uncond_cands_and_profitable_phis (slsr_cand_t c)
{
if (phi_dependent_cand_p (c))
{
- if (c->kind == CAND_MULT)
+ /* A multiply candidate with a stride of 1 is just an artifice
+ of a copy or cast; there is no value in replacing it. */
+ if (c->kind == CAND_MULT && wi::to_widest (c->stride) != 1)
{
/* A candidate dependent upon a phi will replace a multiply by
a constant with an add, and will insert at most one add for
@@ -2725,8 +2759,9 @@ phi_incr_cost (slsr_cand_t c, const widest_int &incr, gimple *phi,
if (gimple_code (arg_def) == GIMPLE_PHI)
{
int feeding_savings = 0;
+ tree feeding_var = gimple_phi_result (arg_def);
cost += phi_incr_cost (c, incr, arg_def, &feeding_savings);
- if (has_single_use (gimple_phi_result (arg_def)))
+ if (uses_consumed_by_stmt (feeding_var, phi))
*savings += feeding_savings;
}
else
@@ -2739,7 +2774,7 @@ phi_incr_cost (slsr_cand_t c, const widest_int &incr, gimple *phi,
tree basis_lhs = gimple_assign_lhs (basis->cand_stmt);
tree lhs = gimple_assign_lhs (arg_cand->cand_stmt);
cost += add_cost (true, TYPE_MODE (TREE_TYPE (basis_lhs)));
- if (has_single_use (lhs))
+ if (uses_consumed_by_stmt (lhs, phi))
*savings += stmt_cost (arg_cand->cand_stmt, true);
}
}
@@ -2816,7 +2851,7 @@ lowest_cost_path (int cost_in, int repl_savings, slsr_cand_t c,
gimple *phi = lookup_cand (c->def_phi)->cand_stmt;
local_cost += phi_incr_cost (c, incr, phi, &savings);
- if (has_single_use (gimple_phi_result (phi)))
+ if (uses_consumed_by_stmt (gimple_phi_result (phi), c->cand_stmt))
local_cost -= savings;
}
@@ -2860,7 +2895,7 @@ total_savings (int repl_savings, slsr_cand_t c, const widest_int &incr,
gimple *phi = lookup_cand (c->def_phi)->cand_stmt;
savings -= phi_incr_cost (c, incr, phi, &phi_savings);
- if (has_single_use (gimple_phi_result (phi)))
+ if (uses_consumed_by_stmt (gimple_phi_result (phi), c->cand_stmt))
savings += phi_savings;
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 488f8c82b82..3a32b530cce 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -117,7 +117,7 @@ gimple_size (enum gimple_code code)
operands. */
gimple *
-gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
+gimple_alloc (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
{
size_t size;
gimple *stmt;
@@ -169,7 +169,7 @@ static gimple *
gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
unsigned num_ops MEM_STAT_DECL)
{
- gimple *s = gimple_alloc_stat (code, num_ops PASS_MEM_STAT);
+ gimple *s = gimple_alloc (code, num_ops PASS_MEM_STAT);
gimple_set_subcode (s, subcode);
return s;
@@ -796,7 +796,7 @@ gimple_build_eh_dispatch (int region)
VAR is bound to VALUE; block and location are taken from STMT. */
gdebug *
-gimple_build_debug_bind_stat (tree var, tree value, gimple *stmt MEM_STAT_DECL)
+gimple_build_debug_bind (tree var, tree value, gimple *stmt MEM_STAT_DECL)
{
gdebug *p
= as_a <gdebug *> (gimple_build_with_ops_stat (GIMPLE_DEBUG,
@@ -816,7 +816,7 @@ gimple_build_debug_bind_stat (tree var, tree value, gimple *stmt MEM_STAT_DECL)
VAR is bound to VALUE; block and location are taken from STMT. */
gdebug *
-gimple_build_debug_source_bind_stat (tree var, tree value,
+gimple_build_debug_source_bind (tree var, tree value,
gimple *stmt MEM_STAT_DECL)
{
gdebug *p
@@ -1613,7 +1613,7 @@ gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
gimple *new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
gimple_init_singleton (new_stmt);
- gsi_replace (gsi, new_stmt, true);
+ gsi_replace (gsi, new_stmt, false);
stmt = new_stmt;
/* The LHS needs to be reset as this also changes the SSA name
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 575babe11ef..6213c49b91f 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1417,8 +1417,7 @@ extern enum gimple_statement_structure_enum const gss_for_code_[];
of comminucating the profile info to the builtin expanders. */
extern gimple *currently_expanding_gimple_stmt;
-#define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
-gimple *gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
+gimple *gimple_alloc (enum gimple_code, unsigned CXX_MEM_STAT_INFO);
greturn *gimple_build_return (tree);
void gimple_call_reset_alias_info (gcall *);
gcall *gimple_build_call_vec (tree, vec<tree> );
@@ -1454,12 +1453,8 @@ gresx *gimple_build_resx (int);
gswitch *gimple_build_switch_nlabels (unsigned, tree, tree);
gswitch *gimple_build_switch (tree, tree, vec<tree> );
geh_dispatch *gimple_build_eh_dispatch (int);
-gdebug *gimple_build_debug_bind_stat (tree, tree, gimple * MEM_STAT_DECL);
-#define gimple_build_debug_bind(var,val,stmt) \
- gimple_build_debug_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
-gdebug *gimple_build_debug_source_bind_stat (tree, tree, gimple * MEM_STAT_DECL);
-#define gimple_build_debug_source_bind(var,val,stmt) \
- gimple_build_debug_source_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
+gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
+gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree);
gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
@@ -4308,19 +4303,31 @@ gimple_phi_num_args (const gimple *gs)
/* Return the SSA name created by GIMPLE_PHI GS. */
static inline tree
+gimple_phi_result (const gphi *gs)
+{
+ return gs->result;
+}
+
+static inline tree
gimple_phi_result (const gimple *gs)
{
const gphi *phi_stmt = as_a <const gphi *> (gs);
- return phi_stmt->result;
+ return gimple_phi_result (phi_stmt);
}
/* Return a pointer to the SSA name created by GIMPLE_PHI GS. */
static inline tree *
+gimple_phi_result_ptr (gphi *gs)
+{
+ return &gs->result;
+}
+
+static inline tree *
gimple_phi_result_ptr (gimple *gs)
{
gphi *phi_stmt = as_a <gphi *> (gs);
- return &phi_stmt->result;
+ return gimple_phi_result_ptr (phi_stmt);
}
/* Set RESULT to be the SSA name created by GIMPLE_PHI PHI. */
@@ -4338,11 +4345,17 @@ gimple_phi_set_result (gphi *phi, tree result)
GIMPLE_PHI GS. */
static inline struct phi_arg_d *
+gimple_phi_arg (gphi *gs, unsigned index)
+{
+ gcc_gimple_checking_assert (index < gs->nargs);
+ return &(gs->args[index]);
+}
+
+static inline struct phi_arg_d *
gimple_phi_arg (gimple *gs, unsigned index)
{
gphi *phi_stmt = as_a <gphi *> (gs);
- gcc_gimple_checking_assert (index <= phi_stmt->capacity);
- return &(phi_stmt->args[index]);
+ return gimple_phi_arg (phi_stmt, index);
}
/* Set PHIARG to be the argument corresponding to incoming edge INDEX
@@ -4351,7 +4364,7 @@ gimple_phi_arg (gimple *gs, unsigned index)
static inline void
gimple_phi_set_arg (gphi *phi, unsigned index, struct phi_arg_d * phiarg)
{
- gcc_gimple_checking_assert (index <= phi->nargs);
+ gcc_gimple_checking_assert (index < phi->nargs);
phi->args[index] = *phiarg;
}
@@ -4377,6 +4390,12 @@ phi_nodes_ptr (basic_block bb)
/* Return the tree operand for argument I of PHI node GS. */
static inline tree
+gimple_phi_arg_def (gphi *gs, size_t index)
+{
+ return gimple_phi_arg (gs, index)->def;
+}
+
+static inline tree
gimple_phi_arg_def (gimple *gs, size_t index)
{
return gimple_phi_arg (gs, index)->def;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 641a8210dad..76a08c67061 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -818,12 +818,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
/* Stop at types, decls, constants like copy_tree_r. */
else if (TREE_CODE_CLASS (code) == tcc_type
|| TREE_CODE_CLASS (code) == tcc_declaration
- || TREE_CODE_CLASS (code) == tcc_constant
- /* We can't do anything sensible with a BLOCK used as an
- expression, but we also can't just die when we see it
- because of non-expression uses. So we avert our eyes
- and cross our fingers. Silly Java. */
- || code == BLOCK)
+ || TREE_CODE_CLASS (code) == tcc_constant)
*walk_subtrees = 0;
/* Cope with the statement expression extension. */
@@ -2042,7 +2037,9 @@ should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
gsi = *gsi_p;
/* Skip all immediately following labels. */
- while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
+ while (!gsi_end_p (gsi)
+ && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
+ || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT))
gsi_next (&gsi);
/* { ... something; default:; } */
@@ -5807,8 +5804,7 @@ gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
/* If the SAVE_EXPR has not been resolved, then evaluate it once. */
if (!SAVE_EXPR_RESOLVED_P (*expr_p))
{
- /* The operand may be a void-valued expression such as SAVE_EXPRs
- generated by the Java frontend for class initialization. It is
+ /* The operand may be a void-valued expression. It is
being executed only for its side-effects. */
if (TREE_TYPE (val) == void_type_node)
{
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index ac0dbe3f99d..1925111f169 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2017-07-27 Tony Reix <tony.reix@atos.net>
+
+ * go-backend.c (go_write_export_data): Use EXCLUDE section for
+ AIX.
+
2017-06-09 Ian Lance Taylor <iant@golang.org>
* go-lang.c (go_langhook_post_options): If -fsplit-stack is turned
diff --git a/gcc/go/go-backend.c b/gcc/go/go-backend.c
index 2f8d2f405da..21277ea2eb9 100644
--- a/gcc/go/go-backend.c
+++ b/gcc/go/go-backend.c
@@ -45,6 +45,10 @@ along with GCC; see the file COPYING3. If not see
#define GO_EXPORT_SECTION_NAME ".go_export"
#endif
+#ifndef TARGET_AIX
+#define TARGET_AIX 0
+#endif
+
/* This file holds all the cases where the Go frontend needs
information from gcc's backend. */
@@ -101,7 +105,9 @@ go_write_export_data (const char *bytes, unsigned int size)
if (sec == NULL)
{
gcc_assert (targetm_common.have_named_sections);
- sec = get_section (GO_EXPORT_SECTION_NAME, SECTION_DEBUG, NULL);
+ sec = get_section (GO_EXPORT_SECTION_NAME,
+ TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG,
+ NULL);
}
switch_to_section (sec);
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 416a5876da8..685cff9935b 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-0a20181d00d43a423c55f4e772b759fba0619478
+f7c36b27a49131f60eedde260896d310d735d408
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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 12505b23939..eb23ec26ecf 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -1204,7 +1204,14 @@ Func_expression::do_get_backend(Translate_context* context)
// expression. It is a pointer to a struct whose first field points
// to the function code and whose remaining fields are the addresses
// of the closed-over variables.
- return this->closure_->get_backend(context);
+ Bexpression *bexpr = this->closure_->get_backend(context);
+
+ // Introduce a backend type conversion, to account for any differences
+ // between the argument type (function descriptor, struct with a
+ // single field) and the closure (struct with multiple fields).
+ Gogo* gogo = context->gogo();
+ Btype *btype = this->type()->get_backend(gogo);
+ return gogo->backend()->convert_expression(btype, bexpr, this->location());
}
// Ast dump for function.
@@ -9456,24 +9463,28 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
this->is_varargs_, loc);
// If this call returns multiple results, create a temporary
- // variable for each result.
- size_t rc = this->result_count();
- if (rc > 1 && this->results_ == NULL)
+ // variable to hold them.
+ if (this->result_count() > 1 && this->call_temp_ == NULL)
{
- std::vector<Temporary_statement*>* temps =
- new std::vector<Temporary_statement*>;
- temps->reserve(rc);
+ Struct_field_list* sfl = new Struct_field_list();
+ Function_type* fntype = this->get_function_type();
const Typed_identifier_list* results = fntype->results();
+ Location loc = this->location();
+
+ int i = 0;
+ char buf[20];
for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- ++p)
- {
- Temporary_statement* temp = Statement::make_temporary(p->type(),
- NULL, loc);
- inserter->insert(temp);
- temps->push_back(temp);
- }
- this->results_ = temps;
+ p != results->end();
+ ++p, ++i)
+ {
+ snprintf(buf, sizeof buf, "res%d", i);
+ sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc)));
+ }
+
+ Struct_type* st = Type::make_struct_type(sfl, loc);
+ st->set_is_struct_incomparable();
+ this->call_temp_ = Statement::make_temporary(st, NULL, loc);
+ inserter->insert(this->call_temp_);
}
// Handle a call to a varargs function by packaging up the extra
@@ -9772,30 +9783,6 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
this->args_ = args;
}
- size_t rc = this->result_count();
- if (rc > 1 && this->call_temp_ == NULL)
- {
- Struct_field_list* sfl = new Struct_field_list();
- Function_type* fntype = this->get_function_type();
- const Typed_identifier_list* results = fntype->results();
- Location loc = this->location();
-
- int i = 0;
- char buf[20];
- for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- ++p, ++i)
- {
- snprintf(buf, sizeof buf, "res%d", i);
- sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc)));
- }
-
- Struct_type* st = Type::make_struct_type(sfl, loc);
- st->set_is_struct_incomparable();
- this->call_temp_ = Statement::make_temporary(st, NULL, loc);
- inserter->insert(this->call_temp_);
- }
-
return this;
}
@@ -9820,17 +9807,18 @@ Call_expression::result_count() const
return fntype->results()->size();
}
-// Return the temporary which holds a result.
+// Return the temporary that holds the result for a call with multiple
+// results.
Temporary_statement*
-Call_expression::result(size_t i) const
+Call_expression::results() const
{
- if (this->results_ == NULL || this->results_->size() <= i)
+ if (this->call_temp_ == NULL)
{
go_assert(saw_errors());
return NULL;
}
- return (*this->results_)[i];
+ return this->call_temp_;
}
// Set the number of results expected from a call expression.
@@ -10184,8 +10172,21 @@ Call_expression::interface_method_function(
Bexpression*
Call_expression::do_get_backend(Translate_context* context)
{
+ Location location = this->location();
+
if (this->call_ != NULL)
- return this->call_;
+ {
+ // If the call returns multiple results, make a new reference to
+ // the temporary.
+ if (this->call_temp_ != NULL)
+ {
+ Expression* ref =
+ Expression::make_temporary_reference(this->call_temp_, location);
+ return ref->get_backend(context);
+ }
+
+ return this->call_;
+ }
Function_type* fntype = this->get_function_type();
if (fntype == NULL)
@@ -10195,7 +10196,6 @@ Call_expression::do_get_backend(Translate_context* context)
return context->backend()->error_expression();
Gogo* gogo = context->gogo();
- Location location = this->location();
Func_expression* func = this->fn_->func_expression();
Interface_field_reference_expression* interface_method =
@@ -10316,91 +10316,28 @@ Call_expression::do_get_backend(Translate_context* context)
fn_args, bclosure,
location);
- if (this->results_ != NULL)
+ if (this->call_temp_ != NULL)
{
- Bexpression* bcall_ref = this->call_result_ref(context);
- Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(bfunction,
- bcall_ref, call, location);
+ // This case occurs when the call returns multiple results.
- this->call_ = this->set_results(context);
+ Expression* ref = Expression::make_temporary_reference(this->call_temp_,
+ location);
+ Bexpression* bref = ref->get_backend(context);
+ Bstatement* bassn = gogo->backend()->assignment_statement(bfunction,
+ bref, call,
+ location);
- Bexpression* set_and_call =
- gogo->backend()->compound_expression(assn_stmt, this->call_,
- location);
- return set_and_call;
+ ref = Expression::make_temporary_reference(this->call_temp_, location);
+ this->call_ = ref->get_backend(context);
+
+ return gogo->backend()->compound_expression(bassn, this->call_,
+ location);
}
this->call_ = call;
return this->call_;
}
-// Return the backend representation of a reference to the struct used
-// to capture the result of a multiple-output call.
-
-Bexpression*
-Call_expression::call_result_ref(Translate_context* context)
-{
- go_assert(this->call_temp_ != NULL);
- Location location = this->location();
- Expression* call_ref =
- Expression::make_temporary_reference(this->call_temp_, location);
- Bexpression* bcall_ref = call_ref->get_backend(context);
- return bcall_ref;
-}
-
-// Set the result variables if this call returns multiple results.
-
-Bexpression*
-Call_expression::set_results(Translate_context* context)
-{
- Gogo* gogo = context->gogo();
-
- Bexpression* results = NULL;
- Location loc = this->location();
-
- go_assert(this->call_temp_ != NULL);
-
- size_t rc = this->result_count();
- for (size_t i = 0; i < rc; ++i)
- {
- Temporary_statement* temp = this->result(i);
- if (temp == NULL)
- {
- go_assert(saw_errors());
- return gogo->backend()->error_expression();
- }
- Temporary_reference_expression* ref =
- Expression::make_temporary_reference(temp, loc);
- ref->set_is_lvalue();
-
- Bfunction* bfunction = context->function()->func_value()->get_decl();
- Bexpression* result_ref = ref->get_backend(context);
- Bexpression* bcall_ref = this->call_result_ref(context);
- Bexpression* call_result =
- gogo->backend()->struct_field_expression(bcall_ref, i, loc);
- Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(bfunction,
- result_ref, call_result, loc);
-
- bcall_ref = this->call_result_ref(context);
- call_result = gogo->backend()->struct_field_expression(bcall_ref, i, loc);
- Bexpression* result =
- gogo->backend()->compound_expression(assn_stmt, call_result, loc);
-
- if (results == NULL)
- results = result;
- else
- {
- Bstatement* expr_stmt =
- gogo->backend()->expression_statement(bfunction, result);
- results =
- gogo->backend()->compound_expression(expr_stmt, results, loc);
- }
- }
- return results;
-}
-
// Dump ast representation for a call expressin.
void
@@ -10521,13 +10458,14 @@ Call_result_expression::do_get_backend(Translate_context* context)
go_assert(this->call_->is_error_expression());
return context->backend()->error_expression();
}
- Temporary_statement* ts = ce->result(this->index_);
+ Temporary_statement* ts = ce->results();
if (ts == NULL)
{
go_assert(saw_errors());
return context->backend()->error_expression();
}
Expression* ref = Expression::make_temporary_reference(ts, this->location());
+ ref = Expression::make_field_reference(ref, this->index_, this->location());
return ref->get_backend(context);
}
@@ -12119,12 +12057,15 @@ Interface_field_reference_expression::do_get_backend(Translate_context* context)
Bexpression* bclosure =
Expression::make_heap_expression(expr, loc)->get_backend(context);
+ Gogo* gogo = context->gogo();
+ Btype* btype = this->type()->get_backend(gogo);
+ bclosure = gogo->backend()->convert_expression(btype, bclosure, loc);
+
Expression* nil_check =
Expression::make_binary(OPERATOR_EQEQ, this->expr_,
Expression::make_nil(loc), loc);
Bexpression* bnil_check = nil_check->get_backend(context);
- Gogo* gogo = context->gogo();
Bexpression* bcrash = gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
loc)->get_backend(context);
@@ -14300,7 +14241,10 @@ Type_guard_expression::do_get_backend(Translate_context* context)
Expression::convert_for_assignment(context->gogo(), this->type_,
this->expr_, this->location());
- return conversion->get_backend(context);
+ Gogo* gogo = context->gogo();
+ Btype* bt = this->type_->get_backend(gogo);
+ Bexpression* bexpr = conversion->get_backend(context);
+ return gogo->backend()->convert_expression(bt, bexpr, this->location());
}
// Dump ast representation for a type guard expression.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index a144ff4168b..0c742fd92df 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -2115,8 +2115,8 @@ class Call_expression : public Expression
Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
Location location)
: Expression(EXPRESSION_CALL, location),
- fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
- call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
+ fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
+ , expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false),
is_deferred_(false), is_concurrent_(false), issued_error_(false),
is_multi_value_arg_(false), is_flattened_(false)
@@ -2144,11 +2144,11 @@ class Call_expression : public Expression
size_t
result_count() const;
- // Return the temporary variable which holds result I. This is only
- // valid after the expression has been lowered, and is only valid
- // for calls which return multiple results.
+ // Return the temporary variable that holds the results. This is
+ // only valid after the expression has been lowered, and is only
+ // valid for calls which return multiple results.
Temporary_statement*
- result(size_t i) const;
+ results() const;
// Set the number of results expected from this call. This is used
// when the call appears in a context that expects multiple results,
@@ -2292,9 +2292,6 @@ class Call_expression : public Expression
Bexpression*
set_results(Translate_context*);
- Bexpression*
- call_result_ref(Translate_context* context);
-
// The function to call.
Expression* fn_;
// The arguments to pass. This may be NULL if there are no
@@ -2302,9 +2299,6 @@ class Call_expression : public Expression
Expression_list* args_;
// The type of the expression, to avoid recomputing it.
Type* type_;
- // The list of temporaries which will hold the results if the
- // function returns a tuple.
- std::vector<Temporary_statement*>* results_;
// The backend expression for the call, used for a call which returns a tuple.
Bexpression* call_;
// A temporary variable to store this call if the function returns a tuple.
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index a9d72ff4aa0..ca4b454a238 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -4824,6 +4824,8 @@ Gogo::convert_named_types()
Runtime::convert_types(this);
this->named_types_are_converted_ = true;
+
+ Type::finish_pointer_types(this);
}
// Convert all names types in a set of bindings.
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index b2756fde048..4d923733667 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1057,6 +1057,8 @@ Type::get_backend_placeholder(Gogo* gogo)
{
Location loc = Linemap::unknown_location();
bt = gogo->backend()->placeholder_pointer_type("", loc, false);
+ Pointer_type* pt = this->convert<Pointer_type, TYPE_POINTER>();
+ Type::placeholder_pointers.push_back(pt);
}
break;
@@ -5516,14 +5518,22 @@ Pointer_type::do_import(Import* imp)
return Type::make_pointer_type(to);
}
+// Cache of pointer types. Key is "to" type, value is pointer type
+// that points to key.
+
+Type::Pointer_type_table Type::pointer_types;
+
+// A list of placeholder pointer types. We keep this so we can ensure
+// they are finalized.
+
+std::vector<Pointer_type*> Type::placeholder_pointers;
+
// Make a pointer type.
Pointer_type*
Type::make_pointer_type(Type* to_type)
{
- typedef Unordered_map(Type*, Pointer_type*) Hashtable;
- static Hashtable pointer_types;
- Hashtable::const_iterator p = pointer_types.find(to_type);
+ Pointer_type_table::const_iterator p = pointer_types.find(to_type);
if (p != pointer_types.end())
return p->second;
Pointer_type* ret = new Pointer_type(to_type);
@@ -5531,6 +5541,37 @@ Type::make_pointer_type(Type* to_type)
return ret;
}
+// This helper is invoked immediately after named types have been
+// converted, to clean up any unresolved pointer types remaining in
+// the pointer type cache.
+//
+// The motivation for this routine: occasionally the compiler creates
+// some specific pointer type as part of a lowering operation (ex:
+// pointer-to-void), then Type::backend_type_size() is invoked on the
+// type (which creates a Btype placeholder for it), that placeholder
+// passed somewhere along the line to the back end, but since there is
+// no reference to the type in user code, there is never a call to
+// Type::finish_backend for the type (hence the Btype remains as an
+// unresolved placeholder). Calling this routine will clean up such
+// instances.
+
+void
+Type::finish_pointer_types(Gogo* gogo)
+{
+ // We don't use begin() and end() because it is possible to add new
+ // placeholder pointer types as we finalized existing ones.
+ for (size_t i = 0; i < Type::placeholder_pointers.size(); i++)
+ {
+ Pointer_type* pt = Type::placeholder_pointers[i];
+ Type_btypes::iterator tbti = Type::type_btypes.find(pt);
+ if (tbti != Type::type_btypes.end() && tbti->second.is_placeholder)
+ {
+ pt->finish_backend(gogo, tbti->second.btype);
+ tbti->second.is_placeholder = false;
+ }
+ }
+}
+
// The nil type. We use a special type for nil because it is not the
// same as any other type. In C term nil has type void*, but there is
// no such type in Go.
@@ -10994,13 +11035,13 @@ Named_type::do_get_backend(Gogo* gogo)
if (this->seen_in_get_backend_)
{
this->is_circular_ = true;
- return gogo->backend()->circular_pointer_type(bt, false);
+ return gogo->backend()->circular_pointer_type(bt, true);
}
this->seen_in_get_backend_ = true;
bt1 = Type::get_named_base_btype(gogo, base);
this->seen_in_get_backend_ = false;
if (this->is_circular_)
- bt1 = gogo->backend()->circular_pointer_type(bt, false);
+ bt1 = gogo->backend()->circular_pointer_type(bt, true);
if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1))
bt = gogo->backend()->error_type();
return bt;
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index aeb04d6c50f..f15f08ae4f0 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -504,6 +504,9 @@ class Type
static Pointer_type*
make_pointer_type(Type*);
+ static void
+ finish_pointer_types(Gogo* gogo);
+
static Type*
make_nil_type();
@@ -1341,6 +1344,15 @@ class Type
static Type_functions type_functions_table;
+ // Cache for reusing existing pointer types; maps from pointed-to-type
+ // to pointer type.
+ typedef Unordered_map(Type*, Pointer_type*) Pointer_type_table;
+
+ static Pointer_type_table pointer_types;
+
+ // List of placeholder pointer types.
+ static std::vector<Pointer_type*> placeholder_pointers;
+
// The type classification.
Type_classification classification_;
// The backend representation of the type, once it has been
diff --git a/gcc/godump.c b/gcc/godump.c
index 3e905319b8f..28d81a1e260 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "wide-int-print.h"
#include "diagnostic-core.h"
#include "debug.h"
#include "stor-layout.h"
diff --git a/gcc/graph.c b/gcc/graph.c
index 9261732d23e..9864120ff37 100644
--- a/gcc/graph.c
+++ b/gcc/graph.c
@@ -136,12 +136,16 @@ draw_cfg_node_succ_edges (pretty_printer *pp, int funcdef_no, basic_block bb)
pp_printf (pp,
"\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
- "[style=%s,color=%s,weight=%d,constraint=%s, label=\"[%i%%]\"];\n",
+ "[style=%s,color=%s,weight=%d,constraint=%s",
funcdef_no, e->src->index,
funcdef_no, e->dest->index,
style, color, weight,
- (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true",
- e->probability * 100 / REG_BR_PROB_BASE);
+ (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true");
+ if (e->probability.initialized_p ())
+ pp_printf (pp, ",label=\"[%i%%]\"",
+ e->probability.to_reg_br_prob_base ()
+ * 100 / REG_BR_PROB_BASE);
+ pp_printf (pp, "];\n");
}
pp_flush (pp);
}
@@ -243,19 +247,42 @@ draw_cfg_nodes (pretty_printer *pp, struct function *fun)
}
/* Draw all edges in the CFG. Retreating edges are drawin as not
- constraining, this makes the layout of the graph better.
- (??? Calling mark_dfs_back may change the compiler's behavior when
- dumping, but computing back edges here for ourselves is also not
- desirable.) */
+ constraining, this makes the layout of the graph better. */
static void
draw_cfg_edges (pretty_printer *pp, struct function *fun)
{
basic_block bb;
+
+ /* Save EDGE_DFS_BACK flag to dfs_back. */
+ auto_bitmap dfs_back;
+ edge e;
+ edge_iterator ei;
+ unsigned int idx = 0;
+ FOR_EACH_BB_FN (bb, cfun)
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ if (e->flags & EDGE_DFS_BACK)
+ bitmap_set_bit (dfs_back, idx);
+ idx++;
+ }
+
mark_dfs_back_edges ();
FOR_ALL_BB_FN (bb, cfun)
draw_cfg_node_succ_edges (pp, fun->funcdef_no, bb);
+ /* Restore EDGE_DFS_BACK flag from dfs_back. */
+ idx = 0;
+ FOR_EACH_BB_FN (bb, cfun)
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ if (bitmap_bit_p (dfs_back, idx))
+ e->flags |= EDGE_DFS_BACK;
+ else
+ e->flags &= ~EDGE_DFS_BACK;
+ idx++;
+ }
+
/* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */
pp_printf (pp,
"\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 9632a6d75db..af0ed27b18f 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -8302,7 +8302,19 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
else
edge_flags = 0;
- make_edge (first_bb, rec, edge_flags);
+ edge e2 = single_succ_edge (first_bb);
+ edge e = make_edge (first_bb, rec, edge_flags);
+
+ /* TODO: The actual probability can be determined and is computed as
+ 'todo_spec' variable in create_check_block_twin and
+ in sel-sched.c `check_ds' in create_speculation_check. */
+ e->probability = profile_probability::very_unlikely ();
+ e->count = first_bb->count.apply_probability (e->probability);
+ rec->count = e->count;
+ rec->frequency = EDGE_FREQUENCY (e);
+ e2->probability = e->probability.invert ();
+ e2->count = first_bb->count - e2->count;
+
rtx_code_label *label = block_label (second_bb);
rtx_jump_insn *jump = emit_jump_insn_after (targetm.gen_jump (label),
BB_END (rec));
diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c
index 1fd796e8cb0..fb5b365c129 100644
--- a/gcc/hash-map-tests.c
+++ b/gcc/hash-map-tests.c
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
-#include "signop.h"
#include "hash-set.h"
#include "fixed-value.h"
#include "alias.h"
diff --git a/gcc/hash-set-tests.c b/gcc/hash-set-tests.c
index 67ba42007db..9c48da25159 100644
--- a/gcc/hash-set-tests.c
+++ b/gcc/hash-set-tests.c
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
-#include "signop.h"
#include "hash-set.h"
#include "selftest.h"
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 443d16c1837..64d3157953c 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -325,7 +325,7 @@ hash_table_mod1 (hashval_t hash, unsigned int index)
{
const struct prime_ent *p = &prime_tab[index];
gcc_checking_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
- return mul_mod (hash, p->prime, p->inv, p->shift);
+ return mul_mod (hash, p->prime, p->inv, p->shift);
}
/* Compute the secondary table index for HASH given current prime index. */
diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 6eed0140492..0f6cac57776 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -500,7 +500,7 @@ brig_init (void)
else
part++;
char *modname2;
- asprintf (&modname2, "%s_%s", modname, part);
+ modname2 = xasprintf ("%s_%s", modname, part);
free (modname);
modname = modname2;
}
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 85f053cbed9..6ec8c348eb4 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1929,7 +1929,7 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
if (handled_component_p (ref))
{
- enum machine_mode mode;
+ machine_mode mode;
int unsignedp, volatilep, preversep;
ref = get_inner_reference (ref, &bitsize, &bitpos, &varoffset, &mode,
@@ -6139,7 +6139,7 @@ convert_switch_statements (void)
auto_vec <edge> new_edges;
auto_vec <phi_definition *> phi_todo_list;
auto_vec <profile_count> edge_counts;
- auto_vec <int> edge_probabilities;
+ auto_vec <profile_probability> edge_probabilities;
/* Investigate all labels that and PHI nodes in these edges which
should be fixed after we add new collection of edges. */
@@ -6231,12 +6231,12 @@ convert_switch_statements (void)
basic_block label_bb
= label_to_block_fn (func, CASE_LABEL (label));
edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
- int prob_sum = sum_slice <int> (edge_probabilities, i, labels, 0) +
- edge_probabilities[0];
+ profile_probability prob_sum = sum_slice <profile_probability>
+ (edge_probabilities, i, labels, profile_probability::never ())
+ + edge_probabilities[0];
- if (prob_sum)
- new_edge->probability
- = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
+ if (prob_sum.initialized_p ())
+ new_edge->probability = edge_probabilities[i] / prob_sum;
new_edge->count = edge_counts[i];
new_edges.safe_push (new_edge);
@@ -6253,8 +6253,7 @@ convert_switch_statements (void)
}
edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
- next_edge->probability
- = inverse_probability (new_edge->probability);
+ next_edge->probability = new_edge->probability.invert ();
next_edge->count = edge_counts[0]
+ sum_slice <profile_count> (edge_counts, i, labels,
profile_count::zero ());
@@ -6265,7 +6264,7 @@ convert_switch_statements (void)
of the switch. */
{
edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
- e->probability = inverse_probability (new_edge->probability);
+ e->probability = new_edge->probability.invert ();
e->count = edge_counts[0];
new_edges.safe_insert (0, e);
}
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 75458589468..46a13c41c09 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -78,14 +78,12 @@ static int cond_exec_changed_p;
/* Forward references. */
static int count_bb_insns (const_basic_block);
-static bool cheap_bb_rtx_cost_p (const_basic_block, int, int);
+static bool cheap_bb_rtx_cost_p (const_basic_block, profile_probability, int);
static rtx_insn *first_active_insn (basic_block);
static rtx_insn *last_active_insn (basic_block, int);
static rtx_insn *find_active_insn_before (basic_block, rtx_insn *);
static rtx_insn *find_active_insn_after (basic_block, rtx_insn *);
static basic_block block_fallthru (basic_block);
-static int cond_exec_process_insns (ce_if_block *, rtx_insn *, rtx, rtx, int,
- int);
static rtx cond_exec_get_condition (rtx_insn *);
static rtx noce_get_condition (rtx_insn *, rtx_insn **, bool);
static int noce_operand_ok (const_rtx);
@@ -132,11 +130,14 @@ count_bb_insns (const_basic_block bb)
plus a small fudge factor. */
static bool
-cheap_bb_rtx_cost_p (const_basic_block bb, int scale, int max_cost)
+cheap_bb_rtx_cost_p (const_basic_block bb,
+ profile_probability prob, int max_cost)
{
int count = 0;
rtx_insn *insn = BB_HEAD (bb);
bool speed = optimize_bb_for_speed_p (bb);
+ int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
+ : REG_BR_PROB_BASE;
/* Set scale to REG_BR_PROB_BASE to void the identical scaling
applied to insn_rtx_cost when optimizing for size. Only do
@@ -332,7 +333,8 @@ cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
/* if block information */rtx_insn *start,
/* first insn to look at */rtx end,
/* last insn to look at */rtx test,
- /* conditional execution test */int prob_val,
+ /* conditional execution test */profile_probability
+ prob_val,
/* probability of branch taken. */int mod_ok)
{
int must_be_last = FALSE;
@@ -407,10 +409,11 @@ cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
validate_change (insn, &PATTERN (insn), pattern, 1);
- if (CALL_P (insn) && prob_val >= 0)
+ if (CALL_P (insn) && prob_val.initialized_p ())
validate_change (insn, &REG_NOTES (insn),
gen_rtx_INT_LIST ((machine_mode) REG_BR_PROB,
- prob_val, REG_NOTES (insn)), 1);
+ prob_val.to_reg_br_prob_note (),
+ REG_NOTES (insn)), 1);
insn_done:
if (insn == end)
@@ -469,8 +472,8 @@ cond_exec_process_if_block (ce_if_block * ce_info,
int then_mod_ok; /* whether conditional mods are ok in THEN */
rtx true_expr; /* test for else block insns */
rtx false_expr; /* test for then block insns */
- int true_prob_val; /* probability of else block */
- int false_prob_val; /* probability of then block */
+ profile_probability true_prob_val;/* probability of else block */
+ profile_probability false_prob_val;/* probability of then block */
rtx_insn *then_last_head = NULL; /* Last match at the head of THEN */
rtx_insn *else_last_head = NULL; /* Last match at the head of ELSE */
rtx_insn *then_first_tail = NULL; /* First match at the tail of THEN */
@@ -615,13 +618,13 @@ cond_exec_process_if_block (ce_if_block * ce_info,
note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
if (note)
{
- true_prob_val = XINT (note, 0);
- false_prob_val = REG_BR_PROB_BASE - true_prob_val;
+ true_prob_val = profile_probability::from_reg_br_prob_note (XINT (note, 0));
+ false_prob_val = true_prob_val.invert ();
}
else
{
- true_prob_val = -1;
- false_prob_val = -1;
+ true_prob_val = profile_probability::uninitialized ();
+ false_prob_val = profile_probability::uninitialized ();
}
/* If we have && or || tests, do them here. These tests are in the adjacent
@@ -4807,7 +4810,8 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
basic_block new_bb;
- int then_bb_index, then_prob;
+ int then_bb_index;
+ profile_probability then_prob;
rtx else_target = NULL_RTX;
/* If we are partitioning hot/cold basic blocks, we don't want to
@@ -4853,10 +4857,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
"\nIF-CASE-1 found, start %d, then %d\n",
test_bb->index, then_bb->index);
- if (then_edge->probability)
- then_prob = REG_BR_PROB_BASE - then_edge->probability;
- else
- then_prob = REG_BR_PROB_BASE / 2;
+ then_prob = then_edge->probability.invert ();
/* We're speculating from the THEN path, we want to make sure the cost
of speculation is within reason. */
@@ -4927,7 +4928,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
edge else_succ;
- int then_prob, else_prob;
+ profile_probability then_prob, else_prob;
/* We do not want to speculate (empty) loop latches. */
if (current_loops
@@ -4973,16 +4974,8 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
if (then_bb->index < NUM_FIXED_BLOCKS)
return FALSE;
- if (else_edge->probability)
- {
- else_prob = else_edge->probability;
- then_prob = REG_BR_PROB_BASE - else_prob;
- }
- else
- {
- else_prob = REG_BR_PROB_BASE / 2;
- then_prob = REG_BR_PROB_BASE / 2;
- }
+ else_prob = else_edge->probability;
+ then_prob = else_prob.invert ();
/* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
if (else_prob > then_prob)
@@ -5128,7 +5121,9 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
return FALSE;
rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
- int prob_val = (note ? XINT (note, 0) : -1);
+ profile_probability prob_val
+ = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ : profile_probability::uninitialized ());
if (reversep)
{
@@ -5137,8 +5132,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
return FALSE;
cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
- if (prob_val >= 0)
- prob_val = REG_BR_PROB_BASE - prob_val;
+ prob_val = prob_val.invert ();
}
if (cond_exec_process_insns (NULL, head, end, cond, prob_val, 0)
diff --git a/gcc/input.c b/gcc/input.c
index 80718100d0c..0480eb24ec0 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -147,11 +147,14 @@ static const size_t fcache_line_record_size = 100;
associated line/column) in the context of a macro expansion, the
returned location is the first one (while unwinding the macro
location towards its expansion point) that is in real source
- code. */
+ code.
+
+ ASPECT controls which part of the location to use. */
static expanded_location
expand_location_1 (source_location loc,
- bool expansion_point_p)
+ bool expansion_point_p,
+ enum location_aspect aspect)
{
expanded_location xloc;
const line_map_ordinary *map;
@@ -181,8 +184,36 @@ expand_location_1 (source_location loc,
loc, NULL);
lrk = LRK_SPELLING_LOCATION;
}
- loc = linemap_resolve_location (line_table, loc,
- lrk, &map);
+ loc = linemap_resolve_location (line_table, loc, lrk, &map);
+
+ /* loc is now either in an ordinary map, or is a reserved location.
+ If it is a compound location, the caret is in a spelling location,
+ but the start/finish might still be a virtual location.
+ Depending of what the caller asked for, we may need to recurse
+ one level in order to resolve any virtual locations in the
+ end-points. */
+ switch (aspect)
+ {
+ default:
+ gcc_unreachable ();
+ /* Fall through. */
+ case LOCATION_ASPECT_CARET:
+ break;
+ case LOCATION_ASPECT_START:
+ {
+ source_location start = get_start (loc);
+ if (start != loc)
+ return expand_location_1 (start, expansion_point_p, aspect);
+ }
+ break;
+ case LOCATION_ASPECT_FINISH:
+ {
+ source_location finish = get_finish (loc);
+ if (finish != loc)
+ return expand_location_1 (finish, expansion_point_p, aspect);
+ }
+ break;
+ }
xloc = linemap_expand_location (line_table, map, loc);
}
@@ -773,7 +804,8 @@ is_location_from_builtin_token (source_location loc)
expanded_location
expand_location (source_location loc)
{
- return expand_location_1 (loc, /*expansion_point_p=*/true);
+ return expand_location_1 (loc, /*expansion_point_p=*/true,
+ LOCATION_ASPECT_CARET);
}
/* Expand the source location LOC into a human readable location. If
@@ -785,7 +817,8 @@ expand_location (source_location loc)
expanded_location
expand_location_to_spelling_point (source_location loc)
{
- return expand_location_1 (loc, /*expansion_point_p=*/false);
+ return expand_location_1 (loc, /*expansion_point_p=*/false,
+ LOCATION_ASPECT_CARET);
}
/* The rich_location class within libcpp requires a way to expand
@@ -795,12 +828,13 @@ expand_location_to_spelling_point (source_location loc)
to do this.
This is the implementation for libcommon.a (all host binaries),
- which simply calls into expand_location_to_spelling_point. */
+ which simply calls into expand_location_1. */
expanded_location
-linemap_client_expand_location_to_spelling_point (source_location loc)
+linemap_client_expand_location_to_spelling_point (source_location loc,
+ enum location_aspect aspect)
{
- return expand_location_to_spelling_point (loc);
+ return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
}
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 75fe027f7b2..e24ed169515 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "dojump.h"
#include "expr.h"
+#include "asan.h"
#include "ubsan.h"
#include "recog.h"
#include "builtins.h"
@@ -401,6 +402,14 @@ expand_UBSAN_VPTR (internal_fn, gcall *)
/* This should get expanded in the sanopt pass. */
static void
+expand_UBSAN_PTR (internal_fn, gcall *)
+{
+ gcc_unreachable ();
+}
+
+/* This should get expanded in the sanopt pass. */
+
+static void
expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
{
gcc_unreachable ();
@@ -569,7 +578,7 @@ expand_arith_overflow_result_store (tree lhs, rtx target,
gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
EQ, true, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
@@ -597,7 +606,7 @@ expand_arith_overflow_result_store (tree lhs, rtx target,
}
do_compare_rtx_and_jump (res, lres,
EQ, true, tgtmode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
@@ -740,7 +749,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
&& JUMP_P (last)
&& any_condjump_p (last)
&& !find_reg_note (last, REG_BR_PROB, 0))
- add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
+ add_reg_br_prob_note (last,
+ profile_probability::very_unlikely ());
emit_jump (done_label);
goto do_error_label;
}
@@ -767,7 +777,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
tem = op1;
do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
true, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
goto do_error_label;
}
@@ -782,7 +792,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
code == PLUS_EXPR ? res : op0, sgn,
NULL_RTX, false, OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -824,9 +834,9 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
else if (pos_neg == 3)
/* If ARG0 is not known to be always positive, check at runtime. */
do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -840,7 +850,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -852,7 +862,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
rtx tem = op1;
/* The operation is commutative, so we can pick operand to compare
against. For prec <= BITS_PER_WORD, I think preferring REG operand
@@ -866,7 +876,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
: CONST_SCALAR_INT_P (op0))
tem = op0;
do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -894,7 +904,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
? and_optab : ior_optab,
op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
else
{
@@ -902,17 +912,17 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
do_compare_rtx_and_jump (op1, const0_rtx,
code == MINUS_EXPR ? GE : LT, false, mode,
NULL_RTX, NULL, do_ior_label,
- PROB_EVEN);
+ profile_probability::even ());
tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
emit_jump (do_error);
emit_label (do_ior_label);
tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
goto do_error_label;
}
@@ -926,13 +936,13 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
OPTAB_LIB_WIDEN);
rtx_code_label *op0_geu_op1 = gen_label_rtx ();
do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
- op0_geu_op1, PROB_EVEN);
+ op0_geu_op1, profile_probability::even ());
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
emit_jump (do_error);
emit_label (op0_geu_op1);
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -960,7 +970,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
&& JUMP_P (last)
&& any_condjump_p (last)
&& !find_reg_note (last, REG_BR_PROB, 0))
- add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
+ add_reg_br_prob_note (last,
+ profile_probability::very_unlikely ());
emit_jump (done_label);
goto do_error_label;
}
@@ -1020,7 +1031,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
/* No overflow if the result has bit sign cleared. */
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
/* Compare the result of the operation with the first operand.
@@ -1031,7 +1042,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
do_compare_rtx_and_jump (res, op0,
(pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
false, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
do_error_label:
@@ -1109,7 +1120,8 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
&& JUMP_P (last)
&& any_condjump_p (last)
&& !find_reg_note (last, REG_BR_PROB, 0))
- add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
+ add_reg_br_prob_note (last,
+ profile_probability::very_unlikely ());
emit_jump (done_label);
}
else
@@ -1128,7 +1140,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
/* Compare the operand with the most negative value. */
rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
}
emit_label (do_error);
@@ -1261,15 +1273,15 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
case 3:
rtx_code_label *do_main_label;
do_main_label = gen_label_rtx ();
do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
@@ -1306,15 +1318,15 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
int prec;
prec = GET_MODE_PRECISION (mode);
rtx sgn;
sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
case 3:
/* Rest of handling of this case after res is computed. */
@@ -1361,7 +1373,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
goto do_error_label;
}
/* The general case, do all the needed comparisons at runtime. */
@@ -1378,7 +1390,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, after_negate_label, PROB_VERY_LIKELY);
+ NULL, after_negate_label, profile_probability::very_likely ());
/* Both arguments negative here, negate them and continue with
normal unsigned overflow checking multiplication. */
emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
@@ -1394,13 +1406,13 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
/* One argument is negative here, the other positive. This
overflows always, unless one of the arguments is 0. But
if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
is, thus we can keep do_main code oring in overflow as is. */
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
@@ -1430,7 +1442,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
&& JUMP_P (last)
&& any_condjump_p (last)
&& !find_reg_note (last, REG_BR_PROB, 0))
- add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
+ add_reg_br_prob_note (last,
+ profile_probability::very_unlikely ());
emit_jump (done_label);
}
else
@@ -1467,7 +1480,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
HIPART is non-zero. */
do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
else
{
rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
@@ -1477,7 +1490,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
HIPART is different from RES < 0 ? -1 : 0. */
do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
}
else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
@@ -1570,12 +1583,12 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (!op0_small_p)
do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
NULL_RTX, NULL, large_op0,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
if (!op1_small_p)
do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
NULL_RTX, NULL, small_op0_large_op1,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
/* If both op0 and op1 are sign (!uns) or zero (uns) extended from
hmode to mode, the multiplication will never overflow. We can
@@ -1621,7 +1634,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (!op1_small_p)
do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
NULL_RTX, NULL, both_ops_large,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
/* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
but op0 is not, prepare larger, hipart and lopart pseudos and
@@ -1658,7 +1671,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
else if (larger_sign != -1)
do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
NULL_RTX, NULL, after_hipart_neg,
- PROB_EVEN);
+ profile_probability::even ());
tem = convert_modes (mode, hmode, lopart, 1);
tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
@@ -1674,7 +1687,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
else if (smaller_sign != -1)
do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
NULL_RTX, NULL, after_lopart_neg,
- PROB_EVEN);
+ profile_probability::even ());
tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1, OPTAB_DIRECT);
@@ -1704,7 +1717,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
NULL_RTX, NULL, do_overflow,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
/* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
@@ -1741,7 +1754,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
NULL_RTX, 1, OPTAB_DIRECT);
do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
}
if (!op1_medium_p)
@@ -1750,7 +1763,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
NULL_RTX, 1, OPTAB_DIRECT);
do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
}
/* At this point hipart{0,1} are both in [-1, 0]. If they are
@@ -1761,18 +1774,18 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
else if (op0_sign == 1 || op1_sign == 1)
do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
NULL_RTX, NULL, hipart_different,
- PROB_EVEN);
+ profile_probability::even ());
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
emit_jump (done_label);
emit_label (hipart_different);
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
emit_jump (done_label);
}
@@ -1817,7 +1830,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
{
rtx_code_label *all_done_label = gen_label_rtx ();
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_LIKELY);
+ NULL, all_done_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (all_done_label);
}
@@ -1828,14 +1841,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
rtx_code_label *all_done_label = gen_label_rtx ();
rtx_code_label *set_noovf = gen_label_rtx ();
do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_LIKELY);
+ NULL, all_done_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, set_noovf, PROB_VERY_LIKELY);
+ NULL, set_noovf, profile_probability::very_likely ());
do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_UNLIKELY);
+ NULL, all_done_label, profile_probability::very_unlikely ());
do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
- all_done_label, PROB_VERY_UNLIKELY);
+ all_done_label, profile_probability::very_unlikely ());
emit_label (set_noovf);
write_complex_part (target, const0_rtx, true);
emit_label (all_done_label);
@@ -1977,7 +1990,7 @@ expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
emit_move_insn (cntvar, ret);
do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
if (lhs && resv == NULL_TREE)
{
@@ -2104,7 +2117,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
/* The infinity precision result will always fit into result. */
rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
write_complex_part (target, const0_rtx, true);
- enum machine_mode mode = TYPE_MODE (type);
+ machine_mode mode = TYPE_MODE (type);
struct separate_ops ops;
ops.code = code;
ops.type = type;
@@ -2157,7 +2170,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
if (orig_precres == precres && precop <= BITS_PER_WORD)
{
int p = MAX (min_precision, precop);
- enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
+ machine_mode m = smallest_mode_for_size (p, MODE_INT);
tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
uns0_p && uns1_p
&& unsr_p);
@@ -2199,7 +2212,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
if (orig_precres == precres)
{
int p = MAX (prec0, prec1);
- enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
+ machine_mode m = smallest_mode_for_size (p, MODE_INT);
tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
uns0_p && uns1_p
&& unsr_p);
@@ -2250,6 +2263,14 @@ expand_LOOP_VECTORIZED (internal_fn, gcall *)
gcc_unreachable ();
}
+/* This should get folded in tree-vectorizer.c. */
+
+static void
+expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
+{
+ gcc_unreachable ();
+}
+
/* Expand MASK_LOAD call STMT using optab OPTAB. */
static void
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index e162d81121c..a9a3f7606eb 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -158,6 +158,7 @@ DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_START, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_END, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (LOOP_DIST_ALIAS, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ".R.")
DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, NULL)
@@ -165,6 +166,7 @@ DEF_INTERNAL_FN (UBSAN_VPTR, ECF_LEAF | ECF_NOTHROW, ".RR..")
DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_PTR, ECF_LEAF | ECF_NOTHROW, ".R.")
DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c
index a234245a1dc..4fa3e146428 100644
--- a/gcc/ipa-comdats.c
+++ b/gcc/ipa-comdats.c
@@ -416,7 +416,7 @@ public:
bool
pass_ipa_comdats::gate (function *)
{
- return HAVE_COMDAT_GROUP && optimize;
+ return HAVE_COMDAT_GROUP;
}
} // anon namespace
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index c7e3c7107ca..3b9eab41672 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -159,6 +159,10 @@ public:
/* Time benefit and size cost that specializing the function for this value
can bring about in it's callees (transitively). */
int prop_time_benefit, prop_size_cost;
+
+ ipcp_value_base ()
+ : local_time_benefit (0), local_size_cost (0),
+ prop_time_benefit (0), prop_size_cost (0) {}
};
/* Describes one particular value stored in struct ipcp_lattice. */
@@ -188,6 +192,10 @@ public:
/* True if this valye is currently on the topo-sort stack. */
bool on_stack;
+ ipcp_value()
+ : sources (0), next (0), scc_next (0), topo_next (0),
+ spec_node (0), dfs (0), low_link (0), on_stack (false) {}
+
void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
HOST_WIDE_INT offset);
};
@@ -2623,7 +2631,8 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
struct ipa_node_params *info = IPA_NODE_REF (node);
if (max_count > profile_count::zero ())
{
- int factor = RDIV (count_sum.probability_in (max_count)
+ int factor = RDIV (count_sum.probability_in
+ (max_count).to_reg_br_prob_base ()
* 1000, REG_BR_PROB_BASE);
int64_t evaluation = (((int64_t) time_benefit * factor)
/ size_cost);
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index f0bc2501c27..9781acd0766 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -1602,62 +1602,6 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
return false;
}
- if ((TYPE_MAIN_VARIANT (t1) == t1 || TYPE_MAIN_VARIANT (t2) == t2)
- && COMPLETE_TYPE_P (TYPE_MAIN_VARIANT (t1))
- && COMPLETE_TYPE_P (TYPE_MAIN_VARIANT (t2))
- && odr_type_p (TYPE_MAIN_VARIANT (t1))
- && odr_type_p (TYPE_MAIN_VARIANT (t2))
- && (TYPE_METHODS (TYPE_MAIN_VARIANT (t1))
- != TYPE_METHODS (TYPE_MAIN_VARIANT (t2))))
- {
- /* Currently free_lang_data sets TYPE_METHODS to error_mark_node
- if it is non-NULL so this loop will never realy execute. */
- if (TYPE_METHODS (TYPE_MAIN_VARIANT (t1)) != error_mark_node
- && TYPE_METHODS (TYPE_MAIN_VARIANT (t2)) != error_mark_node)
- for (f1 = TYPE_METHODS (TYPE_MAIN_VARIANT (t1)),
- f2 = TYPE_METHODS (TYPE_MAIN_VARIANT (t2));
- f1 && f2 ; f1 = DECL_CHAIN (f1), f2 = DECL_CHAIN (f2))
- {
- if (DECL_ASSEMBLER_NAME (f1) != DECL_ASSEMBLER_NAME (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("a different method of same type "
- "is defined in another "
- "translation unit"));
- return false;
- }
- if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("a definition that differs by virtual "
- "keyword in another translation unit"));
- return false;
- }
- if (DECL_VINDEX (f1) != DECL_VINDEX (f2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("virtual table layout differs "
- "in another translation unit"));
- return false;
- }
- if (odr_subtypes_equivalent_p (TREE_TYPE (f1),
- TREE_TYPE (f2), visited,
- loc1, loc2))
- {
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("method with incompatible type is "
- "defined in another translation unit"));
- return false;
- }
- }
- if ((f1 == NULL) != (f2 == NULL))
- {
- warn_odr (t1, t2, NULL, NULL, warn, warned,
- G_("a type with different number of methods "
- "is defined in another translation unit"));
- return false;
- }
- }
}
break;
}
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 878f9a891f3..27e8d73f9df 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -3176,20 +3176,16 @@ ipa_fn_summary_generate (void)
if (DECL_STRUCT_FUNCTION (node->decl))
node->local.versionable = tree_versionable_function_p (node->decl);
- /* When not optimizing, do not bother to analyze. Inlining is still done
- because edge redirection needs to happen there. */
- if (!optimize && !flag_generate_lto && !flag_generate_offload && !flag_wpa)
- return;
-
ipa_fn_summary_alloc ();
ipa_fn_summaries->enable_insertion_hook ();
ipa_register_cgraph_hooks ();
- ipa_free_fn_summary ();
FOR_EACH_DEFINED_FUNCTION (node)
- if (!node->alias)
+ if (!node->alias
+ && (flag_generate_lto || flag_generate_offload|| flag_wpa
+ || opt_for_fn (node->decl, optimize)))
inline_analyze_function (node);
}
@@ -3342,12 +3338,9 @@ ipa_fn_summary_read (void)
fatal_error (input_location,
"ipa inline summary is missing in input file");
}
- if (optimize)
- {
- ipa_register_cgraph_hooks ();
- if (!flag_ipa_cp)
- ipa_prop_read_jump_functions ();
- }
+ ipa_register_cgraph_hooks ();
+ if (!flag_ipa_cp)
+ ipa_prop_read_jump_functions ();
gcc_assert (ipa_fn_summaries);
ipa_fn_summaries->enable_insertion_hook ();
@@ -3462,7 +3455,7 @@ ipa_fn_summary_write (void)
produce_asm (ob, NULL);
destroy_output_block (ob);
- if (optimize && !flag_ipa_cp)
+ if (!flag_ipa_cp)
ipa_prop_write_jump_functions ();
}
@@ -3577,7 +3570,7 @@ const pass_data pass_data_ipa_fn_summary =
IPA_PASS, /* type */
"fnsummary", /* name */
OPTGROUP_INLINE, /* optinfo_flags */
- TV_IPA_INLINING, /* tv_id */
+ TV_IPA_FNSUMMARY, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 1d79ec41097..38f3d2e762a 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -326,7 +326,8 @@ do_estimate_growth_1 (struct cgraph_node *node, void *data)
{
gcc_checking_assert (e->inline_failed);
- if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+ if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR
+ || !opt_for_fn (e->caller->decl, optimize))
{
d->uninlinable = true;
continue;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index fb20d3723cc..608db8f8857 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -322,6 +322,11 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
inlinable = false;
}
+ if (!early && !opt_for_fn (callee->decl, optimize))
+ {
+ e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
+ inlinable = false;
+ }
else if (callee->calls_comdat_local)
{
e->inline_failed = CIF_USES_COMDAT_LOCAL;
@@ -402,6 +407,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
Not even for always_inline declared functions. */
else if (check_match (flag_wrapv)
|| check_match (flag_trapv)
+ || check_match (flag_pcc_struct_return)
/* When caller or callee does FP math, be sure FP codegen flags
compatible. */
|| ((caller_info->fp_expressions && callee_info->fp_expressions)
@@ -939,7 +945,8 @@ check_callers (struct cgraph_node *node, void *has_hot_call)
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
{
- if (!opt_for_fn (e->caller->decl, flag_inline_functions_called_once))
+ if (!opt_for_fn (e->caller->decl, flag_inline_functions_called_once)
+ || !opt_for_fn (e->caller->decl, optimize))
return true;
if (!can_inline_edge_p (e, true))
return true;
@@ -1746,7 +1753,8 @@ inline_small_functions (void)
if (!node->global.inlined_to)
{
if (!node->alias && node->analyzed
- && (node->has_gimple_body_p () || node->thunk.thunk_p))
+ && (node->has_gimple_body_p () || node->thunk.thunk_p)
+ && opt_for_fn (node->decl, optimize))
{
struct ipa_fn_summary *info = ipa_fn_summaries->get (node);
struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux;
@@ -1768,12 +1776,13 @@ inline_small_functions (void)
int id = dfs->scc_no + 1;
for (n2 = node; n2;
n2 = ((struct ipa_dfs_info *) node->aux)->next_cycle)
- {
- struct ipa_fn_summary *info2 = ipa_fn_summaries->get (n2);
- if (info2->scc_no)
- break;
- info2->scc_no = id;
- }
+ if (opt_for_fn (n2->decl, optimize))
+ {
+ struct ipa_fn_summary *info2 = ipa_fn_summaries->get (n2);
+ if (info2->scc_no)
+ break;
+ info2->scc_no = id;
+ }
}
}
@@ -1801,6 +1810,9 @@ inline_small_functions (void)
struct cgraph_edge *next = NULL;
bool has_speculative = false;
+ if (!opt_for_fn (node->decl, optimize))
+ continue;
+
if (dump_file)
fprintf (dump_file, "Enqueueing calls in %s.\n", node->dump_name ());
@@ -2048,8 +2060,8 @@ inline_small_functions (void)
fprintf (dump_file,
" Inlined %s into %s which now has time %f and size %i, "
"net change of %+i.\n",
- edge->callee->name (),
- edge->caller->name (),
+ xstrdup_for_dump (edge->callee->name ()),
+ xstrdup_for_dump (edge->caller->name ()),
ipa_fn_summaries->get (edge->caller)->time.to_double (),
ipa_fn_summaries->get (edge->caller)->size,
overall_size - old_size);
@@ -2369,9 +2381,6 @@ ipa_inline (void)
int cold;
bool remove_functions = false;
- if (!optimize)
- return 0;
-
cgraph_freq_base_rec = (sreal) 1 / (sreal) CGRAPH_FREQ_BASE;
percent_rec = (sreal) 1 / (sreal) 100;
@@ -2467,6 +2476,10 @@ ipa_inline (void)
struct cgraph_edge *edge, *next;
bool update=false;
+ if (!opt_for_fn (node->decl, optimize)
+ || !opt_for_fn (node->decl, flag_inline_functions_called_once))
+ continue;
+
for (edge = node->callees; edge; edge = next)
{
next = edge->next_callee;
@@ -2499,8 +2512,7 @@ ipa_inline (void)
}
/* Free ipa-prop structures if they are no longer needed. */
- if (optimize)
- ipa_free_all_structures_after_iinln ();
+ ipa_free_all_structures_after_iinln ();
if (dump_file)
{
diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h
index 54c1ed97d57..4b9a1c2191a 100644
--- a/gcc/ipa-inline.h
+++ b/gcc/ipa-inline.h
@@ -28,6 +28,14 @@ struct edge_growth_cache_entry
sreal time, nonspec_time;
int size;
ipa_hints hints;
+
+ edge_growth_cache_entry()
+ : size (0), hints (0) {}
+
+ edge_growth_cache_entry(int64_t time, int64_t nonspec_time,
+ int size, ipa_hints hints)
+ : time (time), nonspec_time (nonspec_time), size (size),
+ hints (hints) {}
};
extern vec<edge_growth_cache_entry> edge_growth_cache;
@@ -116,7 +124,7 @@ reset_edge_growth_cache (struct cgraph_edge *edge)
{
if ((int)edge_growth_cache.length () > edge->uid)
{
- struct edge_growth_cache_entry zero = {0, 0, 0, 0};
+ struct edge_growth_cache_entry zero (0, 0, 0, 0);
edge_growth_cache[edge->uid] = zero;
}
}
diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c
index 6b9f82138dc..9ac5153bf67 100644
--- a/gcc/ipa-polymorphic-call.c
+++ b/gcc/ipa-polymorphic-call.c
@@ -921,9 +921,13 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
and MEM_REF is meaningless, but we can look futher. */
if (TREE_CODE (base) == MEM_REF)
{
+ offset_int o = mem_ref_offset (base) * BITS_PER_UNIT;
+ o += offset;
+ o += offset2;
+ if (!wi::fits_shwi_p (o))
+ break;
base_pointer = TREE_OPERAND (base, 0);
- offset
- += offset2 + mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
+ offset = o.to_shwi ();
outer_type = NULL;
}
/* We found base object. In this case the outer_type
@@ -961,10 +965,15 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
break;
}
else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
- && tree_fits_uhwi_p (TREE_OPERAND (base_pointer, 1)))
+ && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
{
- offset += tree_to_shwi (TREE_OPERAND (base_pointer, 1))
- * BITS_PER_UNIT;
+ offset_int o = offset_int::from (TREE_OPERAND (base_pointer, 1),
+ SIGNED);
+ o *= BITS_PER_UNIT;
+ o += offset;
+ if (!wi::fits_shwi_p (o))
+ break;
+ offset = o.to_shwi ();
base_pointer = TREE_OPERAND (base_pointer, 0);
}
else
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 0af31d68353..e3759d6c50e 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1292,9 +1292,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
break;
}
}
- e = make_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- e->count = new_return_bb->count;
+ e = make_single_succ_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
add_bb_to_loop (new_return_bb, current_loops->tree_root);
bitmap_set_bit (split_point->split_bbs, new_return_bb->index);
retbnd = find_retbnd (return_bb);
@@ -1527,11 +1525,9 @@ split_function (basic_block return_bb, struct split_point *split_point,
}
else
{
- e = make_edge (call_bb, return_bb,
- return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
- ? 0 : EDGE_FALLTHRU);
- e->count = call_bb->count;
- e->probability = REG_BR_PROB_BASE;
+ e = make_single_succ_edge (call_bb, return_bb,
+ return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+ ? 0 : EDGE_FALLTHRU);
/* If there is return basic block, see what value we need to store
return value into and put call just before it. */
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 73151248234..708710d6135 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -404,14 +404,17 @@ ipa_merge_profiles (struct cgraph_node *dst,
/* FIXME when we merge in unknown profile, we ought to set counts as
unsafe. */
- if (!dst->count.initialized_p ())
+ if (!src->count.initialized_p ())
return;
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "Merging profiles of %s to %s\n",
src->dump_name (), dst->dump_name ());
}
- dst->count += src->count;
+ if (dst->count.initialized_p ())
+ dst->count += src->count;
+ else
+ dst->count = src->count;
/* This is ugly. We need to get both function bodies into memory.
If declaration is merged, we need to duplicate it to be able
@@ -521,12 +524,20 @@ ipa_merge_profiles (struct cgraph_node *dst,
unsigned int i;
dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
- dstbb->count += srcbb->count;
+ if (dstbb->count.initialized_p ())
+ dstbb->count += srcbb->count;
+ else
+ dstbb->count = srcbb->count;
for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
{
edge srce = EDGE_SUCC (srcbb, i);
edge dste = EDGE_SUCC (dstbb, i);
- dste->count += srce->count;
+ if (dstbb->count.initialized_p ())
+ dste->count += srce->count;
+ else
+ dste->count = srce->count;
+ if (dstbb->count > 0 && dste->count.initialized_p ())
+ dste->probability = dste->count.probability_in (dstbb->count);
}
}
push_cfun (dstcfun);
@@ -598,7 +609,8 @@ ipa_merge_profiles (struct cgraph_node *dst,
}
}
int prob = direct->count.probability_in (direct->count
- + indirect->count);
+ + indirect->count).
+ to_reg_br_prob_base ();
direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE);
indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob),
REG_BR_PROB_BASE);
@@ -616,7 +628,8 @@ ipa_merge_profiles (struct cgraph_node *dst,
e2->speculative_call_info (direct, indirect, ref);
e->count = count;
e->frequency = freq;
- int prob = direct->count.probability_in (e->count);
+ int prob = direct->count.probability_in (e->count)
+ .to_reg_br_prob_base ();
e->make_speculative (direct->callee, direct->count,
RDIV (freq * prob, REG_BR_PROB_BASE));
}
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index e992f65948b..f061c84c8a9 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -169,9 +169,6 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
inline bool
polymorphic_type_binfo_p (const_tree binfo)
{
- /* See if BINFO's type has an virtual table associtated with it.
- Check is defensive because of Java FE produces BINFOs
- without BINFO_TYPE set. */
return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
&& BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
}
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index d5a3ae56c46..3033f20e3f1 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "calls.h"
#include "varasm.h"
+#include "ipa-utils.h"
/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
@@ -91,13 +92,15 @@ non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
return !(node->only_called_directly_or_aliased_p ()
/* i386 would need update to output thunk with local calling
- convetions. */
+ conventions. */
&& !node->thunk.thunk_p
&& node->definition
&& !DECL_EXTERNAL (node->decl)
+ && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))
&& !node->externally_visible
&& !node->used_from_other_partition
- && !node->in_other_partition);
+ && !node->in_other_partition
+ && node->get_availability () >= AVAIL_AVAILABLE);
}
/* Return true when function can be marked local. */
@@ -209,6 +212,8 @@ cgraph_externally_visible_p (struct cgraph_node *node,
if (lookup_attribute ("externally_visible",
DECL_ATTRIBUTES (node->decl)))
return true;
+ if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
+ return true;
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& lookup_attribute ("dllexport",
DECL_ATTRIBUTES (node->decl)))
@@ -613,17 +618,53 @@ function_and_variable_visibility (bool whole_program)
struct cgraph_node *node;
varpool_node *vnode;
- /* All aliases should be procssed at this point. */
+ /* All aliases should be processed at this point. */
gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
+#ifdef ASM_OUTPUT_DEF
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ if (node->get_availability () != AVAIL_INTERPOSABLE
+ || DECL_EXTERNAL (node->decl)
+ || node->has_aliases_p ())
+ continue;
+
+ cgraph_node *alias = 0;
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ /* Recursive function calls usually can't be interposed. */
+
+ if (!e->recursive_p ())
+ continue;
+
+ if (!alias)
+ {
+ alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
+ gcc_assert (alias && alias != node);
+ }
+
+ e->redirect_callee (alias);
+ if (gimple_has_body_p (e->caller->decl))
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+ e->redirect_call_stmt_to_callee ();
+ pop_cfun ();
+ }
+ }
+ }
+#endif
+
FOR_EACH_FUNCTION (node)
{
int flags = flags_from_decl_or_type (node->decl);
/* Optimize away PURE and CONST constructors and destructors. */
- if (optimize
+ if (node->analyzed
+ && (DECL_STATIC_CONSTRUCTOR (node->decl)
+ || DECL_STATIC_DESTRUCTOR (node->decl))
&& (flags & (ECF_CONST | ECF_PURE))
- && !(flags & ECF_LOOPING_CONST_OR_PURE))
+ && !(flags & ECF_LOOPING_CONST_OR_PURE)
+ && opt_for_fn (node->decl, optimize))
{
DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
DECL_STATIC_DESTRUCTOR (node->decl) = 0;
@@ -875,7 +916,7 @@ static unsigned int
whole_program_function_and_variable_visibility (void)
{
function_and_variable_visibility (flag_whole_program);
- if (optimize)
+ if (optimize || in_lto_p)
ipa_discover_readonly_nonaddressable_vars ();
return 0;
}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 3dc8e41a7ff..00cd3084f66 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -118,8 +118,7 @@ process_references (symtab_node *snode,
if (node->definition && !node->in_other_partition
&& ((!DECL_EXTERNAL (node->decl) || node->alias)
|| (((before_inlining_p
- && ((TREE_CODE (node->decl) != FUNCTION_DECL
- && optimize)
+ && (TREE_CODE (node->decl) != FUNCTION_DECL
|| (TREE_CODE (node->decl) == FUNCTION_DECL
&& opt_for_fn (body->decl, optimize))
|| (symtab->state < IPA_SSA
@@ -312,7 +311,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
hash_set<symtab_node *> reachable;
hash_set<tree> body_needed_for_clonning;
hash_set<void *> reachable_call_targets;
- bool before_inlining_p = symtab->state < (!optimize ? IPA_SSA
+ bool before_inlining_p = symtab->state < (!optimize && !in_lto_p ? IPA_SSA
: IPA_SSA_AFTER_INLINING);
timevar_push (TV_IPA_UNREACHABLE);
@@ -696,7 +695,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
symtab_node::checking_verify_symtab_nodes ();
/* If we removed something, perhaps profile could be improved. */
- if (changed && optimize && ipa_call_summaries)
+ if (changed && (optimize || in_lto_p) && ipa_call_summaries)
FOR_EACH_DEFINED_FUNCTION (node)
ipa_propagate_frequency (node);
@@ -757,7 +756,7 @@ bool
set_writeonly_bit (varpool_node *vnode, void *data)
{
vnode->writeonly = true;
- if (optimize)
+ if (optimize || in_lto_p)
{
DECL_INITIAL (vnode->decl) = NULL;
if (!vnode->alias)
@@ -1175,7 +1174,7 @@ pass_ipa_cdtor_merge::gate (function *)
/* Perform the pass when we have no ctors/dtors support
or at LTO time to merge multiple constructors into single
function. */
- return !targetm.have_ctors_dtors || (optimize && in_lto_p);
+ return !targetm.have_ctors_dtors || in_lto_p;
}
} // anon namespace
@@ -1387,17 +1386,10 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *);
virtual unsigned int execute (function *) { return ipa_single_use (); }
}; // class pass_ipa_single_use
-bool
-pass_ipa_single_use::gate (function *)
-{
- return optimize;
-}
-
} // anon namespace
ipa_opt_pass_d *
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 698458eb638..f08bf37b4c5 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -2745,7 +2745,7 @@ static int
allocno_copy_cost_saving (ira_allocno_t allocno, int hard_regno)
{
int cost = 0;
- enum machine_mode allocno_mode = ALLOCNO_MODE (allocno);
+ machine_mode allocno_mode = ALLOCNO_MODE (allocno);
enum reg_class rclass;
ira_copy_t cp, next_cp;
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index dc7dda604d0..8fd2fd43dc0 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,10 @@
+2017-07-05 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * dummy-frontend.c (jit_langhook_type_for_mode): Remove "enum" before
+ "machine_mode".
+
2017-04-24 David Malcolm <dmalcolm@redhat.com>
* docs/cp/topics/types.rst (gccjit::type::get_const): Remove
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 87f583f68c2..d7d21728358 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -163,7 +163,7 @@ jit_langhook_parse_file (void)
}
static tree
-jit_langhook_type_for_mode (enum machine_mode mode, int unsignedp)
+jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
{
if (mode == TYPE_MODE (float_type_node))
return float_type_node;
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index b2f0f922b89..88f6f71b559 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -293,7 +293,7 @@ struct lang_hooks_for_lto
struct lang_hooks
{
/* String identifying the front end and optionally language standard
- version, e.g. "GNU C++98" or "GNU Java". */
+ version, e.g. "GNU C++98". */
const char *name;
/* sizeof (struct lang_identifier), so make_node () creates
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 05daabb22fb..49861b8e362 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -347,6 +347,8 @@ add_test (rtx cond, edge *e, basic_block dest)
rtx op0 = XEXP (cond, 0), op1 = XEXP (cond, 1);
enum rtx_code code = GET_CODE (cond);
basic_block bb;
+ /* The jump is supposed to handle an unlikely special case. */
+ profile_probability prob = profile_probability::guessed_never ();
mode = GET_MODE (XEXP (cond, 0));
if (mode == VOIDmode)
@@ -356,7 +358,8 @@ add_test (rtx cond, edge *e, basic_block dest)
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
label = block_label (dest);
- do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label, -1);
+ do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label,
+ prob);
jump = get_last_insn ();
if (!jump || !JUMP_P (jump))
@@ -386,12 +389,14 @@ add_test (rtx cond, edge *e, basic_block dest)
JUMP_LABEL (jump) = label;
- /* The jump is supposed to handle an unlikely special case. */
- add_int_reg_note (jump, REG_BR_PROB, 0);
-
LABEL_NUSES (label)++;
- make_edge (bb, dest, (*e)->flags & ~EDGE_FALLTHRU);
+ edge e2 = make_edge (bb, dest, (*e)->flags & ~EDGE_FALLTHRU);
+ e2->probability = prob;
+ e2->count = e2->src->count.apply_probability (prob);
+ (*e)->probability = prob.invert ();
+ (*e)->count = (*e)->count.apply_probability (prob);
+ update_br_prob_note (e2->src);
return true;
}
@@ -414,7 +419,6 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
bool increment_count;
basic_block loop_end = desc->out_edge->src;
machine_mode mode;
- rtx true_prob_val;
widest_int iterations;
jump_insn = BB_END (loop_end);
@@ -429,10 +433,6 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
fputs (" iterations).\n", dump_file);
}
- /* Get the probability of the original branch. If it exists we would
- need to update REG_BR_PROB of the new jump_insn. */
- true_prob_val = find_reg_note (jump_insn, REG_BR_PROB, NULL_RTX);
-
/* Discard original jump to continue loop. The original compare
result may still be live, so it cannot be discarded explicitly. */
delete_insn (jump_insn);
@@ -575,11 +575,8 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
add_reg_note (jump_insn, REG_NONNEG, NULL_RTX);
/* Update the REG_BR_PROB note. */
- if (true_prob_val)
- {
- /* Seems safer to use the branch probability. */
- add_int_reg_note (jump_insn, REG_BR_PROB, desc->in_edge->probability);
- }
+ if (desc->in_edge->probability.initialized_p ())
+ add_reg_br_prob_note (jump_insn, desc->in_edge->probability);
}
/* Called through note_stores. */
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index e39766c2a79..84145bb4a4f 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -774,7 +774,8 @@ split_edge_and_insert (edge e, rtx_insn *insns)
static rtx_insn *
compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp,
- rtx_code_label *label, int prob, rtx_insn *cinsn)
+ rtx_code_label *label, profile_probability prob,
+ rtx_insn *cinsn)
{
rtx_insn *seq;
rtx_jump_insn *jump;
@@ -808,12 +809,14 @@ compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp,
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
do_compare_rtx_and_jump (op0, op1, comp, 0,
- mode, NULL_RTX, NULL, label, -1);
+ mode, NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
jump = as_a <rtx_jump_insn *> (get_last_insn ());
jump->set_jump_target (label);
LABEL_NUSES (label)++;
}
- add_int_reg_note (jump, REG_BR_PROB, prob);
+ if (prob.initialized_p ())
+ add_reg_br_prob_note (jump, prob);
seq = get_insns ();
end_sequence ();
@@ -857,7 +860,8 @@ unroll_loop_runtime_iterations (struct loop *loop)
{
rtx old_niter, niter, tmp;
rtx_insn *init_code, *branch_code;
- unsigned i, j, p;
+ unsigned i, j;
+ profile_probability p;
basic_block preheader, *body, swtch, ezc_swtch = NULL;
int may_exit_copy, iter_freq, new_freq;
profile_count iter_count, new_count;
@@ -989,7 +993,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
/* Create item for switch. */
j = n_peel - i - (extra_zero_check ? 0 : 1);
- p = REG_BR_PROB_BASE / (i + 2);
+ p = profile_probability::always ().apply_scale (1, i + 2);
preheader = split_edge (loop_preheader_edge (loop));
/* Add in frequency/count of edge from switch block. */
@@ -1006,7 +1010,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
swtch = split_edge_and_insert (single_pred_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
- single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
+ single_succ_edge (swtch)->probability = p.invert ();
single_succ_edge (swtch)->count = new_count;
new_freq += iter_freq;
new_count += iter_count;
@@ -1021,7 +1025,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
if (extra_zero_check)
{
/* Add branch for zero iterations. */
- p = REG_BR_PROB_BASE / (max_unroll + 1);
+ p = profile_probability::always ().apply_scale (1, max_unroll + 1);
swtch = ezc_swtch;
preheader = split_edge (loop_preheader_edge (loop));
/* Recompute frequency/count adjustments since initial peel copy may
@@ -1039,7 +1043,7 @@ unroll_loop_runtime_iterations (struct loop *loop)
swtch = split_edge_and_insert (single_succ_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
- single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
+ single_succ_edge (swtch)->probability = p.invert ();
single_succ_edge (swtch)->count -= iter_count;
e = make_edge (swtch, preheader,
single_succ_edge (swtch)->flags & EDGE_IRREDUCIBLE_LOOP);
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index e4cc43ac820..2aadeefb214 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -253,10 +253,9 @@ pseudo_compare_func (const void *v1p, const void *v2p)
/* Assign hard reg to static chain pointer first pseudo when
non-local goto is used. */
- if (non_spilled_static_chain_regno_p (r1))
- return -1;
- else if (non_spilled_static_chain_regno_p (r2))
- return 1;
+ if ((diff = (non_spilled_static_chain_regno_p (r2)
+ - non_spilled_static_chain_regno_p (r1))) != 0)
+ return diff;
/* Prefer to assign more frequently used registers first. */
if ((diff = lra_reg_info[r2].freq - lra_reg_info[r1].freq) != 0)
@@ -585,7 +584,7 @@ find_hard_regno_for_1 (int regno, int *cost, int try_only_hard_regno,
}
else
{
- enum machine_mode biggest_conflict_mode
+ machine_mode biggest_conflict_mode
= lra_reg_info[conflict_regno].biggest_mode;
int biggest_conflict_nregs
= hard_regno_nregs[conflict_hr][biggest_conflict_mode];
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index a41a578c965..13d2bf2e0a1 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1841,7 +1841,7 @@ reg_in_class_p (rtx reg, enum reg_class cl)
static bool
prohibited_class_reg_set_mode_p (enum reg_class rclass,
HARD_REG_SET &set,
- enum machine_mode mode)
+ machine_mode mode)
{
HARD_REG_SET temp;
@@ -5729,7 +5729,7 @@ process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx)
int insn_regno;
bool succ_p = false;
int dst_regno = REGNO (dst_reg);
- enum machine_mode dst_mode = GET_MODE (dst_reg);
+ machine_mode dst_mode = GET_MODE (dst_reg);
enum reg_class cl = lra_get_allocno_class (dst_regno), insn_reg_cl;
invariant_ptr = insert_invariant (invariant_rtx);
@@ -6486,7 +6486,8 @@ lra_inheritance (void)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability < EBB_PROBABILITY_CUTOFF)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () < EBB_PROBABILITY_CUTOFF)
break;
bb = bb->next_bb;
}
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index ab51b673826..900e4d462b9 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -279,7 +279,7 @@ static rtx
move_plus_up (rtx x)
{
rtx subreg_reg;
- enum machine_mode x_mode, subreg_reg_mode;
+ machine_mode x_mode, subreg_reg_mode;
if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
return x;
diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c
index 9618bfb318f..641b2795b2c 100644
--- a/gcc/lto-opts.c
+++ b/gcc/lto-opts.c
@@ -108,8 +108,8 @@ lto_write_options (void)
gcc_unreachable ();
}
/* The default -fmath-errno, -fsigned-zeros and -ftrapping-math change
- depending on the language (they can be disabled by the Ada and Java
- front-ends). Pass thru conservative standard settings. */
+ depending on the language (they can be disabled by the Ada front-end).
+ Pass thru conservative standard settings. */
if (!global_options_set.x_flag_errno_math)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
global_options.x_flag_errno_math
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index ccc8cf602df..5710e8f126d 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -754,12 +754,12 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
unsigned int dest_index;
unsigned int edge_flags;
basic_block dest;
- int probability;
+ profile_probability probability;
profile_count count;
edge e;
dest_index = streamer_read_uhwi (ib);
- probability = (int) streamer_read_hwi (ib);
+ probability = profile_probability::stream_in (ib);
count = profile_count::stream_in (ib).apply_scale
(count_materialization_scale, REG_BR_PROB_BASE);
edge_flags = streamer_read_uhwi (ib);
@@ -1143,6 +1143,10 @@ input_function (tree fn_decl, struct data_in *data_in,
if ((flag_sanitize & SANITIZE_OBJECT_SIZE) == 0)
remove = true;
break;
+ case IFN_UBSAN_PTR:
+ if ((flag_sanitize & SANITIZE_POINTER_OVERFLOW) == 0)
+ remove = true;
+ break;
case IFN_ASAN_MARK:
if ((flag_sanitize & SANITIZE_ADDRESS) == 0)
remove = true;
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 9378d5cf7b4..41fba318cb5 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -835,8 +835,8 @@ DFS::DFS_write_tree_body (struct output_block *ob,
DFS_follow_tree_edge (TYPE_ARG_TYPES (expr));
if (!POINTER_TYPE_P (expr))
- DFS_follow_tree_edge (TYPE_MINVAL (expr));
- DFS_follow_tree_edge (TYPE_MAXVAL (expr));
+ DFS_follow_tree_edge (TYPE_MIN_VALUE_RAW (expr));
+ DFS_follow_tree_edge (TYPE_MAX_VALUE_RAW (expr));
if (RECORD_OR_UNION_TYPE_P (expr))
DFS_follow_tree_edge (TYPE_BINFO (expr));
}
@@ -1271,8 +1271,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
|| code == METHOD_TYPE)
visit (TYPE_ARG_TYPES (t));
if (!POINTER_TYPE_P (t))
- visit (TYPE_MINVAL (t));
- visit (TYPE_MAXVAL (t));
+ visit (TYPE_MIN_VALUE_RAW (t));
+ visit (TYPE_MAX_VALUE_RAW (t));
if (RECORD_OR_UNION_TYPE_P (t))
visit (TYPE_BINFO (t));
}
@@ -1860,7 +1860,7 @@ output_cfg (struct output_block *ob, struct function *fn)
FOR_EACH_EDGE (e, ei, bb->succs)
{
streamer_write_uhwi (ob, e->dest->index);
- streamer_write_hwi (ob, e->probability);
+ e->probability.stream_out (ob);
e->count.stream_out (ob);
streamer_write_uhwi (ob, e->flags);
}
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 4b86f939ca2..5e75a4fa48c 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -192,6 +192,20 @@ append_option (struct cl_decoded_option **decoded_options,
sizeof (struct cl_decoded_option));
}
+/* Remove option number INDEX from DECODED_OPTIONS, update
+ DECODED_OPTIONS_COUNT. */
+
+static void
+remove_option (struct cl_decoded_option **decoded_options,
+ int index, unsigned int *decoded_options_count)
+{
+ --*decoded_options_count;
+ memmove (&(*decoded_options)[index + 1],
+ &(*decoded_options)[index],
+ sizeof (struct cl_decoded_option)
+ * (*decoded_options_count - index));
+}
+
/* Try to merge and complain about options FDECODED_OPTIONS when applied
ontop of DECODED_OPTIONS. */
@@ -202,6 +216,8 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
unsigned int fdecoded_options_count)
{
unsigned int i, j;
+ struct cl_decoded_option *pic_option = NULL;
+ struct cl_decoded_option *pie_option = NULL;
/* ??? Merge options from files. Most cases can be
handled by either unioning or intersecting
@@ -238,13 +254,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
case OPT_fshow_column:
- case OPT_fPIC:
- case OPT_fpic:
- case OPT_fPIE:
- case OPT_fpie:
case OPT_fcommon:
- case OPT_fexceptions:
- case OPT_fnon_call_exceptions:
case OPT_fgnu_tm:
/* Do what the old LTO code did - collect exactly one option
setting per OPT code, we pick the first we encounter.
@@ -257,25 +267,16 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
append_option (decoded_options, decoded_options_count, foption);
break;
- case OPT_ftrapv:
- case OPT_ffp_contract_:
- /* For selected options we can merge conservatively. */
- for (j = 0; j < *decoded_options_count; ++j)
- if ((*decoded_options)[j].opt_index == foption->opt_index)
- break;
- if (j == *decoded_options_count)
- append_option (decoded_options, decoded_options_count, foption);
- /* FP_CONTRACT_OFF < FP_CONTRACT_ON < FP_CONTRACT_FAST,
- -fno-trapv < -ftrapv,
- -fno-strict-overflow < -fstrict-overflow */
- else if (foption->value < (*decoded_options)[j].value)
- (*decoded_options)[j] = *foption;
+ /* Figure out what PIC/PIE level wins and merge the results. */
+ case OPT_fPIC:
+ case OPT_fpic:
+ pic_option = foption;
+ break;
+ case OPT_fPIE:
+ case OPT_fpie:
+ pie_option = foption;
break;
- case OPT_fmath_errno:
- case OPT_fsigned_zeros:
- case OPT_ftrapping_math:
- case OPT_fwrapv:
case OPT_fopenmp:
case OPT_fopenacc:
case OPT_fcilkplus:
@@ -286,10 +287,10 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
break;
if (j == *decoded_options_count)
append_option (decoded_options, decoded_options_count, foption);
- /* -fmath-errno > -fno-math-errno,
- -fsigned-zeros > -fno-signed-zeros,
- -ftrapping-math > -fno-trapping-math,
- -fwrapv > -fno-wrapv. */
+ /* -fopenmp > -fno-openmp,
+ -fopenacc > -fno-openacc,
+ -fcilkplus > -fno-cilkplus,
+ -fcheck_pointer_bounds > -fcheck_pointer_bounds */
else if (foption->value > (*decoded_options)[j].value)
(*decoded_options)[j] = *foption;
break;
@@ -307,29 +308,6 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
foption->orig_option_with_args_text);
break;
- case OPT_freg_struct_return:
- case OPT_fpcc_struct_return:
- for (j = 0; j < *decoded_options_count; ++j)
- if ((*decoded_options)[j].opt_index == foption->opt_index)
- break;
- if (j == *decoded_options_count)
- fatal_error (input_location,
- "Option %s not used consistently in all LTO input"
- " files", foption->orig_option_with_args_text);
- break;
-
- case OPT_foffload_abi_:
- for (j = 0; j < *decoded_options_count; ++j)
- if ((*decoded_options)[j].opt_index == foption->opt_index)
- break;
- if (j == *decoded_options_count)
- append_option (decoded_options, decoded_options_count, foption);
- else if (foption->value != (*decoded_options)[j].value)
- fatal_error (input_location,
- "Option %s not used consistently in all LTO input"
- " files", foption->orig_option_with_args_text);
- break;
-
case OPT_O:
case OPT_Ofast:
case OPT_Og:
@@ -400,12 +378,70 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
(*decoded_options)[j].value = 1;
}
break;
+
+
+ case OPT_foffload_abi_:
+ for (j = 0; j < *decoded_options_count; ++j)
+ if ((*decoded_options)[j].opt_index == foption->opt_index)
+ break;
+ if (j == *decoded_options_count)
+ append_option (decoded_options, decoded_options_count, foption);
+ else if (foption->value != (*decoded_options)[j].value)
+ fatal_error (input_location,
+ "Option %s not used consistently in all LTO input"
+ " files", foption->orig_option_with_args_text);
+ break;
+
case OPT_foffload_:
append_option (decoded_options, decoded_options_count, foption);
break;
}
}
+
+ /* Merge PIC options:
+ -fPIC + -fpic = -fpic
+ -fPIC + -fno-pic = -fno-pic
+ -fpic/-fPIC + nothin = nothing.
+ 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.
+
+ It would be good to warn on mismatches, but it is bit hard to do as
+ we do not know what nothing translates to. */
+
+ for (unsigned int j = 0; j < *decoded_options_count;)
+ 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)
+ {
+ (*decoded_options)[j] = *pic_option;
+ j++;
+ }
+ else
+ j++;
+ }
+ 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)
+ {
+ (*decoded_options)[j] = *pie_option;
+ j++;
+ }
+ else
+ j++;
+ }
+ else
+ j++;
}
/* Auxiliary function that frees elements of PTR and PTR itself.
@@ -506,21 +542,11 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
case OPT_fPIE:
case OPT_fpie:
case OPT_fcommon:
- case OPT_fexceptions:
- case OPT_fnon_call_exceptions:
case OPT_fgnu_tm:
- case OPT_freg_struct_return:
- case OPT_fpcc_struct_return:
- case OPT_ffp_contract_:
- case OPT_fmath_errno:
- case OPT_fsigned_zeros:
- case OPT_ftrapping_math:
- case OPT_fwrapv:
case OPT_fopenmp:
case OPT_fopenacc:
case OPT_fopenacc_dim_:
case OPT_fcilkplus:
- case OPT_ftrapv:
case OPT_foffload_abi_:
case OPT_O:
case OPT_Ofast:
@@ -595,12 +621,6 @@ append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
/* We've handled these LTO options, do not pass them on. */
continue;
- case OPT_freg_struct_return:
- case OPT_fpcc_struct_return:
- /* Ignore these, they are determined by the input files.
- ??? We fail to diagnose a possible mismatch here. */
- continue;
-
case OPT_fopenmp:
case OPT_fopenacc:
case OPT_fcilkplus:
@@ -838,6 +858,8 @@ copy_file (const char *dest, const char *src)
fatal_error (input_location, "writing output file");
}
}
+ fclose (d);
+ fclose (s);
}
/* Find the crtoffloadtable.o file in LIBRARY_PATH, make copy and pass name of
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 41f034372d9..cfe8178b887 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,5 +1,19 @@
-2017-06-23 Marc Glisse <marc.glisse@inria.fr>
+2017-07-07 Torsten Duwe <duwe@suse.de>
+
+ * lto-lang.c (lto_attribute_table): Add entry for
+ "patchable_function_entry".
+
+2017-07-19 Nathan Sidwell <nathan@acm.org>
+
+ * lto.c (mentions_vars_p_type): Use TYPE_{MIN,MAX}_VALUE_RAW.
+ (compare_tree_sccs_1, lto_fixup_prevailing_decls): Likewise.
+2017-07-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-partition.c (lto_balanced_map): Do not check
+ flag_toplevel_reorder.
+
+2017-06-23 Marc Glisse <marc.glisse@inria.fr>
* lto-lang.c (lto_init): Use builtin_structptr_types.
2017-06-15 Jan Hubicka <hubicka@ucw.cz>
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 58935172b2c..6e9a138fa3b 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -48,6 +48,8 @@ static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
+ int, bool *);
static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_format_attribute (tree *, tree, tree, int, bool *);
@@ -76,6 +78,9 @@ const struct attribute_spec lto_attribute_table[] =
handle_nonnull_attribute, false },
{ "nothrow", 0, 0, true, false, false,
handle_nothrow_attribute, false },
+ { "patchable_function_entry", 1, 2, true, false, false,
+ handle_patchable_function_entry_attribute,
+ false },
{ "returns_twice", 0, 0, true, false, false,
handle_returns_twice_attribute, false },
{ "sentinel", 0, 1, false, true, true,
@@ -473,6 +478,13 @@ handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+static tree
+handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
+{
+ /* Nothing to be done here. */
+ return NULL_TREE;
+}
+
/* Ignore the given attribute. Used when this attribute may be usefully
overridden by the target, but is not used generically. */
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 3600ab23bd9..3141ecec07c 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -506,7 +506,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
/* Collect all variables that should not be reordered. */
FOR_EACH_VARIABLE (vnode)
if (vnode->get_partitioning_class () == SYMBOL_PARTITION
- && (!flag_toplevel_reorder || vnode->no_reorder))
+ && vnode->no_reorder)
varpool_order.safe_push (vnode);
n_varpool_nodes = varpool_order.length ();
varpool_order.qsort (varpool_node_cmp);
@@ -547,7 +547,8 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
}
add_sorted_nodes (next_nodes, partition);
- add_symbol_to_partition (partition, order[i]);
+ if (!symbol_partitioned_p (order[i]))
+ add_symbol_to_partition (partition, order[i]);
if (!order[i]->alias)
total_size -= ipa_fn_summaries->get (order[i])->size;
@@ -634,7 +635,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
vnode = dyn_cast <varpool_node *> (ref->referred);
if (!vnode->definition)
continue;
- if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
+ if (!symbol_partitioned_p (vnode)
&& !vnode->no_reorder
&& vnode->get_partitioning_class () == SYMBOL_PARTITION)
add_symbol_to_partition (partition, vnode);
@@ -672,7 +673,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
because it allows them to be removed. Coupling
with objects they refer to only helps to reduce
number of symbols promoted to hidden. */
- if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
+ if (!symbol_partitioned_p (vnode)
&& !vnode->no_reorder
&& !vnode->can_remove_if_no_refs_p ()
&& vnode->get_partitioning_class () == SYMBOL_PARTITION)
@@ -767,14 +768,10 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
next_nodes.truncate (0);
/* Varables that are not reachable from the code go into last partition. */
- if (flag_toplevel_reorder)
- {
- FOR_EACH_VARIABLE (vnode)
- if (vnode->get_partitioning_class () == SYMBOL_PARTITION
- && !symbol_partitioned_p (vnode)
- && !vnode->no_reorder)
- next_nodes.safe_push (vnode);
- }
+ FOR_EACH_VARIABLE (vnode)
+ if (vnode->get_partitioning_class () == SYMBOL_PARTITION
+ && !symbol_partitioned_p (vnode))
+ next_nodes.safe_push (vnode);
/* Output remaining ordered symbols. */
while (varpool_pos < n_varpool_nodes)
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 44ddf419570..a3b4d13d27d 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -646,8 +646,8 @@ mentions_vars_p_type (tree t)
CHECK_NO_VAR (TYPE_ATTRIBUTES (t));
CHECK_NO_VAR (TYPE_NAME (t));
- CHECK_VAR (TYPE_MINVAL (t));
- CHECK_VAR (TYPE_MAXVAL (t));
+ CHECK_VAR (TYPE_MIN_VALUE_RAW (t));
+ CHECK_VAR (TYPE_MAX_VALUE_RAW (t));
/* Accessor is for derived node types only. */
CHECK_NO_VAR (t->type_non_common.binfo);
@@ -1414,9 +1414,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
else if (code == FUNCTION_TYPE
|| code == METHOD_TYPE)
compare_tree_edges (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2));
+
if (!POINTER_TYPE_P (t1))
- compare_tree_edges (TYPE_MINVAL (t1), TYPE_MINVAL (t2));
- compare_tree_edges (TYPE_MAXVAL (t1), TYPE_MAXVAL (t2));
+ compare_tree_edges (TYPE_MIN_VALUE_RAW (t1), TYPE_MIN_VALUE_RAW (t2));
+ compare_tree_edges (TYPE_MAX_VALUE_RAW (t1), TYPE_MAX_VALUE_RAW (t2));
}
if (CODE_CONTAINS_STRUCT (code, TS_LIST))
@@ -2580,8 +2581,8 @@ lto_fixup_prevailing_decls (tree t)
LTO_NO_PREVAIL (TYPE_ATTRIBUTES (t));
LTO_NO_PREVAIL (TYPE_NAME (t));
- LTO_SET_PREVAIL (TYPE_MINVAL (t));
- LTO_SET_PREVAIL (TYPE_MAXVAL (t));
+ LTO_SET_PREVAIL (TYPE_MIN_VALUE_RAW (t));
+ LTO_SET_PREVAIL (TYPE_MAX_VALUE_RAW (t));
LTO_NO_PREVAIL (t->type_non_common.binfo);
LTO_SET_PREVAIL (TYPE_CONTEXT (t));
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 42b14d09c1b..4b861ac41dd 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -20,9 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef HAVE_MACHINE_MODES
#define HAVE_MACHINE_MODES
-/* Make an enum class that gives all the machine modes. */
-#include "insn-modes.h"
-
/* Get the name of mode MODE as a string. */
extern const char * const mode_name[NUM_MACHINE_MODES];
diff --git a/gcc/match.pd b/gcc/match.pd
index a4cae113bc8..1cabcfc618a 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -155,6 +155,58 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| !COMPLEX_FLOAT_TYPE_P (type)))
(negate @0)))
+(for cmp (gt ge lt le)
+ outp (convert convert negate negate)
+ outn (negate negate convert convert)
+ /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ (simplify
+ (cond (cmp @0 real_zerop) real_onep@1 real_minus_onep)
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
+ && types_match (type, TREE_TYPE (@0)))
+ (switch
+ (if (types_match (type, float_type_node))
+ (BUILT_IN_COPYSIGNF @1 (outp @0)))
+ (if (types_match (type, double_type_node))
+ (BUILT_IN_COPYSIGN @1 (outp @0)))
+ (if (types_match (type, long_double_type_node))
+ (BUILT_IN_COPYSIGNL @1 (outp @0))))))
+ /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
+ /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
+ /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
+ /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
+ (simplify
+ (cond (cmp @0 real_zerop) real_minus_onep real_onep@1)
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
+ && types_match (type, TREE_TYPE (@0)))
+ (switch
+ (if (types_match (type, float_type_node))
+ (BUILT_IN_COPYSIGNF @1 (outn @0)))
+ (if (types_match (type, double_type_node))
+ (BUILT_IN_COPYSIGN @1 (outn @0)))
+ (if (types_match (type, long_double_type_node))
+ (BUILT_IN_COPYSIGNL @1 (outn @0)))))))
+
+/* Transform X * copysign (1.0, X) into abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN real_onep @0))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+ (abs @0)))
+
+/* Transform X * copysign (1.0, -X) into -abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN real_onep (negate @0)))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+ (negate (abs @0))))
+
+/* Transform copysign (CST, X) into copysign (ABS(CST), X). */
+(simplify
+ (COPYSIGN REAL_CST@0 @1)
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
+ (COPYSIGN (negate @0) @1)))
+
/* X * 1, X / 1 -> X. */
(for op (mult trunc_div ceil_div floor_div round_div exact_div)
(simplify
@@ -191,8 +243,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* X / X is one. */
(simplify
(div @0 @0)
- /* But not for 0 / 0 so that we can get the proper warnings and errors. */
- (if (!integer_zerop (@0))
+ /* But not for 0 / 0 so that we can get the proper warnings and errors.
+ And not for _Fract types where we can't build 1. */
+ (if (!integer_zerop (@0) && !ALL_FRACT_MODE_P (TYPE_MODE (type)))
{ build_one_cst (type); }))
/* X / abs (X) is X < 0 ? -1 : 1. */
(simplify
@@ -231,6 +284,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| mul != wi::min_value (TYPE_PRECISION (type), SIGNED))
{ build_zero_cst (type); })))))
+/* Combine successive multiplications. Similar to above, but handling
+ overflow is different. */
+(simplify
+ (mult (mult @0 INTEGER_CST@1) INTEGER_CST@2)
+ (with {
+ bool overflow_p;
+ wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), &overflow_p);
+ }
+ /* Skip folding on overflow: the only special case is @1 * @2 == -INT_MIN,
+ otherwise undefined overflow implies that @0 must be zero. */
+ (if (!overflow_p || TYPE_OVERFLOW_WRAPS (type))
+ (mult @0 { wide_int_to_tree (type, mul); }))))
+
/* Optimize A / A to 1.0 if we don't care about
NaNs or Infinities. */
(simplify
@@ -590,14 +656,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(minus (bit_and:cs @0 @1) (bit_and:cs @0 (bit_not @1)))
(minus @1 (bit_xor @0 @1)))
-/* Simplify (X & ~Y) | (~X & Y) -> X ^ Y. */
-(simplify
- (bit_ior (bit_and:c @0 (bit_not @1)) (bit_and:c (bit_not @0) @1))
- (bit_xor @0 @1))
-(simplify
- (bit_ior:c (bit_and @0 INTEGER_CST@2) (bit_and (bit_not @0) INTEGER_CST@1))
- (if (wi::bit_not (@2) == @1)
- (bit_xor @0 @1)))
+/* Simplify (X & ~Y) |^+ (~X & Y) -> X ^ Y. */
+(for op (bit_ior bit_xor plus)
+ (simplify
+ (op (bit_and:c @0 (bit_not @1)) (bit_and:c (bit_not @0) @1))
+ (bit_xor @0 @1))
+ (simplify
+ (op:c (bit_and @0 INTEGER_CST@2) (bit_and (bit_not @0) INTEGER_CST@1))
+ (if (wi::bit_not (@2) == @1)
+ (bit_xor @0 @1))))
/* PR53979: Transform ((a ^ b) | a) -> (a | b) */
(simplify
@@ -833,7 +900,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(X | Y) | (X | Z) -> (X | Y) | Z */
(for op (bit_and bit_ior)
(simplify
- (op:c (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2)))
+ (op (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@1))
&& tree_nop_conversion_p (type, TREE_TYPE (@2)))
(if (single_use (@5) && single_use (@6))
@@ -861,7 +928,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(match negate_expr_p
INTEGER_CST
(if ((INTEGRAL_TYPE_P (type)
- && TYPE_OVERFLOW_WRAPS (type))
+ && TYPE_UNSIGNED (type))
|| (!TYPE_OVERFLOW_SANITIZED (type)
&& may_negate_without_overflow_p (t)))))
(match negate_expr_p
@@ -1035,6 +1102,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(convert (bit_and (bit_not @1) @0))))
+/* (m1 CMP m2) * d -> (m1 CMP m2) ? d : 0 */
+(for cmp (gt lt ge le)
+(simplify
+ (mult (convert (cmp @0 @1)) @2)
+ (cond (cmp @0 @1) @2 { build_zero_cst (type); })))
+
/* For integral types with undefined overflow and C != 0 fold
x * C EQ/NE y * C into x EQ/NE y. */
(for cmp (eq ne)
@@ -1045,6 +1118,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& tree_expr_nonzero_p (@1))
(cmp @0 @2))))
+/* For integral types with wrapping overflow and C odd fold
+ x * C EQ/NE y * C into x EQ/NE y. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (mult @0 INTEGER_CST@1) (mult @2 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+ && (TREE_INT_CST_LOW (@1) & 1) != 0)
+ (cmp @0 @2))))
+
/* For integral types with undefined overflow and C != 0 fold
x * C RELOP y * C into:
@@ -1061,6 +1144,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& wi::neg_p (@1, TYPE_SIGN (TREE_TYPE (@1))))
(cmp @2 @0))))))
+/* (X - 1U) <= INT_MAX-1U into (int) X > 0. */
+(for cmp (le gt)
+ icmp (gt le)
+ (simplify
+ (cmp (plus @0 integer_minus_onep@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0)) > 1
+ && wi::eq_p (@2, wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)),
+ SIGNED) - 1))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (icmp (convert:stype @0) { build_int_cst (stype, 0); })))))
+
/* X / 4 < Y / 4 iff X < Y when the division is known to be exact. */
(for cmp (simple_comparison)
(simplify
@@ -1068,6 +1164,60 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (wi::gt_p(@2, 0, TYPE_SIGN (TREE_TYPE (@2))))
(cmp @0 @1))))
+/* X / C1 op C2 into a simple range test. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && integer_nonzerop (@1)
+ && !TREE_OVERFLOW (@1)
+ && !TREE_OVERFLOW (@2))
+ (with { tree lo, hi; bool neg_overflow;
+ enum tree_code code = fold_div_compare (cmp, @1, @2, &lo, &hi,
+ &neg_overflow); }
+ (switch
+ (if (code == LT_EXPR || code == GE_EXPR)
+ (if (TREE_OVERFLOW (lo))
+ { build_int_cst (type, (code == LT_EXPR) ^ neg_overflow); }
+ (if (code == LT_EXPR)
+ (lt @0 { lo; })
+ (ge @0 { lo; }))))
+ (if (code == LE_EXPR || code == GT_EXPR)
+ (if (TREE_OVERFLOW (hi))
+ { build_int_cst (type, (code == LE_EXPR) ^ neg_overflow); }
+ (if (code == LE_EXPR)
+ (le @0 { hi; })
+ (gt @0 { hi; }))))
+ (if (!lo && !hi)
+ { build_int_cst (type, code == NE_EXPR); })
+ (if (code == EQ_EXPR && !hi)
+ (ge @0 { lo; }))
+ (if (code == EQ_EXPR && !lo)
+ (le @0 { hi; }))
+ (if (code == NE_EXPR && !hi)
+ (lt @0 { lo; }))
+ (if (code == NE_EXPR && !lo)
+ (gt @0 { hi; }))
+ (if (GENERIC)
+ { build_range_check (UNKNOWN_LOCATION, type, @0, code == EQ_EXPR,
+ lo, hi); })
+ (with
+ {
+ tree etype = range_check_type (TREE_TYPE (@0));
+ if (etype)
+ {
+ if (! TYPE_UNSIGNED (etype))
+ etype = unsigned_type_for (etype);
+ hi = fold_convert (etype, hi);
+ lo = fold_convert (etype, lo);
+ hi = const_binop (MINUS_EXPR, etype, hi, lo);
+ }
+ }
+ (if (etype && hi && !TREE_OVERFLOW (hi))
+ (if (code == EQ_EXPR)
+ (le (minus (convert:etype @0) { lo; }) { hi; })
+ (gt (minus (convert:etype @0) { lo; }) { hi; })))))))))
+
/* X + Z < Y + Z is the same as X < Y when there is no overflow. */
(for op (lt le ge gt)
(simplify
@@ -1321,6 +1471,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(simplify
(minus @0 (minus @0 @1))
@1)
+ /* (A +- B) + (C - A) -> C +- B */
+ /* (A + B) - (A - C) -> B + C */
+ /* More cases are handled with comparisons. */
+ (simplify
+ (plus:c (plus:c @0 @1) (minus @2 @0))
+ (plus @2 @1))
+ (simplify
+ (plus:c (minus @0 @1) (minus @2 @0))
+ (minus @2 @1))
+ (simplify
+ (minus (plus:c @0 @1) (minus @0 @2))
+ (plus @1 @2))
/* (A +- CST1) +- CST2 -> A + CST3
Use view_convert because it is safe for vectors and equivalent for
@@ -2064,6 +2226,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(mult @0 integer_minus_onep)
(negate @0))
+/* Reassociate (X * CST) * Y to (X * Y) * CST. This does not introduce
+ signed overflow for CST != 0 && CST != -1. */
+(simplify
+ (mult:c (mult:s @0 INTEGER_CST@1) @2)
+ (if (TREE_CODE (@2) != INTEGER_CST
+ && !integer_zerop (@1) && !integer_minus_onep (@1))
+ (mult (mult @0 @2) @1)))
+
/* True if we can easily extract the real and imaginary parts of a complex
number. */
(match compositional_complex
@@ -4008,3 +4178,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ CONSTRUCTOR_ELT (ctor, idx / k)->value; })
(BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / k)->value; }
@1 { bitsize_int ((idx % k) * width); })))))))))
+
+/* Simplify a bit extraction from a bit insertion for the cases with
+ the inserted element fully covering the extraction or the insertion
+ not touching the extraction. */
+(simplify
+ (BIT_FIELD_REF (bit_insert @0 @1 @ipos) @rsize @rpos)
+ (with
+ {
+ unsigned HOST_WIDE_INT isize;
+ if (INTEGRAL_TYPE_P (TREE_TYPE (@1)))
+ isize = TYPE_PRECISION (TREE_TYPE (@1));
+ else
+ isize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (@1)));
+ }
+ (switch
+ (if (wi::leu_p (@ipos, @rpos)
+ && wi::leu_p (wi::add (@rpos, @rsize), wi::add (@ipos, isize)))
+ (BIT_FIELD_REF @1 @rsize { wide_int_to_tree (bitsizetype,
+ wi::sub (@rpos, @ipos)); }))
+ (if (wi::geu_p (@ipos, wi::add (@rpos, @rsize))
+ || wi::geu_p (@rpos, wi::add (@ipos, isize)))
+ (BIT_FIELD_REF @0 @rsize @rpos)))))
diff --git a/gcc/mcf.c b/gcc/mcf.c
index bb4b4f9ef76..67088506dac 100644
--- a/gcc/mcf.c
+++ b/gcc/mcf.c
@@ -1231,12 +1231,15 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
}
if (bb_gcov_count (bb))
- e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
- bb_gcov_count (bb));
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
if (dump_file)
- fprintf (dump_file, " = %" PRId64 "\t(%.1f%%)\n",
- edge_gcov_count (e),
- e->probability * 100.0 / REG_BR_PROB_BASE);
+ {
+ fprintf (dump_file, " = %" PRId64 "\t",
+ edge_gcov_count (e));
+ e->probability.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
}
}
@@ -1251,31 +1254,8 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
if (bb_gcov_count (bb))
{
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
- bb_gcov_count (bb));
- }
- else
- {
- int total = 0;
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- total++;
- if (total)
- {
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- e->probability = REG_BR_PROB_BASE / total;
- else
- e->probability = 0;
- }
- }
- else
- {
- total += EDGE_COUNT (bb->succs);
- FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = REG_BR_PROB_BASE / total;
- }
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
}
}
diff --git a/gcc/mkconfig.sh b/gcc/mkconfig.sh
index 9fc7b5ca734..3ee7fd32218 100644
--- a/gcc/mkconfig.sh
+++ b/gcc/mkconfig.sh
@@ -100,9 +100,6 @@ case $output in
#if defined IN_GCC && !defined GENERATOR_FILE
# include "insn-modes.h"
#endif
-#if defined IN_GCC && defined GENERATOR_FILE && !defined BITS_PER_UNIT
-#include "machmode.h"
-#endif
EOF
;;
esac
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 005c6e596ad..f85011e90c2 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -1713,13 +1713,12 @@ sms_schedule (void)
rtx comp_rtx = gen_rtx_GT (VOIDmode, count_reg,
gen_int_mode (stage_count,
GET_MODE (count_reg)));
- unsigned prob = (PROB_SMS_ENOUGH_ITERATIONS
- * REG_BR_PROB_BASE) / 100;
+ profile_probability prob = profile_probability::guessed_always ()
+ .apply_scale (PROB_SMS_ENOUGH_ITERATIONS, 100);
loop_version (loop, comp_rtx, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
- prob, REG_BR_PROB_BASE - prob,
- true);
+ prob, prob.invert (),
+ prob, prob.invert (), true);
}
/* Set new iteration count of loop kernel. */
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 38d6892af28..0d7cc3a2939 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -68,6 +68,38 @@ create_dispatcher_calls (struct cgraph_node *node)
|| !is_function_default_version (node->decl))
return;
+ if (!targetm.has_ifunc_p ())
+ {
+ error_at (DECL_SOURCE_LOCATION (node->decl),
+ "the call requires ifunc, which is not"
+ " supported by this target");
+ return;
+ }
+ else if (!targetm.get_function_versions_dispatcher)
+ {
+ error_at (DECL_SOURCE_LOCATION (node->decl),
+ "target does not support function version dispatcher");
+ return;
+ }
+
+ tree idecl = targetm.get_function_versions_dispatcher (node->decl);
+ if (!idecl)
+ {
+ error_at (DECL_SOURCE_LOCATION (node->decl),
+ "default target_clones attribute was not set");
+ return;
+ }
+
+ cgraph_node *inode = cgraph_node::get (idecl);
+ gcc_assert (inode);
+ tree resolver_decl = targetm.generate_version_dispatcher_body (inode);
+
+ /* Update aliases. */
+ inode->alias = true;
+ inode->alias_target = resolver_decl;
+ if (!inode->analyzed)
+ inode->resolve_alias (cgraph_node::get (resolver_decl));
+
auto_vec<cgraph_edge *> edges_to_redirect;
auto_vec<ipa_ref *> references_to_redirect;
@@ -80,38 +112,6 @@ create_dispatcher_calls (struct cgraph_node *node)
if (!edges_to_redirect.is_empty () || !references_to_redirect.is_empty ())
{
- if (!targetm.has_ifunc_p ())
- {
- error_at (DECL_SOURCE_LOCATION (node->decl),
- "the call requires ifunc, which is not"
- " supported by this target");
- return;
- }
- else if (!targetm.get_function_versions_dispatcher)
- {
- error_at (DECL_SOURCE_LOCATION (node->decl),
- "target does not support function version dispatcher");
- return;
- }
-
- tree idecl = targetm.get_function_versions_dispatcher (node->decl);
- if (!idecl)
- {
- error_at (DECL_SOURCE_LOCATION (node->decl),
- "default target_clones attribute was not set");
- return;
- }
-
- cgraph_node *inode = cgraph_node::get (idecl);
- gcc_assert (inode);
- tree resolver_decl = targetm.generate_version_dispatcher_body (inode);
-
- /* Update aliases. */
- inode->alias = true;
- inode->alias_target = resolver_decl;
- if (!inode->analyzed)
- inode->resolve_alias (cgraph_node::get (resolver_decl));
-
/* Redirect edges. */
unsigned i;
cgraph_edge *e;
@@ -148,6 +148,7 @@ create_dispatcher_calls (struct cgraph_node *node)
}
}
+ TREE_PUBLIC (node->decl) = 0;
symtab->change_decl_assembler_name (node->decl,
clone_function_name (node->decl,
"default"));
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 0c6f3fcd8ae..27bb0600626 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,14 @@
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ Remove TYPE_METHODS.
+ * objc-runtime-shared-support.c (build_ivar_list_initializer):
+ Don't presume first item is a FIELD_DECL.
+
+2017-07-19 Nathan Sidwell <nathan@acm.org>
+
+ * objc-act.h (CLASS_NST_METHODS, CLASS_CLS_METHODS): Use
+ TYPE_{MIN,MAX}_VALUE_RAW.
+
2017-05-16 Sylvestre Ledru <sylvestre@debian.org>
* objc-runtime-shared-support.c (build_module_descriptor):
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 05ee968036b..92efd9ee45f 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -179,8 +179,8 @@ enum objc_property_assign_semantics {
#define CLASS_SUPER_NAME(CLASS) (TYPE_CONTEXT (CLASS))
#define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
#define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1)
-#define CLASS_NST_METHODS(CLASS) (TYPE_MINVAL (CLASS))
-#define CLASS_CLS_METHODS(CLASS) (TYPE_MAXVAL (CLASS))
+#define CLASS_NST_METHODS(CLASS) (TYPE_MIN_VALUE_RAW (CLASS))
+#define CLASS_CLS_METHODS(CLASS) (TYPE_MAX_VALUE_RAW (CLASS))
#define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
#define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3)
#define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 4)
@@ -189,8 +189,8 @@ enum objc_property_assign_semantics {
#define PROTOCOL_NAME(CLASS) (TYPE_NAME (CLASS))
#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
-#define PROTOCOL_NST_METHODS(CLASS) (TYPE_MINVAL (CLASS))
-#define PROTOCOL_CLS_METHODS(CLASS) (TYPE_MAXVAL (CLASS))
+#define PROTOCOL_NST_METHODS(CLASS) (TYPE_MIN_VALUE_RAW (CLASS))
+#define PROTOCOL_CLS_METHODS(CLASS) (TYPE_MAX_VALUE_RAW (CLASS))
#define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1)
#define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS)
#define PROTOCOL_OPTIONAL_CLS_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c
index 5ead87078c6..53303e47d20 100644
--- a/gcc/objc/objc-runtime-shared-support.c
+++ b/gcc/objc/objc-runtime-shared-support.c
@@ -528,34 +528,32 @@ build_ivar_list_initializer (tree type, tree field_decl)
{
vec<constructor_elt, va_gc> *inits = NULL;
- do
- {
- vec<constructor_elt, va_gc> *ivar = NULL;
- tree id;
-
- /* Set name. */
- if (DECL_NAME (field_decl))
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
- add_objc_string (DECL_NAME (field_decl),
- meth_var_names));
- else
- /* Unnamed bit-field ivar (yuck). */
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
-
- /* Set type. */
- id = add_objc_string (encode_field_decl (field_decl),
- meth_var_types);
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
-
- /* Set offset. */
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
- objc_build_constructor (type, ivar));
- do
- field_decl = DECL_CHAIN (field_decl);
- while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
+ for (; field_decl; field_decl = DECL_CHAIN (field_decl))
+ if (TREE_CODE (field_decl) == FIELD_DECL)
+ {
+ vec<constructor_elt, va_gc> *ivar = NULL;
+ tree id;
+
+ /* Set name. */
+ if (DECL_NAME (field_decl))
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ add_objc_string (DECL_NAME (field_decl),
+ meth_var_names));
+ else
+ /* Unnamed bit-field ivar (yuck). */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ build_int_cst (NULL_TREE, 0));
+
+ /* Set type. */
+ id = add_objc_string (encode_field_decl (field_decl),
+ meth_var_types);
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
+
+ /* Set offset. */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, ivar));
}
- while (field_decl);
return objc_build_constructor (build_array_type (type, 0), inits);
}
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 817b6d466f3..5b4b6bdf2f0 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-03 Nathan Sidwell <nathan@acm.org>
+
+ * config-lang.in: Source cp/config-lang.in, sort objc++ gtfiles list.
+
2017-06-02 Nathan Sidwell <nathan@acm.org>
* objcp-decl.h (SIZEOF_OBJC_TYPE_LANG_SPECIFIC): Use lang_type.
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index 04180947492..5d2b1de8e5a 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -43,8 +43,20 @@ subdir_requires="objc cp"
# avoid having the GC stuff from that header being added to gtype-cp.h
# or gtype-objc.h.
-# This list is separated in two parts: the first one is identical to
-# the C++ one, the second one contains our ObjC++ additions.
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c \
-\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
+# Get the C++ FE's gtfiles list. Do this in a subshell, so we can
+# extract exactly the gtfiles var, but munge cp-lang.c into objcp-lang.c.
+gtfiles="$(. $srcdir/cp/config-lang.in ; \
+ echo $gtfiles | sed 's+/cp/cp-lang.c +/objcp/objcp-lang.c +')"
+
+# Now add our special bits to it. Please keep this list sorted.
+gtfiles="$gtfiles \
+\$(srcdir)/objc/objc-act.h \
+\$(srcdir)/objc/objc-map.h \
+\$(srcdir)/c-family/c-cppbuiltin.c \
+\$(srcdir)/objc/objc-act.c \
+\$(srcdir)/objc/objc-gnu-runtime-abi-01.c \
+\$(srcdir)/objc/objc-next-runtime-abi-01.c \
+\$(srcdir)/objc/objc-next-runtime-abi-02.c \
+\$(srcdir)/objc/objc-runtime-shared-support.c \
+"
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 53d3d3f84fd..d6755cd71ee 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -1741,9 +1741,9 @@ expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
entry_bb);
}
ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
- ne->probability = REG_BR_PROB_BASE / 2000 - 1;
+ ne->probability = profile_probability::very_unlikely ();
e->flags = EDGE_TRUE_VALUE;
- e->probability = REG_BR_PROB_BASE - ne->probability;
+ e->probability = ne->probability.invert ();
if (l2_dom_bb == NULL)
l2_dom_bb = entry_bb;
entry_bb = e->dest;
@@ -1920,7 +1920,7 @@ extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
if (i < fd->collapse - 1)
{
e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (1, 8);
t = fd->loops[i + 1].n1;
t = force_gimple_operand_gsi (&gsi, t,
@@ -1961,7 +1961,7 @@ extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
stmt = gimple_build_cond_empty (t);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
- e->probability = REG_BR_PROB_BASE * 7 / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
}
else
make_edge (bb, body_bb, EDGE_FALLTHRU);
@@ -2219,8 +2219,8 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
GSI_CONTINUE_LINKING);
gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
- e3->probability = REG_BR_PROB_BASE / 8;
- e1->probability = REG_BR_PROB_BASE - e3->probability;
+ e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
+ e1->probability = e3->probability.invert ();
e1->flags = EDGE_TRUE_VALUE;
set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
@@ -2373,9 +2373,9 @@ expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
remove_edge (e1);
make_edge (body_bb, new_header, EDGE_FALLTHRU);
e3->flags = EDGE_FALSE_VALUE;
- e3->probability = REG_BR_PROB_BASE / 8;
+ e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
- e1->probability = REG_BR_PROB_BASE - e3->probability;
+ e1->probability = e3->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
@@ -3149,8 +3149,8 @@ expand_omp_for_generic (struct omp_region *region,
e->flags = EDGE_TRUE_VALUE;
if (e)
{
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ find_edge (cont_bb, l2_bb)->probability = e->probability.invert ();
}
else
{
@@ -3351,9 +3351,9 @@ expand_omp_for_static_nochunk (struct omp_region *region,
ep = split_block (entry_bb, cond_stmt);
ep->flags = EDGE_TRUE_VALUE;
entry_bb = ep->dest;
- ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
+ ep->probability = profile_probability::very_likely ();
ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
- ep->probability = REG_BR_PROB_BASE / 2000 - 1;
+ ep->probability = profile_probability::very_unlikely ();
if (gimple_in_ssa_p (cfun))
{
int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
@@ -3634,10 +3634,10 @@ expand_omp_for_static_nochunk (struct omp_region *region,
/* Connect all the blocks. */
ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
- ep->probability = REG_BR_PROB_BASE / 4 * 3;
+ ep->probability = profile_probability::guessed_always ().apply_scale (3, 4);
ep = find_edge (entry_bb, second_bb);
ep->flags = EDGE_TRUE_VALUE;
- ep->probability = REG_BR_PROB_BASE / 4;
+ ep->probability = profile_probability::guessed_always ().apply_scale (1, 4);
find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
@@ -3835,9 +3835,9 @@ expand_omp_for_static_chunk (struct omp_region *region,
se = split_block (entry_bb, cond_stmt);
se->flags = EDGE_TRUE_VALUE;
entry_bb = se->dest;
- se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
+ se->probability = profile_probability::very_likely ();
se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
- se->probability = REG_BR_PROB_BASE / 2000 - 1;
+ se->probability = profile_probability::very_unlikely ();
if (gimple_in_ssa_p (cfun))
{
int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
@@ -4206,6 +4206,10 @@ expand_omp_for_static_chunk (struct omp_region *region,
source_location locus;
phi = psi.phi ();
+ if (operand_equal_p (gimple_phi_arg_def (phi, 0),
+ redirect_edge_var_map_def (vm), 0))
+ continue;
+
t = gimple_phi_result (phi);
gcc_assert (t == redirect_edge_var_map_result (vm));
@@ -4448,8 +4452,8 @@ expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
}
ne->flags = EDGE_FALSE_VALUE;
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- ne->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ ne->probability = e->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
@@ -4810,8 +4814,8 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
}
ne->flags = EDGE_FALSE_VALUE;
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- ne->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ ne->probability = e->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
@@ -4824,8 +4828,10 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
make_edge (entry_bb, l2_bb, EDGE_FALSE_VALUE);
FALLTHRU_EDGE (entry_bb)->flags = EDGE_TRUE_VALUE;
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE * 7 / 8;
- BRANCH_EDGE (entry_bb)->probability = REG_BR_PROB_BASE / 8;
+ FALLTHRU_EDGE (entry_bb)->probability
+ = profile_probability::guessed_always ().apply_scale (7, 8);
+ BRANCH_EDGE (entry_bb)->probability
+ = FALLTHRU_EDGE (entry_bb)->probability.invert ();
l2_dom_bb = entry_bb;
}
set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
@@ -5018,9 +5024,9 @@ expand_omp_taskloop_for_outer (struct omp_region *region,
gsi = gsi_last_bb (exit_bb);
gsi_remove (&gsi, true);
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
remove_edge (BRANCH_EDGE (entry_bb));
- FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (cont_bb)->probability = profile_probability::always ();
remove_edge (BRANCH_EDGE (cont_bb));
set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
set_immediate_dominator (CDI_DOMINATORS, region->entry,
@@ -5208,7 +5214,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region,
gsi = gsi_last_bb (exit_bb);
gsi_remove (&gsi, true);
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
if (!broken_loop)
remove_edge (BRANCH_EDGE (entry_bb));
else
@@ -6604,8 +6610,11 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
e = single_succ_edge (store_bb);
e->flags &= ~EDGE_FALLTHRU;
e->flags |= EDGE_FALSE_VALUE;
+ /* Expect no looping. */
+ e->probability = profile_probability::guessed_always ();
e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
+ e->probability = profile_probability::guessed_never ();
/* Copy the new value to loadedi (we already did that before the condition
if we are not in SSA). */
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index dd4a0926c44..bf3fc53b07a 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5056,7 +5056,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
/* Determine position in reduction buffer, which may be used
by target. */
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
+ machine_mode mode = TYPE_MODE (TREE_TYPE (var));
unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
offset = (offset + align - 1) & ~(align - 1);
tree off = build_int_cst (sizetype, offset);
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index 3aa8b131565..a1a563e8094 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -1151,8 +1151,7 @@ simd_clone_adjust (struct cgraph_node *node)
if (incr_bb)
{
- edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
gsi = gsi_last_bb (incr_bb);
iter2 = make_ssa_name (iter);
g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
@@ -1264,7 +1263,10 @@ simd_clone_adjust (struct cgraph_node *node)
redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
- make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+ edge new_e = make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+
+ /* FIXME: Do we need to distribute probabilities for the conditional? */
+ new_e->probability = profile_probability::guessed_never ();
/* The successor of incr_bb is already pointing to latch_bb; just
change the flags.
make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index 0736a6f3faf..5ee93f12feb 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -275,7 +275,7 @@ function var_ref(name, flags)
return "offsetof (struct gcc_options, x_target_flags)"
if (opt_args("InverseMask", flags) != "")
return "offsetof (struct gcc_options, x_target_flags)"
- return "-1"
+ return "(unsigned short) -1"
}
# Given the option called NAME return a sanitized version of its name.
@@ -314,6 +314,19 @@ function search_var_name(name, opt_numbers, opts, flags, n_opts)
return ""
}
+function integer_range_info(range_option, init, option)
+{
+ if (range_option != "") {
+ start = nth_arg(0, range_option);
+ end = nth_arg(1, range_option);
+ if (init != "" && init != "-1" && (init < start || init > end))
+ print "#error initial value " init " of '" option "' must be in range [" start "," end "]"
+ return start ", " end
+ }
+ else
+ return "-1, -1"
+}
+
# Handle LangEnabledBy(ENABLED_BY_LANGS, ENABLEDBY_NAME, ENABLEDBY_POSARG,
# ENABLEDBY_NEGARG). This function does not return anything.
function lang_enabled_by(enabledby_langs, enabledby_name, enabledby_posarg, enabledby_negarg)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b69e75943cc..9258e5f888b 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -693,7 +693,8 @@ expand_doubleword_shift (machine_mode op1_mode, optab binoptab,
NO_DEFER_POP;
do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
- 0, 0, subword_label, -1);
+ 0, 0, subword_label,
+ profile_probability::uninitialized ());
OK_DEFER_POP;
if (!expand_superword_shift (binoptab, outof_input, superword_op1,
@@ -3187,7 +3188,8 @@ expand_abs (machine_mode mode, rtx op0, rtx target,
NO_DEFER_POP;
do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
- NULL_RTX, NULL, op1, -1);
+ NULL_RTX, NULL, op1,
+ profile_probability::uninitialized ());
op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
target, target, 0);
@@ -3844,9 +3846,9 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
if (cfun->can_throw_non_call_exceptions)
{
if (may_trap_p (x))
- x = force_reg (mode, x);
+ x = copy_to_reg (x);
if (may_trap_p (y))
- y = force_reg (mode, y);
+ y = copy_to_reg (y);
}
if (GET_MODE_CLASS (mode) == MODE_CC)
@@ -3979,7 +3981,8 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode,
we can do the branch. */
static void
-emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
+emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+ profile_probability prob)
{
machine_mode optab_mode;
enum mode_class mclass;
@@ -3994,13 +3997,13 @@ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
gcc_assert (insn_operand_matches (icode, 0, test));
insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
XEXP (test, 1), label));
- if (prob != -1
+ if (prob.initialized_p ()
&& profile_status_for_fn (cfun) != PROFILE_ABSENT
&& insn
&& JUMP_P (insn)
&& any_condjump_p (insn)
&& !find_reg_note (insn, REG_BR_PROB, 0))
- add_int_reg_note (insn, REG_BR_PROB, prob);
+ add_reg_br_prob_note (insn, prob);
}
/* Generate code to compare X with Y so that the condition codes are
@@ -4025,7 +4028,7 @@ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
void
emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
machine_mode mode, int unsignedp, rtx label,
- int prob)
+ profile_probability prob)
{
rtx op0 = x, op1 = y;
rtx test;
@@ -5856,7 +5859,8 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
/* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
- GET_MODE (success), 1, label, 0);
+ GET_MODE (success), 1, label,
+ profile_probability::guessed_never ());
return true;
}
@@ -6274,7 +6278,7 @@ expand_asm_memory_barrier (void)
{
rtx asm_op, clob;
- asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, empty_string, empty_string, 0,
+ asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
rtvec_alloc (0), rtvec_alloc (0),
rtvec_alloc (0), UNKNOWN_LOCATION);
MEM_VOLATILE_P (asm_op) = 1;
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 728b866f08d..07d07fe8366 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -247,7 +247,9 @@ extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
/* Emit a pair of rtl insns to compare two rtx's and to jump
to a label if the comparison is true. */
extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
- machine_mode, int, rtx, int prob=-1);
+ machine_mode, int, rtx,
+ profile_probability prob
+ = profile_probability::uninitialized ());
/* Generate code to indirectly jump to a location given in the rtx LOC. */
extern void emit_indirect_jump (rtx);
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index 3b9126ccf97..3cb0005ba40 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -336,7 +336,7 @@ for (i = 0; i < n_opts; i++) {
alias_posarg = nth_arg(1, alias_arg)
alias_negarg = nth_arg(2, alias_arg)
- if (var_ref(opts[i], flags[i]) != "-1")
+ if (var_ref(opts[i], flags[i]) != "(unsigned short) -1")
print "#error Alias setting variable"
if (alias_posarg != "" && alias_negarg == "") {
@@ -399,8 +399,9 @@ for (i = 0; i < n_opts; i++) {
printf(" %s,\n" \
" 0, %s,\n",
cl_flags, cl_bit_fields)
- printf(" %s, %s }%s\n", var_ref(opts[i], flags[i]),
- var_set(flags[i]), comma)
+ printf(" %s, %s, %s }%s\n", var_ref(opts[i], flags[i]),
+ var_set(flags[i]), integer_range_info(opt_args("IntegerRange", flags[i]),
+ opt_args("Init", flags[i]), opts[i]), comma)
}
print "};"
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index d79d1e9cd8d..fc582103f6f 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -41,13 +41,10 @@ print "#include " quote "flags.h" quote
print "#include " quote "target.h" quote
print "#include " quote "inchash.h" quote
print "#include " quote "hash-set.h" quote
-print "#include " quote "machmode.h" quote
print "#include " quote "vec.h" quote
-print "#include " quote "double-int.h" quote
print "#include " quote "input.h" quote
print "#include " quote "alias.h" quote
print "#include " quote "symtab.h" quote
-print "#include " quote "wide-int.h" quote
print "#include " quote "inchash.h" quote
print "#include " quote "tree.h" quote
print "#include " quote "fold-const.h" quote
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index f2f7385a4c7..0cab42a021c 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -661,6 +661,11 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
value = integral_argument (arg);
if (value == -1)
errors |= CL_ERR_UINT_ARG;
+
+ /* Reject value out of a range. */
+ if (option->range_max != -1
+ && (value < option->range_min || value > option->range_max))
+ errors |= CL_ERR_INT_RANGE_ARG;
}
/* If the switch takes an enumerated argument, convert it. */
@@ -1137,6 +1142,13 @@ cmdline_handle_error (location_t loc, const struct cl_option *option,
return true;
}
+ if (errors & CL_ERR_INT_RANGE_ARG)
+ {
+ error_at (loc, "argument to %qs is not between %d and %d",
+ option->opt_text, option->range_min, option->range_max);
+ return true;
+ }
+
if (errors & CL_ERR_ENUM_ARG)
{
const struct cl_enum *e = &cl_enums[option->var_enum];
diff --git a/gcc/opts.c b/gcc/opts.c
index 4013ea51fd2..2f9a6380fe1 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -139,13 +139,13 @@ set_struct_debug_option (struct gcc_options *opts, location_t loc,
/* Strip off a legitimate source ending from the input string NAME of
length LEN. Rather than having to know the names used by all of
our front ends, we strip off an ending of a period followed by
- up to five characters. (Java uses ".class".) */
+ up to fource characters. (C++ uses ".cpp".) */
void
strip_off_ending (char *name, int len)
{
int i;
- for (i = 2; i < 6 && len > i; i++)
+ for (i = 2; i < 5 && len > i; i++)
{
if (name[len - i] == '.')
{
@@ -823,8 +823,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
{
if (opts_set->x_flag_reorder_blocks_and_partition)
inform (loc,
- "-freorder-blocks-and-partition does not work "
- "with exceptions on this architecture");
+ "%<-freorder-blocks-and-partition%> does not work "
+ "with exceptions on this architecture");
opts->x_flag_reorder_blocks_and_partition = 0;
opts->x_flag_reorder_blocks = 1;
}
@@ -839,8 +839,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
{
if (opts_set->x_flag_reorder_blocks_and_partition)
inform (loc,
- "-freorder-blocks-and-partition does not support "
- "unwind info on this architecture");
+ "%<-freorder-blocks-and-partition%> does not support "
+ "unwind info on this architecture");
opts->x_flag_reorder_blocks_and_partition = 0;
opts->x_flag_reorder_blocks = 1;
}
@@ -857,8 +857,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
{
if (opts_set->x_flag_reorder_blocks_and_partition)
inform (loc,
- "-freorder-blocks-and-partition does not work "
- "on this architecture");
+ "%<-freorder-blocks-and-partition%> does not work "
+ "on this architecture");
opts->x_flag_reorder_blocks_and_partition = 0;
opts->x_flag_reorder_blocks = 1;
}
@@ -895,7 +895,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
&& !opts->x_flag_use_linker_plugin)))
{
if (opts_set->x_flag_fat_lto_objects)
- error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin");
+ error_at (loc, "%<-fno-fat-lto-objects%> are supported only with "
+ "linker plugin");
opts->x_flag_fat_lto_objects = 1;
}
}
@@ -954,26 +955,26 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
&& (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
error_at (loc,
- "-fsanitize=address is incompatible with "
- "-fsanitize=kernel-address");
+ "%<-fsanitize=address%> is incompatible with "
+ "%<-fsanitize=kernel-address%>");
/* And with TSan. */
if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
&& (opts->x_flag_sanitize & SANITIZE_THREAD))
error_at (loc,
- "-fsanitize=address and -fsanitize=kernel-address "
- "are incompatible with -fsanitize=thread");
+ "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> "
+ "are incompatible with %<-fsanitize=thread%>");
if ((opts->x_flag_sanitize & SANITIZE_LEAK)
&& (opts->x_flag_sanitize & SANITIZE_THREAD))
error_at (loc,
- "-fsanitize=leak is incompatible with -fsanitize=thread");
+ "%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>");
/* Check error recovery for -fsanitize-recover option. */
for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
&& !sanitizer_opts[i].can_recover)
- error_at (loc, "-fsanitize-recover=%s is not supported",
+ error_at (loc, "%<-fsanitize-recover=%s%> is not supported",
sanitizer_opts[i].name);
/* When instrumenting the pointers, we don't want to remove
@@ -999,11 +1000,18 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
if (opts->x_flag_stack_reuse != SR_NONE
&& opts_set->x_flag_stack_reuse != SR_NONE)
error_at (loc,
- "-fsanitize-address-use-after-scope requires "
- "-fstack-reuse=none option");
+ "%<-fsanitize-address-use-after-scope%> requires "
+ "%<-fstack-reuse=none%> option");
opts->x_flag_stack_reuse = SR_NONE;
}
+
+ if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && opts->x_flag_tm)
+ sorry ("transactional memory is not supported with %<-fsanitize=address%>");
+
+ if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm)
+ sorry ("transactional memory is not supported with "
+ "%<-fsanitize=kernel-address%>");
}
#define LEFT_COLUMN 27
@@ -1253,6 +1261,15 @@ print_filtered_help (unsigned int include_flags,
help = new_help;
}
+ if (option->range_max != -1)
+ {
+ char b[128];
+ snprintf (b, sizeof (b), "<%d,%d>", option->range_min,
+ option->range_max);
+ opt = concat (opt, b, NULL);
+ len += strlen (b);
+ }
+
wrap_help (help, opt, len, columns);
displayed = true;
@@ -1504,6 +1521,7 @@ const struct sanitizer_opts_s sanitizer_opts[] =
true),
SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true),
SANITIZER_OPT (vptr, SANITIZE_VPTR, true),
+ SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true),
SANITIZER_OPT (all, ~0U, true),
#undef SANITIZER_OPT
{ NULL, 0U, 0UL, false }
@@ -1604,7 +1622,7 @@ parse_sanitizer_options (const char *p, location_t loc, int scode,
if (code == OPT_fsanitize_)
{
if (complain)
- error_at (loc, "-fsanitize=all option is not valid");
+ error_at (loc, "%<-fsanitize=all%> option is not valid");
}
else
flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK
@@ -1900,6 +1918,9 @@ common_handle_option (struct gcc_options *opts,
opts_set->x_param_values);
maybe_set_param_value (PARAM_ASAN_STACK, 0, opts->x_param_values,
opts_set->x_param_values);
+ maybe_set_param_value (PARAM_ASAN_PROTECT_ALLOCAS, 0,
+ opts->x_param_values,
+ opts_set->x_param_values);
maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
opts->x_param_values,
opts_set->x_param_values);
@@ -2115,7 +2136,7 @@ common_handle_option (struct gcc_options *opts,
#ifndef ACCEL_COMPILER
case OPT_foffload_abi_:
- error_at (loc, "-foffload-abi option can be specified only for "
+ error_at (loc, "%<-foffload-abi%> option can be specified only for "
"offload compiler");
break;
#endif
@@ -2187,6 +2208,33 @@ common_handle_option (struct gcc_options *opts,
opts->x_flag_ipa_reference = false;
break;
+ case OPT_fpatchable_function_entry_:
+ {
+ char *patch_area_arg = xstrdup (arg);
+ char *comma = strchr (patch_area_arg, ',');
+ if (comma)
+ {
+ *comma = '\0';
+ function_entry_patch_area_size =
+ integral_argument (patch_area_arg);
+ function_entry_patch_area_start =
+ integral_argument (comma + 1);
+ }
+ else
+ {
+ function_entry_patch_area_size =
+ integral_argument (patch_area_arg);
+ function_entry_patch_area_start = 0;
+ }
+ if (function_entry_patch_area_size < 0
+ || function_entry_patch_area_start < 0
+ || function_entry_patch_area_size
+ < function_entry_patch_area_start)
+ error ("invalid arguments for %<-fpatchable_function_entry%>");
+ free (patch_area_arg);
+ }
+ break;
+
case OPT_ftree_vectorize:
if (!opts_set->x_flag_tree_loop_vectorize)
opts->x_flag_tree_loop_vectorize = value;
diff --git a/gcc/opts.h b/gcc/opts.h
index 16371e8141f..5599711cc76 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -110,6 +110,10 @@ struct cl_option
enum cl_var_type var_type;
/* Value or bit-mask with which to set a field. */
HOST_WIDE_INT var_value;
+ /* Range info minimum, or -1. */
+ int range_min;
+ /* Range info maximum, or -1. */
+ int range_max;
};
/* Records that the state of an option consists of SIZE bytes starting
@@ -200,8 +204,9 @@ extern const unsigned int cl_enums_count;
#define CL_ERR_MISSING_ARG (1 << 1) /* Argument required but missing. */
#define CL_ERR_WRONG_LANG (1 << 2) /* Option for wrong language. */
#define CL_ERR_UINT_ARG (1 << 3) /* Bad unsigned integer argument. */
-#define CL_ERR_ENUM_ARG (1 << 4) /* Bad enumerated argument. */
-#define CL_ERR_NEGATIVE (1 << 5) /* Negative form of option
+#define CL_ERR_INT_RANGE_ARG (1 << 4) /* Bad unsigned integer argument. */
+#define CL_ERR_ENUM_ARG (1 << 5) /* Bad enumerated argument. */
+#define CL_ERR_NEGATIVE (1 << 6) /* Negative form of option
not permitted (together
with OPT_SPECIAL_unknown). */
diff --git a/gcc/params.def b/gcc/params.def
index 6b07518a34b..805302bb93e 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -1142,6 +1142,11 @@ DEFPARAM (PARAM_ASAN_STACK,
"Enable asan stack protection.",
1, 0, 1)
+DEFPARAM (PARAM_ASAN_PROTECT_ALLOCAS,
+ "asan-instrument-allocas",
+ "Enable asan allocas/VLAs protection.",
+ 1, 0, 1)
+
DEFPARAM (PARAM_ASAN_GLOBALS,
"asan-globals",
"Enable asan globals protection.",
diff --git a/gcc/params.h b/gcc/params.h
index 8b916607f16..2188e1877e9 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -232,6 +232,8 @@ extern void init_param_values (int *params);
PARAM_VALUE (PARAM_ALLOW_PACKED_STORE_DATA_RACES)
#define ASAN_STACK \
PARAM_VALUE (PARAM_ASAN_STACK)
+#define ASAN_PROTECT_ALLOCAS \
+ PARAM_VALUE (PARAM_ASAN_PROTECT_ALLOCAS)
#define ASAN_GLOBALS \
PARAM_VALUE (PARAM_ASAN_GLOBALS)
#define ASAN_INSTRUMENT_READS \
diff --git a/gcc/passes.c b/gcc/passes.c
index 374f6f77897..f5791ac806a 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1796,6 +1796,7 @@ emergency_dump_function ()
if (!dump_file || !cfun)
return;
fnotice (stderr, "dump file: %s\n", dump_file_name);
+ fprintf (dump_file, "\n\n\nEMERGENCY DUMP:\n\n");
execute_function_dump (cfun, current_pass);
}
diff --git a/gcc/predict.c b/gcc/predict.c
index 44151bc2e6c..609c099d7b5 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
#include "gimple-pretty-print.h"
#include "selftest.h"
+#include "cfgrtl.h"
/* Enum with reasons why a predictor is ignored. */
@@ -244,7 +245,8 @@ probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
static bool
unlikely_executed_edge_p (edge e)
{
- return e->count == profile_count::zero ()
+ return (e->count == profile_count::zero ()
+ || e->probability == profile_probability::never ())
|| (e->flags & (EDGE_EH | EDGE_FAKE));
}
@@ -253,8 +255,8 @@ unlikely_executed_edge_p (edge e)
bool
probably_never_executed_edge_p (struct function *fun, edge e)
{
- if (e->count.initialized_p ())
- unlikely_executed_edge_p (e);
+ if (unlikely_executed_edge_p (e))
+ return true;
return probably_never_executed (fun, e->count, EDGE_FREQUENCY (e));
}
@@ -404,11 +406,11 @@ optimize_loop_nest_for_size_p (struct loop *loop)
bool
predictable_edge_p (edge e)
{
- if (profile_status_for_fn (cfun) == PROFILE_ABSENT)
+ if (!e->probability.initialized_p ())
return false;
- if ((e->probability
+ if ((e->probability.to_reg_br_prob_base ()
<= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100)
- || (REG_BR_PROB_BASE - e->probability
+ || (REG_BR_PROB_BASE - e->probability.to_reg_br_prob_base ()
<= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100))
return true;
return false;
@@ -511,35 +513,11 @@ edge_predicted_by_p (edge e, enum br_predictor predictor, bool taken)
return false;
}
-/* Return true when the probability of edge is reliable.
-
- The profile guessing code is good at predicting branch outcome (ie.
- taken/not taken), that is predicted right slightly over 75% of time.
- It is however notoriously poor on predicting the probability itself.
- In general the profile appear a lot flatter (with probabilities closer
- to 50%) than the reality so it is bad idea to use it to drive optimization
- such as those disabling dynamic branch prediction for well predictable
- branches.
-
- There are two exceptions - edges leading to noreturn edges and edges
- predicted by number of iterations heuristics are predicted well. This macro
- should be able to distinguish those, but at the moment it simply check for
- noreturn heuristic that is only one giving probability over 99% or bellow
- 1%. In future we might want to propagate reliability information across the
- CFG if we find this information useful on multiple places. */
-static bool
-probability_reliable_p (int prob)
-{
- return (profile_status_for_fn (cfun) == PROFILE_READ
- || (profile_status_for_fn (cfun) == PROFILE_GUESSED
- && (prob <= HITRATE (1) || prob >= HITRATE (99))));
-}
-
/* Same predicate as above, working on edges. */
bool
edge_probability_reliable_p (const_edge e)
{
- return probability_reliable_p (e->probability);
+ return e->probability.probably_reliable_p ();
}
/* Same predicate as edge_probability_reliable_p, working on notes. */
@@ -547,7 +525,8 @@ bool
br_prob_note_reliable_p (const_rtx note)
{
gcc_assert (REG_NOTE_KIND (note) == REG_BR_PROB);
- return probability_reliable_p (XINT (note, 0));
+ return profile_probability::from_reg_br_prob_note
+ (XINT (note, 0)).probably_reliable_p ();
}
static void
@@ -721,7 +700,8 @@ invert_br_probabilities (rtx insn)
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_BR_PROB)
- XINT (note, 0) = REG_BR_PROB_BASE - XINT (note, 0);
+ XINT (note, 0) = profile_probability::from_reg_br_prob_note
+ (XINT (note, 0)).invert ().to_reg_br_prob_note ();
else if (REG_NOTE_KIND (note) == REG_BR_PRED)
XEXP (XEXP (note, 0), 1)
= GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (XEXP (note, 0), 1)));
@@ -837,16 +817,25 @@ static void
set_even_probabilities (basic_block bb,
hash_set<edge> *unlikely_edges = NULL)
{
- unsigned nedges = 0;
+ unsigned nedges = 0, unlikely_count = 0;
edge e = NULL;
edge_iterator ei;
+ profile_probability all = profile_probability::always ();
FOR_EACH_EDGE (e, ei, bb->succs)
- if (!unlikely_executed_edge_p (e))
- nedges ++;
+ if (e->probability.initialized_p ())
+ all -= e->probability;
+ else if (!unlikely_executed_edge_p (e))
+ {
+ nedges ++;
+ if (unlikely_edges != NULL && unlikely_edges->contains (e))
+ {
+ all -= profile_probability::very_unlikely ();
+ unlikely_count++;
+ }
+ }
/* Make the distribution even if all edges are unlikely. */
- unsigned unlikely_count = unlikely_edges ? unlikely_edges->elements () : 0;
if (unlikely_count == nedges)
{
unlikely_edges = NULL;
@@ -856,15 +845,26 @@ set_even_probabilities (basic_block bb,
unsigned c = nedges - unlikely_count;
FOR_EACH_EDGE (e, ei, bb->succs)
- if (!unlikely_executed_edge_p (e))
+ if (e->probability.initialized_p ())
+ ;
+ else if (!unlikely_executed_edge_p (e))
{
if (unlikely_edges != NULL && unlikely_edges->contains (e))
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
else
- e->probability = (REG_BR_PROB_BASE + c / 2) / c;
+ e->probability = all.apply_scale (1, c).guessed ();
}
else
- e->probability = 0;
+ e->probability = profile_probability::never ();
+}
+
+/* Add REG_BR_PROB note to JUMP with PROB. */
+
+void
+add_reg_br_prob_note (rtx_insn *jump, profile_probability prob)
+{
+ gcc_checking_assert (JUMP_P (jump) && !find_reg_note (jump, REG_BR_PROB, 0));
+ add_int_reg_note (jump, REG_BR_PROB, prob.to_reg_br_prob_note ());
}
/* Combine all REG_BR_PRED notes into single probability and attach REG_BR_PROB
@@ -965,26 +965,29 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
if (!prob_note)
{
- add_int_reg_note (insn, REG_BR_PROB, combined_probability);
+ profile_probability p
+ = profile_probability::from_reg_br_prob_base (combined_probability);
+ add_reg_br_prob_note (insn, p);
/* Save the prediction into CFG in case we are seeing non-degenerated
conditional jump. */
if (!single_succ_p (bb))
{
- BRANCH_EDGE (bb)->probability = combined_probability;
+ BRANCH_EDGE (bb)->probability = p;
FALLTHRU_EDGE (bb)->probability
- = REG_BR_PROB_BASE - combined_probability;
+ = BRANCH_EDGE (bb)->probability.invert ();
}
}
else if (!single_succ_p (bb))
{
- int prob = XINT (prob_note, 0);
+ profile_probability prob = profile_probability::from_reg_br_prob_note
+ (XINT (prob_note, 0));
BRANCH_EDGE (bb)->probability = prob;
- FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
+ FALLTHRU_EDGE (bb)->probability = prob.invert ();
}
else
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
}
/* Edge prediction hash traits. */
@@ -1129,6 +1132,8 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
if (!first)
first = e;
}
+ else if (!e->probability.initialized_p ())
+ e->probability = profile_probability::never ();
/* When there is no successor or only one choice, prediction is easy.
@@ -1156,7 +1161,7 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
if (pred->ep_probability <= PROB_VERY_UNLIKELY)
unlikely_edges.add (pred->ep_edge);
- if (!bb->count.initialized_p () && !dry_run)
+ if (!dry_run)
set_even_probabilities (bb, &unlikely_edges);
clear_bb_predictions (bb);
if (dump_file)
@@ -1173,8 +1178,8 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
nedges, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
if (!unlikely_executed_edge_p (e))
- dump_prediction (dump_file, PRED_COMBINED, e->probability,
- bb, REASON_NONE, e);
+ dump_prediction (dump_file, PRED_COMBINED,
+ e->probability.to_reg_br_prob_base (), bb, REASON_NONE, e);
}
}
return;
@@ -1284,8 +1289,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
if (!bb->count.initialized_p () && !dry_run)
{
- first->probability = combined_probability;
- second->probability = REG_BR_PROB_BASE - combined_probability;
+ first->probability
+ = profile_probability::from_reg_br_prob_base (combined_probability);
+ second->probability = first->probability.invert ();
}
}
@@ -3042,7 +3048,7 @@ propagate_freq (basic_block head, bitmap tovisit)
* BLOCK_INFO (e->src)->frequency /
REG_BR_PROB_BASE); */
- sreal tmp = e->probability;
+ sreal tmp = e->probability.to_reg_br_prob_base ();
tmp *= BLOCK_INFO (e->src)->frequency;
tmp *= real_inv_br_prob_base;
frequency += tmp;
@@ -3074,7 +3080,7 @@ propagate_freq (basic_block head, bitmap tovisit)
= ((e->probability * BLOCK_INFO (bb)->frequency)
/ REG_BR_PROB_BASE); */
- sreal tmp = e->probability;
+ sreal tmp = e->probability.to_reg_br_prob_base ();
tmp *= BLOCK_INFO (bb)->frequency;
EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base;
}
@@ -3368,6 +3374,55 @@ expensive_function_p (int threshold)
return false;
}
+/* All basic blocks that are reachable only from unlikely basic blocks are
+ unlikely. */
+
+void
+propagate_unlikely_bbs_forward (void)
+{
+ auto_vec<basic_block, 64> worklist;
+ basic_block bb;
+ edge_iterator ei;
+ edge e;
+
+ if (!(ENTRY_BLOCK_PTR_FOR_FN (cfun)->count == profile_count::zero ()))
+ {
+ ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = (void *)(size_t) 1;
+ worklist.safe_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+
+ while (worklist.length () > 0)
+ {
+ bb = worklist.pop ();
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!(e->count == profile_count::zero ())
+ && !(e->dest->count == profile_count::zero ())
+ && !e->dest->aux)
+ {
+ e->dest->aux = (void *)(size_t) 1;
+ worklist.safe_push (e->dest);
+ }
+ }
+ }
+
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ if (!bb->aux)
+ {
+ if (!(bb->count == profile_count::zero ())
+ && (dump_file && (dump_flags & TDF_DETAILS)))
+ fprintf (dump_file,
+ "Basic block %i is marked unlikely by forward prop\n",
+ bb->index);
+ bb->count = profile_count::zero ();
+ bb->frequency = 0;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->count = profile_count::zero ();
+ }
+ else
+ bb->aux = NULL;
+ }
+}
+
/* Determine basic blocks/edges that are known to be unlikely executed and set
their counters to zero.
This is done with first identifying obviously unlikely BBs/edges and then
@@ -3412,43 +3467,6 @@ determine_unlikely_bbs ()
gcc_checking_assert (!bb->aux);
}
- if (!(ENTRY_BLOCK_PTR_FOR_FN (cfun)->count == profile_count::zero ()))
- {
- ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = (void *)(size_t) 1;
- worklist.safe_push (ENTRY_BLOCK_PTR_FOR_FN (cfun));
-
- while (worklist.length () > 0)
- {
- bb = worklist.pop ();
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->count == profile_count::zero ())
- && !(e->dest->count == profile_count::zero ())
- && !e->dest->aux)
- {
- e->dest->aux = (void *)(size_t) 1;
- worklist.safe_push (e->dest);
- }
- }
- }
-
- FOR_ALL_BB_FN (bb, cfun)
- {
- if (!bb->aux)
- {
- if (!(bb->count == profile_count::zero ())
- && (dump_file && (dump_flags & TDF_DETAILS)))
- fprintf (dump_file,
- "Basic block %i is marked unlikely by forward prop\n",
- bb->index);
- bb->count = profile_count::zero ();
- bb->frequency = 0;
- FOR_EACH_EDGE (e, ei, bb->succs)
- e->count = profile_count::zero ();
- }
- else
- bb->aux = NULL;
- }
-
auto_vec<int, 64> nsuccs;
nsuccs.safe_grow_cleared (last_basic_block_for_fn (cfun));
FOR_ALL_BB_FN (bb, cfun)
@@ -3534,7 +3552,7 @@ estimate_bb_frequencies (bool force)
mark_dfs_back_edges ();
single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->probability =
- REG_BR_PROB_BASE;
+ profile_probability::always ();
/* Set up block info for each basic block. */
alloc_aux_for_blocks (sizeof (block_info));
@@ -3546,7 +3564,8 @@ estimate_bb_frequencies (bool force)
FOR_EACH_EDGE (e, ei, bb->succs)
{
- EDGE_INFO (e)->back_edge_prob = e->probability;
+ EDGE_INFO (e)->back_edge_prob
+ = e->probability.to_reg_br_prob_base ();
EDGE_INFO (e)->back_edge_prob *= real_inv_br_prob_base;
}
}
@@ -3898,16 +3917,18 @@ void
force_edge_cold (edge e, bool impossible)
{
profile_count count_sum = profile_count::zero ();
- int prob_sum = 0;
+ profile_probability prob_sum = profile_probability::never ();
edge_iterator ei;
edge e2;
profile_count old_count = e->count;
- int old_probability = e->probability;
- int prob_scale = REG_BR_PROB_BASE;
+ profile_probability old_probability = e->probability;
bool uninitialized_exit = false;
+ profile_probability goal = (impossible ? profile_probability::never ()
+ : profile_probability::very_unlikely ());
+
/* If edge is already improbably or cold, just return. */
- if (e->probability <= (impossible ? PROB_VERY_UNLIKELY : 0)
+ if (e->probability <= goal
&& (!impossible || e->count == profile_count::zero ()))
return;
FOR_EACH_EDGE (e2, ei, e->src->succs)
@@ -3917,24 +3938,26 @@ force_edge_cold (edge e, bool impossible)
count_sum += e2->count;
else
uninitialized_exit = true;
- prob_sum += e2->probability;
+ if (e2->probability.initialized_p ())
+ prob_sum += e2->probability;
}
/* If there are other edges out of e->src, redistribute probabilitity
there. */
- if (prob_sum)
+ if (prob_sum > profile_probability::never ())
{
- e->probability
- = MIN (e->probability, impossible ? 0 : PROB_VERY_UNLIKELY);
+ if (!(e->probability < goal))
+ e->probability = goal;
if (impossible)
e->count = profile_count::zero ();
- else if (old_probability)
- e->count = e->count.apply_scale (e->probability, old_probability);
+ else if (old_probability > profile_probability::never ())
+ e->count = e->count.apply_probability (e->probability
+ / old_probability);
else
e->count = e->count.apply_scale (1, REG_BR_PROB_BASE);
- prob_scale = RDIV ((REG_BR_PROB_BASE - e->probability) * REG_BR_PROB_BASE,
- prob_sum);
+ profile_probability prob_comp = prob_sum / e->probability.invert ();
+
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Making edge %i->%i %s by redistributing "
"probability to other edges.\n",
@@ -3946,30 +3969,50 @@ force_edge_cold (edge e, bool impossible)
{
if (count_sum > 0)
e2->count.apply_scale (count_sum2, count_sum);
- e2->probability = RDIV (e2->probability * prob_scale,
- REG_BR_PROB_BASE);
+ e2->probability /= prob_comp;
}
+ if (current_ir_type () != IR_GIMPLE
+ && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
+ update_br_prob_note (e->src);
}
/* If all edges out of e->src are unlikely, the basic block itself
is unlikely. */
else
{
- e->probability = REG_BR_PROB_BASE;
+ if (prob_sum == profile_probability::never ())
+ e->probability = profile_probability::always ();
+ else
+ {
+ if (impossible)
+ e->probability = profile_probability::never ();
+ /* If BB has some edges out that are not impossible, we can not
+ assume that BB itself is. */
+ impossible = false;
+ }
+ if (current_ir_type () != IR_GIMPLE
+ && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
+ update_br_prob_note (e->src);
if (e->src->count == profile_count::zero ())
return;
if (count_sum == profile_count::zero () && !uninitialized_exit
&& impossible)
{
bool found = false;
- for (gimple_stmt_iterator gsi = gsi_start_bb (e->src);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- if (stmt_can_terminate_bb_p (gsi_stmt (gsi)))
- {
- found = true;
- break;
- }
- }
+ if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
+ ;
+ else if (current_ir_type () == IR_GIMPLE)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (e->src);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ if (stmt_can_terminate_bb_p (gsi_stmt (gsi)))
+ {
+ found = true;
+ break;
+ }
+ }
+ /* FIXME: Implement RTL path. */
+ else
+ found = true;
if (!found)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3989,7 +4032,8 @@ force_edge_cold (edge e, bool impossible)
This in general is difficult task to do, but handle special case when
BB has only one predecestor. This is common case when we are updating
after loop transforms. */
- if (!prob_sum && count_sum == profile_count::zero ()
+ if (!(prob_sum > profile_probability::never ())
+ && count_sum == profile_count::zero ()
&& single_pred_p (e->src) && e->src->frequency > (impossible ? 0 : 1))
{
int old_frequency = e->src->frequency;
@@ -4031,7 +4075,7 @@ test_prediction_value_range ()
{
branch_predictor predictors[] = {
#include "predict.def"
- {NULL, -1}
+ {NULL, -1U}
};
for (unsigned i = 0; predictors[i].name != NULL; i++)
diff --git a/gcc/predict.def b/gcc/predict.def
index f7b2bf7738c..326c39ae4c9 100644
--- a/gcc/predict.def
+++ b/gcc/predict.def
@@ -132,9 +132,8 @@ DEF_PREDICTOR (PRED_RECURSIVE_CALL, "recursive call", HITRATE (75), 0)
DEF_PREDICTOR (PRED_TREE_EARLY_RETURN, "early return (on trees)", HITRATE (66),
0)
-/* Branch containing goto is probably not taken.
- FIXME: Currently not used. */
-DEF_PREDICTOR (PRED_GOTO, "goto", HITRATE (70), 0)
+/* Branch containing goto is probably not taken. */
+DEF_PREDICTOR (PRED_GOTO, "goto", HITRATE (66), 0)
/* Branch ending with return constant is probably not taken. */
DEF_PREDICTOR (PRED_CONST_RETURN, "const return", HITRATE (69), 0)
diff --git a/gcc/predict.h b/gcc/predict.h
index 1441fa4d8eb..9b8b14022e3 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -47,6 +47,9 @@ enum prediction
TAKEN
};
+/* In emit-rtl.c. */
+extern profile_probability split_branch_probability;
+
extern gcov_type get_hot_bb_threshold (void);
extern void set_hot_bb_threshold (gcov_type);
extern bool maybe_hot_count_p (struct function *, profile_count);
@@ -95,5 +98,8 @@ extern const char *predictor_name (enum br_predictor);
extern void rebuild_frequencies (void);
extern void report_predictor_hitrates (void);
extern void force_edge_cold (edge, bool);
+extern void propagate_unlikely_bbs_forward (void);
+
+extern void add_reg_br_prob_note (rtx_insn *, profile_probability);
#endif /* GCC_PREDICT_H */
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 40e56a35d93..98296b1c20f 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#define GCC_PRETTY_PRINT_H
#include "obstack.h"
-#include "wide-int-print.h"
/* Maximum number of format string arguments. */
#define PP_NL_ARGMAX 30
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index ea26a0b022e..6a237cc1253 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -487,7 +487,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
{
- print_node_brief (file, "attributes",
+ print_node (file, "attributes",
DECL_ATTRIBUTES (node), indent + 4);
if (code != PARM_DECL)
print_node_brief (file, "initial", DECL_INITIAL (node),
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index e64d1b56421..4d22428a195 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -31,6 +31,8 @@ along with GCC; see the file COPYING3. If not see
#include "data-streamer.h"
#include "cgraph.h"
+/* Dump THIS to F. */
+
void
profile_count::dump (FILE *f) const
{
@@ -39,43 +41,53 @@ profile_count::dump (FILE *f) const
else
{
fprintf (f, "%" PRId64, m_val);
- if (m_quality == count_adjusted)
- fprintf (f, "(adjusted)");
- else if (m_quality == count_afdo)
- fprintf (f, "(auto FDO)");
- else if (m_quality == count_guessed)
- fprintf (f, "(guessed)");
+ if (m_quality == profile_adjusted)
+ fprintf (f, " (adjusted)");
+ else if (m_quality == profile_afdo)
+ fprintf (f, " (auto FDO)");
+ else if (m_quality == profile_guessed)
+ fprintf (f, " (guessed)");
}
}
+/* Dump THIS to stderr. */
+
void
profile_count::debug () const
{
dump (stderr);
+ fprintf (stderr, "\n");
}
+/* Return true if THIS differs from OTHER; tolerate small diferences. */
+
bool
profile_count::differs_from_p (profile_count other) const
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (m_val - other.m_val < 100 || other.m_val - m_val < 100)
+ if ((uint64_t)m_val - (uint64_t)other.m_val < 100
+ || (uint64_t)other.m_val - (uint64_t)m_val < 100)
return false;
if (!other.m_val)
return true;
- int64_t ratio = m_val * 100 / other.m_val;
+ int64_t ratio = (int64_t)m_val * 100 / other.m_val;
return ratio < 99 || ratio > 101;
}
+/* Stream THIS from IB. */
+
profile_count
profile_count::stream_in (struct lto_input_block *ib)
{
profile_count ret;
ret.m_val = streamer_read_gcov_count (ib);
- ret.m_quality = (profile_count_quality) streamer_read_uhwi (ib);
+ ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
return ret;
}
+/* Stream THIS to OB. */
+
void
profile_count::stream_out (struct output_block *ob)
{
@@ -83,9 +95,102 @@ profile_count::stream_out (struct output_block *ob)
streamer_write_uhwi (ob, m_quality);
}
+/* Stream THIS to OB. */
+
void
profile_count::stream_out (struct lto_output_stream *ob)
{
streamer_write_gcov_count_stream (ob, m_val);
streamer_write_uhwi_stream (ob, m_quality);
}
+
+/* Dump THIS to F. */
+
+void
+profile_probability::dump (FILE *f) const
+{
+ if (!initialized_p ())
+ fprintf (f, "uninitialized");
+ else
+ {
+ /* Make difference between 0.00 as a roundoff error and actual 0.
+ Similarly for 1. */
+ if (m_val == 0)
+ fprintf (f, "never");
+ else if (m_val == max_probability)
+ fprintf (f, "always");
+ else
+ fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
+ if (m_quality == profile_adjusted)
+ fprintf (f, " (adjusted)");
+ else if (m_quality == profile_afdo)
+ fprintf (f, " (auto FDO)");
+ else if (m_quality == profile_guessed)
+ fprintf (f, " (guessed)");
+ }
+}
+
+/* Dump THIS to stderr. */
+
+void
+profile_probability::debug () const
+{
+ dump (stderr);
+ fprintf (stderr, "\n");
+}
+
+/* Return true if THIS differs from OTHER; tolerate small diferences. */
+
+bool
+profile_probability::differs_from_p (profile_probability other) const
+{
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if ((uint64_t)m_val - (uint64_t)other.m_val < 10
+ || (uint64_t)other.m_val - (uint64_t)m_val < 10)
+ return false;
+ if (!other.m_val)
+ return true;
+ int64_t ratio = m_val * 100 / other.m_val;
+ return ratio < 99 || ratio > 101;
+}
+
+/* Return true if THIS differs significantly from OTHER. */
+
+bool
+profile_probability::differs_lot_from_p (profile_probability other) const
+{
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
+ return d > max_probability / 2;
+}
+
+/* Stream THIS from IB. */
+
+profile_probability
+profile_probability::stream_in (struct lto_input_block *ib)
+{
+ profile_probability ret;
+ ret.m_val = streamer_read_uhwi (ib);
+ ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
+ return ret;
+}
+
+/* Stream THIS to OB. */
+
+void
+profile_probability::stream_out (struct output_block *ob)
+{
+ streamer_write_uhwi (ob, m_val);
+ streamer_write_uhwi (ob, m_quality);
+}
+
+/* Stream THIS to OB. */
+
+void
+profile_probability::stream_out (struct lto_output_stream *ob)
+{
+ streamer_write_uhwi_stream (ob, m_val);
+ streamer_write_uhwi_stream (ob, m_quality);
+}
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 0f77e4efc36..8fd22b8b68a 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -21,21 +21,21 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_PROFILE_COUNT_H
#define GCC_PROFILE_COUNT_H
-/* Quality of the proflie count. Because gengtype does not support enums
- inside of clases, this is in global namespace. */
-enum profile_count_quality {
+/* Quality of the profile count. Because gengtype does not support enums
+ inside of classes, this is in global namespace. */
+enum profile_quality {
/* Profile is based on static branch prediction heuristics. It may or may
not reflect the reality. */
- count_guessed = 0,
+ profile_guessed = 0,
/* Profile was determined by autofdo. */
- count_afdo = 1,
- /* Profile was originally based on feedback but it was adjusted
+ profile_afdo = 1,
+ /* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
- count_adjusted = 2,
+ profile_adjusted = 2,
/* Profile was read from profile feedback or determined by accurate static
method. */
- count_read = 3
+ profile_precise = 3
};
/* The base value for branch probability notes and edge probabilities. */
@@ -43,6 +43,455 @@ enum profile_count_quality {
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
+/* Data type to hold probabilities. It implements fixed point arithmetics
+ with capping so probability is always in range [0,1] and scaling requiring
+ values greater than 1 needs to be represented otherwise.
+
+ In addition to actual value the quality of profile is tracked and propagated
+ through all operations. Special value UNINITIALIZED is used for probabilities
+ that has not been determined yet (for example bacause of
+ -fno-guess-branch-probability)
+
+ Typically probabilities are derived from profile feedback (via
+ probability_in_gcov_type), autoFDO or guessed statically and then propagated
+ thorough the compilation.
+
+ Named probabilities are available:
+ - never (0 probability)
+ - guessed_never
+ - very_unlikely (1/2000 probability)
+ - unlikely (1/5 probablity)
+ - even (1/2 probability)
+ - likely (4/5 probability)
+ - very_likely (1999/2000 probability)
+ - guessed_always
+ - always
+
+ Named probabilities except for never/always are assumed to be statically
+ guessed and thus not necessarily accurate. The difference between never
+ and guessed_never is that the first one should be used only in case that
+ well behaving program will very likely not execute the "never" path.
+ For example if the path is going to abort () call or it exception handling.
+
+ Always and guessed_always probabilities are symmetric.
+
+ For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
+ integer arithmetics. Once the code is converted to branch probabilities,
+ these conversions will probably go away because they are lossy.
+*/
+
+class GTY((user)) profile_probability
+{
+ /* For now use values in range 0...REG_BR_PROB_BASE. Later we can use full
+ precision of 30 bits available. */
+
+ static const int n_bits = 30;
+ static const uint32_t max_probability = REG_BR_PROB_BASE;
+ static const uint32_t uninitialized_probability = ((uint32_t) 1 << n_bits) - 1;
+
+ uint32_t m_val : 30;
+ enum profile_quality m_quality : 2;
+
+ friend class profile_count;
+public:
+
+ /* Named probabilities. */
+ static profile_probability never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+ static profile_probability guessed_never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ static profile_probability very_unlikely ()
+ {
+ /* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
+ profile_probability r
+ = profile_probability::always ().apply_scale (1, 2000);
+ r.m_val--;
+ return r;
+ }
+ static profile_probability unlikely ()
+ {
+ /* Be consistent with PROB_VERY_LIKELY in predict.h. */
+ profile_probability r
+ = profile_probability::always ().apply_scale (1, 5);
+ r.m_val--;
+ return r;
+ }
+ static profile_probability even ()
+ {
+ return profile_probability::always ().apply_scale (1, 2);
+ }
+ static profile_probability very_likely ()
+ {
+ return profile_probability::always () - very_unlikely ();
+ }
+ static profile_probability likely ()
+ {
+ return profile_probability::always () - unlikely ();
+ }
+ static profile_probability guessed_always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ static profile_probability always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+ /* Probabilities which has not been initialized. Either because
+ initialization did not happen yet or because profile is unknown. */
+ static profile_probability uninitialized ()
+ {
+ profile_probability c;
+ c.m_val = uninitialized_probability;
+ c.m_quality = profile_guessed;
+ return c;
+ }
+
+
+ /* Return true if value has been initialized. */
+ bool initialized_p () const
+ {
+ return m_val != uninitialized_probability;
+ }
+ /* Return true if value can be trusted. */
+ bool reliable_p () const
+ {
+ return initialized_p ();
+ }
+
+ /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
+ this is mostly to support legacy code and should go away. */
+ static profile_probability from_reg_br_prob_base (int v)
+ {
+ profile_probability ret;
+ gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
+ ret.m_val = RDIV (v * max_probability, REG_BR_PROB_BASE);
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ int to_reg_br_prob_base () const
+ {
+ gcc_checking_assert (initialized_p ());
+ return RDIV (m_val * REG_BR_PROB_BASE, max_probability);
+ }
+
+ /* Conversion to and from RTL representation of profile probabilities. */
+ static profile_probability from_reg_br_prob_note (int v)
+ {
+ profile_probability ret;
+ ret.m_val = ((unsigned int)v) / 4;
+ ret.m_quality = (enum profile_quality)(v & 3);
+ return ret;
+ }
+ int to_reg_br_prob_note () const
+ {
+ gcc_checking_assert (initialized_p ());
+ int ret = m_val * 4 + m_quality;
+ gcc_checking_assert (profile_probability::from_reg_br_prob_note (ret)
+ == *this);
+ return ret;
+ }
+
+ /* Return VAL1/VAL2. */
+ static profile_probability probability_in_gcov_type
+ (gcov_type val1, gcov_type val2)
+ {
+ profile_probability ret;
+ gcc_checking_assert (val1 >= 0 && val2 > 0);
+ if (val1 > val2)
+ ret.m_val = max_probability;
+ else
+ ret.m_val = RDIV (val1 * max_probability, val2);
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+
+ /* Basic operations. */
+ bool operator== (const profile_probability &other) const
+ {
+ return m_val == other.m_val && m_quality == other.m_quality;
+ }
+ profile_probability operator+ (const profile_probability &other) const
+ {
+ if (other == profile_probability::never ())
+ return *this;
+ if (*this == profile_probability::never ())
+ return other;
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+
+ profile_probability ret;
+ ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator+= (const profile_probability &other)
+ {
+ if (other == profile_probability::never ())
+ return *this;
+ if (*this == profile_probability::never ())
+ {
+ *this = other;
+ return *this;
+ }
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator- (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator-= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator* (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator*= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this = profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator/ (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ())
+ return profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ if (m_val >= other.m_val)
+ ret.m_val = max_probability;
+ else if (!m_val)
+ ret.m_val = 0;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator/= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ())
+ return *this = profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ if (m_val > other.m_val)
+ m_val = max_probability;
+ else if (!m_val)
+ ;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ gcov_type apply (gcov_type val) const
+ {
+ if (*this == profile_probability::uninitialized ())
+ return val / 2;
+ return RDIV (val * m_val, max_probability);
+ }
+
+ /* Return 1-*THIS. */
+ profile_probability invert () const
+ {
+ return profile_probability::always() - *this;
+ }
+
+ /* Return THIS with quality dropped to GUESSED. */
+ profile_probability guessed () const
+ {
+ profile_probability ret = *this;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to AFDO. */
+ profile_probability afdo () const
+ {
+ profile_probability ret = *this;
+ ret.m_quality = profile_afdo;
+ return ret;
+ }
+
+ profile_probability combine_with_freq (int freq1, profile_probability other,
+ int freq2) const
+ {
+ profile_probability ret;
+
+ if (*this == profile_probability::uninitialized ()
+ || other == profile_probability::uninitialized ())
+ return profile_probability::uninitialized ();
+
+ gcc_checking_assert (freq1 >= 0 && freq2 >= 0);
+ if (!freq1 && !freq2)
+ {
+ ret.m_val = (m_val + other.m_val) / 2;
+ }
+ else
+ ret.m_val = RDIV (m_val * (uint64_t) freq1
+ + other.m_val * (uint64_t) freq2, freq1 + freq2);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ /* Return *THIS * NUM / DEN. */
+ profile_probability apply_scale (int64_t num, int64_t den) const
+ {
+ if (*this == profile_probability::never ())
+ return *this;
+ if (!initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = MIN (RDIV (m_val * num, den),
+ max_probability);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
+ return ret;
+ }
+
+ /* Return true when the probability of edge is reliable.
+
+ The profile guessing code is good at predicting branch outcome (ie.
+ taken/not taken), that is predicted right slightly over 75% of time.
+ It is however notoriously poor on predicting the probability itself.
+ In general the profile appear a lot flatter (with probabilities closer
+ to 50%) than the reality so it is bad idea to use it to drive optimization
+ such as those disabling dynamic branch prediction for well predictable
+ branches.
+
+ There are two exceptions - edges leading to noreturn edges and edges
+ predicted by number of iterations heuristics are predicted well. This macro
+ should be able to distinguish those, but at the moment it simply check for
+ noreturn heuristic that is only one giving probability over 99% or bellow
+ 1%. In future we might want to propagate reliability information across the
+ CFG if we find this information useful on multiple places. */
+
+ bool probably_reliable_p () const
+ {
+ if (m_quality >= profile_adjusted)
+ return true;
+ if (!initialized_p ())
+ return false;
+ return m_val < max_probability / 100
+ || m_val > max_probability - max_probability / 100;
+ }
+
+ /* Return false if profile_probability is bogus. */
+ bool verify () const
+ {
+ if (m_val == uninitialized_probability)
+ return m_quality == profile_guessed;
+ else
+ return m_val <= REG_BR_PROB_BASE;
+ }
+
+ /* Comparsions are three-state and conservative. False is returned if
+ the inequality can not be decided. */
+ bool operator< (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val < other.m_val;
+ }
+ bool operator> (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val > other.m_val;
+ }
+
+ bool operator<= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val <= other.m_val;
+ }
+ bool operator>= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val >= other.m_val;
+ }
+
+ /* Output THIS to F. */
+ void dump (FILE *f) const;
+
+ /* Print THIS to stderr. */
+ void debug () const;
+
+ /* Return true if THIS is known to differ significantly from OTHER. */
+ bool differs_from_p (profile_probability other) const;
+ /* Return if difference is greater than 50%. */
+ bool differs_lot_from_p (profile_probability other) const;
+
+ /* LTO streaming support. */
+ static profile_probability stream_in (struct lto_input_block *);
+ void stream_out (struct output_block *);
+ void stream_out (struct lto_output_stream *);
+};
+
/* Main data type to hold profile counters in GCC. In most cases profile
counts originate from profile feedback. They are 64bit integers
representing number of executions during the train run.
@@ -85,12 +534,12 @@ class GTY(()) profile_count
static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
uint64_t m_val : n_bits;
- enum profile_count_quality m_quality : 2;
+ enum profile_quality m_quality : 2;
/* Assume numbers smaller than this to multiply. This is set to make
testsuite pass, in future we may implement precise multiplication in higer
rangers. */
- static const int64_t max_safe_multiplier = 131072;
+ static const uint64_t max_safe_multiplier = 131072;
public:
/* Used for counters which are expected to be never executed. */
@@ -98,6 +547,13 @@ public:
{
return from_gcov_type (0);
}
+ static profile_count guessed_zero ()
+ {
+ profile_count c;
+ c.m_val = 0;
+ c.m_quality = profile_guessed;
+ return c;
+ }
static profile_count one ()
{
return from_gcov_type (1);
@@ -108,7 +564,7 @@ public:
{
profile_count c;
c.m_val = uninitialized_count;
- c.m_quality = count_guessed;
+ c.m_quality = profile_guessed;
return c;
}
@@ -120,7 +576,7 @@ public:
profile_count ret;
gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
ret.m_val = v;
- ret.m_quality = count_read;
+ ret.m_quality = profile_precise;
return ret;
}
@@ -142,6 +598,31 @@ public:
return initialized_p ();
}
+ /* When merging basic blocks, the two different profile counts are unified.
+ Return true if this can be done without losing info about profile.
+ The only case we care about here is when first BB contains something
+ that makes it terminate in a way not visible in CFG. */
+ bool ok_for_merging (profile_count other) const
+ {
+ if (m_quality < profile_adjusted
+ || other.m_quality < profile_adjusted)
+ return true;
+ return !(other < *this);
+ }
+
+ /* When merging two BBs with different counts, pick common count that looks
+ most representative. */
+ profile_count merge (profile_count other) const
+ {
+ if (*this == other || !other.initialized_p ()
+ || m_quality > other.m_quality)
+ return *this;
+ if (other.m_quality > m_quality
+ || other > *this)
+ return other;
+ return *this;
+ }
+
/* Basic operations. */
bool operator== (const profile_count &other) const
{
@@ -175,7 +656,7 @@ public:
else
{
m_val += other.m_val;
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -199,7 +680,7 @@ public:
else
{
m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -207,7 +688,7 @@ public:
/* Return false if profile_count is bogus. */
bool verify () const
{
- return m_val != uninitialized_count || m_quality == count_guessed;
+ return m_val != uninitialized_count || m_quality == profile_guessed;
}
/* Comparsions are three-state and conservative. False is returned if
@@ -237,7 +718,7 @@ public:
}
bool operator>= (const profile_count &other) const
{
- return initialized_p () && m_val >= other.m_val;
+ return initialized_p () && other.initialized_p () && m_val >= other.m_val;
}
bool operator<= (const gcov_type other) const
{
@@ -261,7 +742,23 @@ public:
return profile_count::uninitialized ();
profile_count ret;
ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
+ return ret;
+ }
+
+ /* Scale counter according to PROB. */
+ profile_count apply_probability (profile_probability prob) const
+ {
+ if (*this == profile_count::zero ())
+ return *this;
+ if (prob == profile_probability::never ())
+ return profile_count::zero ();
+ if (!initialized_p ())
+ return profile_count::uninitialized ();
+ profile_count ret;
+ ret.m_val = RDIV (m_val * prob.m_val,
+ profile_probability::max_probability);
+ ret.m_quality = MIN (m_quality, prob.m_quality);
return ret;
}
/* Return *THIS * NUM / DEN. */
@@ -277,7 +774,7 @@ public:
gcc_checking_assert ((num <= REG_BR_PROB_BASE
|| den <= REG_BR_PROB_BASE) || 1);
ret.m_val = RDIV (m_val * num, den);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
return ret;
}
profile_count apply_scale (profile_count num, profile_count den) const
@@ -295,27 +792,47 @@ public:
profile_count ret;
/* Take care for overflows! */
if (num.m_val < max_safe_multiplier || m_val < max_safe_multiplier)
- ret.m_val = RDIV (m_val * num.m_val, den.m_val);
+ ret.m_val = RDIV (m_val * num.m_val, den.m_val);
else
- ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
+ ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
den.m_val), max_safe_multiplier);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to GUESSED. */
+ profile_count guessed () const
+ {
+ profile_count ret = *this;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to AFDO. */
+ profile_count afdo () const
+ {
+ profile_count ret = *this;
+ ret.m_quality = profile_afdo;
return ret;
}
/* Return probability of event with counter THIS within event with counter
OVERALL. */
- int probability_in (profile_count overall)
+ profile_probability probability_in (const profile_count overall) const
{
if (!m_val)
- return 0;
- if (!initialized_p () || !overall.initialized_p ())
- return REG_BR_PROB_BASE / 2;
- if (overall < *this)
- return REG_BR_PROB_BASE;
- if (!overall.m_val)
- return REG_BR_PROB_BASE / 2;
- return RDIV (m_val * REG_BR_PROB_BASE, overall.m_val);
+ return profile_probability::never ();
+ if (!initialized_p () || !overall.initialized_p ()
+ || !overall.m_val)
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ if (overall < m_val)
+ ret.m_val = profile_probability::max_probability;
+ else
+ ret.m_val = RDIV (m_val * profile_probability::max_probability,
+ overall.m_val);
+ ret.m_quality = MIN (m_quality, overall.m_quality);
+ return ret;
}
/* Output THIS to F. */
diff --git a/gcc/profile.c b/gcc/profile.c
index 51ca248f5ad..6d40241a37b 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -768,8 +768,8 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
if (bb_gcov_count (bb))
{
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = GCOV_COMPUTE_SCALE (edge_gcov_count (e),
- bb_gcov_count (bb));
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
if (bb->index >= NUM_FIXED_BLOCKS
&& block_ends_with_condjump_p (bb)
&& EDGE_COUNT (bb->succs) >= 2)
@@ -784,7 +784,7 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
if (!(e->flags & (EDGE_FAKE | EDGE_FALLTHRU)))
break;
- prob = e->probability;
+ prob = e->probability.to_reg_br_prob_base ();
index = prob * 20 / REG_BR_PROB_BASE;
if (index == 20)
@@ -810,15 +810,17 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
{
FOR_EACH_EDGE (e, ei, bb->succs)
if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- e->probability = REG_BR_PROB_BASE / total;
+ e->probability
+ = profile_probability::guessed_always ().apply_scale (1, total);
else
- e->probability = 0;
+ e->probability = profile_probability::never ();
}
else
{
total += EDGE_COUNT (bb->succs);
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = REG_BR_PROB_BASE / total;
+ e->probability
+ = profile_probability::guessed_always ().apply_scale (1, total);
}
if (bb->index >= NUM_FIXED_BLOCKS
&& block_ends_with_condjump_p (bb)
diff --git a/gcc/recog.c b/gcc/recog.c
index 63cdc237240..fd4e4605830 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -3460,8 +3460,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
flags);
nehe->probability = eh_edge->probability;
- nfte->probability
- = REG_BR_PROB_BASE - nehe->probability;
+ nfte->probability = nehe->probability.invert ();
peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
bb = nfte->src;
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 8734d26e5b4..943eff41d30 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -99,20 +99,21 @@ REG_NOTE (DEP_OUTPUT)
REG_NOTE (DEP_ANTI)
REG_NOTE (DEP_CONTROL)
-/* REG_BR_PROB is attached to JUMP_INSNs and CALL_INSNs. It has an
+/* REG_BR_PROB is attached to JUMP_INSNs. It has an
integer value (in an INT_LIST). For jumps, it is the probability
- that this is a taken branch. For calls, it is the probability that
- this call won't return. */
+ that this is a taken branch. The integer represents a value of
+ profile_probability type. Use to_reg_br_prob_note and from_reg_br_prob_note
+ to extract the actual value. */
REG_NOTE (BR_PROB)
/* Attached to a call insn; indicates that the call is malloc-like and
that the pointer returned cannot alias anything else. */
REG_NOTE (NOALIAS)
-/* REG_BR_PRED is attached to JUMP_INSNs and CALL_INSNSs. It contains
+/* REG_BR_PRED is attached to JUMP_INSNs. It contains
CONCAT of two integer value. First specifies the branch predictor
that added the note, second specifies the predicted hitrate of
- branch in the same format as REG_BR_PROB note uses. */
+ branch in a fixed point arithmetic based on REG_BR_PROB_BASE. */
REG_NOTE (BR_PRED)
/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
diff --git a/gcc/reorg.c b/gcc/reorg.c
index dbd74ab2404..5914af655b6 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -840,7 +840,8 @@ mostly_true_jump (rtx jump_insn)
rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note)
{
- int prob = XINT (note, 0);
+ int prob = profile_probability::from_reg_br_prob_note (XINT (note, 0))
+ .to_reg_br_prob_base ();
if (prob >= REG_BR_PROB_BASE * 9 / 10)
return 2;
diff --git a/gcc/rtl-tests.c b/gcc/rtl-tests.c
index 705434012d6..54bd6a37e7f 100644
--- a/gcc/rtl-tests.c
+++ b/gcc/rtl-tests.c
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
-#include "signop.h"
#include "hash-set.h"
#include "fixed-value.h"
#include "alias.h"
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 1f6a77aa08e..b0f977eca9c 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -223,7 +223,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
all the rest is initialized to zero. */
rtx
-rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
+rtx_alloc (RTX_CODE code MEM_STAT_DECL)
{
return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
}
@@ -359,7 +359,7 @@ copy_rtx (rtx orig)
/* Create a new copy of an rtx. Only copy just one level. */
rtx
-shallow_copy_rtx_stat (const_rtx orig MEM_STAT_DECL)
+shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
{
const unsigned int size = rtx_size (orig);
rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index c3790ccde9b..8a68bb152bc 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -24,10 +24,6 @@ along with GCC; see the file COPYING3. If not see
machmode.h and other files to exist and would not normally have been
included by coretypes.h. */
#ifdef GENERATOR_FILE
-#include "machmode.h"
-#include "signop.h"
-#include "wide-int.h"
-#include "double-int.h"
#include "real.h"
#include "fixed-value.h"
#include "statistics.h"
@@ -2709,8 +2705,7 @@ extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, machine_mode);
extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false);
/* In rtl.c */
-extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
-#define rtx_alloc(c) rtx_alloc_stat (c MEM_STAT_INFO)
+extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
#define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
#define const_wide_int_alloc(NWORDS) \
@@ -2730,8 +2725,7 @@ extern rtx copy_rtx_if_shared (rtx);
/* In rtl.c */
extern unsigned int rtx_size (const_rtx);
-extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL);
-#define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO)
+extern rtx shallow_copy_rtx (const_rtx CXX_MEM_STAT_INFO);
extern int rtx_equal_p (const_rtx, const_rtx);
extern bool rtvec_all_equal_p (const_rtvec);
@@ -2942,7 +2936,6 @@ extern rtx *find_constant_term_loc (rtx *);
/* In emit-rtl.c */
extern rtx_insn *try_split (rtx, rtx_insn *, int);
-extern int split_branch_probability;
/* In insn-recog.c (generated by genrecog). */
extern rtx_insn *split_insns (rtx, rtx_insn *);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index bf4183e793d..9bfae8cb9b0 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5263,23 +5263,41 @@ insn_rtx_cost (rtx pat, bool speed)
int i, cost;
rtx set;
- /* Extract the single set rtx from the instruction pattern.
- We can't use single_set since we only have the pattern. */
+ /* Extract the single set rtx from the instruction pattern. We
+ can't use single_set since we only have the pattern. We also
+ consider PARALLELs of a normal set and a single comparison. In
+ that case we use the cost of the non-comparison SET operation,
+ which is most-likely to be the real cost of this operation. */
if (GET_CODE (pat) == SET)
set = pat;
else if (GET_CODE (pat) == PARALLEL)
{
set = NULL_RTX;
+ rtx comparison = NULL_RTX;
+
for (i = 0; i < XVECLEN (pat, 0); i++)
{
rtx x = XVECEXP (pat, 0, i);
if (GET_CODE (x) == SET)
{
- if (set)
- return 0;
- set = x;
+ if (GET_CODE (SET_SRC (x)) == COMPARE)
+ {
+ if (comparison)
+ return 0;
+ comparison = x;
+ }
+ else
+ {
+ if (set)
+ return 0;
+ set = x;
+ }
}
}
+
+ if (!set && comparison)
+ set = comparison;
+
if (!set)
return 0;
}
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 8b4acfcf453..c90fa94c4a9 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -171,6 +171,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POISON_STACK_MEMORY,
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNPOISON_STACK_MEMORY,
"__asan_unpoison_stack_memory",
BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_ALLOCA_POISON, "__asan_alloca_poison",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_ALLOCAS_UNPOISON, "__asan_allocas_unpoison",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
/* Thread Sanitizer */
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",
@@ -444,6 +448,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE,
"__ubsan_handle_load_invalid_value",
BT_FN_VOID_PTR_PTR,
ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW,
+ "__ubsan_handle_pointer_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
"__ubsan_handle_divrem_overflow_abort",
BT_FN_VOID_PTR_PTR_PTR,
@@ -480,6 +488,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT,
"__ubsan_handle_load_invalid_value_abort",
BT_FN_VOID_PTR_PTR,
ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT,
+ "__ubsan_handle_pointer_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
"__ubsan_handle_float_cast_overflow",
BT_FN_VOID_PTR_PTR,
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 16bdba76042..f6dd14da00d 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -37,6 +37,12 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-ssa.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "cfghooks.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
/* This is used to carry information about basic blocks. It is
attached to the AUX field of the standard CFG block. */
@@ -858,6 +864,137 @@ sanitize_asan_mark_poison (void)
}
}
+/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL
+ that is it's DECL_VALUE_EXPR. */
+
+static tree
+rewrite_usage_of_param (tree *op, int *walk_subtrees, void *)
+{
+ if (TREE_CODE (*op) == PARM_DECL && DECL_HAS_VALUE_EXPR_P (*op))
+ {
+ *op = DECL_VALUE_EXPR (*op);
+ *walk_subtrees = 0;
+ }
+
+ return NULL;
+}
+
+/* For a given function FUN, rewrite all addressable parameters so that
+ a new automatic variable is introduced. Right after function entry
+ a parameter is assigned to the variable. */
+
+static void
+sanitize_rewrite_addressable_params (function *fun)
+{
+ gimple *g;
+ gimple_seq stmts = NULL;
+ bool has_any_addressable_param = false;
+ auto_vec<tree> clear_value_expr_list;
+
+ for (tree arg = DECL_ARGUMENTS (current_function_decl);
+ arg; arg = DECL_CHAIN (arg))
+ {
+ tree type = TREE_TYPE (arg);
+ if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (type)
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+ {
+ TREE_ADDRESSABLE (arg) = 0;
+ /* The parameter is no longer addressable. */
+ has_any_addressable_param = true;
+
+ /* Create a new automatic variable. */
+ tree var = build_decl (DECL_SOURCE_LOCATION (arg),
+ VAR_DECL, DECL_NAME (arg), type);
+ TREE_ADDRESSABLE (var) = 1;
+ DECL_IGNORED_P (var) = 1;
+
+ gimple_add_tmp_var (var);
+
+ 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. */
+ if ((TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE))
+ {
+ /* We need to create a SSA name that will be used for the
+ assignment. */
+ DECL_GIMPLE_REG_P (arg) = 1;
+ tree tmp = get_or_create_ssa_default_def (cfun, arg);
+ g = gimple_build_assign (var, tmp);
+ gimple_set_location (g, DECL_SOURCE_LOCATION (arg));
+ gimple_seq_add_stmt (&stmts, g);
+ }
+ else
+ {
+ g = gimple_build_assign (var, arg);
+ gimple_set_location (g, DECL_SOURCE_LOCATION (arg));
+ gimple_seq_add_stmt (&stmts, g);
+ }
+
+ if (target_for_debug_bind (arg))
+ {
+ g = gimple_build_debug_bind (arg, var, NULL);
+ gimple_seq_add_stmt (&stmts, g);
+ clear_value_expr_list.safe_push (arg);
+ }
+
+ DECL_HAS_VALUE_EXPR_P (arg) = 1;
+ SET_DECL_VALUE_EXPR (arg, var);
+ }
+ }
+
+ if (!has_any_addressable_param)
+ return;
+
+ /* Replace all usages of PARM_DECLs with the newly
+ created variable VAR. */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ gimple_stmt_iterator it = gsi_for_stmt (stmt);
+ walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, NULL);
+ }
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi));
+ for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
+ {
+ hash_set<tree> visited_nodes;
+ walk_tree (gimple_phi_arg_def_ptr (phi, i),
+ rewrite_usage_of_param, NULL, &visited_nodes);
+ }
+ }
+ }
+
+ /* Unset value expr for parameters for which we created debug bind
+ expressions. */
+ unsigned i;
+ tree arg;
+ FOR_EACH_VEC_ELT (clear_value_expr_list, i, arg)
+ {
+ DECL_HAS_VALUE_EXPR_P (arg) = 0;
+ SET_DECL_VALUE_EXPR (arg, NULL_TREE);
+ }
+
+ /* Insert default assignments at the beginning of a function. */
+ basic_block entry_bb = ENTRY_BLOCK_PTR_FOR_FN (fun);
+ entry_bb = split_edge (single_succ_edge (entry_bb));
+
+ gimple_stmt_iterator gsi = gsi_start_bb (entry_bb);
+ gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
+}
+
unsigned int
pass_sanopt::execute (function *fun)
{
@@ -891,6 +1028,9 @@ pass_sanopt::execute (function *fun)
sanitize_asan_mark_poison ();
}
+ if (asan_sanitize_stack_p ())
+ sanitize_rewrite_addressable_params (fun);
+
bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX
&& asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD;
@@ -924,6 +1064,9 @@ pass_sanopt::execute (function *fun)
case IFN_UBSAN_OBJECT_SIZE:
no_next = ubsan_expand_objsize_ifn (&gsi);
break;
+ case IFN_UBSAN_PTR:
+ no_next = ubsan_expand_ptr_ifn (&gsi);
+ break;
case IFN_UBSAN_VPTR:
no_next = ubsan_expand_vptr_ifn (&gsi);
break;
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index b2393bf28fb..4c459e6587f 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -2834,34 +2834,30 @@ static void
sched_macro_fuse_insns (rtx_insn *insn)
{
rtx_insn *prev;
-
+ prev = prev_nonnote_nondebug_insn (insn);
+ if (!prev)
+ return;
+
if (any_condjump_p (insn))
{
unsigned int condreg1, condreg2;
rtx cc_reg_1;
targetm.fixed_condition_code_regs (&condreg1, &condreg2);
cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
- prev = prev_nonnote_nondebug_insn (insn);
- if (!reg_referenced_p (cc_reg_1, PATTERN (insn))
- || !prev
- || !modified_in_p (cc_reg_1, prev))
- return;
+ if (reg_referenced_p (cc_reg_1, PATTERN (insn))
+ && modified_in_p (cc_reg_1, prev))
+ {
+ if (targetm.sched.macro_fusion_pair_p (prev, insn))
+ SCHED_GROUP_P (insn) = 1;
+ return;
+ }
}
- else
- {
- rtx insn_set = single_set (insn);
-
- prev = prev_nonnote_nondebug_insn (insn);
- if (!prev
- || !insn_set
- || !single_set (prev))
- return;
+ if (single_set (insn) && single_set (prev))
+ {
+ if (targetm.sched.macro_fusion_pair_p (prev, insn))
+ SCHED_GROUP_P (insn) = 1;
}
-
- if (targetm.sched.macro_fusion_pair_p (prev, insn))
- SCHED_GROUP_P (insn) = 1;
-
}
/* Get the implicit reg pending clobbers for INSN and save them in TEMP. */
diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c
index 9123343fa0f..a0422f4b1ba 100644
--- a/gcc/sched-ebb.c
+++ b/gcc/sched-ebb.c
@@ -648,7 +648,8 @@ schedule_ebbs (void)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability <= probability_cutoff)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () <= probability_cutoff)
break;
if (e->dest->flags & BB_DISABLE_SCHEDULE)
break;
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 3bb9356693e..492094e3624 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -507,7 +507,8 @@ find_single_block_region (bool ebbs_p)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability <= probability_cutoff)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () <= probability_cutoff)
break;
}
@@ -1441,7 +1442,11 @@ compute_dom_prob_ps (int bb)
FOR_EACH_EDGE (out_edge, out_ei, in_edge->src->succs)
bitmap_set_bit (pot_split[bb], EDGE_TO_BIT (out_edge));
- prob[bb] += combine_probabilities (prob[pred_bb], in_edge->probability);
+ prob[bb] += combine_probabilities
+ (prob[pred_bb],
+ in_edge->probability.initialized_p ()
+ ? in_edge->probability.to_reg_br_prob_base ()
+ : 0);
// The rounding divide in combine_probabilities can result in an extra
// probability increment propagating along 50-50 edges. Eventually when
// the edges re-merge, the accumulated probability can go slightly above
@@ -3171,8 +3176,10 @@ schedule_region (int rgn)
sched_rgn_n_insns += sched_n_insns;
realloc_bb_state_array (saved_last_basic_block);
f = find_fallthru_edge (last_bb->succs);
- if (f && f->probability * 100 / REG_BR_PROB_BASE >=
- PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF))
+ if (f
+ && (!f->probability.initialized_p ()
+ || f->probability.to_reg_br_prob_base () * 100 / REG_BR_PROB_BASE >=
+ PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF)))
{
memcpy (bb_state[f->dest->index], curr_state,
dfa_state_size);
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index 84798ac9fb3..a67f9d64cb1 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -301,7 +301,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
sdbout_early_global_decl, /* early_global_decl */
sdbout_late_global_decl, /* late_global_decl */
sdbout_symbol, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
sdbout_label, /* label */
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index c1e2c24d950..fa88259733b 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -4747,7 +4747,11 @@ compute_succs_info (insn_t insn, short flags)
sinfo->probs_ok.safe_push (
/* FIXME: Improve calculation when skipping
inner loop to exits. */
- si.bb_end ? si.e1->probability : REG_BR_PROB_BASE);
+ si.bb_end
+ ? (si.e1->probability.initialized_p ()
+ ? si.e1->probability.to_reg_br_prob_base ()
+ : 0)
+ : REG_BR_PROB_BASE);
sinfo->succs_ok_n++;
}
else
@@ -4756,8 +4760,8 @@ compute_succs_info (insn_t insn, short flags)
/* Compute all_prob. */
if (!si.bb_end)
sinfo->all_prob = REG_BR_PROB_BASE;
- else
- sinfo->all_prob += si.e1->probability;
+ else if (si.e1->probability.initialized_p ())
+ sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
sinfo->all_succs_n++;
}
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a6f9af976e9..06a3f3cd718 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -857,6 +857,15 @@ simplify_truncation (machine_mode mode, rtx op,
return simplify_gen_unary (TRUNCATE, mode, XEXP (op, 0),
GET_MODE (XEXP (op, 0)));
+ /* (truncate:A (ior X C)) is (const_int -1) if C is equal to that already,
+ in mode A. */
+ if (GET_CODE (op) == IOR
+ && SCALAR_INT_MODE_P (mode)
+ && SCALAR_INT_MODE_P (op_mode)
+ && CONST_INT_P (XEXP (op, 1))
+ && trunc_int_for_mode (INTVAL (XEXP (op, 1)), mode) == -1)
+ return constm1_rtx;
+
return NULL_RTX;
}
@@ -6267,7 +6276,7 @@ simplify_subreg (machine_mode outermode, rtx op,
unsigned int part_size, final_offset;
rtx part, res;
- enum machine_mode part_mode = GET_MODE (XEXP (op, 0));
+ machine_mode part_mode = GET_MODE (XEXP (op, 0));
if (part_mode == VOIDmode)
part_mode = GET_MODE_INNER (GET_MODE (op));
part_size = GET_MODE_SIZE (part_mode);
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 9b5157d345b..05e24f00707 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -93,9 +93,9 @@ struct case_node
tree low; /* Lowest index value for this label */
tree high; /* Highest index value for this label */
tree code_label; /* Label to jump to when node matches */
- int prob; /* Probability of taking this case. */
+ profile_probability prob; /* Probability of taking this case. */
/* Probability of reaching subtree rooted at this node */
- int subtree_prob;
+ profile_probability subtree_prob;
};
typedef struct case_node *case_node_ptr;
@@ -108,7 +108,8 @@ static void balance_case_nodes (case_node_ptr *, case_node_ptr);
static int node_has_low_bound (case_node_ptr, tree);
static int node_has_high_bound (case_node_ptr, tree);
static int node_is_bounded (case_node_ptr, tree);
-static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *, int, tree);
+static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *,
+ profile_probability, tree);
/* Return the rtx-label that corresponds to a LABEL_DECL,
creating it if necessary. */
@@ -704,9 +705,8 @@ expand_naked_return (void)
is the probability of jumping to LABEL. */
static void
do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
- int unsignedp, int prob)
+ int unsignedp, profile_probability prob)
{
- gcc_assert (prob <= REG_BR_PROB_BASE);
do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
NULL_RTX, NULL, label, prob);
}
@@ -722,7 +722,7 @@ do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
static struct case_node *
add_case_node (struct case_node *head, tree low, tree high,
- tree label, int prob,
+ tree label, profile_probability prob,
object_allocator<case_node> &case_node_pool)
{
struct case_node *r;
@@ -859,7 +859,7 @@ expand_switch_as_decision_tree_p (tree range,
static void
emit_case_decision_tree (tree index_expr, tree index_type,
case_node_ptr case_list, rtx_code_label *default_label,
- int default_prob)
+ profile_probability default_prob)
{
rtx index = expand_normal (index_expr);
@@ -902,14 +902,14 @@ emit_case_decision_tree (tree index_expr, tree index_type,
/* Return the sum of probabilities of outgoing edges of basic block BB. */
-static int
+static profile_probability
get_outgoing_edge_probs (basic_block bb)
{
edge e;
edge_iterator ei;
- int prob_sum = 0;
+ profile_probability prob_sum = profile_probability::never ();
if (!bb)
- return 0;
+ return profile_probability::never ();
FOR_EACH_EDGE (e, ei, bb->succs)
prob_sum += e->probability;
return prob_sum;
@@ -922,16 +922,11 @@ get_outgoing_edge_probs (basic_block bb)
BASE_PROB is the probability of reaching the branch instruction relative
to the same basic block BB. */
-static inline int
-conditional_probability (int target_prob, int base_prob)
+static inline profile_probability
+conditional_probability (profile_probability target_prob,
+ profile_probability base_prob)
{
- if (base_prob > 0)
- {
- gcc_assert (target_prob >= 0);
- gcc_assert (target_prob <= base_prob);
- return GCOV_COMPUTE_SCALE (target_prob, base_prob);
- }
- return -1;
+ return target_prob / base_prob;
}
/* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
@@ -960,12 +955,13 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
rtx_code_label *table_label = gen_label_rtx ();
bool has_gaps = false;
edge default_edge = stmt_bb ? EDGE_SUCC (stmt_bb, 0) : NULL;
- int default_prob = default_edge ? default_edge->probability : 0;
- int base = get_outgoing_edge_probs (stmt_bb);
+ profile_probability default_prob = default_edge ? default_edge->probability
+ : profile_probability::never ();
+ profile_probability base = get_outgoing_edge_probs (stmt_bb);
bool try_with_tablejump = false;
- int new_default_prob = conditional_probability (default_prob,
- base);
+ profile_probability new_default_prob = conditional_probability (default_prob,
+ base);
if (! try_casesi (index_type, index_expr, minval, range,
table_label, default_label, fallback_label,
@@ -1030,15 +1026,16 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
through the indirect jump or the direct conditional jump
before that. Split the probability of reaching the
default label among these two jumps. */
- new_default_prob = conditional_probability (default_prob/2,
+ new_default_prob = conditional_probability (default_prob.apply_scale
+ (1, 2),
base);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
base -= default_prob;
}
else
{
base -= default_prob;
- default_prob = 0;
+ default_prob = profile_probability::never ();
}
if (default_edge)
@@ -1047,12 +1044,12 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
/* We have altered the probability of the default edge. So the probabilities
of all other edges need to be adjusted so that it sums up to
REG_BR_PROB_BASE. */
- if (base)
+ if (base > profile_probability::never ())
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, stmt_bb->succs)
- e->probability = GCOV_COMPUTE_SCALE (e->probability, base);
+ e->probability /= base;
}
if (try_with_tablejump)
@@ -1108,7 +1105,7 @@ compute_cases_per_edge (gswitch *stmt)
}
}
-/* Terminate a case (Pascal/Ada) or switch (C) statement
+/* Terminate a case Ada or switch (C) statement
in which ORIG_INDEX is the expression to be tested.
If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
type as given in the source before any compiler conversions.
@@ -1142,7 +1139,10 @@ expand_case (gswitch *stmt)
/* cleanup_tree_cfg removes all SWITCH_EXPR with their index
expressions being INTEGER_CST. */
gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
-
+
+ /* Optimization of switch statements with only one label has already
+ occurred, so we should never see them at this point. */
+ gcc_assert (ncases > 1);
do_pending_stack_adjust ();
@@ -1150,7 +1150,7 @@ expand_case (gswitch *stmt)
default_label = jump_target_rtx
(CASE_LABEL (gimple_switch_default_label (stmt)));
edge default_edge = EDGE_SUCC (bb, 0);
- int default_prob = default_edge->probability;
+ profile_probability default_prob = default_edge->probability;
/* Get upper and lower bounds of case values. */
elt = gimple_switch_label (stmt, 1);
@@ -1213,7 +1213,7 @@ expand_case (gswitch *stmt)
edge case_edge = find_edge (bb, case_bb);
case_list = add_case_node (
case_list, low, high, lab,
- case_edge->probability / (intptr_t)(case_edge->aux),
+ case_edge->probability.apply_scale (1, (intptr_t)(case_edge->aux)),
case_node_pool);
}
reset_out_edges_aux (bb);
@@ -1310,7 +1310,8 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
{
tree elt = dispatch_table[i];
rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt));
- do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
+ do_jump_if_equal (index_mode, index, zero, lab, 0,
+ profile_probability::uninitialized ());
force_expand_binop (index_mode, sub_optab,
index, CONST1_RTX (index_mode),
index, 0, OPTAB_DIRECT);
@@ -1332,7 +1333,10 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
tree elt = dispatch_table[i];
tree low = CASE_LOW (elt);
tree lab = CASE_LABEL (elt);
- case_list = add_case_node (case_list, low, low, lab, 0, case_node_pool);
+ case_list = add_case_node (case_list, low, low, lab,
+ profile_probability::guessed_always ()
+ .apply_scale (1, ncases),
+ case_node_pool);
}
emit_case_dispatch_table (index_expr, index_type,
@@ -1576,12 +1580,12 @@ node_is_bounded (case_node_ptr node, tree index_type)
static void
emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
- int default_prob, tree index_type)
+ profile_probability default_prob, tree index_type)
{
/* If INDEX has an unsigned type, we must make unsigned branches. */
int unsignedp = TYPE_UNSIGNED (index_type);
- int probability;
- int prob = node->prob, subtree_prob = node->subtree_prob;
+ profile_probability probability;
+ profile_probability prob = node->prob, subtree_prob = node->subtree_prob;
machine_mode mode = GET_MODE (index);
machine_mode imode = TYPE_MODE (index_type);
@@ -1701,7 +1705,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
subtree or the left subtree. Divide the probability
equally. */
probability = conditional_probability (
- node->right->subtree_prob + default_prob/2,
+ node->right->subtree_prob + default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
/* See if the value is on the right. */
emit_cmp_and_jump_insns (index,
@@ -1712,7 +1716,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
GT, NULL_RTX, mode, unsignedp,
label_rtx (test_label),
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
/* Value must be on the left.
Handle the left-hand subtree. */
@@ -1743,7 +1747,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
if (!node_has_low_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1753,7 +1757,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
LT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
@@ -1785,7 +1789,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
if (!node_has_high_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1795,7 +1799,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
GT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
emit_case_nodes (index, node->left, default_label,
@@ -1858,7 +1862,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
test_label = build_decl (curr_insn_location (),
LABEL_DECL, NULL_TREE, void_type_node);
probability = conditional_probability (
- node->right->subtree_prob + default_prob/2,
+ node->right->subtree_prob + default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1868,7 +1872,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
GT, NULL_RTX, mode, unsignedp,
label_rtx (test_label),
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the left-hand subtree. */
@@ -1909,7 +1913,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
if (!node_has_low_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1919,7 +1923,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
LT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the right-hand subtree. */
@@ -1946,7 +1950,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
if (!node_has_high_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1956,7 +1960,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
GT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the left-hand subtree. */
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 1574e4383e8..f733b1e4609 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2647,8 +2647,7 @@ set_min_and_max_values_for_integral_type (tree type,
/* Set the extreme values of TYPE based on its precision in bits,
then lay it out. Used when make_signed_type won't do
- because the tree code is not INTEGER_TYPE.
- E.g. for Pascal, when the -fsigned-char option is given. */
+ because the tree code is not INTEGER_TYPE. */
void
fixup_signed_type (tree type)
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index 689327548e3..7aa4e8638d7 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -30,18 +30,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tree.h"
-/* The "" allocated string. */
-const char empty_string[] = "";
-
-/* Character strings, each containing a single decimal digit.
- Written this way to save space. */
-static const char digit_vector[] = {
- '0', 0, '1', 0, '2', 0, '3', 0, '4', 0,
- '5', 0, '6', 0, '7', 0, '8', 0, '9', 0
-};
-
-#define digit_string(d) (digit_vector + ((d) * 2))
-
struct ht *ident_hash;
static hashnode alloc_node (cpp_hash_table *);
@@ -82,19 +70,16 @@ alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
const char *
ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
{
- char *result;
-
if (length == -1)
length = strlen (contents);
- if (length == 0)
- return empty_string;
- if (length == 1 && ISDIGIT (contents[0]))
- return digit_string (contents[0] - '0');
+ if (!length)
+ return "";
- result = (char *) ggc_internal_cleared_alloc (length + 1 PASS_MEM_STAT);
+ char *result = (char *) ggc_alloc_atomic (length + 1);
memcpy (result, contents, length);
result[length] = '\0';
+
return (const char *) result;
}
diff --git a/gcc/target.def b/gcc/target.def
index bd60484c4fd..6d67b1fe8ba 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -288,6 +288,17 @@ hidden, protected or internal visibility as specified by @var{visibility}.",
void, (tree decl, int visibility),
default_assemble_visibility)
+DEFHOOK
+(print_patchable_function_entry,
+ "Generate a patchable area at the function start, consisting of\n\
+@var{patch_area_size} NOP instructions. If the target supports named\n\
+sections and if @var{record_p} is true, insert a pointer to the current\n\
+location in the table of patchable functions. The default implementation\n\
+of the hook places the table of pointers in the special section named\n\
+@code{__patchable_function_entries}.",
+ void, (FILE *file, unsigned HOST_WIDE_INT patch_area_size, bool record_p),
+ default_print_patchable_function_entry)
+
/* Output the assembler code for entry to a function. */
DEFHOOK
(function_prologue,
@@ -2369,7 +2380,7 @@ DEFHOOK
DEFHOOK
(chkp_bound_mode,
"Return mode to be used for bounds.",
- enum machine_mode, (void),
+ machine_mode, (void),
default_chkp_bound_mode)
DEFHOOK
@@ -4370,7 +4381,7 @@ DEFHOOK
"Use it to store bounds for anonymous register arguments stored\n\
into the stack. Arguments meaning is similar to\n\
@code{TARGET_SETUP_INCOMING_VARARGS}.",
- void, (cumulative_args_t args_so_far, enum machine_mode mode, tree type,
+ void, (cumulative_args_t args_so_far, machine_mode mode, tree type,
int *pretend_args_size, int second_time),
default_setup_incoming_vararg_bounds)
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 1cdec068ed8..6a8fae656d0 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "tree-vrp.h"
#include "tree-ssanames.h"
+#include "profile-count.h"
#include "optabs.h"
#include "regs.h"
#include "recog.h"
@@ -72,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "calls.h"
#include "expr.h"
#include "output.h"
+#include "common/common-target.h"
#include "reload.h"
#include "intl.h"
#include "opts.h"
@@ -1609,6 +1611,51 @@ default_compare_by_pieces_branch_ratio (machine_mode)
return 1;
}
+/* Write PATCH_AREA_SIZE NOPs into the asm outfile FILE around a function
+ entry. If RECORD_P is true and the target supports named sections,
+ the location of the NOPs will be recorded in a special object section
+ called "__patchable_function_entries". This routine may be called
+ twice per function to put NOPs before and after the function
+ entry. */
+
+void
+default_print_patchable_function_entry (FILE *file,
+ unsigned HOST_WIDE_INT patch_area_size,
+ bool record_p)
+{
+ const char *nop_templ = 0;
+ int code_num;
+ rtx_insn *my_nop = make_insn_raw (gen_nop ());
+
+ /* We use the template alone, relying on the (currently sane) assumption
+ that the NOP template does not have variable operands. */
+ code_num = recog_memoized (my_nop);
+ nop_templ = get_insn_template (code_num, my_nop);
+
+ if (record_p && targetm_common.have_named_sections)
+ {
+ char buf[256];
+ static int patch_area_number;
+ section *previous_section = in_section;
+
+ patch_area_number++;
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
+
+ switch_to_section (get_section ("__patchable_function_entries",
+ 0, NULL));
+ fputs (integer_asm_op (POINTER_SIZE_UNITS, false), file);
+ assemble_name_raw (file, buf);
+ fputc ('\n', file);
+
+ switch_to_section (previous_section);
+ ASM_OUTPUT_LABEL (file, buf);
+ }
+
+ unsigned i;
+ for (i = 0; i < patch_area_size; ++i)
+ fprintf (file, "\t%s\n", nop_templ);
+}
+
bool
default_profile_before_prologue (void)
{
@@ -2008,7 +2055,7 @@ default_chkp_bound_type (void)
return res;
}
-enum machine_mode
+machine_mode
default_chkp_bound_mode (void)
{
return VOIDmode;
@@ -2046,7 +2093,7 @@ default_chkp_initialize_bounds (tree var ATTRIBUTE_UNUSED,
void
default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
int *pretend_arg_size ATTRIBUTE_UNUSED,
int second_time ATTRIBUTE_UNUSED)
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 18070df7839..c73ea0bda20 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -203,6 +203,9 @@ extern bool default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
bool);
extern int default_compare_by_pieces_branch_ratio (machine_mode);
+extern void default_print_patchable_function_entry (FILE *,
+ unsigned HOST_WIDE_INT,
+ bool);
extern bool default_profile_before_prologue (void);
extern reg_class_t default_preferred_reload_class (rtx, reg_class_t);
extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t);
@@ -243,14 +246,14 @@ extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx);
extern rtx default_load_returned_bounds (rtx);
extern void default_store_returned_bounds (rtx,rtx);
extern tree default_chkp_bound_type (void);
-extern enum machine_mode default_chkp_bound_mode (void);
+extern machine_mode default_chkp_bound_mode (void);
extern tree default_builtin_chkp_function (unsigned int);
extern rtx default_chkp_function_value_bounds (const_tree, const_tree, bool);
extern tree default_chkp_make_bounds_constant (HOST_WIDE_INT lb, HOST_WIDE_INT ub);
extern int default_chkp_initialize_bounds (tree var, tree lb, tree ub,
tree *stmts);
extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
int *pretend_arg_size ATTRIBUTE_UNUSED,
int second_time ATTRIBUTE_UNUSED);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ad5ccb7dc64..7243fdf3372 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1616 @@
+2017-07-31 Jan Hubicka <hubicka@ucw.cz>
+ Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/predict-15.c: New test.
+ * gcc.dg/tree-ssa/vrp24.c: Update scanned pattern.
+
+2017-07-31 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/25967
+ * gcc.target/i386/naked-1.c: New test.
+ * gcc.target/i386/naked-2.c: Ditto.
+ * gcc.target/i386/naked-3.c: Ditto.
+ * gcc.target/x86_64/abi/ms-sysv/ms-sysv.c: Remove
+ do_test_body0 stub function, use attribute "naked" instead.
+ * gcc.dg/pr44290-1.c: Use naked_functions effective target.
+ * gcc.dg/pr44290-2.c: Ditto.
+
+2017-07-31 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/81581
+ * gfortran.dg/dim_sum_1.f90: New test case.
+ * gfortran.dg/dim_sum_2.f90: New test case.
+ * gfortran.dg/dim_sum_3.f90: New test case.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/builtin-unreachable-6.c: Update scanned patterns.
+ * gcc.dg/tree-ssa/attr-hotcold-2.c: Likewise.
+
+2017-07-31 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81530
+ * g++.dg/ubsan/pr81530.C: New test.
+
+2017-07-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81604
+ * c-c++-common/ubsan/pr81604.c: New test.
+
+2017-07-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/79793
+ * gcc.dg/guality/pr68037-1.c: Update gdb breakpoints.
+ * gcc.target/i386/interrupt-5.c (interrupt_frame): New struct.
+ (foo): Check the builtin return address against the return address
+ in interrupt frame.
+ * gcc.target/i386/pr79793-1.c: New test.
+ * gcc.target/i386/pr79793-2.c: Likewise.
+
+2017-07-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-c++-common/dump-ada-spec-7.c: New test.
+
+2017-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/debug/dwarf2/inline-ns-1.C: New test.
+ * g++.dg/debug/dwarf2/inline-ns-2.C: New test.
+
+2017-07-28 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gcc.target/powerpc/cpu-builtin-1.c (darn, scv): Add tests.
+
+2017-07-28 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/int_mov_immediate_1.c: New.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/vect/pr80815-3.c: Require vect_perm.
+
+2017-07-28 Tamar Christina <tamar.christina@arm.com>
+ Bilyan Borisov <bilyan.borisov@arm.com>
+
+ * gcc.target/aarch64/dbl_mov_immediate_1.c: New.
+ * gcc.target/aarch64/flt_mov_immediate_1.c: New.
+ * gcc.target/aarch64/f16_mov_immediate_1.c: New.
+ * gcc.target/aarch64/f16_mov_immediate_2.c: New.
+ * gcc.target/aarch64/pr63304_1.c: Changed to double.
+
+2017-07-28 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/predcom-dse-1.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-2.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-3.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-4.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-5.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-6.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-7.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-8.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-9.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-10.c: New test.
+ * gcc.dg/tree-ssa/predcom-dse-11.c: New test.
+
+2017-07-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81340
+ * g++.dg/asan/pr81340.C: New test.
+
+2017-07-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81502
+ * gcc.target/i386/pr81502.c: New testcase.
+
+2017-07-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81460
+ * gcc.dg/asan/pr81460.c: New test.
+
+2017-07-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/80998
+ * c-c++-common/ubsan/ptr-overflow-1.c: New test.
+ * c-c++-common/ubsan/ptr-overflow-2.c: New test.
+
+ PR tree-optimization/81578
+ * gcc.dg/pr81578.c: New test.
+
+2017-07-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81573
+ * gcc.dg/torture/pr81573.c: Explicitely use signed char.
+
+2017-07-27 Peter Bergner <bergner@vnet.ibm.com>
+
+ * g++.dg/pr69667.C: Remove option -mlra.
+ * gcc.target/powerpc/dform-1.c: Likewise.
+ * gcc.target/powerpc/dform-2.c: Likewise.
+ * gcc.target/powerpc/dform-3.c: Likewise.
+ * gcc.target/powerpc/p8vector-int128-1.c: Likewise.
+ * gcc.target/powerpc/p9-vparity.c: Likewise.
+ * gcc.target/powerpc/pr63491.c: Likewise.
+ * gcc.target/powerpc/pr67808.c: Likewise.
+ * gcc.target/powerpc/pr68805.c: Likewise.
+ * gcc.target/powerpc/pr69461.c: Likewise.
+ * gcc.target/powerpc/pr71680.c: Likewise.
+ * gcc.target/powerpc/pr77289.c: Likewise.
+ * gcc.target/powerpc/pr78458.c: Likewise.
+ * gcc.target/powerpc/pr78543.c: Likewise.
+ * g++.dg/pr71294.C: Remove option -mno-lra.
+ * gcc.target/powerpc/pr71656-1.c: Likewise.
+ * gcc.target/powerpc/pr71656-2.c: Likewise.
+ * gcc.target/powerpc/pr71698.c: Likewise.
+
+2017-07-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Sudakshina Das <sudi.das@arm.com>
+
+ * gcc.target/aarch64/tst_imm_split_1.c: New Test.
+
+2017-07-27 Marek Polacek <polacek@redhat.com>
+
+ PR c/81417
+ * c-c++-common/Wsign-compare-1.c: New test.
+ * g++.dg/warn/Wsign-compare-2.C: Update dg-warning.
+ * g++.dg/warn/Wsign-compare-4.C: Likewise.
+ * g++.dg/warn/Wsign-compare-6.C: Likewise.
+ * g++.dg/warn/compare1.C: Likewise.
+ * gcc.dg/compare1.c: Likewise.
+ * gcc.dg/compare2.c: Likewise.
+ * gcc.dg/compare4.c: Likewise.
+ * gcc.dg/compare5.c: Likewise.
+ * gcc.dg/pr35430.c: Likewise.
+ * gcc.dg/pr60087.c: Likewise.
+
+2017-07-27 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR middle-end/81564
+ * gcc.dg/pr81564.c: New test.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81573
+ PR tree-optimization/81494
+ * gcc.dg/torture/pr81573.c: New testcase.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81571
+ * gcc.dg/torture/pr81571.c: New testcase.
+
+2017-07-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81502
+ * gcc.target/i386/vect-insert-1.c: New testcase.
+
+2017-07-27 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/81534
+ * gcc.target/s390/pr81534.c: New test.
+
+2017-07-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81555
+ PR tree-optimization/81556
+ * gcc.c-torture/execute/pr81555.c: New test.
+ * gcc.c-torture/execute/pr81556.c: New test.
+
+ * gcc.dg/attr-noipa.c: New test.
+ * gcc.dg/ipa/ipa-pta-18.c: New test.
+ * gcc.dg/ipa/ipa-sra-11.c: New test.
+
+2017-07-25 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-himode.c: Delete -mvsx-small-integer
+ option.
+ * gcc.target/powerpc/vsx-himode2.c: Likewise.
+ * gcc.target/powerpc/vsx-himode3.c: Likewise.
+ * gcc.target/powerpc/vsx-qimode.c: Likewise.
+ * gcc.target/powerpc/vsx-qimode2.c: Likewise.
+ * gcc.target/powerpc/vsx-qimode3.c: Likewise.
+ * gcc.target/powerpc/vsx-simode.c: Likewise.
+ * gcc.target/powerpc/vsx-simode2.c: Likewise.
+ * gcc.target/powerpc/vsx-simode3.c: Likewise.
+
+2017-07-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/71570
+ * g++.dg/cpp0x/lambda/lambda-ice17.C: New.
+
+2017-07-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/81563
+ * gcc.target/i386/pr81563.c: New test
+
+2017-07-26 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/79041
+ * gcc.target/aarch64/pr79041-2.c: Don't run in ILP32.
+
+2017-07-26 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/70992
+ * gcc.dg/overflow-warn-1.c: Adjust dg-error.
+ * gcc.dg/overflow-warn-2.c: Likewise.
+ * gcc.dg/overflow-warn-3.c: Likewise.
+ * gcc.dg/overflow-warn-4.c: Likewise.
+ * gcc.dg/torture/pr70992-2.c: New test.
+ * gcc.dg/torture/pr70992.c: New test.
+
+2017-07-26 Richard Biener <rguenther@suse.de>
+
+ * gcc/testsuite/gcc.dg/pr70920-2.c: Adjust for transform already
+ happening in ccp1.
+ * gcc/testsuite/gcc.dg/pr70920-4.c: Likewise.
+
+2017-07-26 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/46932
+ * gcc.dg/pr46932.c: New testcase.
+
+2017-07-26 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81186
+ * gcc.dg/asan/pr81186.c: New test.
+
+2017-07-25 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-4-p9-runnable.c: Add test file for
+ vec_cnttz builtins.
+
+2017-07-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt66.adb: New test.
+
+2017-07-25 Alexander Monakov <amonakov@ispras.ru>
+
+ * gcc.dg/tree-ssa/assoc-2.c: Enhance.
+ * gcc.dg/tree-ssa/slsr-4.c: Adjust.
+
+2017-07-25 Alexander Monakov <amonakov@ispras.ru>
+
+ * gcc.dg/tree-ssa/assoc-2.c: New testcase.
+
+2017-07-25 Torsten Duwe <duwe@suse.de>
+
+ * c-c++-common/patchable_function_entry-default.c: New test.
+ * c-c++-common/patchable_function_entry-decl.c: Likewise.
+ * c-c++-common/patchable_function_entry-definition.c: Likewise.
+
+2017-07-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/81532
+ * gcc.target/i386/pr80833-3.c: New test.
+ * gcc.target/i386/avx512dq-pr81532.c: New test.
+ * gcc.target/i386/avx512bw-pr81532.c: New test.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81455
+ * gcc.dg/pr81455.c: New testcase.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81529
+ * gfortran.dg/pr81529.f90: New testcase.
+
+2017-07-25 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * gcc.target/aarch64/pr79041-2.c: Improve test.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81410
+ * gcc.dg/vect/pr81410.c: Do not typedef uint64_t.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81510
+ * gcc.dg/torture/pr81510.c: New testcase.
+ * gcc.dg/torture/pr81510-2.c: Likewise.
+
+2017-07-25 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81520
+ * gcc.dg/ipa/pr81520.c: New test.
+
+2017-07-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/81364
+ * Wmultistatement-macros-12.c: New test.
+
+2017-07-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/81414
+ * gcc.target/aarch64/pr81414.C: New.
+
+2017-07-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81505
+ * gcc.dg/ubsan/pr81505.c: New testcase.
+
+2017-07-24 Daniel Santos <daniel.santos@pobox.com>
+
+ PR testsuite/80759
+ * gcc.target/x86_64/abi/ms-sysv/do-test.S
+ (ELFFN_BEGIN): Rename to FN_TYPE.
+ (ELFFN_END): Rename to FN_SIZE.
+ (ASMNAME): New macro.
+ (FUNC): Rename to FUNC_BEGIN, use ASMNAME and use .globl instead of
+ .global.
+ (FUNC_END): Use ASMNAME.
+ (test_data_save): Remove.
+ (test_data_input): Likewise.
+ (test_data_output: Likewise.
+ (test_data_fn): Likewise.
+ (test_data_retaddr): Likewise.
+ (regs_to_mem): Make globals, use r10 instead of rax.
+ (mem_to_regs): Likewise.
+ (do_test_unaligned): Remove .cfi directives, remove pushf/popf, move
+ body to ms-sysv.c.
+ (do_test_aligned): Likewise.
+ * gcc.target/x86_64/abi/ms-sysv/ms-sysv.c:
+ Add dg-* directives.
+ (PASTE_STR): New macro.
+ (ASMNAME): Likewise.
+ (LOAD_TEST_DATA_ADDR): Likewise.
+ (TEST_DATA_OFFSET): Likewise.
+ (do_test_body0): New C function.
+ (do_test_body): New inline assembly routine.
+ * gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp
+ (runtest_ms_sysv): Modify.
+
+2017-07-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pr65849-1.c: Delete, test no longer valid
+ since the upper-regs options have been deleted.
+ * gcc.target/powerpc/pr65849-2.c: Likewise.
+ * gcc.target/powerpc/pr80099-1.c: Likewise.
+ * gcc.target/powerpc/pr80099-2.c: Likewise.
+ * gcc.target/powerpc/pr80099-3.c: Likewise.
+ * gcc.target/powerpc/pr80099-4.c: Likewise.
+ * gcc.target/powerpc/pr80099-5.c: Likewise.
+ * gcc.target/powerpc/builtins-2-p9-runnable.c: Update test to
+ support removal of the upper-regs options.
+ * gcc.target/powerpc/p8vector-fp.c: Likewise.
+ * gcc.target/powerpc/p8vector-ldst.c: Likewise.
+ * gcc.target/powerpc/p9-dimode1.c: Likewise.
+ * gcc.target/powerpc/p9-dimode2.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-1.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-10.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-5.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-9.c: Likewise.
+ * gcc.target/powerpc/ppc-round.c: Likewise.
+ * gcc.target/powerpc/pr71720.c: Likewise.
+ * gcc.target/powerpc/pr72853.c: Likewise.
+ * gcc.target/powerpc/pr79907.c: Likewise.
+ * gcc.target/powerpc/pr78953.c: Likewise.
+ * gcc.target/powerpc/upper-regs-df.c: Likewise.
+ * gcc.target/powerpc/upper-regs-sf.c: Likewise.
+ * gcc.target/powerpc/vec-extract-1.c: Likewise.
+ * gcc.target/powerpc/vec-init-3.c: Likewise.
+ * gcc.target/powerpc/vec-init-6.c: Likewise.
+ * gcc.target/powerpc/vec-init-7.c: Likewise.
+ * gcc.target/powerpc/vec-set-char.c: Likewise.
+ * gcc.target/powerpc/vec-set-int.c: Likewise.
+ * gcc.target/powerpc/vec-set-short.c: Likewise.
+
+2017-07-24 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/79041
+ * gcc.target/aarch64/pr79041-2.c: New test.
+
+2017-07-24 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-3-p9-runnable.c: Add new test file for
+ the new built-ins.
+
+2017-07-24 Jackson Woodruff <jackson.woodruff@arm.com>
+
+ * gcc.target/aarch64/simd/vmla_elem_1.c: New.
+
+2017-07-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+ Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/66102
+ * gfortran.dg/realloc_on_assign_28.f90: New test.
+
+2017-07-23 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/pr56727-2.c: Limit to powerpc-linux.
+ * gcc.dg/debug/dwarf2/stacked-qualified-types-3.c: Remove AIX XFAIL.
+
+2017-07-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/80569
+ * gcc.target/i386/pr80569.c: New test.
+
+2017-07-21 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-2.c (vmulosh, vmulouh, vmulesh,
+ vmuleuh): Fix scan-assembler-times should check for word not half word
+ instructions.
+
+2017-07-21 Jim Wilson <jim.wilson@linaro.org>
+
+ * lib/target-supports.exp (add_options_for_arm_v8_1a_neon): Delete
+ redundant -march option.
+ (check_effective_target_arm_v8_1a_neon_ok_nocache): Try armv8-a+rdma
+ in addition to armv8.1-a.
+
+2017-07-21 Yury Gribov <tetra2005@gmail.com>
+
+ PR middle-end/56727
+ * gcc.dg/pr56727-1.c: New test.
+ * gcc.dg/pr56727-2.c: New test.
+
+2017-07-21 Steven Munroe <munroesj@gcc.gnu.org>
+
+ * gcc.target/powerpc/mmx-check.h: New file.
+ * gcc.target/powerpc/mmx-packs.c: New file.
+ * gcc.target/powerpc/mmx-packssdw-1.c: New file.
+ * gcc.target/powerpc/mmx-packsswb-1.c: New file.
+ * gcc.target/powerpc/mmx-packuswb-1.c: New file.
+ * gcc.target/powerpc/mmx-paddb-1.c: New file.
+ * gcc.target/powerpc/mmx-paddd-1.c: New file.
+ * gcc.target/powerpc/mmx-paddsb-1.c: New file.
+ * gcc.target/powerpc/mmx-paddsw-1.c: New file.
+ * gcc.target/powerpc/mmx-paddusb-1.c: New file.
+ * gcc.target/powerpc/mmx-paddusw-1.c: New file.
+ * gcc.target/powerpc/mmx-paddw-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpeqb-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpeqd-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpeqw-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpgtb-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpgtd-1.c: New file.
+ * gcc.target/powerpc/mmx-pcmpgtw-1.c: New file.
+ * gcc.target/powerpc/mmx-pmaddwd-1.c: New file.
+ * gcc.target/powerpc/mmx-pmulhw-1.c: New file.
+ * gcc.target/powerpc/mmx-pmullw-1.c: New file.
+ * gcc.target/powerpc/mmx-pslld-1.c: New file.
+ * gcc.target/powerpc/mmx-psllw-1.c: New file.
+ * gcc.target/powerpc/mmx-psrad-1.c: New file.
+ * gcc.target/powerpc/mmx-psraw-1.c: New file.
+ * gcc.target/powerpc/mmx-psrld-1.c: New file.
+ * gcc.target/powerpc/mmx-psrlw-1.c: New file.
+ * gcc.target/powerpc/mmx-psubb-2.c: New file.
+ * gcc.target/powerpc/mmx-psubd-2.c: New file.
+ * gcc.target/powerpc/mmx-psubsb-1.c: New file.
+ * gcc.target/powerpc/mmx-psubsw-1.c: New file.
+ * gcc.target/powerpc/mmx-psubusb-1.c: New file.
+ * gcc.target/powerpc/mmx-psubusw-1.c: New file.
+ * gcc.target/powerpc/mmx-psubw-2.c: New file.
+ * gcc.target/powerpc/mmx-punpckhbw-1.c: New file.
+ * gcc.target/powerpc/mmx-punpckhdq-1.c: New file.
+ * gcc.target/powerpc/mmx-punpckhwd-1.c: New file.
+ * gcc.target/powerpc/mmx-punpcklbw-1.c: New file.
+ * gcc.target/powerpc/mmx-punpckldq-1.c: New file.
+ * gcc.target/powerpc/mmx-punpcklwd-1.c: New file.
+
+2017-06-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81500
+ * gcc.dg/torture/pr81500.c: New testcase.
+
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/ext/anon-struct6.C: Adjust diag.
+ * g++.old-deja/g++.other/anon4.C: Adjust diag.
+
+2017-07-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/80846
+ * gcc.target/i386/avx-pr80846.c: New test.
+ * gcc.target/i386/avx2-pr80846.c: New test.
+ * gcc.target/i386/avx512f-pr80846.c: New test.
+
+2017-07-20 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/81388
+ * gcc.dg/tree-ssa/pr81388-1.c: New test.
+ * gcc.dg/tree-ssa/pr81388-2.c: New test.
+
+2017-07-17 Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/81030
+ * gcc.dg/pr81030.c: New test.
+
+2017-07-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61171
+ * g++.dg/vect/pr61171.cc: New testcase.
+ * gfortran.dg/vect/pr61171.f: Likewise.
+ * gcc.dg/vect/vect-reduc-11.c: Likewise.
+
+2017-07-20 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/slp-43.c: Increase loop count to enable vectorization
+ with V64QImode.
+ * gcc.dg/vect/slp-45.c: Likewise.
+
+2017-07-20 Naveen H.S <Naveen.Hurugalawadi@cavium.com>
+
+ * gcc.dg/tree-ssa/vrp116.c: New Test.
+
+2017-07-19 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/cpu-builtin-1.c: Change test to use #ifdef
+ __BUILTIN_CPU_SUPPORTS to see if the GLIBC is new enough that
+ __builtin_cpu_is and __builtin_cpu_supports are supported.
+
+2017-07-19 Steven Munroe <munroesj@gcc.gnu.org>
+
+ * gcc.target/powerpc/bmi-check.h (main): Skip unless
+ __BUILTIN_CPU_SUPPORTS__ defined.
+ * gcc.target/powerpc/bmi2-check.h (main): Skip unless
+ __BUILTIN_CPU_SUPPORTS__ defined.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81346
+ * gcc.dg/tree-ssa/pr81346-5.c: New test.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/nvptx/decl-init.c: Update alignment.
+ * gcc.target/nvptx/slp-2-run.c: New test.
+ * gcc.target/nvptx/slp-2.c: New test.
+ * gcc.target/nvptx/v2di.c: New test.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/nvptx/slp-run.c: New test.
+ * gcc.target/nvptx/slp.c: New test.
+ * gcc.target/nvptx/v2si-cvt.c: New test.
+ * gcc.target/nvptx/v2si-run.c: New test.
+ * gcc.target/nvptx/v2si.c: New test.
+ * gcc.target/nvptx/vec.inc: New test.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81346
+ * gcc.dg/tree-ssa/pr81346-1.c: New test.
+ * gcc.dg/tree-ssa/pr81346-2.c: New test.
+ * gcc.dg/tree-ssa/pr81346-3.c: New test.
+ * gcc.dg/tree-ssa/pr81346-4.c: New test.
+ * gcc.target/i386/umod-3.c: Hide comparison against 1 from the
+ compiler to avoid X / C1 op C2 optimization to trigger.
+
+2017-07-19 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/63361
+ * c-c++-common/ubsan/float-cast-overflow-1.c: Add either
+ -ffloat-store or -mieee for targets that need it.
+
+2017-07-18 Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/81464
+ * gfortran.dg/pr81464.f90: New test.
+
+2017-07-18 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81471
+ * gcc.target/i386/pr81471.c: New test.
+
+2017-06-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81410
+ * gcc.dg/vect/pr81410.c: New testcase.
+
+2017-07-18 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81462
+ * g++.dg/torture/pr81462.C: New testcase.
+
+2017-07-18 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81408
+ * g++.dg/tree-ssa/pr81408.C: New.
+ * gcc.dg/tree-ssa/pr19210-1.c: Check dump message rather than warning.
+
+2017-07-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80620
+ PR tree-optimization/81403
+ * gcc.dg/torture/pr80620.c: New testcase.
+ * gcc.dg/torture/pr81403.c: Likewise.
+
+2017-07-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81418
+ * gcc.dg/torture/pr81418.c: New testcase.
+
+2017-07-17 Carl Love <cel@us.ibm.com>
+
+ Revert commit r249572 2017-06-22 Carl Love <cel@us.ibm.com>
+ test case changes for commit 249424
+
+ * gcc.target/powerpc/builtins-2.c (vmulosh, vmulouh, vmulesh,
+ vmuleuh): Fix scan-assembler-times should check for word not half word
+ instructions.
+
+2017-07-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/81162
+ * gcc.dg/pr81162.c: Move this to...
+ * gcc.dg/ubsan/pr81162.c: ...here.
+
+2017-07-17 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * g++.dg/diagnostic/friend1.C: New test.
+ * g++.dg/cpp0x/auto1.C: Add check for fix-it hint.
+
+2017-07-17 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/warn/ctor-dtor-privacy-3.C: New.
+
+2017-07-17 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * lib/gcc-dg.exp: Increase expect's match buffer size.
+
+2017-07-17 Bin Cheng <bin.cheng@arm.com>
+
+ PR target/81369
+ * gcc.dg/tree-ssa/pr81369.c: New.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/pr9000674901.c: New file.
+ * gcc.target/arc/pic-1.c: Likewise.
+ * gcc.target/arc/pr9001191897.c: Likewise.
+
+2017-07-17 Claudiu Zissulescu <claziss@synopsys.com>
+ Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gcc.target/arc/naked-1.c: New file.
+ * gcc.target/arc/naked-2.c: Likewise.
+
+2017-07-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/81428
+ * gcc.dg/fixed-point/pr81428.c: New test.
+
+ PR tree-optimization/81365
+ * g++.dg/torture/pr81365.C: New test.
+
+ PR tree-optimization/81396
+ * gcc.dg/tree-ssa/pr81396.c: New test.
+
+2017-07-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt65.adb: New test.
+
+2017-07-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/predict-8.c: Update.
+
+2017-07-16 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * g++.dg/cpp1z/direct-enum-init1.C: Revert special enum handling.
+ * g++.dg/warn/pr12242.C: Likewise.
+
+2017-07-14 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-eq-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-eq-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-gt-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-gt-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-lt-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-lt-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-exp-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-exp-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-exp-5.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-exp-6.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-exp-7.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-3.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-5.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-6.c: New test.
+ * gcc.target/powerpc/bfp/scalar-extract-sig-7.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-10.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-11.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-12.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-13.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-14.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-15.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-6.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-7.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: New test.
+ * gcc.target/powerpc/bfp/scalar-insert-exp-9.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-10.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-11.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-12.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-13.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-14.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-15.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-8.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-data-class-9.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-neg-4.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-neg-5.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-neg-6.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-neg-7.c: New test.
+ * gcc.target/powerpc/bfp/scalar-test-neg-8.c: New test.
+ * gcc.target/powerpc/bfp/vec-extract-exp-4.c: New test.
+ * gcc.target/powerpc/bfp/vec-extract-exp-5.c: New test.
+ * gcc.target/powerpc/bfp/vec-extract-sig-4.c: New test.
+ * gcc.target/powerpc/bfp/vec-extract-sig-5.c: New test.
+ * gcc.target/powerpc/bfp/vec-insert-exp-10.c: New test.
+ * gcc.target/powerpc/bfp/vec-insert-exp-11.c: New test.
+ * gcc.target/powerpc/bfp/vec-insert-exp-8.c: New test.
+ * gcc.target/powerpc/bfp/vec-insert-exp-9.c: New test.
+ * gcc.target/powerpc/bfp/vec-test-data-class-8.c: New test.
+ * gcc.target/powerpc/bfp/vec-test-data-class-9.c: New test.
+
+2016-07-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/81162
+ * gcc.dg/pr81162.c: New file.
+
+2017-07-14 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-dse-30.c: Correct test to look for memmove
+ that bcopy is expected to be transformed to.
+
+2017-07-14 David Malcolm <dmalcolm@redhat.com>
+
+ * g++.dg/cpp0x/missing-initializer_list-include.C: New test case.
+ * g++.dg/lookup/missing-std-include-2.C: New test case.
+ * g++.dg/lookup/missing-std-include-3.C: New test case.
+ * g++.dg/rtti/missing-typeinfo-include.C: New test case.
+ * gcc.dg/missing-header-fixit-1.c: New test case.
+ * gcc.dg/missing-header-fixit-2.c: New test case.
+ * gcc.dg/missing-header-fixit-2.h: New header.
+
+2017-07-13 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/81405
+ * gcc.dg/Wmissing-braces-fixits.c: Add coverage for PR c/81405. */
+
+2017-07-13 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * gcc.target/powerpc/fold-vec-missing-lhs.c: New.
+
+2017-07-13 Martin Liska <mliska@suse.cz>
+
+ * c-c++-common/ubsan/sanitize-all-1.c: Update scanned pattern.
+ * c-c++-common/ubsan/sanitize-recover-1.c:Likewise.
+ * c-c++-common/ubsan/sanitize-recover-2.c:Likewise.
+ * c-c++-common/ubsan/sanitize-recover-5.c:Likewise.
+ * c-c++-common/ubsan/sanitize-recover-7.c:Likewise.
+ * c-c++-common/ubsan/sanitize-recover-8.c:Likewise.
+ * c-c++-common/ubsan/sanitize-recover-9.c:Likewise.
+
+2017-07-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/81193
+ * gcc.target/powerpc/bmi-andn-1.c: Add guard against using
+ __builtin_cpu_supports with old GLIBC's.
+ * gcc.target/powerpc/bmi-andn-2.c: Likewise.
+ * gcc.target/powerpc/bmi-bextr-1.c: Likewise.
+ * gcc.target/powerpc/bmi-bextr-2.c: Likewise.
+ * gcc.target/powerpc/bmi-bextr-4.c: Likewise.
+ * gcc.target/powerpc/bmi-bextr-5.c: Likewise.
+ * gcc.target/powerpc/bmi-blsi-1.c: Likewise.
+ * gcc.target/powerpc/bmi-blsi-2.c: Likewise.
+ * gcc.target/powerpc/bmi-blsmsk-1.c: Likewise.
+ * gcc.target/powerpc/bmi-blsmsk-2.c: Likewise.
+ * gcc.target/powerpc/bmi-blsr-1.c: Likewise.
+ * gcc.target/powerpc/bmi-blsr-2.c: Likewise.
+ * gcc.target/powerpc/bmi-tzcnt-1.c: Likewise.
+ * gcc.target/powerpc/bmi-tzcnt-2.c: Likewise.
+ * gcc.target/powerpc/bmi2-bzhi32-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-bzhi64-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-mulx32-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-mulx32-2.c: Likewise.
+ * gcc.target/powerpc/bmi2-mulx64-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-mulx64-2.c: Likewise.
+ * gcc.target/powerpc/bmi2-pdep32-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-pdep64-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-pext32-1.c: Likewise.
+ * gcc.target/powerpc/bmi2-pext64-1.c: Likewise.
+ * gcc.target/powerpc/cpu-builtin-1.c: Likewise.
+
+2017-07-12 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/p9-xxbr-1.c (rev_bool_char, rev_bool_short,
+ rev_bool_int): Add test cases for builtins.
+ * gcc.target/powerpc/p9-xxbr-2.c (rev_long_long, rev_ulong_ulong): Add
+ test cases for builtins.
+
+2017-07-12 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-1-p9-runnable.c (dg-ddo run): Add
+ lp64 && p9vector_hw.
+
+2017-07-12 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * lib/target-supports.exp (check_stack_check_available): Make
+ testcase name depend on stack_kind.
+
+2017-07-11 Michael Collison <michael.collison@arm.com>
+
+ * gcc.target/aarch64/cmp-2.c: New testcase.
+
+2017-07-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51270
+ * g++.dg/warn/Wreturn-local-addr-3.C: New.
+
+2017-07-11 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-2-p9-runnable.c: Add new file with
+ test cases for the builtins.
+
+2017-07-11 Yury Gribov <tetra2005@gmail.com>
+
+ * lib/profopt.exp: Print relative names in UNSUPPORTED
+ AutoFDO tests.
+
+2017-07-10 Michael Collison <michael.collison@arm.com>
+
+ * gcc.target/aarch64/var_shift_mask_1.c: Fix for ILP32
+
+2017-07-10 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81375
+ * gcc.target/i386/pr81375.c: New test.
+
+2017-07-10 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/80397
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-17.c: New test.
+
+2017-07-10 Martin Sebor <msebor@redhat.com>
+
+ PR other/81345
+ * gcc.dg/pr81345.c: New test.
+
+2017-07-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/mulsi3_highpart-1.c: Remove 'X' constraint.
+ * gcc.target/arc/mulsi3_highpart-2.c: Likewise.
+
+2017-07-09 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81313
+ * gcc.dg/stack-layout-dynamic-1.c (bar): Add 4 additional
+ integer argumets to bypass x86_64 outgoing args optimization.
+
+2017-07-09 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.dg/eoshift_4.f90: New test.
+ * gfortran.dg/eoshift_5.f90: New test.
+ * gfortran.dg/eoshift_6.f90: New test.
+
+2017-07-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/81313
+ * gcc.target/i386/pr81313-1.c: New test.
+ * gcc.target/i386/pr81313-2.c: Likewise.
+ * gcc.target/i386/pr81313-3.c: Likewise.
+ * gcc.target/i386/pr81313-4.c: Likewise.
+ * gcc.target/i386/pr81313-5.c: Likewise.
+
+2017-07-08 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gnat.dg/vect15.ads (Sarray): Increase range to 1 .. 5.
+ * gnat.dg/vect16.ads (Sarray): Likewise.
+ * gnat.dg/vect17.ads (Sarray): Likewise.
+ * gnat.dg/vect15.adb (Add): Create a dependence distance of 1.
+ * gnat.dg/vect16.adb (Add): Likewise.
+ * gnat.dg/vect17.adb (Add): Likewise.
+
+2017-07-07 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/79300
+ * g++.dg/diagnostic/pr79300.C: New test case.
+
+2017-07-07 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/clone1.c: Add check to make sure the
+ __builtin_cpu_supports function is fully supported.
+ * gcc.target/powerpc/clone2.c: New runtime test for
+ target_clones.
+
+ PR target/81348
+ * gcc.target/powerpc/pr81348.c: New test.
+
+2017-07-07 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * gfortran.dg/vect/pr60510.f: Require vect_double support.
+
+2017-07-07 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-1-p9-runnable.c: Add new test
+ file for built-ins.
+
+2017-07-07 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * gcc.target/sparc/dictunpack.c: New file.
+ * gcc.target/sparc/fpcmpdeshl.c: Likewise.
+ * gcc.target/sparc/fpcmpshl.c: Likewise.
+ * gcc.target/sparc/fpcmpurshl.c: Likewise.
+ * gcc.target/sparc/fpcmpushl.c: Likewise.
+
+2017-07-06 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/70071
+ * gfortran.dg/coarray_44.f90: New testcase.
+
+2017-07-06 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * c-c++-common/asan/kasan-alloca-1.c: New test.
+ * c-c++-common/asan/kasan-alloca-2.c: Likewise.
+
+2017-07-06 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * c-c++-common/asan/alloca_big_alignment.c: New test.
+ * c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
+ * c-c++-common/asan/alloca_instruments_all_paddings.c: Likewise.
+ * c-c++-common/asan/alloca_loop_unpoisoning.c: Likewise.
+ * c-c++-common/asan/alloca_overflow_partial.c: Likewise.
+ * c-c++-common/asan/alloca_overflow_right.c: Likewise.
+ * c-c++-common/asan/alloca_safe_access.c: Likewise.
+ * c-c++-common/asan/alloca_underflow_left.c: Likewise.
+
+2017-07-06 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/81305
+ * gcc.target/avr/isr-test.h: Fix warnings.
+
+2017-07-06 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * lib/target-supports.exp: Generate
+ check_effective_target_arm_arch_v8r_ok, add_options_for_arm_arch_v8r
+ and check_effective_target_arm_arch_v8r_multilib.
+
+2017-07-06 Carl Love <cel@us.ibm.com>
+
+ * ChangeLog: Clean up from mid air collision
+
+2017-07-06 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/p8vector-builtin-8.c (foo): Add test cases for
+ the new vec_subc, vec_sube, vec_subec built-ins. Add the missing test
+ cases for vec_addc, adde and addec builtins.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/79300
+ * c-c++-common/Wmisleading-indentation-3.c (fn_14): Update
+ expected underlining within macro expansion.
+ * c-c++-common/pr70264.c: Likewise.
+ * g++.dg/plugin/diagnostic-test-expressions-1.C
+ (test_within_macro_1): New test.
+ (test_within_macro_2): Likewise.
+ (test_within_macro_3): Likewise.
+ (test_within_macro_4): Likewise.
+ * gcc.dg/format/diagnostic-ranges.c (test_macro_3): Update
+ expected underlining within macro expansion.
+ (test_macro_4): Likewise.
+ * gcc.dg/plugin/diagnostic-test-expressions-1.c
+ (test_within_macro_1): New test.
+ (test_within_macro_2): Likewise.
+ (test_within_macro_3): Likewise.
+ (test_within_macro_4): Likewise.
+ * gcc.dg/spellcheck-fields-2.c (test_macro): Update expected
+ underlining within macro expansion.
+
+2017-07-06 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * gcc.target/i386/avx512f-vgetexpsd-1.c (_mm_mask_getexp_sd,
+ _mm_maskz_getexp_sd, _mm_mask_getexp_round_sd,
+ _mm_maskz_getexp_round_sd): Test new intrinsics.
+ * gcc.target/i386/avx512f-vgetexpss-1.c (_mm_mask_getexp_ss,
+ _mm_maskz_getexp_ss, _mm_mask_getexp_round_ss,
+ _mm_maskz_getexp_round_ss): Ditto.
+ * gcc.target/i386/avx512f-vgetmantsd-1.c (_mm_mask_getmant_sd,
+ _mm_maskz_getmant_sd, _mm_mask_getmant_round_sd,
+ _mm_maskz_getmant_round_sd): Ditto.
+ * gcc.target/i386/avx512f-vgetmantss-1.c (_mm_mask_getmant_ss,
+ _mm_maskz_getmant_ss, _mm_mask_getmant_round_ss,
+ _mm_maskz_getmant_round_ss): Ditto.
+ * gcc.target/i386/avx512f-vgetexpsd-2.c (_mm_mask_getexp_sd,
+ _mm_maskz_getexp_sd, _mm_getexp_round_sd, _mm_mask_getexp_round_sd,
+ _mm_maskz_getexp_round_sd): New runtime tests.
+ * gcc.target/i386/avx512f-vgetexpss-2.c (_mm_mask_getexp_ss,
+ _mm_maskz_getexp_ss, _mm_getexp_round_ss, _mm_mask_getexp_round_ss,
+ _mm_maskz_getexp_round_ss): Ditto.
+ * gcc.target/i386/avx512f-vgetmantsd-2.c (_mm_mask_getmant_sd,
+ _mm_maskz_getmant_sd, _mm_getmant_round_sd, _mm_mask_getmant_round_sd,
+ _mm_maskz_getmant_round_sd): Ditto.
+ * gcc.target/i386/avx512f-vgetmantss-2.c (_mm_mask_getmant_ss,
+ _mm_maskz_getmant_ss, _mm_getmant_round_ss, _mm_mask_getmant_round_ss,
+ _mm_maskz_getmant_round_ss): Ditto.
+ * gcc.target/i386/avx-1.c (__builtin_ia32_getexpsd_mask_round,
+ __builtin_ia32_getexpss_mask_round, __builtin_ia32_getmantsd_mask_round,
+ __builtin_ia32_getmantss_mask_round): Test new builtins.
+ * gcc.target/i386/sse-13.c : Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * gcc.target/i386/sse-14.c (_mm_maskz_getexp_round_sd,
+ _mm_maskz_getexp_round_ss, _mm_mask_getmant_round_sd,
+ _mm_maskz_getmant_round_sd, _mm_mask_getmant_round_ss,
+ _mm_maskz_getmant_round_ss, _mm_mask_getexp_round_sd,
+ _mm_mask_getexp_round_ss): Test new intrinsics.
+ * gcc.target/i386/testround-1.c: Ditto.
+ * gcc.target/i386/sse-22.c (_mm_maskz_getmant_round_sd,
+ _mm_maskz_getmant_round_ss, _mm_mask_getmant_round_sd,
+ _mm_mask_getmant_round_ss): Test new intrinsics
+ * gcc.target/i386/testimm-10.c (_mm_mask_getmant_sd,
+ _mm_maskz_getmant_sd, _mm_mask_getmant_ss,
+ _mm_maskz_getmant_ss): Test new intrinsics.
+
+2017-07-06 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * lib/target-supports-dg.exp (dg-require-stack-check): New.
+ * lib/target-supports.exp (check_stack_check_available): New.
+ * g++.dg/other/i386-9.C: Add dg-require-stack-check.
+ * gcc.c-torture/compile/stack-check-1.c: Likewise.
+ * gcc.dg/graphite/run-id-pr47653.c: Likewise.
+ * gcc.dg/pr47443.c: Likewise.
+ * gcc.dg/pr48134.c: Likewise.
+ * gcc.dg/pr70017.c: Likewise.
+ * gcc.target/aarch64/stack-checking.c: Likewise.
+ * gcc.target/arm/stack-checking.c: Likewise.
+ * gcc.target/i386/pr48723.c: Likewise.
+ * gcc.target/i386/pr55672.c: Likewise.
+ * gcc.target/i386/pr67265-2.c: Likewise.
+ * gcc.target/i386/pr67265.c: Likewise.
+ * gnat.dg/opt49.adb: Likewise.
+ * gnat.dg/stack_check1.adb: Likewise.
+ * gnat.dg/stack_check2.adb: Likewise.
+ * gnat.dg/stack_check3.adb: Likewise.
+
+2017-07-05 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ PR target/80103
+ * gcc.target/powerpc/pr80103-1.c (void b): Correct spelling of
+ __attribute__.
+
+2017-07-05 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * gcc.target/i386/avx512f-vaddsd-3.c: New test for mask 0 verification.
+ * gcc.target/i386/avx512f-vaddss-3.c: Ditto.
+ * gcc.target/i386/avx512f-vdivsd-3.c: Ditto.
+ * gcc.target/i386/avx512f-vdivss-3.c: Ditto.
+ * gcc.target/i386/avx512f-vmaxsd-3.c: Ditto.
+ * gcc.target/i386/avx512f-vmaxss-3.c: Ditto.
+ * gcc.target/i386/avx512f-vminsd-3.c: Ditto.
+ * gcc.target/i386/avx512f-vminss-3.c: Ditto.
+ * gcc.target/i386/avx512f-vmulsd-3.c: Ditto.
+ * gcc.target/i386/avx512f-vmulss-3.c: Ditto.
+ * gcc.target/i386/avx512f-vsubsd-3.c: Ditto.
+ * gcc.target/i386/avx512f-vsubss-3.c: Ditto.
+
+2017-07-05 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/81305
+ * gcc.target/avr/isr-test.h: New file.
+ * gcc.target/avr/torture/isr-01-simple.c: New test.
+ * gcc.target/avr/torture/isr-02-call.c: New test.
+ * gcc.target/avr/torture/isr-03-fixed.c: New test.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/ldist-4.c: Adjust test string.
+ * gcc.dg/tree-ssa/ldist-12.c: Ditto.
+ * gcc.dg/tree-ssa/ldist-13.c: Ditto.
+ * gcc.dg/tree-ssa/ldist-14.c: Ditto.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/ldist-26.c: New test.
+
+2017-07-05 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/ldist-6.c: XFAIL.
+
+2017-07-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81300
+ * gcc.target/i386/pr81300.c: New test.
+
+2017-07-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/81294
+ * gcc.target/i386/adx-addcarryx32-2.c (adx_test): Swap
+ x and y arguments in the call to _subborrow_u32.
+ * gcc.target/i386/adx-addcarryx64-2.c (adx_test): Swap
+ x and y arguments in the call to _subborrow_u64.
+ * gcc.target/i386/pr81294-1.c: New test.
+ * gcc.target/i386/pr81294-2.c: Ditto.
+
+2017-07-04 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/simd/vminmaxnm_1.c: Fix strict aliasing issues.
+
+2017-07-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/81231
+ * gcc.dg/atomic-pr81231.c: New test.
+
+2017-07-04 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/81292
+ * gcc.dg/pr81292-1.c: New test.
+ * gcc.dg/pr81292-2.c: Likewise.
+
+2017-07-04 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81040
+ * g++.dg/asan/function-argument-1.C: Run the test-case w/o
+ use-after-scope sanitization.
+
+2017-07-04 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/asan/function-argument-3.C: Add -Wno-psabi to additional
+ options.
+
+ PR target/81175
+ * gcc.target/i386/pr69255-2.c (foo): Use the return value of the
+ gather.
+
+2017-07-04 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81214
+ * g++.dg/ext/mvc2.C: Add dg-require ifunc.
+ * g++.dg/ext/mvc3.C: Likewise.
+ * gcc.target/i386/mvc2.c: Likewise.
+ * gcc.target/i386/mvc3.c: Likewise.
+
+2017-07-04 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp1z/decomp1.C: Expect structured binding instead of
+ decomposition declaration in diagnostics.
+ * g++.dg/cpp1z/decomp2.C: Likewise.
+ * g++.dg/cpp1z/decomp3.C: Likewise.
+ * g++.dg/cpp1z/decomp4.C: Likewise.
+ * g++.dg/cpp1z/decomp5.C: Likewise.
+ * g++.dg/cpp1z/decomp6.C: Likewise.
+ * g++.dg/cpp1z/decomp7.C: Likewise.
+ * g++.dg/cpp1z/decomp8.C: Likewise.
+ * g++.dg/cpp1z/decomp13.C: Likewise.
+ * g++.dg/cpp1z/decomp14.C: Likewise.
+ * g++.dg/cpp1z/decomp18.C: Likewise.
+ * g++.dg/cpp1z/decomp19.C: Likewise.
+ * g++.dg/cpp1z/decomp22.C: Likewise.
+ * g++.dg/cpp1z/decomp23.C: Likewise.
+ * g++.dg/cpp1z/decomp24.C: Likewise.
+ * g++.dg/cpp1z/decomp25.C: Likewise.
+ * g++.dg/cpp1z/decomp26.C: Likewise.
+ * g++.dg/cpp1z/decomp28.C: Likewise.
+
+ PR c++/81258
+ * g++.dg/cpp1z/decomp21.C (foo): Adjust expected diagnostics.
+ * g++.dg/cpp1z/decomp30.C: New test.
+
+2017-07-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/65775
+ * g++.dg/cpp0x/trailing14.C: New.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR testsuite/79866
+ * gfortran.dg/coarray_event_2.f08: New test.
+
+2017-07-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR testsuite/79843
+ * gfortran.dg/namelist_3.f90: Adjust the dg-error string.
+ * gfortran.dg/pointer_intent_2.f90: Likewise.
+
+2017-07-02 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/81290
+ * gcc.c-torture/compile/pr81290.c: New.
+
+2017-07-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/60510
+ * gfortran.dg/vect/pr60510.f: New testcase.
+
+2017-07-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.target/i386/mvc6.c: Require ifunc support.
+
+2017-07-03 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/81040
+ * g++.dg/asan/function-argument-1.C: New test.
+ * g++.dg/asan/function-argument-2.C: New test.
+ * g++.dg/asan/function-argument-3.C: New test.
+
+2017-07-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gcc.dg/vect/bb-slp-pr65935.c: Expect SLP to be used in main
+ as well.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/69468
+ * gcc.dg/pr81192.c: Update.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/81192
+ * gcc.dg/pr81192.c: Update.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/81192
+ * gcc.dg/pr81192.c: New test.
+
+2017-07-02 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran/eoshift_3.f90: New test.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gcc.dg/strlenopt-32.c: New testcase.
+ * gcc.dg/strlenopt-33.c: Likewise.
+ * gcc.dg/strlenopt-33g.c: Likewise.
+ * gcc.dg/strlenopt-34.c: Likewise.
+ * gcc.dg/strlenopt-35.c: Likewise.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/80769
+ * gcc.dg/strlenopt-31.c: New test.
+ * gcc.dg/strlenopt-31g.c: Likewise.
+
+2017-07-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR tree-optimization/81136
+ * gcc.dg/vect/pr81136.c: New test.
+
+2017-07-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81262
+ * gcc.c-torture/compile/pr81262.c: New test.
+ * g++.dg/ubsan/pr81262.C: New test.
+
+2017-06-29 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/81261
+ * g++.dg/ipa/pr81261.C: New testcase.
+
+2017-06-30 Andrew Pinski <apinski@cavium.com>
+
+ * gcc.dg/torture/pr81245.c: New testcase.
+
+2017-06-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/Walloca-14.c: Adapt test to recognize new complaint of
+ unbounded use.
+
+2017-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/80014
+ * g++.dg/plugin/diagnostic-test-expressions-1.C (std::type_info):
+ Add declaration.
+ (test_typeid): New test function.
+
+2017-06-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/81225
+ * gcc.target/i386/pr81225.c: New test.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/concepts/memfun-err.C: Adjust diagnostics.
+ * g++.dg/cpp0x/decltype9.C: Likewise.
+ * g++.dg/cpp0x/forw_enum9.C: Likewise.
+ * g++.dg/lookup/decl1.C: Likewise.
+ * g++.dg/lookup/extern-c-redecl.C: Likewise.
+ * g++.dg/other/pr28432.C: Likewise.
+ * g++.dg/parse/crash12.C: Likewise.
+ * g++.dg/parse/enum3.C: Likewise.
+ * g++.dg/parse/operator6.C: Likewise.
+ * g++.dg/template/crash69.C: Likewise.
+ * g++.dg/template/error27.C: Likewise.
+ * g++.dg/template/error28.C: Likewise.
+ * g++.dg/template/memfriend6.C: Likewise.
+ * g++.old-deja/g++.mike/err1.C: Likewise.
+ * g++.old-deja/g++.mike/p811.C: Likewise.
+ * g++.old-deja/g++.other/crash25.C: Likewise.
+ * g++.old-deja/g++.other/dtor4.C: Likewise.
+ * g++.old-deja/g++.pt/t37.C: Likewise.
+
+2017-06-30 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81214
+ * gcc.target/i386/pr81214.c: New test.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/plugin/decl-plugin-test.C: Expect special ctor name.
+
+ PR c++/81229
+ * g++.dg/lookup/pr81229.C: New.
+
+2017-06-30 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81021
+ * g++.dg/asan/pr81021.C: New test.
+
+2017-06-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81249
+ * g++.dg/torture/pr81249.C: New testcase.
+
+2017-06-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp0x/inh-ctor3.C: Adjust for dg-message vs dg-error.
+ * g++.dg/diagnostic/variadic1.C: Likewise.
+ * g++.dg/gomp/udr-3.C: Likewise.
+ * g++.dg/overload/error1.C: Likewise.
+ * g++.dg/overload/error2.C: Likewise.
+ * g++.dg/template/duplicate1.C: Likewise.
+ * g++.old-deja/g++.benjamin/warn02.C: Likewise.
+ * g++.old-deja/g++.brendan/arm2.C: Likewise.
+ * g++.old-deja/g++.other/redecl2.C: Likewise.
+ * g++.old-deja/g++.other/redecl4.C: Likewise.
+ * g++.old-deja/g++.pt/memtemp78.C: Likewise.
+
+2017-06-29 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR fortran/77765
+ * gfortran.dg/goacc/pr77765.f90: New test.
+
+2017-06-29 Steve Ellcey <sellcey@cavium.com>
+
+ * gcc.target/aarch64/ccmp_2.c: New test.
+
+2017-06-29 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/81247
+ * g++.dg/parse/pr81247-[abc].C: New.
+
+2017-06-29 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-3-runnable.c (test_int_result,
+ test_unsigned_int_result, test_ll_int_result,
+ test_ll_unsigned_int_result): Add result checking functions, add
+ debug support.
+ (main): Add builtin function tests.
+
+2017-06-29 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-3-vec_reve-runnable.c (dg-options,
+ dg-skip-if): Add -mvsx -mcpu=power7.
+
+2017-06-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/slp-reduc-8.c: New testcase.
+
+2017-06-29 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/cpp1y/builtin_FUNCTION.C: New.
+
+2017-06-29 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR middle-end/81194
+ * g++.dg/pr81194.C: New test.
+
+2017-06-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ipa/80565
+ * gcc.dg/torture/pr80565.c: New file.
+
+2017-06-29 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/81196
+ * gcc.dg/vect/pr81196.c: New.
+
+2017-06-29 Michael Collison <michael.collison@arm.com>
+
+ Fix date on previous ChangeLog entry.
+
+2017-06-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Michael Collison <michael.collison@arm.com>
+
+ PR target/70119
+ * gcc.target/aarch64/var_shift_mask_1.c: New test.
+
+2017-06-28 Sebastian Peryt <sebastian.peryt@intel.com>
+
+ * gcc.target/i386/avx512vl-vpermd-1.c (_mm256_permutexvar_epi32):
+ Test new intrinsic.
+ * gcc.target/i386/avx512vl-vpermq-imm-1.c (_mm256_permutex_epi64):
+ Ditto.
+ * gcc.target/i386/avx512vl-vpermq-var-1.c (_mm256_permutexvar_epi64):
+ Ditto.
+ * gcc.target/i386/avx512f-vpermd-2.c: Do not check for AVX512F_LEN.
+ * gcc.target/i386/avx512f-vpermq-imm-2.c: Ditto.
+ * gcc.target/i386/avx512f-vpermq-var-2.c: Ditto.
+
+2017-06-28 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * lib/target-supports.exp (check_effective_target_vect_int): Replace
+ current ARM check by ARM NEON's availability check.
+ (check_effective_target_vect_intfloat_cvt): Likewise.
+ (check_effective_target_vect_uintfloat_cvt): Likewise.
+ (check_effective_target_vect_floatint_cvt): Likewise.
+ (check_effective_target_vect_floatuint_cvt): Likewise.
+ (check_effective_target_vect_shift): Likewise.
+ (check_effective_target_whole_vector_shift): Likewise.
+ (check_effective_target_vect_bswap): Likewise.
+ (check_effective_target_vect_shift_char): Likewise.
+ (check_effective_target_vect_long): Likewise.
+ (check_effective_target_vect_float): Likewise.
+ (check_effective_target_vect_perm): Likewise.
+ (check_effective_target_vect_perm_byte): Likewise.
+ (check_effective_target_vect_perm_short): Likewise.
+ (check_effective_target_vect_widen_sum_hi_to_si_pattern): Likewise.
+ (check_effective_target_vect_widen_sum_qi_to_hi): Likewise.
+ (check_effective_target_vect_widen_mult_qi_to_hi): Likewise.
+ (check_effective_target_vect_widen_mult_hi_to_si): Likewise.
+ (check_effective_target_vect_widen_mult_qi_to_hi_pattern): Likewise.
+ (check_effective_target_vect_widen_mult_hi_to_si_pattern): Likewise.
+ (check_effective_target_vect_widen_shift): Likewise.
+ (check_effective_target_vect_extract_even_odd): Likewise.
+ (check_effective_target_vect_interleave): Likewise.
+ (check_effective_target_vect_multiple_sizes): Likewise.
+ (check_effective_target_vect64): Likewise.
+ (check_effective_target_vect_max_reduc): Likewise.
+
+2017-06-28 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81227
+ * gcc.dg/pr81227.c: New testcase.
+
+2017-06-28 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/81193
+ * lib/target-supports.exp
+ (check_ppc_cpu_supports_hw_available): New test to make sure
+ __builtin_cpu_supports works on power7 and newer.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR ipa/81128
+ * gcc.target/i386/pr81128.c: New test.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR driver/79659
+ * g++.dg/opt/pr79659.C: New test.
+
+2017-06-28 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.dg/tree-ssa/copy-sign-1.c: Add c99_runtime effective target
+ and options.
+ * gcc.dg/tree-ssa/mult-abs-2.c: Likewise.
+
+2017-06-28 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/addadd.c: Remove test duplicated in addadd-2.c.
+ * gcc.dg/tree-ssa/mulcmp-1.c: New file.
+
+2017-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/cmov7.c (sgn): Renamed to ...
+ (foo): ... this. Change constants such that it isn't matched
+ as __builtin_copysign, yet tests the combiner the same.
+
+2017-06-28 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/81224
+ * gcc.dg/asan/pr81224.c: New test.
+
+2017-06-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/tree-prof/val-profiler-threads-1.c (main): Fix 2nd argument
+ passed to pthread_join.
+
+2017-06-28 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * gcc.target/s390/nodatarel-1.c: New test.
+
+2017-06-27 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/80164
+ * gfortran.dg/array_temporaries_4.f90: New test.
+
+2017-06-27 Andrew Pinski <apinski@cavium.com>
+
+ * gcc.dg/tree-ssa/copy-sign-1.c: New testcase.
+ * gcc.dg/tree-ssa/copy-sign-2.c: New testcase.
+ * gcc.dg/tree-ssa/mult-abs-2.c: New testcase.
+
+2017-06-27 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/81223
+ * gcc.dg/ubsan/pr81223.c: New test.
+
+2017-06-27 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/assoc-1.c: New file.
+
+2017-06-27 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/62046
+ * g++.dg/parse/catch2.C: New.
+
+2017-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81209
+ * g++.dg/ubsan/pr81209.C: New test.
+
+ PR middle-end/81207
+ * gcc.c-torture/compile/pr81207.c: New test.
+
+2017-06-27 Marek Polacek <polacek@redhat.com>
+
+ PR bootstrap/81216
+ * g++.dg/warn/Wmultistatement-macros-1.C: New test.
+
+2017-06-26 Martin Sebor <msebor@redhat.com>
+
+ PR c++/81169
+ * g++.dg/Wclass-memaccess-2.C: New test.
+
+2017-06-26 Carl Love <cel@us.ibm.com>
+
+ * gcc.target/powerpc/builtins-3-vec_reve-runnable.c:
+ Add new runnable test file for the vec_rev built-ins.
+
+2016-06-26 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR/tree-optimization 71815
+ * gcc.dg/tree-ssa/slsr-35.c: Remove -fno-code-hoisting workaround.
+ * gcc.dg/tree-ssa/slsr-36.c: Likewise.
+
+2017-06-26 Renlin Li <renlin.li@arm.com>
+ Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * gcc.c-torture/execute/builtins/memops-asm-lib.c (my_memmove): New.
+ * gcc.c-torture/execute/builtins/memops-asm.c (memmove): Declare
+ memmove.
+
+2017-06-26 Richard Biener <rguenther@suse.de>
+
+ PR target/81175
+ * gfortran.dg/pr81175.f: New testcase.
+
+2017-06-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81203
+ * gcc.dg/torture/pr81203.c: New testcase.
+
+2017-06-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/80116
+ * c-c++-common/Wmultistatement-macros-1.c: New test.
+ * c-c++-common/Wmultistatement-macros-2.c: New test.
+ * c-c++-common/Wmultistatement-macros-3.c: New test.
+ * c-c++-common/Wmultistatement-macros-4.c: New test.
+ * c-c++-common/Wmultistatement-macros-5.c: New test.
+ * c-c++-common/Wmultistatement-macros-6.c: New test.
+ * c-c++-common/Wmultistatement-macros-7.c: New test.
+ * c-c++-common/Wmultistatement-macros-8.c: New test.
+ * c-c++-common/Wmultistatement-macros-9.c: New test.
+ * c-c++-common/Wmultistatement-macros-10.c: New test.
+ * c-c++-common/Wmultistatement-macros-11.c: New test.
+
+2017-06-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-c++-common/ubsan/sanitize-recover-7.c (dg-options): Add -w.
+
+2017-06-26 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * lib/target-supports.exp
+ (check_effective_target_arm_neon_ok_nocache): Add flags with
+ -mfloat-abi=hard. Include arm_neon.h.
+ (check_effective_target_arm_neon_ok_no_float_abi_nocache): New.
+ (check_effective_target_arm_neon_ok_no_float_abi): New.
+ * gcc.target/arm/lto/pr65837_0.c: Require
+ arm_neon_ok_no_float_abi. Add -mfpu=neon to dg-lto-options.
+ * gcc.target/arm/lto/pr65837-attr_0.c: Require
+ arm_neon_ok_no_float_abi. Remove dg-suppress-ld-options.
+
2017-06-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/62315
@@ -5,7 +1618,7 @@
2017-06-24 Thomas Koenig <tkoenig@gcc.gnu.org>
- PR fortran/52473
+ PR fortran/52473
* gfortran.dg/cshift_2.f90: New test.
2017-06-23 Jim Wilson <jim.wilson@linaro.org>
@@ -36,8 +1649,7 @@
2017-06-23 James Cowgill <James.Cowgill@imgtec.com>
- * go.test/go-test.exp (go-set-goarch): Update MIPS architecture
- names.
+ * go.test/go-test.exp (go-set-goarch): Update MIPS architecture names.
2017-06-22 Matt Turner <mattst88@gmail.com>
@@ -394,7 +2006,7 @@
* gcc.dg/fold-bcopy.c: New test.
* gcc.dg/tree-ssa/ssa-dse-30.c: Likewise..
* gcc.dg/tree-ssa/alias-36.c: Likewise.
- * gcc/testsuite/gcc.dg/pr79214.c: Adjust.
+ * gcc.dg/pr79214.c: Adjust.
* gcc.dg/tree-prof/val-prof-7.c: Likewise.
* gcc.dg/Wsizeof-pointer-memaccess1.c: Likewise.
* gcc.dg/builtins-nonnull.c: Likewise.
@@ -735,12 +2347,12 @@
2017-06-08 Will Schmidt <will_schmidt@vnet.ibm.com>
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-char.c: New.
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-float.c: New.
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-floatdouble.c: New.
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-int.c: New.
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-longlong.c: New.
- * testsuite/gcc.target/powerpc/fold-vec-logical-eqv-short.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-char.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-float.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-floatdouble.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-int.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-longlong.c: New.
+ * gcc.target/powerpc/fold-vec-logical-eqv-short.c: New.
2017-06-08 Jakub Jelinek <jakub@redhat.com>
@@ -2463,8 +4075,8 @@
2017-05-08 Wilco Dijkstra <wdijkstr@arm.com>
- * testsuite/gcc.dg/vect/vect-44.c: Add -fno-vect-cost-model.
- * gcc/testsuite/gcc.dg/vect/vect-50.c: Likewise.
+ * gcc.dg/vect/vect-44.c: Add -fno-vect-cost-model.
+ * gcc.dg/vect/vect-50.c: Likewise.
2017-05-07 Jeff Law <law@redhat.com>
diff --git a/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c b/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c
index 6482b006c7f..870ba720c5f 100644
--- a/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c
+++ b/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c
@@ -68,7 +68,7 @@ void fn_14 (void)
/* { dg-begin-multiline-output "" }
for ((VAR) = (START); (VAR) < (STOP); (VAR++))
- ^
+ ^~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
FOR_EACH (i, 0, 10)
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c
new file mode 100644
index 00000000000..cdecbb4aca4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c
@@ -0,0 +1,118 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(X, Y) \
+ tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \
+ X = Y; \
+ Y = tmp
+
+#define STUFF \
+ if (0) x = y
+
+#define STUFF2 \
+ if (0) x = y; x++
+
+#define STUFF3 \
+ if (x) /* { dg-message "not guarded by this 'if' clause" } */ \
+ SWAP(x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define SET(X, Y) \
+ (X) = (Y)
+
+#define STUFF4 \
+ if (x) \
+ SET(x, y); \
+ SET(x, y)
+
+#define STUFF5 \
+ { tmp = x; x = y; }
+
+#define STUFF6 \
+ x++;;
+
+int x, y, tmp;
+
+void
+fn1 (void)
+{
+ if (x) /* { dg-message "not guarded by this 'if' clause" } */
+ SWAP(x, y); /* { dg-message "in expansion of macro .SWAP." } */
+}
+
+void
+fn2 (void)
+{
+ SWAP(x, y);
+}
+
+void
+fn3 (void)
+{
+ if (x)
+ {
+ SWAP(x, y);
+ }
+}
+
+void
+fn4 (void)
+{
+ if (x)
+ ({ x = 10; x++; });
+}
+
+void
+fn5 (void)
+{
+ if (x) /* { dg-message "not guarded by this 'if' clause" } */
+L1:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+ goto L1;
+}
+
+void
+fn6 (void)
+{
+ if (x)
+ SET (x, y);
+ SET (tmp, x);
+}
+
+void
+fn7 (void)
+{
+ STUFF;
+}
+
+void
+fn8 (void)
+{
+ STUFF2;
+}
+
+void
+fn9 (void)
+{
+ STUFF3; /* { dg-message "in expansion of macro .STUFF3." } */
+}
+
+void
+fn10 (void)
+{
+ STUFF4;
+}
+
+void
+fn11 (void)
+{
+ if (x)
+ STUFF5;
+}
+
+void
+fn12 (void)
+{
+ if (x)
+ STUFF6;
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c
new file mode 100644
index 00000000000..766ed25242a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c
@@ -0,0 +1,82 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(x, y) \
+ tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \
+ x = y; \
+ y = tmp
+
+#define M1 \
+ switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ \
+ case 1: \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define M2 \
+ switch (x) \
+ case 1: \
+ x++
+
+#define M3 \
+ switch (x) \
+ case 1: \
+ x++;;
+
+#define M4 \
+ switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ \
+L1: \
+ case 1: \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define INC \
+ x++;;
+
+int x, y, tmp;
+
+void
+fn0 (void)
+{
+ switch (x) /* { dg-message "not guarded by this 'switch' clause" } */
+ case 1:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+
+ switch (x) /* { dg-message "not guarded by this 'switch' clause" } */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+}
+
+void
+fn1 (void)
+{
+ M1; /* { dg-message "in expansion of macro .M1." } */
+ M2;
+ M3;
+ M4; /* { dg-message "in expansion of macro .M4." } */
+ goto L1;
+}
+
+void
+fn2 (void)
+{
+ switch (x)
+ case 1:
+ INC
+
+ switch (x)
+ case 1:
+ ({ x = 10; x++; });
+}
+
+void
+fn3 (void)
+{
+ switch (x)
+ {
+ case 1:
+ SWAP (x, y);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c
new file mode 100644
index 00000000000..4f4a123631d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c
@@ -0,0 +1,19 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+enum E { A, B };
+
+const char *
+foo (enum E e)
+{
+#define CASE(X) case X: return #X
+ switch (e)
+ {
+ CASE (A);
+ CASE (B);
+ default:
+ return "<unknown>";
+ }
+#undef CASE
+};
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-12.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-12.c
new file mode 100644
index 00000000000..ac8915c24b0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-12.c
@@ -0,0 +1,43 @@
+/* PR c/81364 */
+/* { dg-do compile } */
+/* { dg-options "-Wmultistatement-macros" } */
+
+#define FOO0 if (1) { } else
+#define TST0 \
+void bar0 (void) \
+{ \
+ FOO0 { } /* { dg-bogus "macro expands to multiple statements" } */ \
+}
+TST0
+
+#define FOO1 for (;;)
+#define TST1 \
+void bar1 (void) \
+{ \
+ FOO1 { } /* { dg-bogus "macro expands to multiple statements" } */ \
+}
+TST1
+
+#define FOO2 while (1)
+#define TST2 \
+void bar2 (void) \
+{ \
+ FOO2 { } /* { dg-bogus "macro expands to multiple statements" } */ \
+}
+TST2
+
+#define FOO3 switch (1)
+#define TST3 \
+void bar3 (void) \
+{ \
+ FOO3 { } /* { dg-bogus "macro expands to multiple statements" } */ \
+}
+TST3
+
+#define FOO4 if (1)
+#define TST4 \
+void bar4 (void) \
+{ \
+ FOO4 { } /* { dg-bogus "macro expands to multiple statements" } */ \
+}
+TST4
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c
new file mode 100644
index 00000000000..9fef90177eb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c
@@ -0,0 +1,137 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(X, Y) \
+ tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \
+ X = Y; \
+ Y = tmp
+
+#define STUFF \
+ if (0) {} else x = y
+
+#define STUFF2 \
+ if (0) {} else x = y; x++
+
+#define STUFF3 \
+ if (x) \
+ {} \
+ else /* { dg-message "not guarded by this 'else' clause" } */ \
+ SWAP(x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define SET(X, Y) \
+ (X) = (Y)
+
+#define STUFF4 \
+ if (x) \
+ {} \
+ else \
+ SET(x, y); \
+ SET(x, y)
+
+#define STUFF5 \
+ { tmp = x; x = y; }
+
+#define STUFF6 \
+ x++;;
+
+int x, y, tmp;
+
+void
+fn1 (void)
+{
+ if (x)
+ {
+ }
+ else /* { dg-message "not guarded by this 'else' clause" } */
+ SWAP(x, y); /* { dg-message "in expansion of macro .SWAP." } */
+}
+
+void
+fn2 (void)
+{
+ SWAP(x, y);
+}
+
+void
+fn3 (void)
+{
+ if (x)
+ {
+ }
+ else
+ {
+ SWAP(x, y);
+ }
+}
+
+void
+fn4 (void)
+{
+ if (x)
+ {
+ }
+ else
+ ({ x = 10; x++; });
+}
+
+void
+fn5 (void)
+{
+ if (x)
+ {
+ }
+ else /* { dg-message "not guarded by this 'else' clause" } */
+L1:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+ goto L1;
+}
+
+void
+fn6 (void)
+{
+ if (x)
+ {
+ }
+ else
+ SET (x, y);
+ SET (tmp, x);
+}
+
+void
+fn7 (void)
+{
+ STUFF;
+}
+
+void
+fn8 (void)
+{
+ STUFF2;
+}
+
+void
+fn9 (void)
+{
+ STUFF3; /* { dg-message "in expansion of macro .STUFF3." } */
+}
+
+void
+fn10 (void)
+{
+ STUFF4;
+}
+
+void
+fn11 (void)
+{
+ if (x)
+ STUFF5;
+}
+
+void
+fn12 (void)
+{
+ if (x)
+ STUFF6;
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c
new file mode 100644
index 00000000000..d130a35f8cc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c
@@ -0,0 +1,12 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define CHECK(X) if (!(X)) __builtin_abort ()
+
+void
+fn (int i)
+{
+ CHECK (i == 1);
+ CHECK (i == 2);
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c
new file mode 100644
index 00000000000..e5cc9c35d5b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c
@@ -0,0 +1,14 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define FN(C) \
+ void \
+ fn (void) \
+ { \
+ C; \
+ }
+
+int i;
+
+FN (if (i) ++i)
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c
new file mode 100644
index 00000000000..0ac84f54480
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c
@@ -0,0 +1,18 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define M(N) \
+L ## N: \
+ x++; x++ /* { dg-warning "macro expands to multiple statements" } */
+
+int x, y, tmp;
+
+void
+fn1 (void)
+{
+ if (x) /* { dg-message "not guarded by this 'if' clause" } */
+ M (0); /* { dg-message "in expansion of macro .M." } */
+ if (x) /* { dg-message "not guarded by this 'if' clause" } */
+ M (1); /* { dg-message "in expansion of macro .M." } */
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c
new file mode 100644
index 00000000000..5ec9cd9db26
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c
@@ -0,0 +1,22 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define M \
+ if (x) x++; x++
+
+void
+f (int x)
+{
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+ M;
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c
new file mode 100644
index 00000000000..d661f148ddf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c
@@ -0,0 +1,18 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(X, Y) \
+ tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \
+ X = Y; \
+ Y = tmp
+
+#define BODY_AND_IF(COND, X, Y) \
+ if (COND) SWAP (X, Y) /* { dg-message "in expansion of macro .SWAP." } */
+
+void
+fn (int x, int y)
+{
+ int tmp;
+ BODY_AND_IF (1, x, y); /* { dg-message "in expansion of macro .BODY_AND_IF." } */
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c
new file mode 100644
index 00000000000..06522a7d737
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c
@@ -0,0 +1,64 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(x, y) \
+ tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \
+ x = y; \
+ y = tmp
+
+#define M1 \
+ for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define M2 \
+ for (i = 0; i < 1; ++i) \
+ x++
+
+#define M3 \
+ for (i = 0; i < 1; ++i) \
+ x++;;
+
+#define M4 \
+ for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ \
+L1: \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define INC \
+ x++;;
+
+int x, y, tmp;
+
+void
+fn0 (void)
+{
+ int i;
+ for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+
+ for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */
+L:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+ goto L;
+}
+
+void
+fn1 (void)
+{
+ int i;
+ M1; /* { dg-message "in expansion of macro .M1." } */
+ M2;
+ M3;
+ M4; /* { dg-message "in expansion of macro .M4." } */
+ goto L1;
+}
+
+void
+fn2 (void)
+{
+ for (int i = 0; i < 1; ++i)
+ INC
+
+ for (int i = 0; i < 1; ++i)
+ ({ x = 10; x++; });
+}
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c
new file mode 100644
index 00000000000..350c4f9ffd0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c
@@ -0,0 +1,62 @@
+/* PR c/80116 */
+/* { dg-options "-Wmultistatement-macros" } */
+/* { dg-do compile } */
+
+#define SWAP(x, y) \
+ tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \
+ x = y; \
+ y = tmp
+
+#define M1 \
+ while (x) /* { dg-message "not guarded by this 'while' claus" } */ \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define M2 \
+ while (x) \
+ x++
+
+#define M3 \
+ while (x) \
+ x++;;
+
+#define M4 \
+ while (x) /* { dg-message "not guarded by this 'while' claus" } */ \
+L1: \
+ SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */
+
+#define INC \
+ x++;;
+
+int x, y, tmp;
+
+void
+fn0 (void)
+{
+ while (x) /* { dg-message "not guarded by this 'while' claus" } */
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+
+ while (x) /* { dg-message "not guarded by this 'while' claus" } */
+L:
+ SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */
+ goto L;
+}
+
+void
+fn1 (void)
+{
+ M1; /* { dg-message "in expansion of macro .M1." } */
+ M2;
+ M3;
+ M4; /* { dg-message "in expansion of macro .M4." } */
+ goto L1;
+}
+
+void
+fn2 (void)
+{
+ while (x)
+ INC
+
+ while (x)
+ ({ x = 10; x++; });
+}
diff --git a/gcc/testsuite/c-c++-common/Wsign-compare-1.c b/gcc/testsuite/c-c++-common/Wsign-compare-1.c
new file mode 100644
index 00000000000..b9b17a99280
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wsign-compare-1.c
@@ -0,0 +1,33 @@
+/* PR c/81417 */
+/* { dg-do compile } */
+/* { dg-options "-Wsign-compare" } */
+
+int
+fn1 (signed int a, unsigned int b)
+{
+ return a < b; /* { dg-warning "comparison of integer expressions of different signedness: 'int' and 'unsigned int'" } */
+}
+
+int
+fn2 (signed int a, unsigned int b)
+{
+ return b < a; /* { dg-warning "comparison of integer expressions of different signedness: 'unsigned int' and 'int'" } */
+}
+
+int
+fn3 (signed long int a, unsigned long int b)
+{
+ return b < a; /* { dg-warning "comparison of integer expressions of different signedness: 'long unsigned int' and 'long int'" } */
+}
+
+int
+fn4 (signed short int a, unsigned int b)
+{
+ return b < a; /* { dg-warning "comparison of integer expressions of different signedness: 'unsigned int' and 'short int'" } */
+}
+
+int
+fn5 (unsigned int a, signed int b)
+{
+ return a < b; /* { dg-warning "comparison of integer expressions of different signedness: 'unsigned int' and 'int'" } */
+}
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c b/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c
new file mode 100644
index 00000000000..54f03b8e301
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+
+volatile int ten = 10;
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(128)));
+ assert(!((long) str & 127L));
+ str[index] = '1'; // BOOM
+}
+
+int main() {
+ foo(ten, ten);
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_big_alignment.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in foo.*alloca_big_alignment.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c b/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c
new file mode 100644
index 00000000000..609dafe7bd8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+
+struct A {
+ char a[3];
+ int b[3];
+};
+
+volatile int ten = 10;
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile struct A str[len] __attribute__((aligned(32)));
+ assert(!((long) str & 31L));
+ str[index].a[0] = '1'; // BOOM
+}
+
+int main(int argc, char **argv) {
+ foo(ten, ten);
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_detect_custom_size.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in foo.*alloca_detect_custom_size.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_instruments_all_paddings.c b/gcc/testsuite/c-c++-common/asan/alloca_instruments_all_paddings.c
new file mode 100644
index 00000000000..6b08c0bf614
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_instruments_all_paddings.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+#include "sanitizer/asan_interface.h"
+#include <assert.h>
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(32)));
+ assert(!((long) str & 31L));
+ char *q = (char *)__asan_region_is_poisoned((char *)str, 64);
+ assert(q && ((q - str) == index));
+}
+
+int main(int argc, char **argv) {
+ for (int i = 1; i < 33; ++i)
+ foo(i, i);
+
+ for (int i = 1; i < 33; ++i)
+ foo(i, i);
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c b/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c
new file mode 100644
index 00000000000..0ddadb9c385
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+
+/* This testcase checks that allocas and VLAs inside loop are correctly unpoisoned. */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "sanitizer/asan_interface.h"
+
+void *top, *bot;
+volatile int thirty_two = 32;
+
+__attribute__((noinline)) void foo(int len) {
+ char x;
+ top = &x;
+ volatile char array[len];
+ assert(!((uintptr_t) array & 31L));
+ alloca(len);
+ for (int i = 0; i < thirty_two; ++i) {
+ char array[i];
+ bot = array;
+ /* Just to prevent optimization. */
+ printf("%p\n", bot);
+ assert(!((uintptr_t) bot & 31L));
+ }
+}
+
+int main(int argc, char **argv) {
+ foo(thirty_two);
+ void *q = __asan_region_is_poisoned(bot, (char *)top - (char *)bot);
+ assert(!q);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c b/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c
new file mode 100644
index 00000000000..9f4d0780bff
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+
+volatile const int ten = 10;
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(32)));
+ assert(!((long) str & 31L));
+ str[index] = '1'; // BOOM
+}
+
+int main(int argc, char **argv) {
+ foo(ten, ten);
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_partial.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in foo.*alloca_overflow_partial.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c b/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c
new file mode 100644
index 00000000000..085fdae350b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+
+volatile const int ten = 10;
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(32)));
+ assert(!((long) str & 31L));
+ str[index] = '1'; // BOOM
+}
+
+int main(int argc, char **argv) {
+ foo(33, ten);
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_right.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in foo.*alloca_overflow_right.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_safe_access.c b/gcc/testsuite/c-c++-common/asan/alloca_safe_access.c
new file mode 100644
index 00000000000..92da1b2ed46
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_safe_access.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+#include <assert.h>
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(32)));
+ assert(!((long)str & 31L));
+ str[index] = '1';
+}
+
+int main(int argc, char **argv) {
+ foo(4, 5);
+ foo(39, 40);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c b/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c
new file mode 100644
index 00000000000..fe2abe11461
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <assert.h>
+
+volatile const int ten = 10;
+
+__attribute__((noinline)) void foo(int index, int len) {
+ volatile char str[len] __attribute__((aligned(32)));
+ assert(!((long) str & 31L));
+ str[index] = '1'; // BOOM
+}
+
+int main(int argc, char **argv) {
+ foo(-1, ten);
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_underflow_left.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in foo.*alloca_underflow_left.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/asan/kasan-alloca-1.c b/gcc/testsuite/c-c++-common/asan/kasan-alloca-1.c
new file mode 100644
index 00000000000..518d19050ed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/kasan-alloca-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address -fdump-tree-sanopt" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+void foo(int index, int len) {
+ char str[len];
+ str[index] = '1'; // BOOM
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin___asan_alloca_poison" "sanopt" } } */
+/* { dg-final { scan-tree-dump-not "__builtin___asan_allocas_unpoison" "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/kasan-alloca-2.c b/gcc/testsuite/c-c++-common/asan/kasan-alloca-2.c
new file mode 100644
index 00000000000..e3999d93f6f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/kasan-alloca-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrument-allocas=1 --param asan-stack=1 -fdump-tree-sanopt" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+void foo(int index, int len) {
+ char str[len];
+ str[index] = '1'; // BOOM
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___asan_alloca_poison" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_allocas_unpoison" 1 "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/dump-ada-spec-7.c b/gcc/testsuite/c-c++-common/dump-ada-spec-7.c
new file mode 100644
index 00000000000..515d2597662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/dump-ada-spec-7.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-ada-spec" } */
+
+enum E1 {
+ A1 = -1L,
+ A2 = 0,
+ A3 = 1
+};
+
+static enum {B1 = -1L, B2, B3} Obj1;
+
+static struct { int i; } Obj2;
+
+/* { dg-final { scan-ada-spec-not "unsigned" } } */
+/* { dg-final { cleanup-ada-spec } } */
diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c b/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c
new file mode 100644
index 00000000000..8514b10e820
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
+/* { dg-final { scan-assembler-times "nop" 2 } } */
+
+extern int a;
+
+/* Respect overriding attributes in the declaration. */
+int f3 (void) __attribute__((patchable_function_entry(2)));
+
+/* F3 should now get 2 NOPs. */
+int
+__attribute__((noinline))
+f3 (void)
+{
+ return 5*a;
+}
diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-default.c b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c
new file mode 100644
index 00000000000..0dcf1181dde
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
+/* { dg-final { scan-assembler-times "nop" 3 } } */
+
+extern int a;
+
+/* Nothing declared must not mean anything. */
+int f3 (void);
+
+/* F3 should get a default-sized NOP area. */
+int
+__attribute__((noinline))
+f3 (void)
+{
+ return 5*a;
+}
diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c b/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c
new file mode 100644
index 00000000000..a007867dcb0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
+/* { dg-final { scan-assembler-times "nop" 1 } } */
+
+extern int a;
+
+int f3 (void);
+
+/* F3 should now get 1 NOP. */
+int
+__attribute__((noinline))
+__attribute__((patchable_function_entry(1)))
+f3 (void)
+{
+ return 5*a;
+}
diff --git a/gcc/testsuite/c-c++-common/pr70264.c b/gcc/testsuite/c-c++-common/pr70264.c
index 815aad175e5..c446942d0b8 100644
--- a/gcc/testsuite/c-c++-common/pr70264.c
+++ b/gcc/testsuite/c-c++-common/pr70264.c
@@ -5,7 +5,7 @@ X
/* { dg-begin-multiline-output "" }
#define X __LINE__
- ^
+ ^~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
X
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
index cd6941c9d30..aae88aa3180 100644
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
@@ -1,6 +1,7 @@
/* { dg-do run { target { lp64 || ilp32 } } } */
/* { dg-options "-fsanitize=float-cast-overflow" } */
-/* { dg-additional-options "-msse2 -mfpmath=sse" { target { sse2_runtime && ia32 } } } */
+/* { dg-additional-options "-ffloat-store" { target { ia32 } } } */
+/* { dg-additional-options "-mieee" { target { { alpha*-*-* } || { sh*-*-* } } } } */
#include <limits.h>
#include "float-cast.h"
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr81604.c b/gcc/testsuite/c-c++-common/ubsan/pr81604.c
new file mode 100644
index 00000000000..a06de76b023
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/pr81604.c
@@ -0,0 +1,31 @@
+/* PR sanitizer/81604 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds,signed-integer-overflow" } */
+
+long a[10];
+
+__attribute__((noinline, noclone)) long *
+foo (int i)
+{
+ return &a[i];
+}
+
+__attribute__((noinline, noclone)) long
+bar (long x, long y)
+{
+ return x * y;
+}
+
+int
+main ()
+{
+ volatile int i = -1;
+ volatile long l = __LONG_MAX__;
+ long *volatile p;
+ p = foo (i);
+ l = bar (l, l);
+ return 0;
+}
+
+/* { dg-output "index -1 out of bounds for type 'long int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: \[0-9]+ \\* \[0-9]+ cannot be represented in type 'long int'" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-1.c
new file mode 100644
index 00000000000..8edfbce0327
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-1.c
@@ -0,0 +1,65 @@
+/* PR sanitizer/80998 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -Wall" } */
+
+struct S { int a; int b; int c[64]; };
+__attribute__((noinline, noclone)) char *f1 (char *p) { return p + 1; }
+__attribute__((noinline, noclone)) char *f2 (char *p) { return p - 1; }
+__attribute__((noinline, noclone)) char *f3 (char *p, int i) { return p + i; }
+__attribute__((noinline, noclone)) char *f4 (char *p, int i) { return p - i; }
+__attribute__((noinline, noclone)) char *f5 (char *p, unsigned long int i) { return p + i; }
+__attribute__((noinline, noclone)) char *f6 (char *p, unsigned long int i) { return p - i; }
+__attribute__((noinline, noclone)) int *f7 (struct S *p) { return &p->a; }
+__attribute__((noinline, noclone)) int *f8 (struct S *p) { return &p->b; }
+__attribute__((noinline, noclone)) int *f9 (struct S *p) { return &p->c[64]; }
+__attribute__((noinline, noclone)) int *f10 (struct S *p, int i) { return &p->c[i]; }
+
+char *volatile p;
+struct S *volatile q;
+char a[64];
+struct S s;
+int *volatile r;
+
+int
+main ()
+{
+ struct S t;
+ p = &a[32];
+ p = f1 (p);
+ p = f1 (p);
+ p = f2 (p);
+ p = f3 (p, 1);
+ p = f3 (p, -1);
+ p = f3 (p, 3);
+ p = f3 (p, -6);
+ p = f4 (p, 1);
+ p = f4 (p, -1);
+ p = f4 (p, 3);
+ p = f4 (p, -6);
+ p = f5 (p, 1);
+ p = f5 (p, 3);
+ p = f6 (p, 1);
+ p = f6 (p, 3);
+ if (sizeof (unsigned long) >= sizeof (char *))
+ {
+ p = f5 (p, -1);
+ p = f5 (p, -6);
+ p = f6 (p, -1);
+ p = f6 (p, -6);
+ }
+ q = &s;
+ r = f7 (q);
+ r = f8 (q);
+ r = f9 (q);
+ r = f10 (q, 0);
+ r = f10 (q, 10);
+ r = f10 (q, 64);
+ q = &t;
+ r = f7 (q);
+ r = f8 (q);
+ r = f9 (q);
+ r = f10 (q, 0);
+ r = f10 (q, 10);
+ r = f10 (q, 64);
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-2.c b/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-2.c
new file mode 100644
index 00000000000..a1110a2ddbc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/ptr-overflow-2.c
@@ -0,0 +1,113 @@
+/* PR sanitizer/80998 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -fno-ipa-icf -Wall" } */
+
+__attribute__((noinline, noclone)) char * f1 (char *p) { return p + 1; }
+__attribute__((noinline, noclone)) char * f2 (char *p) { return p - 1; }
+__attribute__((noinline, noclone)) char * f3 (char *p, int i) { return p + i; }
+__attribute__((noinline, noclone)) char * f4 (char *p, int i) { return p + i; }
+__attribute__((noinline, noclone)) char * f5 (char *p, int i) { return p - i; }
+__attribute__((noinline, noclone)) char * f6 (char *p, int i) { return p - i; }
+__attribute__((noinline, noclone)) char * f7 (char *p, unsigned long int i) { return p + i; }
+__attribute__((noinline, noclone)) char * f8 (char *p, unsigned long int i) { return p + i; }
+__attribute__((noinline, noclone)) char * f9 (char *p, unsigned long int i) { return p - i; }
+__attribute__((noinline, noclone)) char * f10 (char *p, unsigned long int i) { return p - i; }
+struct S { int a; int b; int c[64]; };
+__attribute__((noinline, noclone)) int *f11 (struct S *p) { return &p->a; }
+__attribute__((noinline, noclone)) int *f12 (struct S *p) { return &p->b; }
+__attribute__((noinline, noclone)) int *f13 (struct S *p) { return &p->c[64]; }
+__attribute__((noinline, noclone)) int *f14 (struct S *p, int i) { return &p->c[i]; }
+__attribute__((noinline, noclone)) int *f15 (struct S *p, int i) { return &p->c[i]; }
+__attribute__((noinline, noclone)) int *f16 (struct S *p) { return &p->a; }
+__attribute__((noinline, noclone)) int *f17 (struct S *p) { return &p->b; }
+__attribute__((noinline, noclone)) int *f18 (struct S *p) { return &p->c[64]; }
+__attribute__((noinline, noclone)) int *f19 (struct S *p, int i) { return &p->c[i]; }
+__attribute__((noinline, noclone)) int *f20 (struct S *p, int i) { return &p->c[i]; }
+__attribute__((noinline, noclone)) int *f21 (struct S *p) { return &p->a; }
+__attribute__((noinline, noclone)) int *f22 (struct S *p) { return &p->b; }
+__attribute__((noinline, noclone)) int *f23 (struct S *p) { return &p->c[64]; }
+__attribute__((noinline, noclone)) int *f24 (struct S *p, int i) { return &p->c[i]; }
+__attribute__((noinline, noclone)) int *f25 (struct S *p, int i) { return &p->c[i]; }
+
+char *volatile p;
+__UINTPTR_TYPE__ volatile u;
+struct S *volatile q;
+int *volatile r;
+
+int
+main ()
+{
+ u = ~(__UINTPTR_TYPE__) 0;
+ p = (char *) u;
+ p = f1 (p);
+ u = 0;
+ p = (char *) u;
+ p = f2 (p);
+ u = -(__UINTPTR_TYPE__) 7;
+ p = (char *) u;
+ p = f3 (p, 7);
+ u = 3;
+ p = (char *) u;
+ p = f4 (p, -4);
+ u = 23;
+ p = (char *) u;
+ p = f5 (p, 27);
+ u = -(__UINTPTR_TYPE__) 15;
+ p = (char *) u;
+ p = f6 (p, -15);
+ u = -(__UINTPTR_TYPE__) 29;
+ p = (char *) u;
+ p = f7 (p, 31);
+ u = 23;
+ p = (char *) u;
+ p = f9 (p, 24);
+ if (sizeof (unsigned long) < sizeof (char *))
+ return 0;
+ u = 7;
+ p = (char *) u;
+ p = f8 (p, -8);
+ u = -(__UINTPTR_TYPE__) 25;
+ p = (char *) u;
+ p = f10 (p, -25);
+ u = ~(__UINTPTR_TYPE__) 0;
+ q = (struct S *) u;
+ r = f11 (q);
+ r = f12 (q);
+ r = f13 (q);
+ r = f14 (q, 0);
+ r = f15 (q, 63);
+ u = ~(__UINTPTR_TYPE__) 0 - (17 * sizeof (int));
+ q = (struct S *) u;
+ r = f16 (q);
+ r = f17 (q);
+ r = f18 (q);
+ r = f19 (q, 0);
+ r = f20 (q, 63);
+ u = 3 * sizeof (int);
+ q = (struct S *) u;
+ r = f21 (q);
+ r = f22 (q);
+ r = f23 (q);
+ r = f24 (q, -2);
+ r = f25 (q, -6);
+ return 0;
+}
+
+/* { dg-output ":5:6\[79]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:6:6\[79]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+ overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:7:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+9 overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:8:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+3 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:9:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+17 overflowed to (0\[xX])?\[fF]\+\[cC](\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:10:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+1 overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:11:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[eE]3 overflowed to (0\[xX])?0\+2(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:13:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+17 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:12:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+7 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:14:\[89]\[91]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[eE]7 overflowed to (0\[xX])?0\+" } */
+/* { dg-output "(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:17:\[67]\[82]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+3(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:18:\[67]\[86]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+107(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:19:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+7(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:20:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+103(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:23:\[67]\[86]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[bB]\[bB] overflowed to (0\[xX])?0\+\[cC]3(\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:25:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[bB]\[bB] overflowed to (0\[xX])?0\+\[bB]\[fF](\n|\r\n|\r)" { target int32 } } */
+/* { dg-output "\[^\n\r]*:30:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+\[cC] overflowed to (0\[xX])?\[fF]\+\[cC]" { target int32 } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c
index 9ffba50443a..96a8cc576b6 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-all-1.c
@@ -5,4 +5,4 @@
int i;
-/* { dg-error "-fsanitize=all option is not valid" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize=all. option is not valid" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c
index 4d8c27e945a..efa5ad7291f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-1.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize-recover=unreachable. is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c
index e9849bd50ab..2b7cbcb6a7f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-2.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error "-fsanitize-recover=return is not supported" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize-recover=return. is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c
index 9c1ed322d5e..3d2e51ebb91 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-5.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize-recover=unreachable. is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
index 2e6599fe312..a571f2bcdc1 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fsanitize=address -fsanitize=thread" } */
+/* { dg-options "-fsanitize=address -fsanitize=thread -w" } */
int i;
-/* { dg-error "-fsanitize=address and -fsanitize=kernel-address are incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize=address. and .-fsanitize=kernel-address. are incompatible with .-fsanitize=thread." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c
index ecaf0e648af..97f4bf4c465 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-8.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error "-fsanitize=leak is incompatible with -fsanitize=thread" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize=leak. is incompatible with .-fsanitize=thread." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c
index ef80ef1e27d..0800ecbe155 100644
--- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c
+++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-9.c
@@ -3,4 +3,4 @@
int i;
-/* { dg-error "-fsanitize-recover=unreachable is not supported" "" { target *-*-* } 0 } */
+/* { dg-error ".-fsanitize-recover=unreachable. is not supported" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess-2.C b/gcc/testsuite/g++.dg/Wclass-memaccess-2.C
new file mode 100644
index 00000000000..49581df1204
--- /dev/null
+++ b/gcc/testsuite/g++.dg/Wclass-memaccess-2.C
@@ -0,0 +1,61 @@
+// PR c++/81169 - -Wclass-memaccess illegitimate warning related to volatile
+// { dg-do compile }
+// { dg-options "-Wclass-memaccess" }
+
+struct S { int x; };
+
+void cast_const (const S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void cast_volatile (volatile S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset (const_cast<S*>(p), 0, sizeof *p);
+}
+
+void c_cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset ((S*)p, 0, sizeof *p);
+}
+
+// A C cast to void* suppresses the warning because it casts away
+// the qualifiers from the otherwise trivial pointed-to type..
+void c_void_cast_const_volatile (const volatile S *p)
+{
+ __builtin_memset ((void*)p, 0, sizeof *p);
+}
+
+// Also verify that casting to char* suppresses the warning for
+// non-trivial types.
+
+struct NonTrivial
+{
+ NonTrivial ();
+ NonTrivial (const NonTrivial&);
+ NonTrivial& operator= (const NonTrivial&);
+ ~NonTrivial ();
+};
+
+void cast_void (NonTrivial *p)
+{
+ __builtin_memset (reinterpret_cast<char*>(p), 0, sizeof *p);
+}
+
+// A C cast to a character (or any trivial) type suppresses the warning.
+void c_cast_uchar (NonTrivial *p)
+{
+ __builtin_memset ((unsigned char*)p, 0, sizeof *p);
+}
+
+// A cast to void* does not suppress the warning. That is (or can be)
+// considered a feature.
+void c_cast_void (NonTrivial *p)
+{
+ __builtin_memset ((void*)p, 0, sizeof *p); // { dg-warning "\\\[-Wclass-memaccess]" }
+}
diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C
new file mode 100644
index 00000000000..bdbb37a44a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C
@@ -0,0 +1,31 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+// { dg-options "-fsanitize=address -fno-sanitize-address-use-after-scope" }
+
+struct A
+{
+ int a[5];
+};
+
+static __attribute__ ((noinline)) int
+goo (A *a)
+{
+ int *ptr = &a->a[0];
+ return *(volatile int *) (ptr - 1);
+}
+
+__attribute__ ((noinline)) int
+foo (A arg)
+{
+ return goo (&arg);
+}
+
+int
+main ()
+{
+ return foo (A ());
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-buffer-underflow on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size . at.*" }
+// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* underflows this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/function-argument-2.C b/gcc/testsuite/g++.dg/asan/function-argument-2.C
new file mode 100644
index 00000000000..3a7c33bdaaa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/function-argument-2.C
@@ -0,0 +1,24 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+static __attribute__ ((noinline)) int
+goo (int *a)
+{
+ return *(volatile int *)a;
+}
+
+__attribute__ ((noinline)) int
+foo (char arg)
+{
+ return goo ((int *)&arg);
+}
+
+int
+main ()
+{
+ return foo (12);
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size . at.*" }
+// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* partially overflows this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/function-argument-3.C b/gcc/testsuite/g++.dg/asan/function-argument-3.C
new file mode 100644
index 00000000000..6994b6df1c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/function-argument-3.C
@@ -0,0 +1,28 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+// { dg-additional-options "-Wno-psabi" }
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+static __attribute__ ((noinline)) int
+goo (v4si *a)
+{
+ return (*(volatile v4si *) (a + 1))[2];
+}
+
+__attribute__ ((noinline)) int
+foo (v4si arg)
+{
+ return goo (&arg);
+}
+
+int
+main ()
+{
+ v4si v = {1,2,3,4};
+ return foo (v);
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size . at.*" }
+// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* overflows this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/pr81021.C b/gcc/testsuite/g++.dg/asan/pr81021.C
new file mode 100644
index 00000000000..daa0525c273
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr81021.C
@@ -0,0 +1,33 @@
+// { dg-do run }
+
+#include <string>
+
+struct ConfigFile {
+ ConfigFile(std::string filename, std::string delimiter) { throw "error"; }
+ ConfigFile(std::string filename) {}
+};
+
+struct Configuration {
+ ConfigFile _configFile;
+
+ Configuration(const std::string &root, const char *baseName)
+ : _configFile(root + baseName, "=") { }
+ Configuration(const std::string &root, const char *a, const char *b)
+ : _configFile(root + a + b) { }
+};
+
+
+void test() {
+ std::string root("etc");
+ try {
+ Configuration config(root, "notthere");
+ }
+ catch (...) {
+ // exception is thrown, caught here and ignored...
+ }
+ Configuration config(root, "a", "b"); // ASAN error during constructor here
+}
+
+int main(int argc, const char *argv[]) {
+ test();
+}
diff --git a/gcc/testsuite/g++.dg/asan/pr81340.C b/gcc/testsuite/g++.dg/asan/pr81340.C
new file mode 100644
index 00000000000..76ac08a9a56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr81340.C
@@ -0,0 +1,22 @@
+// { dg-options "-fsanitize=address -O2 -g -Wno-write-strings" }
+
+class a {
+ struct b {
+ b(int, int);
+ } c;
+
+public:
+ int d;
+ a(char *) : c(0, d) {}
+};
+class e {
+ int f(const int &, const int &, const int &, bool, bool, bool, int, bool);
+};
+class g {
+public:
+ static g *h();
+ void i(a, void *);
+};
+int e::f(const int &, const int &, const int &, bool j, bool, bool, int, bool) {
+ g::h()->i("", &j);
+}
diff --git a/gcc/testsuite/g++.dg/concepts/memfun-err.C b/gcc/testsuite/g++.dg/concepts/memfun-err.C
index e44273ca8c8..f44610a6aa0 100644
--- a/gcc/testsuite/g++.dg/concepts/memfun-err.C
+++ b/gcc/testsuite/g++.dg/concepts/memfun-err.C
@@ -15,16 +15,16 @@ int called = 0;
// Test constrained member definitions
template<typename T>
- struct S1 {
+ struct S1 { // { dg-message "defined here" }
void f1() requires C<T>() { }
void g1() requires C<T>() and true;
template<C U> void h1(U u) { called = 1; }
- void g2() requires C<T>(); // { dg-error "candidate" }
+ void g2() requires C<T>(); // { dg-message "candidate" }
};
template<typename T>
- void S1<T>::g2() requires D<T>() { } // { dg-error "prototype" }
+ void S1<T>::g2() requires D<T>() { } // { dg-error "no declaration matches" }
int main() {
S1<X> sx;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C
new file mode 100644
index 00000000000..6bf9b7b1666
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C
@@ -0,0 +1,16 @@
+// PR c++/72764
+// { dg-do compile { target c++11 } }
+
+template < typename > struct A;
+template < typename > struct B {};
+
+template < typename T >
+using C = typename A < T >::template D < T >;
+
+template < typename T > struct A
+{
+ // should be: template < typename > struct D : B < C < T > > {};
+ struct D : B < C < T > > {}; // { dg-error "not a class template" }
+};
+
+A < int >::D a; // { dg-message "required" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto1.C b/gcc/testsuite/g++.dg/cpp0x/auto1.C
index b8d39051821..dd8f5fc8cf9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto1.C
@@ -1,9 +1,14 @@
// { dg-do compile { target c++11 } }
-// { dg-options "-std=c++98 -Wc++11-compat" }
+// { dg-options "-std=c++98 -Wc++11-compat -fdiagnostics-show-caret" }
// Test warning for use of auto in C++98 mode with C++11
// compatibility warnings
void f()
{
- auto int x = 5; // { dg-warning "changes meaning" }
+ auto int x = 5; /* { dg-warning "changes meaning" }
+ { dg-begin-multiline-output "" }
+ auto int x = 5;
+ ^~~~
+ ----
+ { dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call4.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call4.C
new file mode 100644
index 00000000000..d504954bc63
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call4.C
@@ -0,0 +1,13 @@
+// PR c++/81188
+// { dg-do compile { target c++11 } }
+
+template <class F>
+struct C {
+ F fast(long i) const;
+ auto operator[](long i) const -> decltype(this->fast(i));
+};
+
+template <class F>
+auto C<F>::operator[](long i) const -> decltype(this->fast(i)) {
+ return fast(i);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype9.C b/gcc/testsuite/g++.dg/cpp0x/decltype9.C
index 9db3db039a2..45cd9ed7da3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype9.C
@@ -1,9 +1,9 @@
// PR c++/34271
// { dg-do compile { target c++11 } }
-template<int> struct A
-{
+template<int> struct A { // { dg-message "defined here" }
static int i;
};
-template<int N> int A<N>::i(decltype (A::i)); // { dg-error "member function|must be an expression" }
+template<int N> int A<N>::i(decltype (A::i)); // { dg-error "no declaration" }
+// { dg-message "no functions" "note" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
index 4f1475acfde..acf16c6c8bd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
@@ -4,7 +4,7 @@
template<typename T> struct S1
{
enum E1 : int;
- enum class E2 : int;
+ enum class E2 : T;
};
template<typename T> enum S1<T>::E1 : int { e1 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
new file mode 100644
index 00000000000..90a06c610f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
@@ -0,0 +1,7 @@
+// PR c++/81164
+// { dg-do compile { target c++11 } }
+
+struct A {};
+struct B : virtual A {};
+struct C : virtual A {};
+struct D : B,C { using A::A; }; // { dg-error "indirect" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor29.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor29.C
new file mode 100644
index 00000000000..8e31f739d74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor29.C
@@ -0,0 +1,23 @@
+// PR c++/67054
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ A(int) {}
+};
+
+struct C
+{
+ C(int) {}
+};
+
+struct B : A
+{
+ using A::A;
+ C c = 42;
+};
+
+int main()
+{
+ B b = 24;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
index 8cbeed66047..c5a00750236 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
@@ -8,7 +8,7 @@ struct B2 {
B2(int);
};
struct D1 : B1, B2 {
- using B1::B1; // { dg-error "inherited" }
+ using B1::B1; // { dg-message "declared" }
using B2::B2; // { dg-error "inherited" }
}; // ill-formed: attempts to declare D1(int) twice
struct D2 : B1, B2 {
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice17.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice17.C
new file mode 100644
index 00000000000..57111fdef6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice17.C
@@ -0,0 +1,12 @@
+// PR c++/71570
+// { dg-do compile { target c++11 } }
+
+void foo (int);
+
+void foo (void)
+{
+ [&foo] // { dg-error "cannot capture" }
+ {
+ foo (0);
+ };
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/missing-initializer_list-include.C b/gcc/testsuite/g++.dg/cpp0x/missing-initializer_list-include.C
new file mode 100644
index 00000000000..8e803c82f24
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/missing-initializer_list-include.C
@@ -0,0 +1,28 @@
+/* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+// { dg-do compile { target c++11 } }
+
+void test (int i)
+{
+ auto a = { &i }; // { dg-error "deducing from brace-enclosed initializer list requires #include <initializer_list>" }
+}
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing this
+ source filename, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+/* Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -1,3 +1,4 @@
++#include <initializer_list>
+ /* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+{ dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
new file mode 100644
index 00000000000..c51e94e7573
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
@@ -0,0 +1,12 @@
+// PR c++/69300
+// { dg-do compile { target c++11 } }
+
+template<typename A>
+struct F {
+ template<typename B>
+ void f() noexcept(&F::template f<B>) {} // { dg-error "exception specification" }
+};
+
+int main () {
+ F<void>().f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing14.C b/gcc/testsuite/g++.dg/cpp0x/trailing14.C
new file mode 100644
index 00000000000..2544d0bab5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing14.C
@@ -0,0 +1,15 @@
+// PR c++/65775
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wignored-qualifiers" }
+
+using Qi = int const volatile;
+Qi q1(); // { dg-warning "1: type qualifiers ignored" }
+auto q2() -> Qi; // { dg-warning "1: type qualifiers ignored" }
+
+using Fi = int();
+Fi f1(); // { dg-error "1: 'f1' declared as function returning a function" }
+auto f2() -> Fi; // { dg-error "1: 'f2' declared as function returning a function" }
+
+using Ai = int[5];
+Ai a1(); // { dg-error "1: 'a1' declared as function returning an array" }
+auto a2() -> Ai; // { dg-error "1: 'a2' declared as function returning an array" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn2.C
new file mode 100644
index 00000000000..4a02ab22990
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn2.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+
+template <class A0, class... As> struct tuple
+{
+ tuple<As...> tail;
+ template <int Offset, class... More> int apply(const More&... more) {
+ return tail.apply<1>(more...); // { dg-error "" } needs .template
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial1.C
new file mode 100644
index 00000000000..6f8df3e1aaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial1.C
@@ -0,0 +1,22 @@
+// PR c++/72801
+// { dg-do compile { target c++11 } }
+
+template < typename, typename > struct A {};
+
+template < typename ... T > struct B
+{
+ template < typename > struct C
+ {
+ static const int a = 0;
+ };
+
+ template < typename R, typename ... S >
+ struct C < R (A < T, S > ...) >
+ {
+ static const int a = 1;
+ };
+};
+
+#define SA(X) static_assert ((X), #X)
+SA(B <>::C<int()>::a == 1);
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C
new file mode 100644
index 00000000000..0dbe904601d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C
@@ -0,0 +1,16 @@
+// PR c++/81215
+// { dg-do compile { target c++11 } }
+
+template<typename U> struct X { };
+template<typename T, typename U = void> struct set { };
+
+template <typename V, template <typename...> class C>
+void bar (const X<C<V>>&)
+{
+}
+
+void
+foo (X<set<int>>& x)
+{
+ bar (x);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp8.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp8.C
new file mode 100644
index 00000000000..f3e576ae988
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp8.C
@@ -0,0 +1,27 @@
+// PR c++/69111
+// { dg-do compile { target c++11 } }
+
+template <template <typename> class ...>
+struct template_list {};
+
+template <typename T>
+struct A
+{};
+
+template <typename>
+struct B
+{
+ template <typename T>
+ using type = A<T>;
+};
+
+template <typename ... Types>
+struct C
+{
+ using type = template_list<B<Types>::template type...>;
+};
+
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/builtin_FUNCTION.C b/gcc/testsuite/g++.dg/cpp1y/builtin_FUNCTION.C
new file mode 100644
index 00000000000..680ba633611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/builtin_FUNCTION.C
@@ -0,0 +1,42 @@
+// { dg-do run }
+
+#include <string.h>
+
+const char *ct, *dt, *cv;
+
+struct KLASS
+{
+ KLASS () ;
+ ~KLASS ();
+ operator int ();
+};
+
+KLASS::KLASS()
+{
+ ct = __builtin_FUNCTION ();
+}
+
+KLASS::~KLASS ()
+{
+ dt = __builtin_FUNCTION ();
+}
+
+KLASS::operator int ()
+{
+ cv = __builtin_FUNCTION ();
+ return 0;
+}
+
+int main ()
+{
+ int q = int (KLASS ());
+
+ if (strcmp (ct, "KLASS"))
+ return 1;
+ if (strcmp (dt, "~KLASS"))
+ return 2;
+ if (strcmp (cv, "operator int"))
+ return 3;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction40.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction40.C
new file mode 100644
index 00000000000..eeffa69adf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction40.C
@@ -0,0 +1,19 @@
+// PR c++/81180
+// { dg-options -std=c++1z }
+
+template < int I > struct int_{};
+
+template < typename T >
+struct A{
+ template < typename U, int I >
+ struct B{
+ B(U u, int_< I >){}
+ };
+};
+
+
+int main(){
+ A< int >::B v(0, int_< 0 >());
+ (void)v;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C
new file mode 100644
index 00000000000..5e7fa3a2c51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C
@@ -0,0 +1,19 @@
+// { dg-options -std=c++1z }
+
+#include <initializer_list>
+
+struct B { };
+
+template <class T>
+struct A
+{
+ A(std::initializer_list<T>);
+ A(T, B);
+};
+
+A a { 1, B() };
+
+template <class,class> struct same;
+template <class T> struct same<T,T> { };
+
+same<decltype(a), A<int>> s;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C
new file mode 100644
index 00000000000..8217fd4d79a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C
@@ -0,0 +1,19 @@
+// { dg-options -std=c++1z }
+
+#include <initializer_list>
+
+template <class,class> struct same;
+template <class T> struct same<T,T> { };
+
+template <class T>
+struct A
+{
+ A(const A&);
+ A(std::initializer_list<T>);
+};
+
+A a { 1 };
+A b { a };
+
+same<decltype (a), decltype (b)> s;
+
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp1.C b/gcc/testsuite/g++.dg/cpp1z/decomp1.C
index 98f60905e1a..33068917863 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp1.C
@@ -7,10 +7,10 @@ struct S { int a; signed char b; float c; } s = { 6, 7, 8.0f };
int
main ()
{
- auto & [ c, d ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ e, f ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ g, h, i ] = s; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ j, k, l ] = s; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto & [ c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ e, f ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ g, h, i ] = s; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ j, k, l ] = s; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
c++;
d++;
e += 6;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp13.C b/gcc/testsuite/g++.dg/cpp1z/decomp13.C
index 9ebddc6e608..a9bf264a2ca 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp13.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp13.C
@@ -11,27 +11,27 @@ namespace std {
template<> struct std::tuple_size<B> { static constexpr int value = 2; };
template<int I> struct std::tuple_element<I,B> { typedef int type; };
-auto [ aa, bb, cc, dd ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+auto [ aa, bb, cc, dd ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZDC2aa2bb2cc2ddE" } }
-const auto & [ e, f, g, h ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+const auto & [ e, f, g, h ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZDC1e1f1g1hE" } }
-auto [ ee, ff ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+auto [ ee, ff ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZDC2ee2ffE" } }
-auto & [ gg, hh ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+auto & [ gg, hh ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZDC2gg2hhE" } }
namespace N
{
namespace M
{
- auto [ i, j, k, l ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ i, j, k, l ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZN1N1MDC1i1j1k1lEE" } }
- auto & [ m, n, o, ppp ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto & [ m, n, o, ppp ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZN1N1MDC1m1n1o3pppEE" } }
- auto [ ii, jj ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ ii, jj ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZN1N1MDC2ii2jjEE" } }
// { dg-final { scan-assembler "_ZN1N1M2iiE" } }
// { dg-final { scan-assembler "_ZN1N1M2jjE" } }
- auto & [ mm, nn ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto & [ mm, nn ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZN1N1MDC2mm2nnEE" } }
// { dg-final { scan-assembler "_ZN1N1M2mmE" } }
// { dg-final { scan-assembler "_ZN1N1M2nnE" } }
@@ -39,14 +39,14 @@ namespace N
}
namespace std
{
- auto [ i2, j2, k2, l2 ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ i2, j2, k2, l2 ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZStDC2i22j22k22l2E" } }
- auto [ vv, ww ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ vv, ww ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
// { dg-final { scan-assembler "_ZStDC2vv2wwE" } }
// { dg-final { scan-assembler "_ZSt2vv" } }
// { dg-final { scan-assembler "_ZSt2ww" } }
}
namespace
{
- auto [ v, w, x, y ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ v, w, x, y ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp14.C b/gcc/testsuite/g++.dg/cpp1z/decomp14.C
index 5d6d05fb8a4..d05a8903232 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp14.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp14.C
@@ -18,13 +18,13 @@ struct M : virtual J, L {};
void
foo (C &c, F &f, G &g, H &h, I &i, K &k, M &m)
{
- auto [ ci ] = c; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [ ci ] = c; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
auto [ fi ] = f; // { dg-error "cannot decompose class type 'F': both it and its base class 'A' have non-static data members" }
- // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
auto [ gi ] = g; // { dg-error "cannot decompose class type 'G': its base classes 'A' and 'E' have non-static data members" }
- // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
- auto [ hi ] = h; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [ hi ] = h; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
auto [ ki ] = k; // { dg-error "'B' is an ambiguous base of 'K'" }
- // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
- auto [ mi ] = m; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [ mi ] = m; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp18.C b/gcc/testsuite/g++.dg/cpp1z/decomp18.C
index d5c68a26891..7799e462cdd 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp18.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp18.C
@@ -7,6 +7,6 @@ void
foo ()
{
int z = 0;
- for (auto & [ b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto & [ b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
z += b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp19.C b/gcc/testsuite/g++.dg/cpp1z/decomp19.C
index e392e658e27..e7d7abfce7c 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp19.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp19.C
@@ -8,6 +8,6 @@ main ()
int x = 99;
struct S { int &x; };
S s{x};
- auto [p] = s; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [p] = s; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
return p - 99;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp2.C b/gcc/testsuite/g++.dg/cpp1z/decomp2.C
index 5831fc74940..6574028217f 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp2.C
@@ -9,12 +9,12 @@ __complex__ int c = 7 + 8i;
int
main ()
{
- auto & [ d, e, f, g ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ h, i, j, k ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ l, m ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ n, o ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ p, q ] = c; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ r, s ] = c; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto & [ d, e, f, g ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ h, i, j, k ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ l, m ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ n, o ] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ p, q ] = c; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ r, s ] = c; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
d += 10;
e += 11;
f += 12;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp21.C b/gcc/testsuite/g++.dg/cpp1z/decomp21.C
index d046ed54a14..7d3a465d3a3 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp21.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp21.C
@@ -12,5 +12,6 @@ foo ()
auto [ n, o, p ] { a };
auto [ q, r, t ] ( s );
auto [ u, v, w ] ( s, ); // { dg-error "expected primary-expression before '.' token" }
- auto [ x, y, z ] ( a ); // { dg-error "expression list treated as compound expression in initializer" "" { target *-*-* } .-1 }
+ // { dg-error "invalid initializer for structured binding declaration" "" { target *-*-* } .-1 }
+ auto [ x, y, z ] ( a );
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp22.C b/gcc/testsuite/g++.dg/cpp1z/decomp22.C
index 81d40c56931..9e6b8df486a 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp22.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp22.C
@@ -16,6 +16,6 @@ int &&get (C<E...> &&);
int
foo (C<int> t)
{
- auto[x0] = t; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto[x0] = t; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
return x0;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp23.C b/gcc/testsuite/g++.dg/cpp1z/decomp23.C
index c682fa00264..9e9278050c9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp23.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp23.C
@@ -7,6 +7,6 @@
int
foo (std::tuple<int> t)
{
- auto [x0] = t; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [x0] = t; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
return x0;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp24.C b/gcc/testsuite/g++.dg/cpp1z/decomp24.C
index 0e874fa6055..4bd519791ff 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp24.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp24.C
@@ -7,5 +7,5 @@ foo ()
{
int a {10};
auto [b] { [&a](){} }; // { dg-error "cannot decompose lambda closure type" }
- return b - a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+ return b - a; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp25.C b/gcc/testsuite/g++.dg/cpp1z/decomp25.C
index c99273613bc..d90e665add0 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp25.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp25.C
@@ -7,9 +7,9 @@ struct S
{
enum E { A };
void f () { auto [x] = 0; x++; } // { dg-error "cannot decompose non-array non-class type" }
- // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
void g (T t) { auto [y] = t; y++; } // { dg-error "cannot decompose non-array non-class type" }
-}; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .-1 }
+}; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
int
main ()
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp26.C b/gcc/testsuite/g++.dg/cpp1z/decomp26.C
index f413920f545..035433385d7 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp26.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp26.C
@@ -2,5 +2,5 @@
// { dg-do compile { target c++11 } }
// { dg-options "" }
-template<typename T> T &make(); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } .+1 }
+template<typename T> T &make(); // { dg-warning "structured bindings only available with" "" { target c++14_down } .+1 }
auto [d1, d2] = make<int>(); // { dg-error "cannot decompose non-array non-class type" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp28.C b/gcc/testsuite/g++.dg/cpp1z/decomp28.C
index 7561d9dfc02..8b0b5a54999 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp28.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp28.C
@@ -15,14 +15,14 @@ template <int N>
void
foo (std::tuple<int> b)
{
- auto [c] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [c] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
}
template <typename T>
void
bar (std::tuple<T> b)
{
- auto [c] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [c] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
}
void
@@ -35,5 +35,5 @@ baz (std::tuple<int> b)
int
main ()
{
- [](auto) { [](std::tuple<int> b) { auto[c] = b; }; } (0); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ [](auto) { [](std::tuple<int> b) { auto[c] = b; }; } (0); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
index a739d3ace37..58ce71bf6ac 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
@@ -9,36 +9,36 @@ B baz ();
void
test (A &b, B c)
{
- int && [ d ] = c; // { dg-error "decomposition declaration cannot be declared with type 'int'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- char & [ e, f, ff ] { b }; // { dg-error "decomposition declaration cannot be declared with type 'char'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto&[g,h,i]=b; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
- decltype (auto) [ j ] = c; // { dg-error "decomposition declaration cannot be declared with type 'decltype.auto.'" "" { target c++14 } }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ int && [ d ] = c; // { dg-error "structured binding declaration cannot have type 'int'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ char & [ e, f, ff ] { b }; // { dg-error "structured binding declaration cannot have type 'char'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto&[g,h,i]=b; // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
+ decltype (auto) [ j ] = c; // { dg-error "structured binding declaration cannot have type 'decltype.auto.'" "" { target c++14 } }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
// { dg-error "expected primary-expression before 'decltype'" "" { target c++11_down } .-2 }
auto & & && & [ m, n, o ] = b; // { dg-error "multiple ref-qualifiers" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- constexpr auto [ p ] = c; // { dg-error "decomposition declaration cannot be declared 'constexpr'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ constexpr auto [ p ] = c; // { dg-error "structured binding declaration cannot be 'constexpr'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
friend auto [ q ] = c; // { dg-error "'friend' used outside of class" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- typedef auto [ r ] = c; // { dg-error "decomposition declaration cannot be declared 'typedef'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- inline auto [ s ] = c; // { dg-error "decomposition declaration cannot be declared 'inline'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ typedef auto [ r ] = c; // { dg-error "structured binding declaration cannot be 'typedef'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ inline auto [ s ] = c; // { dg-error "structured binding declaration cannot be 'inline'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
__restrict auto [ t ] = c; // { dg-error "invalid use of 'restrict'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- long long auto [ u ] = c; // { dg-error "'long long' invalid for 'decomposition'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ long long auto [ u ] = c; // { dg-error "'long long' invalid for 'structured binding'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
virtual auto [ v ] = c; // { dg-error "'virtual' outside class declaration" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
explicit auto [ w ] = c; // { dg-error "'explicit' outside class declaration" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- static auto [ x ] = c; // { dg-error "decomposition declaration cannot be declared 'static'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- extern auto [ y ] { c }; // { dg-error "decomposition declaration cannot be declared 'extern'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ static auto [ x ] = c; // { dg-error "structured binding declaration cannot be 'static'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ extern auto [ y ] { c }; // { dg-error "structured binding declaration cannot be 'extern'" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
}
void
@@ -52,15 +52,15 @@ void
test3 (A &b, B c)
{
auto [ d, e, f ] = arr; // { dg-error "only 3 names provided while 'int .4.' decomposes into 4 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided while 'int .4.' decomposes into 4 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto [ l, m ] = b; // { dg-error "only 2 names provided while 'A' decomposes into 3 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto & [ n, o, p, q ] = b; // { dg-error "4 names provided while 'A' decomposes into 3 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [] { c }; // { dg-error "empty decomposition declaration" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [] { c }; // { dg-error "empty structured binding declaration" }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto [ r, s ] = c; // { dg-error "2 names provided while 'B' decomposes into 1 elements" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp30.C b/gcc/testsuite/g++.dg/cpp1z/decomp30.C
new file mode 100644
index 00000000000..23115ad1082
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp30.C
@@ -0,0 +1,12 @@
+// PR c++/81258
+// { dg-options -std=c++1z }
+
+int a[2];
+auto [b, c] (a);
+auto [d, e] { a };
+auto [f, g] = a;
+auto [h, i] ( a, a ); // { dg-error "invalid initializer for structured binding declaration" }
+auto [j, k] { a, a }; // { dg-error "invalid initializer for structured binding declaration" }
+auto [l, m] = { a }; // { dg-error "deducing from brace-enclosed initializer list requires" }
+auto [n, o] {}; // { dg-error "invalid initializer for structured binding declaration" }
+auto [p, q] (); // { dg-error "invalid initializer for structured binding declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp4.C b/gcc/testsuite/g++.dg/cpp1z/decomp4.C
index bc85263e986..55460833bd9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp4.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp4.C
@@ -15,18 +15,18 @@ void
test (A &a, B &b, C &c, D &d, E &e, F &f, G &g, H &h, I &i)
{
auto [ j ] = a; // { dg-error "cannot decompose class type 'A' because it has an anonymous struct member" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto [ k ] { b }; // { dg-error "cannot decompose class type 'B' because it has an anonymous union member" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
auto [ l, l2 ] = c; // { dg-error "cannot decompose non-public member 'C::b' of 'C'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [ m ] = d; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [ m ] = d; // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
auto [ n ] { e }; // { dg-error "cannot decompose non-public member 'E::a' of 'E'" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [ o ] { f }; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [ o ] { f }; // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
auto & [ p ] { g }; // { dg-error "cannot decompose class type 'G': both it and its base class 'F' have non-static data members" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
- auto [ q ] { h }; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ auto [ q ] { h }; // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } }
auto [ r ] { i }; // { dg-error "cannot decompose class type 'I': its base classes 'F' and 'H' have non-static data members" }
- // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp5.C b/gcc/testsuite/g++.dg/cpp1z/decomp5.C
index 86b2c22f37a..99610d76832 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp5.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp5.C
@@ -12,19 +12,19 @@ main ()
x.i = i;
x.j = 2 * i++;
}
- for (auto & [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto & [ x, y ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x += 2;
y += 3;
}
i = 0;
- for (const auto [ u, v ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (const auto [ u, v ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
if (u != i + 2 || v != 2 * i++ + 3)
__builtin_abort ();
}
i = 0;
- for (auto [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto [ x, y ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x += 4;
y += 5;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp6.C b/gcc/testsuite/g++.dg/cpp1z/decomp6.C
index 7a8a239d9e1..378a25141f4 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp6.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp6.C
@@ -23,7 +23,7 @@ main ()
if (ccnt != 6 || dcnt || cccnt || tccnt)
__builtin_abort ();
{
- auto [b,c,d,e,f,g] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [b,c,d,e,f,g] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 6 || dcnt || cccnt || tccnt != 6)
__builtin_abort ();
b.a++;
@@ -34,7 +34,7 @@ main ()
if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5])
__builtin_abort ();
{
- auto&[ h, i, j, k, l, m ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto&[ h, i, j, k, l, m ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 6 || dcnt || cccnt || tccnt != 6)
__builtin_abort ();
j.a += 4;
@@ -59,7 +59,7 @@ main ()
if (ccnt != 12 || dcnt != 12 || cccnt || tccnt != 6)
__builtin_abort ();
{
- auto [b,c,d,e,f,g] { a }; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [b,c,d,e,f,g] { a }; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 12 || dcnt != 12 || cccnt != 6 || tccnt != 6)
__builtin_abort ();
b.a++;
@@ -70,7 +70,7 @@ main ()
if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5])
__builtin_abort ();
{
- auto&[ h, i, j, k, l, m ] {a}; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto&[ h, i, j, k, l, m ] {a}; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 12 || dcnt != 12 || cccnt != 6 || tccnt != 6)
__builtin_abort ();
j.a += 4;
@@ -95,7 +95,7 @@ main ()
if (ccnt != 18 || dcnt != 24 || cccnt != 6 || tccnt != 6)
__builtin_abort ();
{
- auto [b,c,d,e,f,g] ( a ); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto [b,c,d,e,f,g] ( a ); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6)
__builtin_abort ();
b.a++;
@@ -106,7 +106,7 @@ main ()
if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5])
__builtin_abort ();
{
- auto&[ h, i, j, k, l, m ] (a); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto&[ h, i, j, k, l, m ] (a); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6)
__builtin_abort ();
j.a += 4;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp7.C b/gcc/testsuite/g++.dg/cpp1z/decomp7.C
index d366adecc4c..545c5cf1060 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp7.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp7.C
@@ -10,14 +10,14 @@ template <typename T, typename U>
void
foo (T &x, U &y)
{
- auto & [ c, d ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ e, f ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ g, h, i ] = sa; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ j, k, l ] = sa; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ m, n ] = x; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ o, p ] = x; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto [ q, r, s ] = y; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
- auto & [ t, u, v ] = y; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ auto & [ c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ e, f ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ g, h, i ] = sa; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ j, k, l ] = sa; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ m, n ] = x; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ o, p ] = x; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [ q, r, s ] = y; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto & [ t, u, v ] = y; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
c += 1;
e += 2;
g += 3;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp8.C b/gcc/testsuite/g++.dg/cpp1z/decomp8.C
index 9e1ea5d5da1..af3075cce98 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp8.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp8.C
@@ -14,19 +14,19 @@ foo (T &b)
x.i = i;
x.j = 2 * i++;
}
- for (auto & [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto & [ x, y ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x += 2;
y += 3;
}
i = 0;
- for (const auto [ u, v ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (const auto [ u, v ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
if (u != i + 2 || v != 2 * i++ + 3)
__builtin_abort ();
}
i = 0;
- for (auto [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto [ x, y ] : a) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x += 4;
y += 5;
@@ -45,19 +45,19 @@ foo (T &b)
x.i = i;
x.j = 2 * i++;
}
- for (auto & [ x, y ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto & [ x, y ] : b) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x -= 2;
y -= 3;
}
i = 0;
- for (const auto [ u, v ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (const auto [ u, v ] : b) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
if (u != i - 2 || v != 2 * i++ - 3)
__builtin_abort ();
}
i = 0;
- for (auto [ x, y ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+ for (auto [ x, y ] : b) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
{
x -= 4;
y -= 5;
diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
index 11269ccbe9c..b473ed553c9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
@@ -17,121 +17,121 @@ void bar (E);
void
foo ()
{
- A a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- B b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ A a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" }
+ B b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
C c1 { s };
- D d1 { D(t) }; // { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
- D d2 { t }; // { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
- // { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
- D d3 { 9 }; // { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
- D d4 { l }; // { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+ D d1 { D(t) }; // { dg-error "invalid cast from type 'T' to type 'D'" }
+ D d2 { t }; // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+ // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+ D d3 { 9 }; // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+ D d4 { l }; // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
D d5 { D(l) };
- D d6 { G }; // { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
- E e1 { 5 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- E e2 { -1 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- E e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- E e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- B b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" }
- C c2 = { C { 8 } }; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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 {enum}' in initialization" "" { target c++14_down } }
- E *e5 = new E { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' 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++1z } .-1 }
- bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
- bar (E { 9 }); // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- V v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E {enum}'" }
- V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- V v3 = { E { 5.0 } }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+ 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++1z } .-1 }
- V v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
- if (B b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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 {enum}' in initialization" "" { 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++1z } .-1 }
- C c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
- B b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
- B b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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++1z } .-1 }
- C c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- C c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
- C c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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 } }
}
struct U
{
- U () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
- U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-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 {enum}' in initialization" "" { target *-*-* } .-1 }
+ // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target *-*-* } .-1 }
E e;
};
struct W
{
- A a { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- B b { 6 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
- C c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" }
+ D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" }
};
template <int N>
void
foo2 ()
{
- A a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- B b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ A a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" }
+ B b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
C c1 { s };
- D d1 { D(t) }; // { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
- D d2 { t }; // { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
- // { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
- D d3 { 9 }; // { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
- D d4 { l }; // { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+ D d1 { D(t) }; // { dg-error "invalid cast from type 'T' to type 'D'" }
+ D d2 { t }; // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+ // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+ D d3 { 9 }; // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+ D d4 { l }; // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
D d5 { D(l) };
- D d6 { G }; // { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
- E e1 { 5 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- E e2 { -1 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- E e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- E e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- B b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" }
- C c2 = { C { 8 } }; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
- D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
- E *e5 = new E { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
- bar (E { 9 }); // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- V v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E {enum}'" }
- V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- V v3 = { E { 5.0 } }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+ 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++1z } .-1 }
- V v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
- if (B b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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 {enum}' in initialization" "" { 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++1z } .-1 }
- C c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
- B b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
- B b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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++1z } .-1 }
- C c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- C c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
- C c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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 } }
}
template <int N>
struct U2
{
- U2 () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
- U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
U2 (float) : e({ 6 }) {}
E e;
@@ -140,11 +140,11 @@ struct U2
template <int N>
struct W2
{
- A a { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
- B b { 6 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
- C c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-4 }
+ A a { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } .-2 }
+ B b { 6 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+ C c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-4 }
// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
- D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
+ D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-6 }
};
template <typename H, typename I, typename J, typename K, typename L, typename M>
@@ -152,54 +152,54 @@ void
foo3 ()
{
void bar3 (L);
- H a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- I b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ H a1 { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" }
+ I b1 { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
J c1 { s };
- K d1 { K(t) }; // { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
- K d2 { t }; // { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
- // { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
- K d3 { 9 }; // { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
- K d4 { l }; // { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+ K d1 { K(t) }; // { dg-error "invalid cast from type 'T' to type 'D'" }
+ K d2 { t }; // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+ // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+ K d3 { 9 }; // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+ K d4 { l }; // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
K d5 { K(l) };
- K d6 { G }; // { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
- L e1 { 5 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- L e2 { -1 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- L e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- L e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- I b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" }
- J c2 = { J { 8 } }; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
- K *d7 = new K { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
- L *e5 = new L { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- bar3 ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
- bar3 (E { 9 }); // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- M v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E {enum}'" }
- M v2 = { L { 12 } }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
- M v3 = { L { 5.0 } }; // { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+ bar3 ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+ 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++1z } .-1 }
- M v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
- if (I b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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 {enum}' in initialization" "" { 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++1z } .-1 }
- J c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
- I b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
- I b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+ 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++1z } .-1 }
- J c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
- J c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
- J c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+ 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 } }
}
template <typename L>
struct U3
{
- U3 () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
- U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+ 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++1z } .-1 }
U3 (float) : e({ 6 }) {}
L e;
@@ -208,11 +208,11 @@ struct U3
template <typename H, typename I, typename J, typename K>
struct W3
{
- H a { 5 }; // { dg-error "invalid conversion from 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
- I b { 6 }; // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
- J c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-4 }
+ H a { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } .-2 }
+ I b { 6 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+ J c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-4 }
// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
- K d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
+ K d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-6 }
};
void
@@ -221,17 +221,17 @@ test ()
foo2<0> ();
U2<0> u20;
U2<1> u21 (5);
- W2<0> w2; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-1 }
- // { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-2 }
+ W2<0> w2; // { dg-error "invalid conversion from 'int' to 'A'" }
+ // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+ // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-2 }
// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
- // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-4 }
+ // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-4 }
foo3<A, B, C, D, E, V> ();
U3<E> u30;
U3<E> u31 (5);
- W3<A, B, C, D> w3; // { dg-error "invalid conversion from 'int' to 'A {enum}'" }
- // { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-1 }
- // { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-2 }
+ W3<A, B, C, D> w3; // { dg-error "invalid conversion from 'int' to 'A'" }
+ // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+ // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-2 }
// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
- // { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-4 }
+ // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-4 }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/dr393.C b/gcc/testsuite/g++.dg/cpp1z/dr393.C
new file mode 100644
index 00000000000..4a7645a618f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/dr393.C
@@ -0,0 +1,4 @@
+// DR 393
+// { dg-options -Wpedantic }
+
+void f(int (&)[]); // { dg-warning "unknown bound" "" { target c++14_down } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-1.C
new file mode 100644
index 00000000000..cae380a21eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-1.C
@@ -0,0 +1,23 @@
+// { dg-options "-O2 -gdwarf-4 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times " DW_AT_export_symbols" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\r\]*\\) DW_TAG_imported_module" 2 } }
+
+namespace A
+{
+ int i = 5;
+ inline namespace B
+ {
+ int j = 6;
+ namespace C
+ {
+ int k = 7;
+ };
+ };
+};
+int l = A::i + A::j + A::C::k;
+int m = A::i + A::B::j + A::B::C::k;
+namespace
+{
+ int n = 8;
+};
+int o = n;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-2.C
new file mode 100644
index 00000000000..4d9aed7e219
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/inline-ns-2.C
@@ -0,0 +1,23 @@
+// { dg-options "-O2 -gdwarf-5 -dA" }
+// { dg-final { scan-assembler-times " DW_AT_export_symbols" 2 } }
+// { dg-final { scan-assembler-not "DIE \\(\[^\n\r\]*\\) DW_TAG_imported_module" } }
+
+namespace A
+{
+ int i = 5;
+ inline namespace B
+ {
+ int j = 6;
+ namespace C
+ {
+ int k = 7;
+ };
+ };
+};
+int l = A::i + A::j + A::C::k;
+int m = A::i + A::B::j + A::B::C::k;
+namespace
+{
+ int n = 8;
+};
+int o = n;
diff --git a/gcc/testsuite/g++.dg/diagnostic/friend1.C b/gcc/testsuite/g++.dg/diagnostic/friend1.C
new file mode 100644
index 00000000000..a35f92ad949
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/friend1.C
@@ -0,0 +1,8 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+friend void foo(); /* { dg-error "used outside of class" }
+ { dg-begin-multiline-output "" }
+ friend void foo();
+ ^~~~~~
+ ------
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr79300.C b/gcc/testsuite/g++.dg/diagnostic/pr79300.C
new file mode 100644
index 00000000000..6805e85873f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr79300.C
@@ -0,0 +1,44 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+#define TEST_1_DEPTH_0 throw bad_alloc; // { dg-line define_TEST_1_DEPTH_0 }
+
+void test_1 ()
+{
+ TEST_1_DEPTH_0 // { dg-line use_TEST_1_DEPTH_0 }
+}
+
+// { dg-error "'bad_alloc' was not declared in this scope" "" { target *-*-* } define_TEST_1_DEPTH_0 }
+/* { dg-begin-multiline-output "" }
+ #define TEST_1_DEPTH_0 throw bad_alloc;
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message "in expansion of macro 'TEST_1_DEPTH_0'" "" { target *-*-* } use_TEST_1_DEPTH_0 }
+/* { dg-begin-multiline-output "" }
+ TEST_1_DEPTH_0
+ ^~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+
+#define TEST_2_DEPTH_0 throw bad_alloc; // { dg-line define_TEST_2_DEPTH_0 }
+#define TEST_2_DEPTH_1 TEST_2_DEPTH_0 // { dg-line define_TEST_2_DEPTH_1 }
+
+void test_2 ()
+{
+ TEST_2_DEPTH_1 // { dg-line use_TEST_2_DEPTH_1 }
+}
+
+// { dg-error "'bad_alloc' was not declared in this scope" "" { target *-*-* } define_TEST_2_DEPTH_0 }
+/* { dg-begin-multiline-output "" }
+ #define TEST_2_DEPTH_0 throw bad_alloc;
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message "in expansion of macro 'TEST_2_DEPTH_0'" "" { target *-*-* } define_TEST_2_DEPTH_1 }
+/* { dg-begin-multiline-output "" }
+ #define TEST_2_DEPTH_1 TEST_2_DEPTH_0
+ ^~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+// { dg-message "in expansion of macro 'TEST_2_DEPTH_1'" "" { target *-*-* } use_TEST_2_DEPTH_1 }
+/* { dg-begin-multiline-output "" }
+ TEST_2_DEPTH_1
+ ^~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/variadic1.C b/gcc/testsuite/g++.dg/diagnostic/variadic1.C
index 69f1f988f30..7e3db314328 100644
--- a/gcc/testsuite/g++.dg/diagnostic/variadic1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/variadic1.C
@@ -4,6 +4,6 @@
template<int N> struct B { };
template<typename... T> struct A
{
- B<sizeof...(T)> f(); // { dg-error "sizeof\\.\\.\\." }
+ B<sizeof...(T)> f(); // { dg-message "sizeof\\.\\.\\." }
B<42> f(); // { dg-error "cannot be overloaded" }
};
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct6.C b/gcc/testsuite/g++.dg/ext/anon-struct6.C
index 66d4b327196..9b59085f670 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct6.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct6.C
@@ -3,8 +3,8 @@
struct A
{
struct
- { // { dg-error "anonymous struct cannot have function members" }
+ {
struct { static int i; }; // { dg-error "prohibits anonymous structs|non-static data members|unnamed class" }
- void foo() { i; }
+ void foo() { i; } // { dg-error "can only have non-static data" }
}; // { dg-error "prohibits anonymous structs" }
};
diff --git a/gcc/testsuite/g++.dg/ext/mvc2.C b/gcc/testsuite/g++.dg/ext/mvc2.C
index e7abab81d95..1b8c6f4d6e9 100644
--- a/gcc/testsuite/g++.dg/ext/mvc2.C
+++ b/gcc/testsuite/g++.dg/ext/mvc2.C
@@ -1,4 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
__attribute__((target_clones("avx","arch=slm","default")))
__attribute__((target("avx")))
diff --git a/gcc/testsuite/g++.dg/ext/mvc3.C b/gcc/testsuite/g++.dg/ext/mvc3.C
index 05bebf7d4fb..d32b2c93aa0 100644
--- a/gcc/testsuite/g++.dg/ext/mvc3.C
+++ b/gcc/testsuite/g++.dg/ext/mvc3.C
@@ -1,4 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
__attribute__((target("avx")))
__attribute__((target_clones("avx","arch=slm","default")))
diff --git a/gcc/testsuite/g++.dg/gomp/udr-3.C b/gcc/testsuite/g++.dg/gomp/udr-3.C
index 9fc6f40820a..57531f2042b 100644
--- a/gcc/testsuite/g++.dg/gomp/udr-3.C
+++ b/gcc/testsuite/g++.dg/gomp/udr-3.C
@@ -77,7 +77,7 @@ namespace N2
{
struct U
{
- #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-message "previous" }
#pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
};
}
@@ -109,9 +109,9 @@ namespace N4
struct U
{
#pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
- #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-message "previous" }
#pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
- #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-error "with" }
+ #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-message "previous" }
#pragma omp declare reduction (bar: long int: omp_out += omp_in) // { dg-error "cannot be overloaded" }
#pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
#pragma omp declare reduction (bar: short int: omp_out += omp_in)
@@ -132,7 +132,7 @@ namespace N5
template <typename T>
struct U
{
- #pragma omp declare reduction (bar: T: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: T: omp_out.s *= omp_in.s) // { dg-message "previous" }
#pragma omp declare reduction (bar: T: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
};
U<S> u;
@@ -159,9 +159,9 @@ namespace N6
{
typedef V V2;
#pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
- #pragma omp declare reduction (bar: V: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: V: omp_out.s *= omp_in.s) // { dg-message "previous" }
#pragma omp declare reduction (bar: V2: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
- #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-error "with" }
+ #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-message "previous" }
#pragma omp declare reduction (bar: long int: omp_out += omp_in) // { dg-error "cannot be overloaded" }
#pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
#pragma omp declare reduction (bar: short int: omp_out += omp_in)
diff --git a/gcc/testsuite/g++.dg/ipa/pr81261.C b/gcc/testsuite/g++.dg/ipa/pr81261.C
new file mode 100644
index 00000000000..f182eb152cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr81261.C
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-guess-branch-probability" } */
+
+struct CBase {
+ virtual void BaseFunc () {}
+};
+
+struct MMixin {
+ virtual void * MixinFunc (int, void *) = 0;
+};
+
+struct CExample: CBase, public MMixin
+{
+ void *MixinFunc (int arg, void *arg2)
+ {
+ if (arg != 1 || arg2)
+ return 0;
+ return this;
+ }
+};
+
+void *test (MMixin & anExample)
+{
+ return anExample.MixinFunc (1, 0);
+}
+
+int main ()
+{
+ CExample c;
+ return (test (c) != &c);
+}
diff --git a/gcc/testsuite/g++.dg/lookup/decl1.C b/gcc/testsuite/g++.dg/lookup/decl1.C
index 42a9978e597..205ffcff1d7 100644
--- a/gcc/testsuite/g++.dg/lookup/decl1.C
+++ b/gcc/testsuite/g++.dg/lookup/decl1.C
@@ -19,14 +19,13 @@ C2<X>::operator C1<Y>()
return C1<Y>();
}
-struct A
-{
- operator int (); // { dg-error "operator" }
- operator float (); // { dg-error "operator" }
- operator float () const; // { dg-error "operator" }
- template <typename T> operator T * (); // { dg-error "candidates" }
+struct A { // { dg-message "defined here" }
+ operator int (); // { dg-message "operator" }
+ operator float (); // { dg-message "operator" }
+ operator float () const; // { dg-message "operator" }
+ template <typename T> operator T * (); // { dg-message "operator" }
};
-A::operator short () { // { dg-error "prototype for" }
+A::operator short () { // { dg-error "no declaration matches" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/lookup/extern-c-redecl.C b/gcc/testsuite/g++.dg/lookup/extern-c-redecl.C
index 31d100a74f9..3e901cc7759 100644
--- a/gcc/testsuite/g++.dg/lookup/extern-c-redecl.C
+++ b/gcc/testsuite/g++.dg/lookup/extern-c-redecl.C
@@ -8,4 +8,4 @@ namespace A {
// next line should trigger an error because
// it conflicts with previous declaration of foo_func (), due to
// different exception specifications.
-extern "C" void foo_func (); // { dg-error "C language|exception specifications" }
+extern "C" void foo_func (); // { dg-error "C language linkage|exception specifications" }
diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-2.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-2.C
new file mode 100644
index 00000000000..ae918f869a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/missing-std-include-2.C
@@ -0,0 +1,55 @@
+/* Example of fix-it hints that add #include directives,
+ adding them after a pre-existing #include. */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+/* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+
+#include <stdio.h>
+
+void test (void)
+{
+ std::string s ("hello world"); // { dg-error ".string. is not a member of .std." }
+ // { dg-message ".std::string. is defined in header .<string>.; did you forget to .#include <string>.?" "" { target *-*-* } .-1 }
+
+ std::cout << 10; // { dg-error ".cout. is not a member of .std." }
+ // { dg-message ".std::cout. is defined in header .<iostream>.; did you forget to .#include <iostream>.?" "" { target *-*-* } .-1 }
+}
+
+/* Same again, to test idempotency of the added "#include" fix-it. */
+
+void test_2 (void)
+{
+ std::string s ("hello again"); // { dg-error ".string. is not a member of .std." }
+ // { dg-message ".std::string. is defined in header .<string>.; did you forget to .#include <string>.?" "" { target *-*-* } .-1 }
+
+ std::cout << 10; // { dg-error ".cout. is not a member of .std." }
+ // { dg-message ".std::cout. is defined in header .<iostream>.; did you forget to .#include <iostream>.?" "" { target *-*-* } .-1 }
+}
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing this
+ source filename, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+
+/* Verify the hunks within the patch.
+ Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment.
+ We expect a "#include <string>" and "#include <iostream>" to each have been
+ added once, immediately below the last #include. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -7,6 +7,8 @@
+ directives). */
+
+ #include <stdio.h>
++#include <string>
++#include <iostream>
+
+ void test (void)
+ {
+{ dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-3.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-3.C
new file mode 100644
index 00000000000..23f868dff09
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/missing-std-include-3.C
@@ -0,0 +1,35 @@
+/* Example of where the error occurs before the first #include,
+ which in this case happens to be the missing header.
+ For this case, expect to insert the #include at the top of the file. */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+void test ()
+{
+ std::string test; // { dg-error ".string. is not a member of .std." }
+ // { dg-message ".std::string. is defined in header .<string>.; did you forget to .#include <string>.?" "" { target *-*-* } .-1 }
+}
+
+#include <string>
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing this
+ source filename, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+
+/* Verify the hunks within the patch.
+ Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment.
+ We expect a "#include <string>" have been added once, at the top
+ of the file. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -1,3 +1,4 @@
++#include <string>
+ /* Example of where the error occurs before the first #include,
+ which in this case happens to be the missing header.
+ For this case, expect to insert the #include at the top of the file. */
+{ dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/g++.dg/lookup/pr81229.C b/gcc/testsuite/g++.dg/lookup/pr81229.C
new file mode 100644
index 00000000000..c9981c9f60a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr81229.C
@@ -0,0 +1,7 @@
+// PR c++/81229 GC ICE with stale pointed in identifier type.
+// { dg-additional-options "--param ggc-min-heapsize=0" }
+
+typedef unsigned L;
+typedef unsigned L;
+
+L l;
diff --git a/gcc/testsuite/g++.dg/opt/pr79659.C b/gcc/testsuite/g++.dg/opt/pr79659.C
new file mode 100644
index 00000000000..132d5c1e7f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr79659.C
@@ -0,0 +1,5 @@
+// PR target/79659
+// { dg-do compile }
+// { dg-options "-flifetime-dse=123456" }
+
+// { dg-error "is not between 0 and 2" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/other/i386-9.C b/gcc/testsuite/g++.dg/other/i386-9.C
index 79640579142..782cf875eef 100644
--- a/gcc/testsuite/g++.dg/other/i386-9.C
+++ b/gcc/testsuite/g++.dg/other/i386-9.C
@@ -2,6 +2,7 @@
// Testcase by Zdenek Sojka <zsojka@seznam.cz>
// { dg-do run { target i?86-*-* x86_64-*-* } }
+/* { dg-require-stack-check "" } */
// { dg-options "-Os -mpreferred-stack-boundary=5 -fstack-check -fno-omit-frame-pointer" }
int main()
diff --git a/gcc/testsuite/g++.dg/other/pr28432.C b/gcc/testsuite/g++.dg/other/pr28432.C
index 2b9c7634367..8e2428594d9 100644
--- a/gcc/testsuite/g++.dg/other/pr28432.C
+++ b/gcc/testsuite/g++.dg/other/pr28432.C
@@ -3,5 +3,7 @@
// { dg-options "" }
-struct A {};
-void A::foo(); // { dg-error "member function declared in class|outside of class is not definition" }
+struct A {}; // { dg-message "defined here" }
+
+void A::foo(); // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/overload/error1.C b/gcc/testsuite/g++.dg/overload/error1.C
index 6c5998c720a..a4fd4854eb2 100644
--- a/gcc/testsuite/g++.dg/overload/error1.C
+++ b/gcc/testsuite/g++.dg/overload/error1.C
@@ -2,6 +2,6 @@
struct S
{
- void f () {} // { dg-error "with" }
+ void f () {} // { dg-message "previous" }
int f () { return 0; } // { dg-error "overloaded" }
};
diff --git a/gcc/testsuite/g++.dg/overload/error2.C b/gcc/testsuite/g++.dg/overload/error2.C
index 4a9d35bc49d..23a2ea18d3a 100644
--- a/gcc/testsuite/g++.dg/overload/error2.C
+++ b/gcc/testsuite/g++.dg/overload/error2.C
@@ -6,6 +6,6 @@
struct A
{
- void foo(); // { dg-error "with" }
+ void foo(); // { dg-message "previous" }
virtual void foo(); // { dg-error "cannot be overloaded" }
};
diff --git a/gcc/testsuite/g++.dg/parse/catch2.C b/gcc/testsuite/g++.dg/parse/catch2.C
new file mode 100644
index 00000000000..528d6c74125
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/catch2.C
@@ -0,0 +1,4 @@
+// PR c++/62046
+
+void foo() { } catch (...); // { dg-error "expected" }
+class bar { void foo() { } catch (...); }; // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/parse/crash12.C b/gcc/testsuite/g++.dg/parse/crash12.C
index 769ca2e9343..61921fded8f 100644
--- a/gcc/testsuite/g++.dg/parse/crash12.C
+++ b/gcc/testsuite/g++.dg/parse/crash12.C
@@ -6,15 +6,16 @@
template <class _Tp> class auto_ptr {};
template <class _Tp>
-class counted_ptr
-{
+class counted_ptr { // { dg-message "defined here" }
public:
- counted_ptr(::auto_ptr<_Tp>& __a); // { dg-error "candidate" }
+ counted_ptr(::auto_ptr<_Tp>& __a); // { dg-message "candidate" }
::auto_ptr<_Tp> auto_ptr();
};
template <class _Tp>
-inline counted_ptr<_Tp>::counted_ptr(class auto_ptr& __a) // { dg-error "required|not match|template" }
+inline counted_ptr<_Tp>::counted_ptr(class auto_ptr& __a)
+// { dg-error "no declaration matches" "" { target *-*-* } .-1 }
+// { dg-error "template argument required" "" { target *-*-* } .-2 }
{
}
diff --git a/gcc/testsuite/g++.dg/parse/enum3.C b/gcc/testsuite/g++.dg/parse/enum3.C
index dc07193d389..81e69635678 100644
--- a/gcc/testsuite/g++.dg/parse/enum3.C
+++ b/gcc/testsuite/g++.dg/parse/enum3.C
@@ -1,5 +1,7 @@
// PR c++/28261
-struct A {}; // { dg-error "A::A" }
+struct A {}; // { dg-message "A::A" }
+// { dg-message "defined here" "" { target *-*-* } .-1 }
-A::A (enum { e }) {} // { dg-error "defined|prototype" }
+A::A (enum { e }) {} // { dg-error "no declaration matches" }
+// { dg-error "in parameter types" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/operator6.C b/gcc/testsuite/g++.dg/parse/operator6.C
index e58a3a682c3..c13860efd80 100644
--- a/gcc/testsuite/g++.dg/parse/operator6.C
+++ b/gcc/testsuite/g++.dg/parse/operator6.C
@@ -1,5 +1,6 @@
// PR c++/25635
-struct A {};
+struct A {}; // { dg-message "defined here" }
-A::operator int(); // { dg-error "class" }
+A::operator int(); // { dg-error "no declaration matches" }
+// { dg-message "no conversion operators" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/pr81247-a.C b/gcc/testsuite/g++.dg/parse/pr81247-a.C
new file mode 100644
index 00000000000..c5b22ab479f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr81247-a.C
@@ -0,0 +1,13 @@
+// PR c++/81247 ICE
+
+namespace N // { dg-message "previous declaration" }
+// { dg-error "expected" "" { target *-*-* } .+1 }
+template < typename T > class A
+{ // { dg-error "redeclared as different" }
+ template < T > friend class N;
+};
+
+void f ()
+{
+ A < int > a1; // { dg-message "required from here" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr81247-b.C b/gcc/testsuite/g++.dg/parse/pr81247-b.C
new file mode 100644
index 00000000000..b2b035b9baf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr81247-b.C
@@ -0,0 +1,14 @@
+// PR c++/81247 confused error
+
+namespace N { // { dg-message "previous declaration" }
+}
+
+template < typename T > class A
+{ // { dg-error "redeclared as different" }
+ template < T > friend class N;
+};
+
+void f ()
+{
+ A < int > a1;
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr81247-c.C b/gcc/testsuite/g++.dg/parse/pr81247-c.C
new file mode 100644
index 00000000000..32f41f28f41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr81247-c.C
@@ -0,0 +1,13 @@
+// PR c++/81247 confused error
+
+namespace N { // { dg-message "previous declaration" }
+ template < typename T > class A
+ { // { dg-error "conflicts with a previous" }
+ template < T > friend class N;
+ };
+}
+
+void f ()
+{
+ N::A < int > a1;
+}
diff --git a/gcc/testsuite/g++.dg/parse/template-keyword1.C b/gcc/testsuite/g++.dg/parse/template-keyword1.C
new file mode 100644
index 00000000000..0a1298e75f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template-keyword1.C
@@ -0,0 +1,3 @@
+// PR c++/81257
+
+template < typename ::template A < int > >; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/plugin/decl-plugin-test.C b/gcc/testsuite/g++.dg/plugin/decl-plugin-test.C
index 08a2ff2aa5d..e6bd746892c 100644
--- a/gcc/testsuite/g++.dg/plugin/decl-plugin-test.C
+++ b/gcc/testsuite/g++.dg/plugin/decl-plugin-test.C
@@ -17,7 +17,7 @@ class test_class {
int class_field1; // { dg-warning "Decl Field class_field1" }
int class_field2; // { dg-warning "Decl Field class_field2" }
- test_class() // { dg-warning "Decl Function test_class" }
+ test_class() // { dg-warning "Decl Function __ct" }
: class_field1(0), class_field2(0)
{}
diff --git a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
index 2c004f30620..a145dfea28c 100644
--- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
+++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
@@ -848,3 +848,113 @@ tests::test_method_calls ()
~~~~~~~~~~~~~~~~~~^~
{ dg-end-multiline-output "" } */
}
+
+namespace std
+{
+ class type_info { public: int foo; };
+}
+
+void test_typeid (int i)
+{
+ __emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, &typeid(i));
+ ^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, &typeid(int)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, &typeid(int));
+ ^~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, &typeid(i * 2));
+ ^~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, typeid(int).foo);
+ ~~~~~~~~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Various tests of locations involving macros. */
+
+void test_within_macro_1 (int lhs, int rhs)
+{
+#define MACRO_1(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_1 (lhs == rhs));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_1 (lhs == rhs));
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_1(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_1
+}
+
+void test_within_macro_2 (int lhs, int rhs)
+{
+#define MACRO_2(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+ ^~~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_2(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_2
+}
+
+void test_within_macro_3 (int lhs, int rhs)
+{
+#define MACRO_3(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_3 (lhs) == MACRO_3 (rhs));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_3 (lhs) == MACRO_3 (rhs));
+ ^
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_3
+}
+
+void test_within_macro_4 (int lhs, int rhs)
+{
+#define MACRO_4(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_4 (MACRO_4 (lhs) == MACRO_4 (rhs)));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_4 (MACRO_4 (lhs) == MACRO_4 (rhs)));
+ ^
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_4(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_4
+}
diff --git a/gcc/testsuite/g++.dg/pr69667.C b/gcc/testsuite/g++.dg/pr69667.C
index 2b3e93d2e1e..76f7cb3d40b 100644
--- a/gcc/testsuite/g++.dg/pr69667.C
+++ b/gcc/testsuite/g++.dg/pr69667.C
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-mcpu=power8 -w -std=c++14 -mlra" } */
+/* { dg-options "-mcpu=power8 -w -std=c++14" } */
/* target/69667, compiler got
internal compiler error: Max. number of generated reload insns per insn is achieved (90) */
diff --git a/gcc/testsuite/g++.dg/pr71294.C b/gcc/testsuite/g++.dg/pr71294.C
index 55dd01e5ccf..67675dd7e30 100644
--- a/gcc/testsuite/g++.dg/pr71294.C
+++ b/gcc/testsuite/g++.dg/pr71294.C
@@ -1,7 +1,7 @@
// { dg-do compile { target { powerpc64*-*-* && lp64 } } }
// { dg-require-effective-target powerpc_p8vector_ok } */
// { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } }
-// { dg-options "-mcpu=power8 -O3 -fstack-protector -mno-lra" }
+// { dg-options "-mcpu=power8 -O3 -fstack-protector" }
// PAR target/71294 failed because RELOAD could not figure how create a V2DI
// vector that auto vectorization created with each element being the same
diff --git a/gcc/testsuite/g++.dg/pr81194.C b/gcc/testsuite/g++.dg/pr81194.C
new file mode 100644
index 00000000000..249fcf3b7c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr81194.C
@@ -0,0 +1,60 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++17 -fno-exceptions" }
+
+template <class a> struct b { typedef a *c; };
+class e {};
+template <typename a> class d {
+public:
+ typedef typename b<a>::c c;
+ c begin();
+ c end();
+};
+struct f {
+ enum { g } h;
+};
+struct i {
+ d<f *> j();
+};
+struct l {
+ d<i *> k();
+};
+class ac;
+class o {
+public:
+ o(int *, int *, int *, ac *);
+};
+class ac {
+public:
+ ac(e);
+ virtual o *ae(int *, int *, int *, int *);
+};
+class p {
+ void af(f *m) {
+ switch (m->h)
+ case f::g:
+ ag();
+ }
+
+public:
+ void n() {
+ l ah;
+ for (i *ai : ah.k())
+ for (f *m : ai->j())
+ af(m);
+ }
+ virtual void ag() { __builtin_unreachable(); }
+};
+template <typename = int> class an : o {
+public:
+ an(int *, int *, int *, int *, ac *);
+};
+class q : ac {
+public:
+ q() : ac([]() -> e {}()) {}
+ o *ae(int *ap, int *aq, int *ar, int *as) { an(ap, aq, ar, as, this); }
+};
+template <typename at>
+an<at>::an(int *, int *aq, int *ar, int *as, ac *au) : o(aq, ar, as, au) {
+ p().n();
+}
+void av() { new q; }
diff --git a/gcc/testsuite/g++.dg/rtti/missing-typeinfo-include.C b/gcc/testsuite/g++.dg/rtti/missing-typeinfo-include.C
new file mode 100644
index 00000000000..937c38f11a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/missing-typeinfo-include.C
@@ -0,0 +1,27 @@
+/* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+void test()
+{
+ typeid(void); // { dg-error "must '#include <typeinfo>' before using 'typeid'" }
+}
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing this
+ source filename, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+/* Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -1,3 +1,4 @@
++#include <typeinfo>
+ /* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+
+{ dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/g++.dg/template/crash69.C b/gcc/testsuite/g++.dg/template/crash69.C
index badf70bd0e4..21ed91bb27e 100644
--- a/gcc/testsuite/g++.dg/template/crash69.C
+++ b/gcc/testsuite/g++.dg/template/crash69.C
@@ -3,10 +3,11 @@
template<typename T> class A
{
static int i; // { dg-message "private" }
- friend int T::foo(); // { dg-error "does not match" }
+ friend int T::foo(); // { dg-error "no declaration matches" }
};
struct B
{
- void foo() { A<B>::i; } // { dg-error "within|candidate" }
+ void foo() { A<B>::i; } // { dg-message "candidate" }
+ // { dg-error "private within" "" { target *-*-* } .-1 }
};
diff --git a/gcc/testsuite/g++.dg/template/duplicate1.C b/gcc/testsuite/g++.dg/template/duplicate1.C
index c9cdab4b932..39185b350e7 100644
--- a/gcc/testsuite/g++.dg/template/duplicate1.C
+++ b/gcc/testsuite/g++.dg/template/duplicate1.C
@@ -2,6 +2,6 @@
template<int> struct A
{
- ~A() {} // { dg-error "with" }
+ ~A() {} // { dg-message "previous" }
~A() {} // { dg-error "cannot be overloaded" }
};
diff --git a/gcc/testsuite/g++.dg/template/error27.C b/gcc/testsuite/g++.dg/template/error27.C
index 8d41d0248ef..7f15f8c284d 100644
--- a/gcc/testsuite/g++.dg/template/error27.C
+++ b/gcc/testsuite/g++.dg/template/error27.C
@@ -1,5 +1,6 @@
// PR c++/27211
-struct A {};
+struct A {}; // { dg-message "defined here" }
-template<int> void A::foo() {} // { dg-error "member function" }
+template<int> void A::foo() {} // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/error28.C b/gcc/testsuite/g++.dg/template/error28.C
index e87d542d888..d4cf031210b 100644
--- a/gcc/testsuite/g++.dg/template/error28.C
+++ b/gcc/testsuite/g++.dg/template/error28.C
@@ -1,5 +1,6 @@
// PR c++/27211
-struct A {};
+struct A {}; // { dg-message "defined here" }
-template<int> void A::foo(); // { dg-error "member function" }
+template<int> void A::foo(); // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/lookup10.C b/gcc/testsuite/g++.dg/template/lookup10.C
new file mode 100644
index 00000000000..fa90af46c7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/lookup10.C
@@ -0,0 +1,12 @@
+// PR c++/81204
+
+namespace std {
+ template<typename, typename> struct set { };
+}
+using namespace std;
+
+template <int I, typename Result>
+inline void set(Result & res)
+{
+ res.template set<I>();
+}
diff --git a/gcc/testsuite/g++.dg/template/lookup11.C b/gcc/testsuite/g++.dg/template/lookup11.C
new file mode 100644
index 00000000000..203460eda73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/lookup11.C
@@ -0,0 +1,11 @@
+// PR c++/81026
+
+namespace std {
+ template<class> struct extent;
+}
+using namespace std;
+
+template <class T>
+struct S {
+ void f() { T().template extent<42>(); }
+};
diff --git a/gcc/testsuite/g++.dg/template/memfriend6.C b/gcc/testsuite/g++.dg/template/memfriend6.C
index 5f82339af54..4f126862670 100644
--- a/gcc/testsuite/g++.dg/template/memfriend6.C
+++ b/gcc/testsuite/g++.dg/template/memfriend6.C
@@ -6,18 +6,21 @@
// Member function of class template as friend
// Erroneous case: mismatch during declaration
-template <class T> struct A {
- template <class U> void f(U); // { dg-error "candidate" }
- void g(); // { dg-error "candidate|with" }
- void h(); // { dg-error "candidate|with" }
- void i(int); // { dg-error "candidate" }
+template <class T> struct A { // { dg-message "defined here" }
+ template <class U> void f(U); // { dg-message "candidate" }
+ void g(); // { dg-message "candidate" }
+ void h(); // { dg-message "candidate" }
+ void i(int); // { dg-message "candidate" }
};
class C {
int ii;
- template <class U> friend void A<U>::f(U); // { dg-error "not match" }
+ template <class U>
+ friend void A<U>::f(U); // { dg-error "no declaration matches" }
template <class U> template <class V>
- friend void A<U>::g(); // { dg-error "not match|cannot be overloaded" }
- template <class U> friend int A<U>::h(); // { dg-error "not match|cannot be overloaded" }
- template <class U> friend void A<U>::i(char); // { dg-error "not match" }
+ friend void A<U>::g(); // { dg-error "no declaration matches" }
+ template <class U>
+ friend int A<U>::h(); // { dg-error "no declaration matches" }
+ template <class U>
+ friend void A<U>::i(char); // { dg-error "no declaration matches" }
};
diff --git a/gcc/testsuite/g++.dg/template/partial-specialization8.C b/gcc/testsuite/g++.dg/template/partial-specialization8.C
new file mode 100644
index 00000000000..e3ffe3b58a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial-specialization8.C
@@ -0,0 +1,19 @@
+// PR c++/55639
+
+template <int number>
+struct SomeClass
+{
+ SomeClass() { }
+
+ template <typename E, int number2>
+ struct Fun {
+ static void
+ fun() { }
+ };
+};
+
+template <int number>
+template <typename E>
+struct SomeClass<number>::template Fun<E, 0> { // { dg-error "template" }
+ static void fun() { }
+};
diff --git a/gcc/testsuite/g++.dg/template/template-keyword1.C b/gcc/testsuite/g++.dg/template/template-keyword1.C
new file mode 100644
index 00000000000..0f928a8523e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/template-keyword1.C
@@ -0,0 +1,15 @@
+// PR c++/45976
+
+template<int a>
+struct A {
+ static const int value;
+
+ template<int b>
+ struct B {
+ static const int value;
+ };
+};
+
+template<int a>
+template<int b>
+const int A<a>::template B<b>::value = 0; // { dg-error "keyword .template" }
diff --git a/gcc/testsuite/g++.dg/torture/pr81249.C b/gcc/testsuite/g++.dg/torture/pr81249.C
new file mode 100644
index 00000000000..7bf617b0421
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr81249.C
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mavx2 -mprefer-avx128" { target x86_64-*-* i?86-*-* } } */
+
+typedef struct rtx_def *rtx;
+union rtunion {
+ rtx rt_rtx;
+};
+struct rtx_def {
+ struct {
+ rtunion fld[0];
+ } u;
+ rtx elem[];
+} a;
+int b, c, d;
+rtx e;
+int main() {
+ for (;;) {
+ d = 0;
+ for (; d < b; d++)
+ if (a.elem[d])
+ e = a.elem[d]->u.fld[1].rt_rtx;
+ if (e)
+ c = 0;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr81365.C b/gcc/testsuite/g++.dg/torture/pr81365.C
new file mode 100644
index 00000000000..fde5e503df9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr81365.C
@@ -0,0 +1,39 @@
+// PR tree-optimization/81365
+// { dg-do run }
+
+struct A { unsigned a; };
+
+struct B {
+ B (const A *x)
+ {
+ __builtin_memcpy (b, x, 3 * sizeof (A));
+ __builtin_memcpy (c, x + 3, sizeof (A));
+ __builtin_memset (c + 1, 0, sizeof (A));
+ }
+ bool
+ foo (unsigned x)
+ {
+ A *it = c;
+ if (it->a == x || (++it)->a == x)
+ {
+ A t(b[0]);
+ b[0] = *it;
+ *it = t;
+ return true;
+ }
+ return false;
+ }
+ A b[3];
+ A c[2];
+};
+
+int
+main ()
+{
+ A x[] = { 4, 8, 12, 18 };
+ B y(x);
+ if (!y.foo (18))
+ __builtin_abort ();
+ if (!y.foo (4))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr81462.C b/gcc/testsuite/g++.dg/torture/pr81462.C
new file mode 100644
index 00000000000..044c8b78ee5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr81462.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O1 -fno-ipa-pure-const" }
+struct B {
+ B* self;
+ B() : self( this ) { self->f(); }
+ virtual void f() = 0;
+ };
+
+ struct D : B
+ {
+ void f() {}
+ };
+
+ int main()
+ {
+ D d;
+ }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr81408.C b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
new file mode 100644
index 00000000000..f94544b9e2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
@@ -0,0 +1,92 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu++11 -fopt-info-loop-missed -Wunsafe-loop-optimizations" } */
+
+namespace a {
+void b () __attribute__ ((__noreturn__));
+template <typename> struct d;
+template <typename e> struct d<e *>
+{
+ typedef e f;
+};
+struct g
+{
+ template <typename h> using i = h *;
+};
+}
+using a::d;
+template <typename j, typename> class k
+{
+ j l;
+
+public:
+ typename d<j>::f operator* () {}
+ void operator++ () { ++l; }
+ j
+ aa ()
+ {
+ return l;
+ }
+};
+template <typename m, typename n, typename ab>
+bool
+operator!= (k<m, ab> o, k<n, ab> p2)
+{
+ return o.aa () != p2.aa ();
+}
+struct p;
+namespace a {
+struct F
+{
+ struct q
+ {
+ using ai = g::i<p>;
+ };
+ using r = q::ai;
+};
+class H
+{
+public:
+ k<F::r, int> begin ();
+ k<F::r, int> end ();
+};
+int s;
+class I
+{
+public:
+ void
+ aq (char)
+ {
+ if (s)
+ b ();
+ }
+};
+class u : public I
+{
+public:
+ void
+ operator<< (u o (u))
+ {
+ o (*this);
+ }
+ u operator<< (void *);
+};
+template <typename at, typename au>
+at
+av (au o)
+{
+ o.aq ('\n');
+}
+u ax;
+}
+struct p
+{
+ char *ay;
+};
+a::H t;
+void
+ShowHelpListCommands ()
+{
+ for (auto c : t) /* { dg-message "note: missed loop optimization: niters analysis .*" } */
+ a::ax << c.ay << a::av;
+}
+
diff --git a/gcc/testsuite/g++.dg/ubsan/pr81209.C b/gcc/testsuite/g++.dg/ubsan/pr81209.C
new file mode 100644
index 00000000000..3f2a5768907
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr81209.C
@@ -0,0 +1,21 @@
+// PR sanitizer/81209
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined -fno-declone-ctor-dtor" }
+
+#ifdef __SIZEOF_INT128__
+typedef __int128 T;
+#else
+typedef long long int T;
+#endif
+
+struct B {};
+struct A : virtual public B
+{
+ A (long);
+ T a;
+};
+
+A::A (long c)
+{
+ long b = a % c;
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/pr81262.C b/gcc/testsuite/g++.dg/ubsan/pr81262.C
new file mode 100644
index 00000000000..1b360de95ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr81262.C
@@ -0,0 +1,14 @@
+// PR sanitizer/81262
+// { dg-do compile }
+// { dg-options "-O2 -fsanitize=unreachable" }
+
+int
+foo ()
+{
+ asm goto ("" : : : : l1, l2);
+ __builtin_unreachable ();
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/pr81530.C b/gcc/testsuite/g++.dg/ubsan/pr81530.C
new file mode 100644
index 00000000000..e21724686c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr81530.C
@@ -0,0 +1,6 @@
+/* PR sanitizer/81530 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+int a[(long) 4e20]; /* { dg-error "overflow in constant expression" } */
+/* { dg-error "size of array .a. is too large" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/g++.dg/vect/pr61171.cc b/gcc/testsuite/g++.dg/vect/pr61171.cc
new file mode 100644
index 00000000000..f3e2e3e4c13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr61171.cc
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_float }
+// { dg-additional-options "-ffast-math" }
+
+float px[1024];
+float xx, vv;
+unsigned int N=1024;
+
+void ok() {
+ for (unsigned j=0U; j<N; ++j) {
+ float ax = px[j]-xx;
+ vv-=ax;
+ }
+}
+
+void noOk() {
+ for (unsigned j=0U; j<N; ++j) {
+ float ax = xx-px[j];
+ vv+=ax;
+ }
+}
+
+// { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } }
diff --git a/gcc/testsuite/g++.dg/warn/Wmultistatement-macros-1.C b/gcc/testsuite/g++.dg/warn/Wmultistatement-macros-1.C
new file mode 100644
index 00000000000..afaef9ad429
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmultistatement-macros-1.C
@@ -0,0 +1,13 @@
+// PR bootstrap/81216
+// { dg-options "-Wmultistatement-macros" }
+// { dg-do compile }
+
+template <typename A, typename B>
+static bool
+equal (A a, A b, B c)
+{
+ for (; a != b; ++a, (void)++c)
+ if (!(*a == *c))
+ return false;
+ return true;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-3.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-3.C
new file mode 100644
index 00000000000..52607b62284
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-3.C
@@ -0,0 +1,8 @@
+// PR c++/51270
+// { dg-options "-O2" }
+
+const int& f(long l)
+{
+ const int& i = l;
+ return i; // { dg-warning "address of local variable" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-2.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-2.C
index 2b8360648fa..b66e8b46565 100644
--- a/gcc/testsuite/g++.dg/warn/Wsign-compare-2.C
+++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-2.C
@@ -6,5 +6,5 @@ void
foo (__complex__ int i)
{
i == 0u;
- i == ~1u; // { dg-warning "comparison between signed and unsigned integer expressions" }
+ i == ~1u; // { dg-warning "comparison of integer expressions of different signedness" }
}
diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-4.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-4.C
index b3eb8e2a7de..e92ab137e3b 100644
--- a/gcc/testsuite/g++.dg/warn/Wsign-compare-4.C
+++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-4.C
@@ -3,10 +3,10 @@
int foo(unsigned int *a, int b)
{
- return (*a) <= b; // { dg-warning "comparison between signed and unsigned" }
+ return (*a) <= b; // { dg-warning "comparison of integer expressions of different signedness" }
}
int bar(unsigned int *a, int b)
{
- return *a <= b; // { dg-warning "comparison between signed and unsigned" }
+ return *a <= b; // { dg-warning "comparison of integer expressions of different signedness" }
}
diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-6.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-6.C
index 1f8af664c7b..71b4ebf1613 100644
--- a/gcc/testsuite/g++.dg/warn/Wsign-compare-6.C
+++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-6.C
@@ -8,7 +8,7 @@ int main()
int i = 5;
int const ic = 5;
- i < 5u; // { dg-warning "5:comparison between signed and unsigned" }
+ i < 5u; // { dg-warning "5:comparison of integer expressions of different signedness" }
ic < 5u;
FIVE < 5u;
}
diff --git a/gcc/testsuite/g++.dg/warn/compare1.C b/gcc/testsuite/g++.dg/warn/compare1.C
index e00592262c6..38f4dffd1da 100644
--- a/gcc/testsuite/g++.dg/warn/compare1.C
+++ b/gcc/testsuite/g++.dg/warn/compare1.C
@@ -6,5 +6,5 @@
int f(unsigned a, int b)
{
- return a < b; /* { dg-warning "signed and unsigned" } */
+ return a < b; /* { dg-warning "comparison of integer expressions of different signedness" } */
}
diff --git a/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C
new file mode 100644
index 00000000000..93a42eac08d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wctor-dtor-privacy" }
+
+class X // { dg-message "only defines private" }
+{
+public:
+ X (X const &); // { dg-message "requires an existing" }
+};
+
+class Y // { dg-message "only defines private" }
+{
+public:
+ Y (Y &&); // { dg-message "requires an existing" }
+};
+
+class Z
+{
+public:
+ Z (int);
+};
diff --git a/gcc/testsuite/g++.dg/warn/pr12242.C b/gcc/testsuite/g++.dg/warn/pr12242.C
index e1cd780d170..f95bf8b92d9 100644
--- a/gcc/testsuite/g++.dg/warn/pr12242.C
+++ b/gcc/testsuite/g++.dg/warn/pr12242.C
@@ -10,14 +10,14 @@ void example ()
X x;
Y y;
- x = 10; // { dg-warning "invalid conversion from .int. to .X {enum}." "invalid" }
+ x = 10; // { dg-warning "invalid conversion from .int. to .X." "invalid" }
// { dg-warning "unspecified" "unspecified" { target *-*-* } .-1 }
- x = 1; // { dg-warning "invalid conversion from .int. to .X {enum}." }
- x = C; // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }
- x = D; // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }
- y = A; // { dg-error "cannot convert .X {enum}. to .Y {enum}. in assignment" }
- x = y; // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }
- x = i; // { dg-warning "invalid conversion from .int. to .X {enum}." }
+ x = 1; // { dg-warning "invalid conversion from .int. to .X." }
+ x = C; // { dg-error "cannot convert .Y. to .X. in assignment" }
+ x = D; // { dg-error "cannot convert .Y. to .X. in assignment" }
+ y = A; // { dg-error "cannot convert .X. to .Y. in assignment" }
+ x = y; // { dg-error "cannot convert .Y. to .X. in assignment" }
+ x = i; // { dg-warning "invalid conversion from .int. to .X." }
}
void foo ()
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C b/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
index a3d23747b48..b3b1387462d 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/warn02.C
@@ -31,7 +31,7 @@ class C
class D
{
public:
- int foo2() {return b;} // { dg-error "with" }
+ int foo2() {return b;} // { dg-message "previous" }
int foo2() {return b;} // { dg-error "overloaded" }
int b;
};
@@ -39,7 +39,7 @@ public:
class E
{
public:
- int foo2(); // { dg-error "with" }
+ int foo2(); // { dg-message "previous" }
int foo2(); // { dg-error "overloaded" }
int b;
};
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/arm2.C b/gcc/testsuite/g++.old-deja/g++.brendan/arm2.C
index fb1ee429d37..23d6ae69f79 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/arm2.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/arm2.C
@@ -8,12 +8,12 @@
class X {
public:
- int foo(); // { dg-error "with" }
+ int foo(); // { dg-message "previous" }
static int foo(); // error: redeclaration// { dg-error "overloaded" } .*
};
class Y {
public:
- static int foo(); // { dg-error "with" }
+ static int foo(); // { dg-message "previous" }
int foo(); // error: redeclaration// { dg-error "overloaded" } .*
};
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900520_03.C b/gcc/testsuite/g++.old-deja/g++.bugs/900520_03.C
index 7978e386aba..ebcb45f57a1 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900520_03.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900520_03.C
@@ -34,7 +34,7 @@
typedef int u_array[];
typedef u_array &u_array_ref;
-void take_u_array_ref (u_array_ref arg) { } // { dg-error "" } reference to array of unknown bound in parmtype
+void take_u_array_ref (u_array_ref arg) { } // { dg-error "" "" { target c++14_down } } reference to array of unknown bound in parmtype
extern u_array u_array_gbl_obj;
u_array_ref u_array_ref_gbl_obj0 = u_array_gbl_obj; // OK
diff --git a/gcc/testsuite/g++.old-deja/g++.law/array2.C b/gcc/testsuite/g++.old-deja/g++.law/array2.C
index 0dcddb03cd5..c51f13de0ac 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/array2.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/array2.C
@@ -6,5 +6,5 @@
// Subject: prototype bug ?
// Date: Thu, 5 Nov 92 15:37:34 PST
- extern unsigned char * (*trt_def(int))[][2];
- extern unsigned char * (trt_rplst(unsigned char *(*)[][2])); // { dg-error "" }
+extern unsigned char * (*trt_def(int))[][2];
+extern unsigned char * (trt_rplst(unsigned char *(*)[][2])); // { dg-error "" "" { target c++14_down } }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/err1.C b/gcc/testsuite/g++.old-deja/g++.mike/err1.C
index 8e15dd27ae4..90f4ce68e55 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/err1.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/err1.C
@@ -1,8 +1,8 @@
// { dg-do assemble }
-struct gorf {
+struct gorf { // { dg-message "defined here" }
int stuff;
- void snarf(); // { dg-error "" }
+ void snarf(); // { dg-message "" }
};
-template <class T> void gorf::snarf() { return; } // { dg-error "" }
+template <class T> void gorf::snarf() { return; } // { dg-error "no declaration" }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p811.C b/gcc/testsuite/g++.old-deja/g++.mike/p811.C
index 260c6459cb8..5c8260aa1f8 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p811.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p811.C
@@ -515,21 +515,22 @@ public:
virtual char *stringify2() const = 0; // { dg-error "overriding" }
};
-class X: public Y {
+class X: public Y { // { dg-message "defined here" }
public:
X(): Y() {}
- const char *stringify(); // { dg-error "candidate" }
- const char *stringify2() const; // { dg-error "candidate|conflicting return type" }
+ const char *stringify(); // { dg-message "candidate" }
+ const char *stringify2() const; // { dg-message "candidate" }
+ // { dg-error "conflicting return type" "" { target *-*-* } .-1 }
};
char *
-X::stringify() const // { dg-error "does not match" }
+X::stringify() const // { dg-error "no declaration matches" }
{
return "stringify";
}
const char *
-X::stringify2() // { dg-error "does not match" }
+X::stringify2() // { dg-error "no declaration matches" }
{
return "stringify2";
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon4.C b/gcc/testsuite/g++.old-deja/g++.other/anon4.C
index 2a01be3d0aa..b6cb3006d71 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/anon4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/anon4.C
@@ -10,7 +10,7 @@
struct A
{
union
- { // { dg-error "" } anon union cannot have member fns
- void bad();
+ {
+ void bad(); // { dg-error "can only have non-static data" }
};
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash25.C b/gcc/testsuite/g++.old-deja/g++.other/crash25.C
index 5b313db1a8d..0611286fdc3 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/crash25.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/crash25.C
@@ -9,7 +9,8 @@ public:
virtual ~X();
}
-X::x() // { dg-error "6:no 'X X::x\\(\\)' member function declared in class 'X'" }
+X::x() // { dg-error "1:no declaration matches" }
+// { dg-message "1:no functions named" "note" { target *-*-* } .-1 }
{
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor4.C b/gcc/testsuite/g++.old-deja/g++.other/dtor4.C
index a4db38ba707..b7ae3706864 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/dtor4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/dtor4.C
@@ -1,10 +1,10 @@
// { dg-do assemble }
-struct S1 {
- ~S1(); // { dg-error "" } candidate
+struct S1 { // { dg-message "defined here" }
+ ~S1(); // { dg-message "candidate" }
};
-S1::~S1() const // { dg-error "" } prototype does not match
+S1::~S1() const // { dg-error "no declaration matches" }
{
}
@@ -15,12 +15,12 @@ struct S2 {
template <class T>
-struct S3 {
- ~S3(); // { dg-error "" } candidate
+struct S3 { // { dg-message "defined here" }
+ ~S3(); // { dg-message "candidate" }
};
template <class T>
-S3<T>::~S3() volatile // { dg-error "" } prototype does not match
+S3<T>::~S3() volatile // { dg-error "no declaration matches" }
{
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/redecl2.C b/gcc/testsuite/g++.old-deja/g++.other/redecl2.C
index 0d6ccf669f0..2da0b4f9978 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/redecl2.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/redecl2.C
@@ -1,9 +1,9 @@
// { dg-do assemble }
struct S {
- S(int); // { dg-error "with" }
+ S(int); // { dg-message "previous" }
S(int); // { dg-error "overloaded" } already declared
- ~S();// { dg-error "with" }
+ ~S();// { dg-message "previous" }
~S(); // { dg-error "overloaded" } already declared
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/redecl4.C b/gcc/testsuite/g++.old-deja/g++.other/redecl4.C
index e3355dafc41..c2303575dfc 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/redecl4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/redecl4.C
@@ -1,7 +1,7 @@
// { dg-do assemble }
int main() {
struct A {
- void f(); // { dg-error "with" } already declared
+ void f(); // { dg-message "previous" } already declared
void f(); // { dg-error "overloaded" } already declared
};
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C
index 73348351f0d..a8ba371af7a 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp78.C
@@ -23,7 +23,7 @@ template struct B<int>;
struct C
{
template <class U>
- void f() {} // { dg-error "with" } redeclaration
+ void f() {} // { dg-message "previous" } redeclaration
template <class U>
void f() {} // { dg-error "overloaded" } redeclaration
@@ -42,7 +42,7 @@ template struct D<int, double>;
template <class T, class U>
struct D2
{
- void f(T); // { dg-error "with" } redeclaration
+ void f(T); // { dg-message "previous" } redeclaration
void f(U); // { dg-error "overloaded" } redeclaration
};
@@ -50,7 +50,7 @@ template struct D2<int, int>;
struct E
{
- void f(); // { dg-error "with" } redeclaration
+ void f(); // { dg-message "previous" } redeclaration
void f(); // { dg-error "overloaded" } redeclaration
};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/t37.C b/gcc/testsuite/g++.old-deja/g++.pt/t37.C
index 99348c05009..dbf1f4403b3 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/t37.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/t37.C
@@ -1,9 +1,10 @@
-// { dg-do assemble }
+// { dg-do compile }
-class A { // { dg-error "" } synthesized copy ctor
+class A { // { dg-message "A::A" } synthesized copy ctor
+ // { dg-message "defined here" "note" { target *-*-* } .-1 }
public:
- A(int); // { dg-error "" } referenced below
- A(float); // { dg-error "" } referenced below
+ A(int); // { dg-message "A::A" }
+ A(float); // { dg-message "A::A" }
~A();
};
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr81207.c b/gcc/testsuite/gcc.c-torture/compile/pr81207.c
new file mode 100644
index 00000000000..f0faa8c0a22
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr81207.c
@@ -0,0 +1,13 @@
+/* PR middle-end/81207 */
+
+static const char *b[2] = { "'", "" };
+
+int
+foo (const char *d)
+{
+ int e;
+ for (e = 0; b[e]; e++)
+ if (__builtin_strstr (d, b[e]))
+ return 1;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr81262.c b/gcc/testsuite/gcc.c-torture/compile/pr81262.c
new file mode 100644
index 00000000000..68fbea2a7ab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr81262.c
@@ -0,0 +1,14 @@
+/* PR sanitizer/81262 */
+
+void bar (void) __attribute__((cold, noreturn));
+
+int
+foo (void)
+{
+ asm goto ("" : : : : l1, l2);
+ bar ();
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr81290.c b/gcc/testsuite/gcc.c-torture/compile/pr81290.c
new file mode 100644
index 00000000000..1fd8b2055da
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr81290.c
@@ -0,0 +1,22 @@
+/* { dg-options "-funroll-loops -w" } */
+int vz;
+
+void
+ms (int sw, int cm)
+{
+ for (vz = 0; vz < 19; ++vz)
+ {
+ fx:
+ sw *= 2;
+ }
+
+ for (;;)
+ {
+ if (sw != 0)
+ for (;;)
+ {
+ }
+ if (1 / 0 && cm != 0)
+ goto fx;
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/stack-check-1.c b/gcc/testsuite/gcc.c-torture/compile/stack-check-1.c
index 5c99688b35a..2a03f7c29ae 100644
--- a/gcc/testsuite/gcc.c-torture/compile/stack-check-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/stack-check-1.c
@@ -1,3 +1,4 @@
/* { dg-require-effective-target untyped_assembly } */
+/* { dg-require-stack-check "" } */
/* { dg-additional-options "-fstack-check" } */
#include "20031023-1.c"
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c
index 00005298d10..25d4a40a67e 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm-lib.c
@@ -37,6 +37,24 @@ my_bcopy (const void *s, void *d, size_t n)
}
}
+__attribute__ ((used))
+void
+my_memmove (void *d, const void *s, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ if (src >= dst)
+ while (n--)
+ *dst++ = *src++;
+ else
+ {
+ dst += n;
+ src += n;
+ while (n--)
+ *--dst = *--src;
+ }
+}
+
/* LTO code is at the present to able to track that asm alias my_bcopy on builtin
actually refers to this function. See PR47181. */
__attribute__ ((used))
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c
index ed2b06cf06f..44e336cce7c 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memops-asm.c
@@ -12,6 +12,8 @@ extern void *memcpy (void *, const void *, size_t)
__asm (ASMNAME ("my_memcpy"));
extern void bcopy (const void *, void *, size_t)
__asm (ASMNAME ("my_bcopy"));
+extern void *memmove (void *, const void *, size_t)
+ __asm (ASMNAME ("my_memmove"));
extern void *memset (void *, int, size_t)
__asm (ASMNAME ("my_memset"));
extern void bzero (void *, size_t)
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr81555.c b/gcc/testsuite/gcc.c-torture/execute/pr81555.c
new file mode 100644
index 00000000000..d546368a39b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr81555.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/81555 */
+
+unsigned int a = 1, d = 0xfaeU, e = 0xe376U;
+_Bool b = 0, f = 1;
+unsigned char g = 1;
+
+void
+foo (void)
+{
+ _Bool c = a != b;
+ if (c)
+ f = 0;
+ if (e & c & (unsigned char)d & c)
+ g = 0;
+}
+
+int
+main ()
+{
+ foo ();
+ if (f || g != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr81556.c b/gcc/testsuite/gcc.c-torture/execute/pr81556.c
new file mode 100644
index 00000000000..cfbc75f861a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr81556.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/81556 */
+
+unsigned long long int b = 0xb82ff73c5c020599ULL;
+unsigned long long int c = 0xd4e8188733a29d8eULL;
+unsigned long long int d = 2, f = 1, g = 0, h = 0;
+unsigned long long int e = 0xf27771784749f32bULL;
+
+__attribute__((noinline, noclone)) void
+foo (void)
+{
+ _Bool a = d > 1;
+ g = f % ((d > 1) << 9);
+ h = a & (e & (a & b & c));
+}
+
+int
+main ()
+{
+ foo ();
+ if (g != 1 || h != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Walloca-14.c b/gcc/testsuite/gcc.dg/Walloca-14.c
index 723dbe5081a..f3e3f579439 100644
--- a/gcc/testsuite/gcc.dg/Walloca-14.c
+++ b/gcc/testsuite/gcc.dg/Walloca-14.c
@@ -9,5 +9,6 @@ g (int *p)
extern void f (void *);
void *q = __builtin_alloca (p); /* { dg-warning "passing argument 1" } */
+ /* { dg-warning "unbounded use of 'alloca'" "unbounded" { target *-*-* } 11 } */
f (q);
}
diff --git a/gcc/testsuite/gcc.dg/Wmissing-braces-fixits.c b/gcc/testsuite/gcc.dg/Wmissing-braces-fixits.c
index b7d66cd6c3d..2cce217369c 100644
--- a/gcc/testsuite/gcc.dg/Wmissing-braces-fixits.c
+++ b/gcc/testsuite/gcc.dg/Wmissing-braces-fixits.c
@@ -162,3 +162,28 @@ struct sa3 arr_4_sa3[4] = \
6, 7, 8, 9, 10, 11};
{{ }}{{ }}
{ dg-end-multiline-output "" } */
+
+/* PR c/81405. */
+int a5[][0][0] = { 1, 2 }; /* { dg-line pr_81405 } */
+
+ /* { dg-warning "missing braces around initializer" "" { target c } pr_81405 } */
+ /* { dg-begin-multiline-output "" }
+ int a5[][0][0] = { 1, 2 };
+ ^
+ { -----
+ {{1}}}}, {{{2 }}
+ { dg-end-multiline-output "" } */
+
+ /* { dg-warning "excess elements" "" { target c } pr_81405 } */
+ /* { dg-begin-multiline-output "" }
+ int a5[][0][0] = { 1, 2 };
+ ^
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+ int a5[][0][0] = { 1, 2 };
+ ^
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+ int a5[][0][0] = { 1, 2 };
+ ^~~
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/asan/pr81186.c b/gcc/testsuite/gcc.dg/asan/pr81186.c
new file mode 100644
index 00000000000..7f0f672ca40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr81186.c
@@ -0,0 +1,18 @@
+/* PR sanitizer/81186 */
+/* { dg-do run } */
+
+int
+main ()
+{
+ __label__ l;
+ void f ()
+ {
+ int a[123];
+
+ goto l;
+ }
+
+ f ();
+l:
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/asan/pr81224.c b/gcc/testsuite/gcc.dg/asan/pr81224.c
new file mode 100644
index 00000000000..def5cb69aec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr81224.c
@@ -0,0 +1,11 @@
+/* PR sanitizer/80659 */
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-additional-options "-msse2" } */
+
+int a;
+int
+b ()
+{
+ register __attribute__ ((__vector_size__ (4 * sizeof (int)))) int c asm("xmm0");
+ return c[a];
+}
diff --git a/gcc/testsuite/gcc.dg/asan/pr81460.c b/gcc/testsuite/gcc.dg/asan/pr81460.c
new file mode 100644
index 00000000000..00c1bb7c9f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr81460.c
@@ -0,0 +1,8 @@
+/* PR sanitizer/80460 */
+/* { dg-do compile } */
+
+int
+f (int a, struct { int b[a]; } c) /* { dg-warning "anonymous struct declared inside parameter list will not be visible outside of this definition or declaration" } */
+{
+ return c.b[0];
+}
diff --git a/gcc/testsuite/gcc.dg/atomic-pr81231.c b/gcc/testsuite/gcc.dg/atomic-pr81231.c
new file mode 100644
index 00000000000..304e4281f7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-pr81231.c
@@ -0,0 +1,12 @@
+/* PR c/81231 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+enum E;
+
+void
+foo (void)
+{
+ __atomic_load_n ((enum E *) 0, 0); /* { dg-error "incompatible" } */
+ __atomic_load_n ((enum X *) 0, 0); /* { dg-error "incompatible" } */
+}
diff --git a/gcc/testsuite/gcc.dg/attr-noipa.c b/gcc/testsuite/gcc.dg/attr-noipa.c
new file mode 100644
index 00000000000..1d2b86894ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-noipa.c
@@ -0,0 +1,188 @@
+/* Test the noipa attribute. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+static inline int __attribute__((noipa))
+fn1 (void) /* { dg-warning "inline function \[^\n\]* given attribute noinline" "" } */
+{
+ return 1;
+}
+
+/* Verify the function is not inlined into its caller. */
+
+static __attribute__((noipa)) int
+fn2 (int x, int y)
+{
+ return x + y;
+}
+
+int
+fn3 (int x)
+{
+ return fn2 (x, 0);
+}
+
+/* { dg-final { scan-tree-dump "= fn2 \\(" "optimized" } } */
+
+void fn4 (char *);
+
+/* Verify the function is not cloned. */
+
+__attribute__((__noipa__)) static int
+fn5 (int x, int y)
+{
+ char *p = __builtin_alloca (x + y);
+ fn4 (p);
+ return x + y;
+}
+
+int
+fn6 (int x)
+{
+ return fn5 (x, 2);
+}
+
+/* { dg-final { scan-tree-dump "= fn5 \\(" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "fn5\\.constprop" "optimized" } } */
+
+/* Verify we still remove unused function calls, even if they have
+ noipa attribute. */
+
+static void fn7 (void) __attribute__((noipa));
+static void
+fn7 (void)
+{
+}
+
+/* { dg-final { scan-tree-dump-not "fn7 \\(" "optimized" } } */
+
+/* Verify noipa functions are not ICF optimized. */
+
+static __attribute__((noipa)) int
+fn8 (int x)
+{
+ return x + 12;
+}
+
+static __attribute__((noipa)) int
+fn9 (int x)
+{
+ return x + 12;
+}
+
+int
+fn10 (int x)
+{
+ return fn8 (x) + fn9 (x);
+}
+
+/* { dg-final { scan-tree-dump "fn8 \\(int" "optimized" } } */
+/* { dg-final { scan-tree-dump "fn9 \\(int" "optimized" } } */
+
+/* Verify IPA-VRP is not performed. */
+
+void fn11 (void);
+
+static int __attribute__((noipa))
+fn12 (int x)
+{
+ if (x < 6 || x >= 29)
+ fn11 ();
+}
+
+void
+fn13 (int x)
+{
+ fn12 (6 + (x & 15));
+}
+
+/* { dg-final { scan-tree-dump "fn11 \\(\\)" "optimized" } } */
+
+void fn14 (void);
+
+__attribute__((noipa)) static int
+fn15 (int x)
+{
+ return x & 7;
+}
+
+int
+fn16 (int x)
+{
+ x = fn15 (x);
+ if (x < 0 || x >= 7)
+ fn14 ();
+}
+
+/* { dg-final { scan-tree-dump "fn14 \\(\\)" "optimized" } } */
+
+/* Verify IPA BIT CP is not performed. */
+
+void fn17 (void);
+
+__attribute__((noipa)) static int
+fn18 (int x)
+{
+ if (x & 8)
+ fn17 ();
+}
+
+void
+fn19 (void)
+{
+ fn18 (1);
+ fn18 (2);
+ fn18 (4);
+ fn18 (16);
+ fn18 (32);
+ fn18 (64);
+}
+
+/* { dg-final { scan-tree-dump "fn17 \\(\\)" "optimized" } } */
+
+/* Ensure pure/const discovery is not performed. */
+
+int var1;
+void fn20 (void);
+
+__attribute__((noipa)) static int
+fn21 (int x, int y)
+{
+ return x * y;
+}
+
+int
+fn22 (void)
+{
+ var1 = 7;
+ asm volatile ("" : "+g" (var1) : : "memory");
+ int a = var1;
+ int b = fn21 (a, a);
+ if (a != var1)
+ fn20 ();
+ return b;
+}
+
+/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */
+
+/* Verify IPA alignment propagation is not performed. */
+
+static __attribute__ ((aligned(16))) char var2[32];
+void fn23 (void);
+
+__attribute__((noipa)) static void
+fn24 (char *p)
+{
+ if ((((__UINTPTR_TYPE__) p) & 15) != 0)
+ fn23 ();
+ asm ("");
+}
+
+void
+fn25 (void)
+{
+ fn24 (var2);
+ fn24 (var2 + 16);
+}
+
+/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/builtin-unreachable-6.c b/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
index d2596e95c3f..2f8ca369546 100644
--- a/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
+++ b/gcc/testsuite/gcc.dg/builtin-unreachable-6.c
@@ -16,5 +16,5 @@ lab2:
goto *x;
}
-/* { dg-final { scan-tree-dump-times "lab \\\[\[0-9.\]+%\\\]" 1 "fab1" } } */
+/* { dg-final { scan-tree-dump-times "lab:" 1 "fab1" } } */
/* { dg-final { scan-tree-dump-times "__builtin_unreachable" 1 "fab1" } } */
diff --git a/gcc/testsuite/gcc.dg/compare1.c b/gcc/testsuite/gcc.dg/compare1.c
index 17ba3ee2098..7becfbdb17f 100644
--- a/gcc/testsuite/gcc.dg/compare1.c
+++ b/gcc/testsuite/gcc.dg/compare1.c
@@ -37,5 +37,5 @@ int h(enum mm2 x)
int i(enum mm2 x)
{
- return x == (tf?DI2:-1); /* { dg-warning "signed and unsigned" "case 4" } */
+ return x == (tf?DI2:-1); /* { dg-warning "different signedness" "case 4" } */
}
diff --git a/gcc/testsuite/gcc.dg/compare2.c b/gcc/testsuite/gcc.dg/compare2.c
index 0625eb9c3f6..c309f1d00eb 100644
--- a/gcc/testsuite/gcc.dg/compare2.c
+++ b/gcc/testsuite/gcc.dg/compare2.c
@@ -18,11 +18,11 @@ void f(int x, unsigned int y)
/* ?: branches are signed constants. */
x > (tf?64:-1); /* { dg-bogus "signed and unsigned" "case 5" } */
- y > (tf?64:-1); /* { dg-warning "signed and unsigned" "case 6" } */
+ y > (tf?64:-1); /* { dg-warning "different signedness" "case 6" } */
/* ?: branches are (recursively) signed constants. */
x > (tf?64:(tf?128:-1)); /* { dg-bogus "signed and unsigned" "case 7" } */
- y > (tf?64:(tf?128:-1)); /* { dg-warning "signed and unsigned" "case 8" } */
+ y > (tf?64:(tf?128:-1)); /* { dg-warning "different signedness" "case 8" } */
/* Statement expression. */
x > ({tf; 64;}); /* { dg-bogus "signed and unsigned" "case 9" } */
@@ -34,11 +34,11 @@ void f(int x, unsigned int y)
/* Statement expression with signed ?:. */
x > ({tf; tf?64:-1;}); /* { dg-bogus "signed and unsigned" "case 13" } */
- y > ({tf; tf?64:-1;}); /* { dg-warning "signed and unsigned" "case 14" } */
+ y > ({tf; tf?64:-1;}); /* { dg-warning "different signedness" "case 14" } */
/* Statement expression with recursive signed ?:. */
x > ({tf; tf?64:(tf?128:-1);}); /* { dg-bogus "signed and unsigned" "case 15" } */
- y > ({tf; tf?64:(tf?128:-1);}); /* { dg-warning "signed and unsigned" "case 16" } */
+ y > ({tf; tf?64:(tf?128:-1);}); /* { dg-warning "different signedness" "case 16" } */
/* ?: branches are constants. */
tf ? x : (tf?64:32); /* { dg-bogus "conditional expression" "case 17" } */
diff --git a/gcc/testsuite/gcc.dg/compare4.c b/gcc/testsuite/gcc.dg/compare4.c
index e5dad4d1e45..299d488edf6 100644
--- a/gcc/testsuite/gcc.dg/compare4.c
+++ b/gcc/testsuite/gcc.dg/compare4.c
@@ -10,7 +10,7 @@ int foo(int x, int y, unsigned u)
{
/* A COMPOUND_EXPR is non-negative if the last element is known to
be non-negative. */
- if (u < (bar(), -1)) /*{ dg-warning "9:signed and unsigned" "COMPOUND_EXPR" }*/
+ if (u < (bar(), -1)) /*{ dg-warning "9:different signedness" "COMPOUND_EXPR" }*/
return x;
if (u < (bar(), 10))
return x;
@@ -34,7 +34,7 @@ int foo(int x, int y, unsigned u)
/* A MODIFY_EXPR is non-negative if the new value is known to be
non-negative. */
- if (u < (x = -1)) /* { dg-warning "9:signed and unsigned" "MODIFY_EXPR" } */
+ if (u < (x = -1)) /* { dg-warning "9:different signedness" "MODIFY_EXPR" } */
return x;
if (u < (x = 10))
return x;
diff --git a/gcc/testsuite/gcc.dg/compare5.c b/gcc/testsuite/gcc.dg/compare5.c
index f19c575efb7..3a502f12de9 100644
--- a/gcc/testsuite/gcc.dg/compare5.c
+++ b/gcc/testsuite/gcc.dg/compare5.c
@@ -10,7 +10,7 @@ int foo(int x, int y, unsigned u)
{
/* A *_DIV_EXPR is non-negative if both operands are. */
- if (u < ((x=-22)/33)) /* { dg-warning "signed and unsigned" "DIV_EXPR" } */
+ if (u < ((x=-22)/33)) /* { dg-warning "different signedness" "DIV_EXPR" } */
return x;
if (u < ((x=22)/33))
@@ -25,7 +25,7 @@ int foo(int x, int y, unsigned u)
/* A *_MOD_EXPR is non-negative if the first operand is. */
- if (u < ((x=-22)%33)) /* { dg-warning "signed and unsigned" "MOD_EXPR" } */
+ if (u < ((x=-22)%33)) /* { dg-warning "different signedness" "MOD_EXPR" } */
return x;
if (u < ((x=22)%-33))
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-3.c b/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-3.c
index dac4405b36c..efa3fa0b1f2 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-3.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-3.c
@@ -31,4 +31,4 @@ char * _Atomic restrict h;
char * _Atomic i;
char * restrict j;
-/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile|atomic|restrict)_type" 8 { xfail { powerpc-ibm-aix* } } } } */
+/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile|atomic|restrict)_type" 8 } } */
diff --git a/gcc/testsuite/gcc.dg/fixed-point/pr81428.c b/gcc/testsuite/gcc.dg/fixed-point/pr81428.c
new file mode 100644
index 00000000000..98f4b235718
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fixed-point/pr81428.c
@@ -0,0 +1,9 @@
+/* PR tree-optimization/81428 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (long _Fract *a, long _Fract *b)
+{
+ *b = *a / *a;
+}
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index cab30f2d7f6..8cce5b38c9f 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -278,7 +278,7 @@ void test_macro_3 (const char *msg)
printf(FMT_STRING, msg); /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
/* { dg-begin-multiline-output "" }
#define FMT_STRING "hello %i world"
- ^
+ ^~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
printf(FMT_STRING, msg);
@@ -293,7 +293,7 @@ void test_macro_4 (const char *msg)
printf(FMT_STRING "\n", msg); /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
/* { dg-begin-multiline-output "" }
#define FMT_STRING "hello %i world"
- ^
+ ^~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
printf(FMT_STRING "\n", msg);
diff --git a/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c b/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c
index cd9d8ebcb16..ca91af471ca 100644
--- a/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c
+++ b/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c
@@ -1,3 +1,4 @@
+/* { dg-require-stack-check "generic" } */
/* { dg-options "-O -fstack-check=generic -ftree-pre -fgraphite-identity" } */
/* nvptx doesn't expose a stack. */
/* { dg-skip-if "" { nvptx-*-* } } */
diff --git a/gcc/testsuite/gcc.dg/guality/pr68037-1.c b/gcc/testsuite/gcc.dg/guality/pr68037-1.c
index 74f61ec5f96..44cab58659f 100644
--- a/gcc/testsuite/gcc.dg/guality/pr68037-1.c
+++ b/gcc/testsuite/gcc.dg/guality/pr68037-1.c
@@ -59,9 +59,9 @@ main ()
return 0;
}
-/* { dg-final { gdb-test 31 "error" "0x12345670" } } */
-/* { dg-final { gdb-test 31 "frame->ip" "0x12345671" } } */
-/* { dg-final { gdb-test 31 "frame->cs" "0x12345672" } } */
-/* { dg-final { gdb-test 31 "frame->flags" "0x12345673" } } */
-/* { dg-final { gdb-test 31 "frame->sp" "0x12345674" } } */
-/* { dg-final { gdb-test 31 "frame->ss" "0x12345675" } } */
+/* { dg-final { gdb-test 33 "error" "0x12345670" } } */
+/* { dg-final { gdb-test 33 "frame->ip" "0x12345671" } } */
+/* { dg-final { gdb-test 33 "frame->cs" "0x12345672" } } */
+/* { dg-final { gdb-test 33 "frame->flags" "0x12345673" } } */
+/* { dg-final { gdb-test 33 "frame->sp" "0x12345674" } } */
+/* { dg-final { gdb-test 33 "frame->ss" "0x12345675" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c b/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c
new file mode 100644
index 00000000000..01b09764097
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fipa-pta -fdump-ipa-pta2-details -fdump-tree-fre3-details" } */
+
+static int __attribute__((noipa))
+foo (int *p, int *q)
+{
+ *p = 1;
+ *q = 0;
+ return *p;
+}
+
+extern void abort (void);
+
+int main()
+{
+ int a, b;
+ if (foo (&a, &b) != 1)
+ abort ();
+ return 0;
+}
+
+/* Verify we can disambiguate *p and *q in foo. */
+
+/* { dg-final { scan-ipa-dump "foo.arg0 = &a" "pta2" } } */
+/* { dg-final { scan-ipa-dump "foo.arg1 = &b" "pta2" } } */
+/* { dg-final { scan-tree-dump-not "Replaced \\\*p_2\\\(D\\\) with 1" "fre3" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c
new file mode 100644
index 00000000000..e91423a62fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fipa-sra -fdump-tree-eipa_sra-details" } */
+
+struct bovid
+{
+ float red;
+ int green;
+ void *blue;
+};
+
+extern int printf (const char *, ...);
+extern void abort (void);
+
+static int
+__attribute__((noipa))
+ox (struct bovid cow)
+{
+ if (cow.green != 6)
+ abort ();
+
+ printf ("green: %f\nblue: %p\nblue again: %p\n", cow.green,
+ cow.blue, cow.blue);
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct bovid cow;
+
+ cow.red = 7.4;
+ cow.green = 6;
+ cow.blue = &cow;
+
+ ox (cow);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "About to replace expr" "eipa_sra" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr81520.c b/gcc/testsuite/gcc.dg/ipa/pr81520.c
new file mode 100644
index 00000000000..b5d33d2dc96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr81520.c
@@ -0,0 +1,11 @@
+/* PR ipa/81520 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-require-effective-target fpic } */
+
+char
+a (int b)
+{
+ a (b);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-1.c b/gcc/testsuite/gcc.dg/missing-header-fixit-1.c
new file mode 100644
index 00000000000..2b28357e1db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-1.c
@@ -0,0 +1,36 @@
+/* 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. */
+
+/* This is padding (to avoid the generated patch containing DejaGnu
+ directives). */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+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 } */
+}
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing this
+ source filename, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+/* Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -1,3 +1,4 @@
++#include <stdio.h>
+ /* 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-end-multiline-output "" }
+#endif
+
+/* FIXME: should we attempt to skip leading comments when determining the
+ insertion location?
+ Similarly, should we attempt to be within single-inclusion guards, etc? */
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-2.c b/gcc/testsuite/gcc.dg/missing-header-fixit-2.c
new file mode 100644
index 00000000000..5d5f87488f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-2.c
@@ -0,0 +1,31 @@
+/* Verify that when we suggest adding #include directives that they
+ are added to the affected file. */
+
+/* The following header file is missing a "#include <stdio.h>". */
+
+#include "missing-header-fixit-2.h"
+
+/* These directives actually apply to the header. */
+/* { dg-warning "implicit declaration of function 'printf'" "" { target *-*-* } 6 } */
+/* { dg-warning "incompatible implicit declaration of built-in function 'printf'" "" { target *-*-* } 6 } */
+
+/* { dg-options "-fdiagnostics-generate-patch" } */
+
+/* Verify the output from -fdiagnostics-generate-patch.
+ We expect the patch to begin with a header, containing the
+ filename of the header, via an absolute path.
+ Given the path, we can only capture it via regexps. */
+/* { dg-regexp "\\-\\-\\- .*" } */
+/* { dg-regexp "\\+\\+\\+ .*" } */
+/* Use #if 0/#endif rather than comments, to allow the text to contain
+ a comment.
+ We expect the *header* to have been patched, adding the missing include. */
+#if 0
+{ dg-begin-multiline-output "" }
+@@ -1,3 +1,4 @@
++#include <stdio.h>
+ /* This is missing-header-fixit-2.h, for use by
+ missing-header-fixit-2.c */
+
+{ dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-2.h b/gcc/testsuite/gcc.dg/missing-header-fixit-2.h
new file mode 100644
index 00000000000..c0bf55dcbe6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-2.h
@@ -0,0 +1,7 @@
+/* This is missing-header-fixit-2.h, for use by
+ missing-header-fixit-2.c */
+
+void test (int i, int j)
+{
+ printf ("%i of %i\n", i, j);
+}
diff --git a/gcc/testsuite/gcc.dg/overflow-warn-1.c b/gcc/testsuite/gcc.dg/overflow-warn-1.c
index 8eb322579cf..a5cd5738636 100644
--- a/gcc/testsuite/gcc.dg/overflow-warn-1.c
+++ b/gcc/testsuite/gcc.dg/overflow-warn-1.c
@@ -49,7 +49,7 @@ static int sc = INT_MAX + 1; /* { dg-warning "25:integer overflow in expression"
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-1 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "initializer element is not computable at load time" "constant" { target *-*-* } .-1 } */
+/* { dg-error "initializer element is not constant" "constant" { target *-*-* } .-1 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *r = (1 ? 0 : INT_MAX+1);
diff --git a/gcc/testsuite/gcc.dg/overflow-warn-2.c b/gcc/testsuite/gcc.dg/overflow-warn-2.c
index f048d6dae2a..05ab104fa4a 100644
--- a/gcc/testsuite/gcc.dg/overflow-warn-2.c
+++ b/gcc/testsuite/gcc.dg/overflow-warn-2.c
@@ -49,7 +49,7 @@ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" }
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-1 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "initializer element is not computable at load time" "constant" { target *-*-* } .-1 } */
+/* { dg-error "initializer element is not constant" "constant" { target *-*-* } .-1 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *r = (1 ? 0 : INT_MAX+1);
diff --git a/gcc/testsuite/gcc.dg/overflow-warn-3.c b/gcc/testsuite/gcc.dg/overflow-warn-3.c
index 664011e401d..fd4a34f67e2 100644
--- a/gcc/testsuite/gcc.dg/overflow-warn-3.c
+++ b/gcc/testsuite/gcc.dg/overflow-warn-3.c
@@ -55,7 +55,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } .-1 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "initializer element is not computable at load time" "constant" { target *-*-* } .-1 } */
+/* { dg-error "initializer element is not constant" "constant" { target *-*-* } .-1 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *r = (1 ? 0 : INT_MAX+1);
diff --git a/gcc/testsuite/gcc.dg/overflow-warn-4.c b/gcc/testsuite/gcc.dg/overflow-warn-4.c
index 52677ce897a..018e3e1e4cd 100644
--- a/gcc/testsuite/gcc.dg/overflow-warn-4.c
+++ b/gcc/testsuite/gcc.dg/overflow-warn-4.c
@@ -55,7 +55,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } .-1 } */
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "initializer element is not computable at load time" "constant" { target *-*-* } .-1 } */
+/* { dg-error "initializer element is not constant" "constant" { target *-*-* } .-1 } */
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } .-2 } */
void *r = (1 ? 0 : INT_MAX+1);
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
index b0dbc05bc1d..03b78042107 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
@@ -708,3 +708,82 @@ baz");
~~~~
{ dg-end-multiline-output "" } */
}
+
+/* Various tests of locations involving macros. */
+
+void test_within_macro_1 (int lhs, int rhs)
+{
+#define MACRO_1(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_1 (lhs == rhs));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_1 (lhs == rhs));
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_1(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_1
+}
+
+void test_within_macro_2 (int lhs, int rhs)
+{
+#define MACRO_2(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_2 (MACRO_2 (lhs == rhs)));
+ ^~~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_2(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_2
+}
+
+void test_within_macro_3 (int lhs, int rhs)
+{
+#define MACRO_3(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_3 (lhs) == MACRO_3 (rhs));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_3 (lhs) == MACRO_3 (rhs));
+ ^
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_3
+}
+
+void test_within_macro_4 (int lhs, int rhs)
+{
+#define MACRO_4(EXPR) EXPR
+
+ __emit_expression_range (0, MACRO_4 (MACRO_4 (lhs) == MACRO_4 (rhs)));
+
+/* { dg-warning "range" "" { target *-*-* } .-2 } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, MACRO_4 (MACRO_4 (lhs) == MACRO_4 (rhs)));
+ ^
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ #define MACRO_4(EXPR) EXPR
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+#undef MACRO_4
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr35430.c b/gcc/testsuite/gcc.dg/pr35430.c
index ab5e4cac8a5..7365ccfcf94 100644
--- a/gcc/testsuite/gcc.dg/pr35430.c
+++ b/gcc/testsuite/gcc.dg/pr35430.c
@@ -6,5 +6,5 @@ void
foo (__complex__ int i)
{
i == 0u;
- i == ~1u; /* { dg-warning "comparison between signed and unsigned integer expressions" } */
+ i == ~1u; /* { dg-warning "comparison of integer expressions of different signedness" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr44290-1.c b/gcc/testsuite/gcc.dg/pr44290-1.c
index c036db654f3..05d2454fc31 100644
--- a/gcc/testsuite/gcc.dg/pr44290-1.c
+++ b/gcc/testsuite/gcc.dg/pr44290-1.c
@@ -1,4 +1,5 @@
-/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target naked_functions } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
static void __attribute__((naked))
diff --git a/gcc/testsuite/gcc.dg/pr44290-2.c b/gcc/testsuite/gcc.dg/pr44290-2.c
index 17615366267..07335109114 100644
--- a/gcc/testsuite/gcc.dg/pr44290-2.c
+++ b/gcc/testsuite/gcc.dg/pr44290-2.c
@@ -1,4 +1,5 @@
-/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target naked_functions } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
static unsigned long __attribute__((naked))
diff --git a/gcc/testsuite/gcc.dg/pr46932.c b/gcc/testsuite/gcc.dg/pr46932.c
new file mode 100644
index 00000000000..b96febcc095
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr46932.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -fdump-rtl-auto_inc_dec" } */
+
+/* Check that accesses based on the frame pointer do not
+ use auto increment. */
+
+extern void foo(char*);
+void t01(char t)
+{
+ char c = t;
+ foo(&c);
+}
+
+/* { dg-final { scan-rtl-dump-not "success" "auto_inc_dec" } } */
diff --git a/gcc/testsuite/gcc.dg/pr47443.c b/gcc/testsuite/gcc.dg/pr47443.c
index 47abea27dd7..5a5c43f2537 100644
--- a/gcc/testsuite/gcc.dg/pr47443.c
+++ b/gcc/testsuite/gcc.dg/pr47443.c
@@ -1,5 +1,6 @@
/* PR tree-optimization/47443 */
/* { dg-do compile } */
+/* { dg-require-stack-check "generic" } */
/* { dg-options "-O -fstack-check=generic" } */
static inline int bar (char *c, int i)
diff --git a/gcc/testsuite/gcc.dg/pr48134.c b/gcc/testsuite/gcc.dg/pr48134.c
index 8dc5a6d0d41..446ad01b452 100644
--- a/gcc/testsuite/gcc.dg/pr48134.c
+++ b/gcc/testsuite/gcc.dg/pr48134.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-stack-check "specific" } */
/* { dg-options "-O2 -fstack-check=specific -fno-tree-dse -fno-tree-fre -fno-tree-loop-optimize -g" } */
struct S
diff --git a/gcc/testsuite/gcc.dg/pr56727-1.c b/gcc/testsuite/gcc.dg/pr56727-1.c
new file mode 100644
index 00000000000..ffc133545e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56727-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-final { scan-assembler-not "@(PLT|plt)" { target i?86-*-* x86_64-*-* powerpc*-*-* } } } */
+
+#define define_func(type) \
+ void f_ ## type (type b) { f_ ## type (0); } \
+ void __attribute__((noinline, noclone)) f_noinline_ ## type (type b) \
+ { f_noinline_ ## type (0); }
+
+define_func(char)
+define_func(short)
+define_func(int)
+define_func(long)
+
+int foo(int n)
+{
+ return (n == 1 || n == 2) ? 1 : foo(n-1) * foo(n-2);
+}
+
+int __attribute__((noinline, noclone)) foo_noinline(int n)
+{
+ return (n == 1 || n == 2) ? 1 : foo_noinline(n-1) * foo_noinline(n-2);
+}
diff --git a/gcc/testsuite/gcc.dg/pr56727-2.c b/gcc/testsuite/gcc.dg/pr56727-2.c
new file mode 100644
index 00000000000..e47ee3cd96b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56727-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-final { scan-assembler "@(PLT|plt)" { target i?86-*-* x86_64-*-* powerpc*-*-linux* } } } */
+
+__attribute__((noinline, noclone))
+void f (short b)
+{
+ f (0);
+}
+
+static void g (short) __attribute__ ((alias ("f")));
+
+void h ()
+{
+ g (0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr60087.c b/gcc/testsuite/gcc.dg/pr60087.c
index 9cdd5897354..c6cf7aa4607 100644
--- a/gcc/testsuite/gcc.dg/pr60087.c
+++ b/gcc/testsuite/gcc.dg/pr60087.c
@@ -10,5 +10,5 @@ foo (unsigned int ui, int i)
b = 0 != ~uc; /* { dg-warning "9:promoted ~unsigned is always non-zero" } */
b = 2 != ~uc; /* { dg-warning "9:comparison of promoted ~unsigned with constant" } */
b = uc == ~uc; /* { dg-warning "10:comparison of promoted ~unsigned with unsigned" } */
- b = i == ui; /* { dg-warning "9:comparison between signed and unsigned integer expressions" } */
+ b = i == ui; /* { dg-warning "9:comparison of integer expressions of different signedness" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr70017.c b/gcc/testsuite/gcc.dg/pr70017.c
index f544167612b..3489d5baf48 100644
--- a/gcc/testsuite/gcc.dg/pr70017.c
+++ b/gcc/testsuite/gcc.dg/pr70017.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-stack-check "generic" } */
/* { dg-options "-fstack-check=generic" } */
/* Check that the expected warning is issued for large frames. */
diff --git a/gcc/testsuite/gcc.dg/pr70920-2.c b/gcc/testsuite/gcc.dg/pr70920-2.c
index 2db9897bad5..98072247e94 100644
--- a/gcc/testsuite/gcc.dg/pr70920-2.c
+++ b/gcc/testsuite/gcc.dg/pr70920-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop-details" } */
+/* { dg-options "-O2 -fdump-tree-ccp1-details" } */
#include <stdint.h>
@@ -18,4 +18,4 @@ foo (int *a)
}
}
-/* { dg-final { scan-tree-dump "gimple_simplified to if \\(a_\[0-9\]*\\(D\\) == 0B\\)" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "gimple_simplified to if \\(a_\[0-9\]*\\(D\\) == 0B\\)" "ccp1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr70920-4.c b/gcc/testsuite/gcc.dg/pr70920-4.c
index e9c2b9587e5..70973cb162a 100644
--- a/gcc/testsuite/gcc.dg/pr70920-4.c
+++ b/gcc/testsuite/gcc.dg/pr70920-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-O2 -fdump-tree-forwprop-details -Wno-int-to-pointer-cast" } */
+/* { dg-options "-O2 -fdump-tree-ccp1 -Wno-int-to-pointer-cast" } */
#include <stdint.h>
@@ -19,4 +19,4 @@ foo (int a)
}
}
-/* { dg-final { scan-tree-dump "if \\(_\[0-9\]* == 0\\)" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "if \\(a_\[0-9\]*\\(D\\) == 0\\)" "ccp1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr81030.c b/gcc/testsuite/gcc.dg/pr81030.c
new file mode 100644
index 00000000000..23da6e528ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81030.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+void __assert_fail (const char *, const char *, unsigned int, const char *);
+
+int a, b, c, d, e, f, h;
+unsigned char g;
+
+int main ()
+{
+ int i, *j = &b;
+ if (a)
+ {
+ if (h)
+ {
+ int **k = &j;
+ d = 0;
+ *k = &e;
+ }
+ else
+ for (b = 0; b > -28; b = g)
+ ;
+ c || !j ? : __assert_fail ("c || !j", "small.c", 20, "main");
+ if (f)
+ for (i = 0; i < 1; i++)
+ ;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr81192.c b/gcc/testsuite/gcc.dg/pr81192.c
new file mode 100644
index 00000000000..57eb4781d4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81192.c
@@ -0,0 +1,22 @@
+/* { dg-options "-Os -fdump-tree-pre-details" } */
+
+unsigned a;
+int b, c;
+
+static int
+fn1 (int p1, int p2)
+{
+ return p1 > 2147483647 - p2 ? p1 : p1 + p2;
+}
+
+void
+fn2 (void)
+{
+ int j;
+ a = 30;
+ for (; a;)
+ for (; c; b = fn1 (j, 1))
+ ;
+}
+
+/* { dg-final { scan-tree-dump-times "(?n)find_duplicates: <bb .*> duplicate of <bb .*>" 1 "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr81227.c b/gcc/testsuite/gcc.dg/pr81227.c
new file mode 100644
index 00000000000..bdaa8cbab2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81227.c
@@ -0,0 +1,22 @@
+/* Copy of gcc.c-torture/compile/pr80443.c */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fwrapv" } */
+
+struct S { int a : 1; } b, c;
+signed char d, e, f;
+
+void
+foo ()
+{
+ while (f)
+ {
+ signed char g = b.a;
+ if (g)
+ b.a = ~(1 + (d || c.a));
+ if (b.a < g && b.a)
+ g = 0;
+ if (b.a > c.a)
+ b.a = g;
+ c.a = e;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr81292-1.c b/gcc/testsuite/gcc.dg/pr81292-1.c
new file mode 100644
index 00000000000..931e4c37c17
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81292-1.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+char a[10];
+
+int __attribute__ ((noinline, noclone))
+f1 (int n)
+{
+ a[0] = '1';
+ a[1] = '2';
+ return strlen (a + 1) < n ? strlen (a) : 100;
+}
+
+int __attribute__ ((noinline, noclone))
+f2 (char *a, int n)
+{
+ a[0] = '1';
+ a[1] = '2';
+ return strlen (a + 1) < n ? strlen (a) : 100;
+}
+
+int
+main (void)
+{
+ char b[10];
+ strcpy (a + 2, "345");
+ strcpy (b + 2, "34567");
+ if (f1 (100) != 5 || f2 (b, 100) != 7)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/pr81292-2.c b/gcc/testsuite/gcc.dg/pr81292-2.c
new file mode 100644
index 00000000000..c1c507f982e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81292-2.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+char a[] = { 0, 'a', 0, 'b', 'c', 0, 'd', 'e', 'f', 0 };
+
+int __attribute__ ((noinline, noclone))
+f1 (void)
+{
+ a[0] = '1';
+ a[strlen (a)] = '2';
+ a[strlen (a)] = '3';
+ return strlen (a);
+}
+
+int __attribute__ ((noinline, noclone))
+f2 (char *a)
+{
+ a[0] = '1';
+ a[strlen (a)] = '2';
+ a[strlen (a)] = '3';
+ return strlen (a);
+}
+
+int
+main (void)
+{
+ char b[] = { 0, 0, 'a', 'b', 0, 0 };
+ if (f1 () != 9 || f2 (b) != 5)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/pr81345.c b/gcc/testsuite/gcc.dg/pr81345.c
new file mode 100644
index 00000000000..c2cbad72967
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81345.c
@@ -0,0 +1,17 @@
+/* PR other/81345 - -Wall resets -Wstringop-overflow to 1 from the default 2
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+char a[3];
+
+void f (const char *s)
+{
+ __builtin_strncpy (a, s, sizeof a + 1); /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+struct S { char a[3]; int i; };
+
+void g (struct S *d, const char *s)
+{
+ __builtin_strncpy (d->a, s, sizeof d->a + 1); /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr81455.c b/gcc/testsuite/gcc.dg/pr81455.c
new file mode 100644
index 00000000000..8ab88639ee8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81455.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -funswitch-loops" } */
+
+void
+jh (unsigned int aw, int sn)
+{
+ int xs;
+
+ for (xs = 0; xs < 1; ++xs)
+ aw &= 1;
+
+ while (aw < 1 || ++sn < 1)
+ {
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr81564.c b/gcc/testsuite/gcc.dg/pr81564.c
new file mode 100644
index 00000000000..13519991f17
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81564.c
@@ -0,0 +1,21 @@
+/* PR middle-end/81564 ICE in group_case_labels_stmt(). */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct a {
+ int b;
+ int c;
+};
+
+void
+foo (void)
+{
+ struct a *e;
+ switch (e->c)
+ {
+ case 7:
+ case 3:
+ if (__builtin_expect(!0, 0))
+ __builtin_unreachable();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr81578.c b/gcc/testsuite/gcc.dg/pr81578.c
new file mode 100644
index 00000000000..a6ef77f20c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81578.c
@@ -0,0 +1,12 @@
+/* PR tree-optimization/81578 */
+/* { dg-do compile { target pthread } } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2" } */
+
+int
+foo (int *x)
+{
+ int i, r = 1;
+ for (i = 0; i != 1024; i++)
+ r *= x[i] < 0;
+ return r;
+}
diff --git a/gcc/testsuite/gcc.dg/predict-15.c b/gcc/testsuite/gcc.dg/predict-15.c
new file mode 100644
index 00000000000..2a8c3ea8597
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-15.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+int main(int argc, char **argv)
+{
+ if (argc == 123)
+ goto exit;
+ else
+ {
+ return 0;
+ }
+
+exit:
+ return 1;
+}
+
+/* { dg-final { scan-tree-dump "goto heuristics of edge" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-8.c b/gcc/testsuite/gcc.dg/predict-8.c
index edead8d90b1..e13cc006f3a 100644
--- a/gcc/testsuite/gcc.dg/predict-8.c
+++ b/gcc/testsuite/gcc.dg/predict-8.c
@@ -8,4 +8,4 @@ int foo(float a, float b) {
return 2;
}
-/* { dg-final { scan-rtl-dump-times "REG_BR_PROB 100" 1 "expand"} } */
+/* { dg-final { scan-rtl-dump-times "REG_BR_PROB 400 " 1 "expand"} } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-fields-2.c b/gcc/testsuite/gcc.dg/spellcheck-fields-2.c
index 7c542145b07..76684f71c80 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-fields-2.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-fields-2.c
@@ -28,7 +28,7 @@ int test_macro (union u *ptr)
/* { dg-begin-multiline-output "" }
#define FIELD colour
- ^
+ ^~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/gcc.dg/stack-layout-dynamic-1.c b/gcc/testsuite/gcc.dg/stack-layout-dynamic-1.c
index 9f2d37daa8b..7e59f28031a 100644
--- a/gcc/testsuite/gcc.dg/stack-layout-dynamic-1.c
+++ b/gcc/testsuite/gcc.dg/stack-layout-dynamic-1.c
@@ -1,15 +1,15 @@
-/* Verify that run time aligned local variables are aloocated in the prologue
+/* Verify that run time aligned local variables are allocated in the prologue
in one pass together with normal local variables. */
/* { dg-do compile } */
/* { dg-options "-O0 -fomit-frame-pointer" } */
/* { dg-require-effective-target ptr32plus } */
-extern void bar (void *, void *, void *);
+extern void bar (void *, void *, void *, void *, void *, void *, void *);
void foo (void)
{
- int i;
+ int i, j, k, l, m;
__attribute__ ((aligned(65536))) char runtime_aligned_1[512];
__attribute__ ((aligned(32768))) char runtime_aligned_2[1024];
- bar (&i, &runtime_aligned_1, &runtime_aligned_2);
+ bar (&i, &j, &k, &l, &m, &runtime_aligned_1, &runtime_aligned_2);
}
/* { dg-final { scan-assembler-not "cfi_def_cfa_register" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-31.c b/gcc/testsuite/gcc.dg/strlenopt-31.c
new file mode 100644
index 00000000000..bdd46ba0000
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-31.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "strlenopt.h"
+
+__attribute__((noinline, noclone)) int
+bar (char *p1, const char *q)
+{
+ strcpy (p1, "abcde");
+ char *p2 = strchr (p1, '\0');
+ strcpy (p2, q);
+ char *p3 = strchr (p2, '\0');
+ memcpy (p3, "x", 2);
+ return strlen (p1);
+}
+
+int
+main (void)
+{
+ char buffer[10];
+ int res = bar (buffer, "foo");
+ if (strcmp (buffer, "abcdefoox") != 0 || res != 9)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-31g.c b/gcc/testsuite/gcc.dg/strlenopt-31g.c
new file mode 100644
index 00000000000..45cc29c1024
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-31g.c
@@ -0,0 +1,9 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#define USE_GNU
+#include "strlenopt-31.c"
+
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
+/* { dg-final { scan-tree-dump-not "strlen \\(" "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-32.c b/gcc/testsuite/gcc.dg/strlenopt-32.c
new file mode 100644
index 00000000000..08eb6bc2b08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-32.c
@@ -0,0 +1,193 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+char temp[30];
+volatile int v;
+
+size_t __attribute__ ((noinline, noclone))
+f1 (void)
+{
+ char a[30];
+ v += 1;
+ memcpy (a, "1234567", 7);
+ memcpy (a + 7, "89abcdefg", 9);
+ memcpy (a + 16, "h", 2);
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f2 (char *a)
+{
+ v += 2;
+ memcpy (a, "1234567", 7);
+ memcpy (a + 7, "89abcdefg", 9);
+ memcpy (a + 16, "h", 2);
+ return strlen (a); // This strlen should be optimized into 17.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f3 (void)
+{
+ char a[30];
+ v += 3;
+ a[0] = '1';
+ memcpy (a + 1, "2345678", 8);
+ return strlen (a); // This strlen should be optimized into 8.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f4 (char *a)
+{
+ v += 4;
+ a[0] = '1';
+ memcpy (a + 1, "2345678", 8);
+ return strlen (a); // This strlen should be optimized into 8.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f5 (void)
+{
+ char a[30];
+ v += 5;
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ memcpy (a + 3, "456", 3);
+ a[6] = '7';
+ a[7] = 0;
+ return strlen (a); // This strlen should be optimized into 7.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f6 (char *a)
+{
+ v += 6;
+ a[0] = '1';
+ a[1] = '2';
+ a[2] = '3';
+ memcpy (a + 3, "456", 3);
+ a[6] = '7';
+ a[7] = 0;
+ return strlen (a); // This strlen should be optimized into 7.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f7 (void)
+{
+ char a[30];
+ v += 7;
+ strcpy (a, "abcde");
+ int len1 = strlen (a);
+ a[2] = '_';
+ int len2 = strlen (a);
+ return len1 + len2; // This should be optimized into 10.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f8 (char *a)
+{
+ v += 8;
+ strcpy (a, "abcde");
+ int len1 = strlen (a);
+ a[2] = '_';
+ int len2 = strlen (a);
+ return len1 + len2; // This should be optimized into 10.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f9 (char b)
+{
+ char a[30];
+ v += 9;
+ strcpy (a, "foo.bar");
+ a[4] = b;
+ a[3] = 0;
+ return strlen (a); // This should be optimized into 3.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f10 (char *a, char b)
+{
+ v += 10;
+ strcpy (a, "foo.bar");
+ a[4] = b;
+ a[3] = 0;
+ return strlen (a); // This should be optimized into 3.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f11 (void)
+{
+ char a[30];
+ v += 11;
+ strcpy (temp, "123456");
+ memcpy (a, temp, 7);
+ return strlen (a); // This should be optimized into 6.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f12 (char *a)
+{
+ v += 12;
+ strcpy (temp, "123456");
+ memcpy (a, temp, 7);
+ return strlen (a); // This should be optimized into 6.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f13 (void)
+{
+ char a[30];
+ v += 13;
+ strcpy (temp, "1234567");
+ memcpy (a, temp, 7);
+ a[7] = 0;
+ return strlen (a); // This should be optimized into 7.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f14 (char *a)
+{
+ v += 14;
+ strcpy (temp, "1234567");
+ memcpy (a, temp, 7);
+ a[7] = 0;
+ return strlen (a); // This should be optimized into 7.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f15 (void)
+{
+ char a[30];
+ v += 15;
+ strcpy (temp, "12345679");
+ memcpy (a, temp, 7);
+ a[7] = 0;
+ return strlen (a); // This should be optimized into 7.
+}
+
+size_t __attribute__ ((noinline, noclone))
+f16 (char *a)
+{
+ v += 16;
+ strcpy (temp, "123456789");
+ memcpy (a, temp, 7);
+ a[7] = 0;
+ return strlen (a); // This should be optimized into 7.
+}
+
+int
+main ()
+{
+ char a[30];
+ if (f1 () != 17 || f2 (a) != 17 || f3 () != 8 || f4 (a) != 8
+ || f5 () != 7 || f6 (a) != 7 || f7 () != 10 || f8 (a) != 10
+ || f9 ('_') != 3 || f10 (a, '_') != 3 || f11 () != 6 || f12 (a) != 6
+ || f13 () != 7 || f14 (a) != 7 || f15 () != 7 || f16 (a) != 7)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-33.c b/gcc/testsuite/gcc.dg/strlenopt-33.c
new file mode 100644
index 00000000000..1e1c4dee1f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-33.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+volatile int v;
+
+size_t __attribute__ ((noinline, noclone))
+f1 (char *b)
+{
+ char a[30];
+ v += 1;
+ strcpy (a, b);
+ // This needs to stay.
+ int len1 = strlen (a);
+ a[0] = '_';
+ a[1] = 0;
+ return len1 + strlen (a);
+}
+
+size_t __attribute__ ((noinline, noclone))
+f2 (char *a, char *b)
+{
+ v += 2;
+ strcpy (a, b);
+ // This needs to stay.
+ int len1 = strlen (a);
+ a[0] = '_';
+ a[1] = 0;
+ return len1 + strlen (a);
+}
+
+int
+main ()
+{
+ char a[30];
+ if (f1 ("foo") != 4 || f2 (a, "foobar") != 7)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-33g.c b/gcc/testsuite/gcc.dg/strlenopt-33g.c
new file mode 100644
index 00000000000..0223f82f1d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-33g.c
@@ -0,0 +1,45 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#define USE_GNU
+#include "strlenopt.h"
+
+volatile int v;
+
+size_t __attribute__ ((noinline, noclone))
+f1 (char *b)
+{
+ char a[30];
+ v += 1;
+ // Should be converted to stpcpy.
+ strcpy (a, b);
+ int len1 = strlen (a);
+ a[0] = '_';
+ a[1] = 0;
+ return len1 + strlen (a);
+}
+
+size_t __attribute__ ((noinline, noclone))
+f2 (char *a, char *b)
+{
+ v += 2;
+ // Should be converted to stpcpy.
+ strcpy (a, b);
+ int len1 = strlen (a);
+ a[0] = '_';
+ a[1] = 0;
+ return len1 + strlen (a);
+}
+
+int
+main ()
+{
+ char a[30];
+ if (f1 ("foo") != 4 || f2 (a, "foobar") != 7)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-34.c b/gcc/testsuite/gcc.dg/strlenopt-34.c
new file mode 100644
index 00000000000..c9433c0399e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-34.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+volatile int v;
+
+size_t __attribute__ ((noinline, noclone))
+f1 (char b)
+{
+ char a[30];
+ v += 1;
+ strcpy (a, "foo.bar");
+ a[3] = b;
+ a[4] = 0;
+ return strlen (a);
+}
+
+size_t __attribute__ ((noinline, noclone))
+f2 (char *a, char b)
+{
+ v += 2;
+ strcpy (a, "foo.bar");
+ a[3] = b;
+ a[4] = 0;
+ return strlen (a);
+}
+
+int
+main ()
+{
+ char a[30];
+ if (f1 ('_') != 4 || f1 (0) != 3 || f2 (a, '_') != 4 || f2 (a, 0) != 3)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-35.c b/gcc/testsuite/gcc.dg/strlenopt-35.c
new file mode 100644
index 00000000000..03b3e13a8e2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-35.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+volatile int v;
+
+size_t
+f1 (char *a1)
+{
+ v += 1;
+ size_t x = strlen (a1);
+ char *a2 = a1 + x;
+ a2[0] = '1';
+ a2[1] = '2';
+ a2[2] = '3';
+ a2[3] = 0;
+ return strlen (a1);
+}
+
+int
+main ()
+{
+ char a[30];
+ strcpy (a, "abcd");
+ if (f1 (a) != 7)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr70992-2.c b/gcc/testsuite/gcc.dg/torture/pr70992-2.c
new file mode 100644
index 00000000000..c5d2c5f2683
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr70992-2.c
@@ -0,0 +1,9 @@
+/* PR middle-end/70992 */
+/* { dg-do compile } */
+
+unsigned int *od;
+int
+fn (void)
+{
+ return (0 % 0 + 1) * *od * 2; /* { dg-warning "division by zero" } */
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr70992.c b/gcc/testsuite/gcc.dg/torture/pr70992.c
new file mode 100644
index 00000000000..56728e09d1b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr70992.c
@@ -0,0 +1,41 @@
+/* PR middle-end/70992 */
+/* { dg-do compile } */
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+uint32_t
+fn (uint32_t so)
+{
+ return (so + so) * (0x80000000 / 0 + 1); /* { dg-warning "division by zero" } */
+}
+
+uint32_t
+fn5 (uint32_t so)
+{
+ return (0x80000000 / 0 + 1) * (so + so); /* { dg-warning "division by zero" } */
+}
+
+uint32_t
+fn6 (uint32_t so)
+{
+ return (0x80000000 / 0 - 1) * (so + so); /* { dg-warning "division by zero" } */
+}
+
+uint32_t
+fn2 (uint32_t so)
+{
+ return (so + so) * (0x80000000 / 0 - 1); /* { dg-warning "division by zero" } */
+}
+
+int32_t
+fn3 (int32_t so)
+{
+ return (so + so) * (0x80000000 / 0 + 1); /* { dg-warning "division by zero" } */
+}
+
+int32_t
+fn4 (int32_t so)
+{
+ return (so + so) * (0x80000000 / 0 - 1); /* { dg-warning "division by zero" } */
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr80565.c b/gcc/testsuite/gcc.dg/torture/pr80565.c
new file mode 100644
index 00000000000..66620656e64
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr80565.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+int a, b, c, e, h, j;
+char d;
+short f, g;
+static short fn2(int p1) {
+ for (;;)
+ for (; g; g++)
+ if (p1)
+ break;
+}
+
+static short fn3(void);
+static char fn4(char p1) {
+ int i;
+ for (; d;)
+ f = 8;
+ for (; f; f = 0)
+ for (; i; i++) {
+ j = 0;
+ for (; j; j++)
+ ;
+ }
+}
+
+static short fn1(short p1) { fn2(b || fn3()); }
+
+short fn3(void) {
+ if (c) {
+ fn4(e);
+ h = 0;
+ for (;; h++)
+ ;
+ }
+}
+
+int main() {
+ for (; a;)
+ fn1(c);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr80620.c b/gcc/testsuite/gcc.dg/torture/pr80620.c
new file mode 100644
index 00000000000..ef56eedba5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr80620.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+long long int a = -465274079317386463LL;
+int b = 856872806;
+int c = -1940894202;
+int d = 1718449211;
+int e = -392681565;
+unsigned long long int f = 13521452247506316486ULL;
+int g = -13194608;
+
+__attribute__((noinline, noclone))
+void foo ()
+{
+ if (!a - a)
+ c = b = 0;
+ else
+ d = 3UL * a == 0;
+ if (g / a)
+ e = 0 < -a + 500849970701012771LL + (unsigned long) -a;
+ else
+ f = 4081116982543369LL & a;
+}
+
+int
+main ()
+{
+ asm volatile ("" : : : "memory");
+ foo ();
+ if (f != 2818598057803777LL)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81203.c b/gcc/testsuite/gcc.dg/torture/pr81203.c
new file mode 100644
index 00000000000..5c9eaf569e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81203.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+int a;
+int b()
+{
+ int c, d;
+ if (a)
+ d = b();
+ return 1 + c + d;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81245.c b/gcc/testsuite/gcc.dg/torture/pr81245.c
new file mode 100644
index 00000000000..b2ee7bb3a9b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81245.c
@@ -0,0 +1,16 @@
+/* { dg-options "-ffast-math" } */
+/* { dg-do compile } */
+/* This test used to crash the vectorizer as the ifconvert pass
+ used to convert the if to copysign but called update_stmt on
+ the old statement after calling fold_stmt. */
+double sg[18];
+void f(void)
+{
+ for (int i = 0 ;i < 18;i++)
+ {
+ if (sg[i] < 0.0)
+ sg[i] = -1.0;
+ else
+ sg[i] = 1.0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81403.c b/gcc/testsuite/gcc.dg/torture/pr81403.c
new file mode 100644
index 00000000000..5fca4d4d6b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81403.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+short var_9 = 19581;
+unsigned char var_33 = 21;
+long long int var_55 = 286697804684061197LL;
+long long int var_59 = -1962393262513510540LL;
+long long int var_71 = 4731868609112929952LL;
+long long int var_773 = -4784633456247777769LL;
+short var_776 = 5894;
+long long int var_1321 = 7573221950916697355LL;
+unsigned char uc = 217;
+
+void foo()
+{
+ if (var_55)
+ var_71 = 0;
+ if (var_9 != ~(0 < uc))
+ var_773 = 0;
+ else
+ var_776 = 1 / ~var_9 * -1;
+ if (var_33)
+ var_59 = ~var_9 & 10393;
+ var_1321 = ~var_9;
+}
+int main()
+{
+ foo();
+ if (var_59 != 8320)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81418.c b/gcc/testsuite/gcc.dg/torture/pr81418.c
new file mode 100644
index 00000000000..245861b7f3c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81418.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ftree-loop-optimize" } */
+
+int
+ol (int ku)
+{
+ int zq = 0;
+
+ while (ku < 1)
+ {
+ int y6;
+
+ for (y6 = 0; y6 < 3; ++y6)
+ zq += (char)ku;
+ ++ku;
+ }
+
+ return zq;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81500.c b/gcc/testsuite/gcc.dg/torture/pr81500.c
new file mode 100644
index 00000000000..7aaec2189fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81500.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+typedef int a;
+void c(int *b)
+{
+ int d;
+ a e, f, *g, *h = b;
+ for (; d; d--) {
+ f = *g & 1;
+ *h-- = *g-- | e;
+ e = f;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81510-2.c b/gcc/testsuite/gcc.dg/torture/pr81510-2.c
new file mode 100644
index 00000000000..7e2bc9866f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81510-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+typedef int h;
+typedef int k;
+int a;
+int b;
+int c;
+int d;
+int e;
+int f(int g)
+{
+ h *i = &e;
+ k *j;
+ if (d -= b)
+ for (; *j; *j += 1) {
+ g = g || (a = e ? c = (__UINTPTR_TYPE__)j : 0) + *i;
+ i = &d;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81510.c b/gcc/testsuite/gcc.dg/torture/pr81510.c
new file mode 100644
index 00000000000..c93c4683629
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81510.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-w" } */
+
+typedef int d;
+typedef int f;
+typedef long h;
+int a;
+int b;
+int c;
+int e()
+{
+ f *g;
+ h i;
+ for (;;)
+ if (g)
+ for (; b; b++) {
+ g = c;
+ if (a &= c) {
+ d *j = &b;
+ h k;
+ for (; i; i++) {
+ *g ?: (*j = k);
+ g = &a;
+ }
+ for (; i <= 3; i++)
+ ;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81571.c b/gcc/testsuite/gcc.dg/torture/pr81571.c
new file mode 100644
index 00000000000..74bceb763ea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81571.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+short fn1(int p1, int p2) { return p1; }
+
+int fn2(int p1) {}
+
+int main()
+{
+ for (; c; c++)
+ a |= fn1(1, a) | fn2(b |= d);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81573.c b/gcc/testsuite/gcc.dg/torture/pr81573.c
new file mode 100644
index 00000000000..3930c56386b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr81573.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+int a = 1, *c = &a, d;
+signed char b;
+
+int main ()
+{
+ for (; b > -27; b--)
+ {
+ *c ^= b;
+ *c ^= 1;
+ }
+ while (a > 1)
+ ;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-profiler-threads-1.c b/gcc/testsuite/gcc.dg/tree-prof/val-profiler-threads-1.c
index 95d6ee3b4a3..830232a7ffa 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-profiler-threads-1.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-profiler-threads-1.c
@@ -35,9 +35,9 @@ int main(int argc, char *argv[])
}
}
- int retval;
+ void *retval;
for(t=0;t<NUM_THREADS;t++)
- pthread_join (threads[t], (void**)&retval);
+ pthread_join (threads[t], &retval);
return buffer[10];
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/addadd.c b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c
index 16474db6565..454ec2a570d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/addadd.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c
@@ -23,11 +23,6 @@ int i(int x){
x += __INT_MAX__;
return x;
}
-typedef int S __attribute__((vector_size(16)));
-void j(S*x){
- *x += __INT_MAX__;
- *x += __INT_MAX__;
-}
/* { dg-final { scan-tree-dump-times " \\+ 24;" 2 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assoc-1.c b/gcc/testsuite/gcc.dg/tree-ssa/assoc-1.c
new file mode 100644
index 00000000000..f9821910bd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/assoc-1.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw -fno-tree-reassoc" } */
+
+int f0(int a,int b,int c){
+ int d = a + b;
+ int e = c + b;
+ return d - e;
+}
+int f1(int a,int b,int c){
+ int d = a + b;
+ int e = b - c;
+ return d - e;
+}
+int f2(int a,int b,int c){
+ int d = a + b;
+ int e = c - b;
+ return e + d;
+}
+int f3(int a,int b,int c){
+ int d = a - b;
+ int e = c - b;
+ return d - e;
+}
+int f4(int a,int b,int c){
+ int d = b - a;
+ int e = c - b;
+ return e + d;
+}
+
+/* { dg-final { scan-tree-dump-times "plus_expr" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "minus_expr" 3 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c b/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c
new file mode 100644
index 00000000000..cc0e9d429b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/assoc-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-gimple-raw -fdump-tree-optimized-raw" } */
+
+int f0(int a, int b){
+ return a * 33 * b * 55;
+}
+
+int f1(int a){
+ a *= 33;
+ return a * 55;
+}
+
+int f2(int a, int b){
+ a *= 33;
+ return a * b * 55;
+}
+
+/* { dg-final { scan-tree-dump-times "mult_expr" 7 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "mult_expr" 5 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
index 184dd10ddae..17526113d4b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
@@ -1,8 +1,7 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-profile_estimate-blocks-details" } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
-void g(void);
-void h(void);
+int v1, v2;
void f(int x, int y)
{
if (x) goto A;
@@ -10,19 +9,19 @@ void f(int x, int y)
return;
A: __attribute__((cold))
- g();
+ v1 = x;
return;
B: __attribute__((hot))
- h();
+ v2 = y;
return;
}
/* { dg-final { scan-tree-dump-times "hot label heuristics" 1 "profile_estimate" } } */
/* { dg-final { scan-tree-dump-times "cold label heuristics" 1 "profile_estimate" } } */
-/* { dg-final { scan-tree-dump "A \\\[0\\\..*\\\]" "profile_estimate" } } */
+/* { dg-final { scan-tree-dump-times "combined heuristics: 0\\\..*" 1 "profile_estimate" } } */
/* Note: we're attempting to match some number > 6000, i.e. > 60%.
The exact number ought to be tweekable without having to juggle
the testcase around too much. */
-/* { dg-final { scan-tree-dump "B \\\[\[6-9\]\[0-9\]\\\..*\\\]" "profile_estimate" } } */
+/* { dg-final { scan-tree-dump-times "combined heuristics: \[6-9\]\[0-9\]\\\..*" 1 "profile_estimate" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-19.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-19.c
new file mode 100644
index 00000000000..e0439384dd7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-19.c
@@ -0,0 +1,62 @@
+/* PR tree-optimization/80397 - missing -Wformat-overflow with arguments
+ of enum types
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
+ { dg-require-effective-target int32plus } */
+
+void sink (char*);
+
+long long integer_range (long long min, long long max)
+{
+ extern long long integer_value (void);
+ long long n = integer_value ();
+ return n < min || max < n ? min : n;
+}
+
+typedef enum { i0, imax = __INT_MAX__ } Int;
+typedef enum { ll0, llmax = __LONG_LONG_MAX__ } LLong;
+
+#define R(T, min, max) (T)integer_range (min, max)
+
+char buffer[1];
+#define T(fmt, ...) \
+ __builtin_sprintf (buffer + 1, fmt, __VA_ARGS__), sink (buffer)
+
+void test_bool (_Bool b)
+{
+ T ("%hhi", b); // { dg-warning "writing 1 byte" }
+ T ( "%hi", b); // { dg-warning "writing 1 byte" }
+ T ( "%i", b); // { dg-warning "writing 1 byte" }
+}
+
+void test_enum (void)
+{
+ T ("%hhi", R (Int, 1, 1)); // { dg-warning "writing 1 byte" }
+ T ("%hhi", R (Int, 1, 22)); // { dg-warning "between 1 and 2 bytes" }
+
+ T ( "%hi", R (Int, 1, 2)); // { dg-warning "writing 1 " }
+ T ( "%hi", R (Int, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T ( "%hi", R (Int, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T ( "%hi", R (Int, 333, 4444)); // { dg-warning "between 3 and 4 " }
+
+ T ( "%i", R (Int, 1, 1)); // { dg-warning "writing 1 " }
+ T ( "%i", R (Int, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T ( "%i", R (Int, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T ( "%i", R (Int, 333, 4444)); // { dg-warning "between 3 and 4 " }
+ T ( "%i", R (Int, 4444, 55555)); // { dg-warning "between 4 and 5 " }
+
+#if __LONG_MAX__ == __LONG_LONG_MAX__
+# define LLI "%li"
+#else
+# define LLI "%lli"
+#endif
+
+ T (LLI, R (LLong, 1, 1)); // { dg-warning "writing 1 " }
+ T (LLI, R (LLong, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T (LLI, R (LLong, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T (LLI, R (LLong, 333, 4444)); // { dg-warning "between 3 and 4 " }
+ T (LLI, R (LLong, 4444, 55555)); // { dg-warning "between 4 and 5 " }
+
+ T (LLI, R (LLong, 4444, 1234567890)); // { dg-warning "between 4 and 10 " }
+ T (LLI, R (LLong, 4444, 12345678901)); // { dg-warning "between 4 and 11 " }
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c
new file mode 100644
index 00000000000..de3e7b242ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target c99_runtime } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-gimple" } */
+/* { dg-add-options c99_runtime } */
+float f(float x)
+{
+ return (x > 0.f ? -1.f : 1.f);
+}
+float f1(float x)
+{
+ return (x > 0.f ? 1.f : -1.f);
+}
+float g(float x)
+{
+ return (x >= 0.f ? -1.f : 1.f);
+}
+float g1(float x)
+{
+ return (x >= 0.f ? 1.f : -1.f);
+}
+float h(float x)
+{
+ return (x < 0.f ? -1.f : 1.f);
+}
+float h1(float x)
+{
+ return (x < 0.f ? 1.f : -1.f);
+}
+float i(float x)
+{
+ return (x <= 0.f ? -1.f : 1.f);
+}
+float i1(float x)
+{
+ return (x <= 0.f ? 1.f : -1.f);
+}
+/* { dg-final { scan-tree-dump-times "copysign" 8 "gimple"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-2.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-2.c
new file mode 100644
index 00000000000..de52c5f7c80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-2.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -ffast-math -fdump-tree-optimized" } */
+/* { dg-do compile } */
+float f(float x)
+{
+ float t = __builtin_copysignf (1.0f, x);
+ return x * t;
+}
+float f1(float x)
+{
+ float t = __builtin_copysignf (1.0f, -x);
+ return x * t;
+}
+/* { dg-final { scan-tree-dump-times "ABS" 2 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c
index 53551cabd1e..625dd92128e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c
@@ -18,4 +18,5 @@ int foo (int * __restrict__ ia,
return oya[22] + oyb[21];
}
-/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */
+/* Distributing the loop doesn't expose more parallelism. */
+/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c
index ba39d4dfce7..8c9fd567e1e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c
@@ -16,6 +16,5 @@ float foo (int n)
return tmp;
}
-/* We should apply loop distribution. */
-
-/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */
+/* Distributing the loop doesn't expose more parallelism. */
+/* { dg-final { scan-tree-dump-not "Loop 1 distributed: split to 2 loops" "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c
index 48c1040f4b3..fa4d1a82879 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c
@@ -21,6 +21,5 @@ float foo (int n)
return tmp;
}
-/* We should apply loop distribution. */
-
-/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */
+/* Distributing the loop doesn't expose more parallelism. */
+/* { dg-final { scan-tree-dump-not "Loop 1 distributed: split to 2 loops" "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c
new file mode 100644
index 00000000000..3a698846c89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+
+extern void abort (void);
+
+int a[130], b[128], c[128];
+
+int __attribute__((noinline,noclone))
+foo (int len, int x)
+{
+ int i;
+ for (i = 1; i <= len; ++i)
+ {
+ a[i] = a[i + 2] + 1;
+ b[i] = 0;
+ a[i + 1] = a[i] - 3;
+ if (i < x)
+ c[i] = a[i];
+ }
+ return i;
+}
+
+int main()
+{
+ int i;
+ for (i = 0; i < 130; ++i)
+ a[i] = i;
+ foo (127, 67);
+ if (a[0] != 0 || a[1] != 4 || a[127] != 130)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "distributed: split to 2 loops and 0 library calls" "ldist" } } */
+/* { dg-final { scan-tree-dump "distributed: split to 1 loops and 1 library calls" "ldist" } } */
+/* { dg-final { scan-tree-dump "generated memset zero" "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c
index c36daf0714b..4def9b4719d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c
@@ -20,7 +20,5 @@ int loop1 (int k)
return b[100-1][1];
}
-/* The current cost model fuses the two partitions because they have
- similar memory accesses. */
-/* { dg-final { scan-tree-dump "similar memory accesses" "ldist" } } */
+/* Distributing inner loop doesn't expose more parallelism. */
/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c
index 8eb1c628837..e0a68d87f7f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c
@@ -34,4 +34,4 @@ int loop1 (int k)
return a[1000-2] + b[1000-1] + c[1000-2] + d[1000-2];
}
-/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/mulcmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/mulcmp-1.c
new file mode 100644
index 00000000000..6ff2ff5a388
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/mulcmp-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int f(unsigned a,unsigned b){
+ a *= 3;
+ b *= 3;
+ return a == b;
+}
+
+/* { dg-final { scan-tree-dump-not "mult_expr" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/mult-abs-2.c b/gcc/testsuite/gcc.dg/tree-ssa/mult-abs-2.c
new file mode 100644
index 00000000000..d74ba2fe630
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/mult-abs-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target c99_runtime } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-gimple" } */
+/* { dg-add-options c99_runtime } */
+
+float f(float x)
+{
+ return x * (x > 0.f ? -1.f : 1.f);
+}
+float f1(float x)
+{
+ return x * (x > 0.f ? 1.f : -1.f);
+}
+float g(float x)
+{
+ return x * (x >= 0.f ? -1.f : 1.f);
+}
+float g1(float x)
+{
+ return x * (x >= 0.f ? 1.f : -1.f);
+}
+float h(float x)
+{
+ return x * (x < 0.f ? -1.f : 1.f);
+}
+float h1(float x)
+{
+ return x * (x < 0.f ? 1.f : -1.f);
+}
+float i(float x)
+{
+ return x * (x <= 0.f ? -1.f : 1.f);
+}
+float i1(float x)
+{
+ return x * (x <= 0.f ? 1.f : -1.f);
+}
+/* { dg-final { scan-tree-dump-times "ABS" 8 "gimple"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
index 3c8ee06016f..0fa5600177e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
@@ -1,15 +1,15 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Wunsafe-loop-optimizations" } */
+/* { dg-options "-O2 -fopt-info-loop-missed -Wunsafe-loop-optimizations" } */
extern void g(void);
void
f (unsigned n)
{
unsigned k;
- for(k = 0;k <= n;k++) /* { dg-warning "missed loop optimization.*overflow" } */
+ for(k = 0;k <= n;k++) /* { dg-message "note: missed loop optimization: niters analysis .*" } */
g();
- for(k = 0;k <= n;k += 4) /* { dg-warning "missed loop optimization.*overflow" } */
+ for(k = 0;k <= n;k += 4) /* { dg-message "note: missed loop optimization: niters analysis .*" } */
g();
/* We used to get warning for this loop. However, since then # of iterations
@@ -21,9 +21,9 @@ f (unsigned n)
g();
/* So we need the following loop, instead. */
- for(k = 4;k <= n;k += 5) /* { dg-warning "missed loop optimization.*overflow" } */
+ for(k = 4;k <= n;k += 5) /* { dg-message "note: missed loop optimization: niters analysis .*" } */
g();
- for(k = 15;k >= n;k--) /* { dg-warning "missed loop optimization.*overflow" } */
+ for(k = 15;k >= n;k--) /* { dg-message "note: missed loop optimization: niters analysis .*" } */
g();
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81346-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-1.c
new file mode 100644
index 00000000000..c766d6ff996
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-1.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/81346 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 32 "optimized" } } */
+
+int f00 (int x) { return x / 49152 > -49152; }
+int f01 (int x) { int a = 49152, b = -49152; return x / a > b; }
+int f02 (int x) { return x / 49152 >= -49152; }
+int f03 (int x) { int a = 49152, b = -49152; return x / a >= b; }
+int f04 (int x) { return x / 49152 < 49152; }
+int f05 (int x) { int a = 49152, b = 49152; return x / a < b; }
+int f06 (int x) { return x / 49152 <= 49152; }
+int f07 (int x) { int a = 49152, b = 49152; return x / a <= b; }
+int f08 (int x) { return x / 46340 >= -46341; }
+int f09 (int x) { int a = 46340, b = -46341; return x / a >= b; }
+int f10 (int x) { return x / 46340 <= 46341; }
+int f11 (int x) { int a = 46340, b = 46341; return x / a <= b; }
+int f12 (int x) { return x / 49152 != -49152; }
+int f13 (int x) { int a = 49152, b = -49152; return x / a != b; }
+int f14 (int x) { return x / 49152 != 49152; }
+int f15 (int x) { int a = 49152, b = 49152; return x / a != b; }
+int f16 (int x) { return x / -49152 > -49152; }
+int f17 (int x) { int a = -49152, b = -49152; return x / a > b; }
+int f18 (int x) { return x / -49152 >= -49152; }
+int f19 (int x) { int a = -49152, b = -49152; return x / a >= b; }
+int f20 (int x) { return x / -49152 < 49152; }
+int f21 (int x) { int a = -49152, b = 49152; return x / a < b; }
+int f22 (int x) { return x / -49152 <= 49152; }
+int f23 (int x) { int a = -49152, b = 49152; return x / a <= b; }
+int f24 (int x) { return x / -46340 >= -46341; }
+int f25 (int x) { int a = -46340, b = -46341; return x / a >= b; }
+int f26 (int x) { return x / -46340 <= 46341; }
+int f27 (int x) { int a = -46340, b = 46341; return x / a <= b; }
+int f28 (int x) { return x / -49152 != 49152; }
+int f29 (int x) { int a = -49152, b = 49152; return x / a != b; }
+int f30 (int x) { return x / -49152 != -49152; }
+int f31 (int x) { int a = -49152, b = -49152; return x / a != b; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81346-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-2.c
new file mode 100644
index 00000000000..87bad395c3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-2.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/81346 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 0;" 32 "optimized" } } */
+
+int f00 (int x) { return x / 49152 > 49152; }
+int f01 (int x) { int a = 49152, b = 49152; return x / a > b; }
+int f02 (int x) { return x / 49152 >= 49152; }
+int f03 (int x) { int a = 49152, b = 49152; return x / a >= b; }
+int f04 (int x) { return x / 49152 < -49152; }
+int f05 (int x) { int a = 49152, b = -49152; return x / a < b; }
+int f06 (int x) { return x / 49152 <= -49152; }
+int f07 (int x) { int a = 49152, b = -49152; return x / a <= b; }
+int f08 (int x) { return x / 46340 > 46341; }
+int f09 (int x) { int a = 46340, b = 46341; return x / a > b; }
+int f10 (int x) { return x / 46340 < -46341; }
+int f11 (int x) { int a = 46340, b = -46341; return x / a < b; }
+int f12 (int x) { return x / 49152 == -49152; }
+int f13 (int x) { int a = 49152, b = -49152; return x / a == b; }
+int f14 (int x) { return x / 49152 == 49152; }
+int f15 (int x) { int a = 49152, b = 49152; return x / a == b; }
+int f16 (int x) { return x / -49152 > 49152; }
+int f17 (int x) { int a = -49152, b = 49152; return x / a > b; }
+int f18 (int x) { return x / -49152 >= 49152; }
+int f19 (int x) { int a = -49152, b = 49152; return x / a >= b; }
+int f20 (int x) { return x / -49152 < -49152; }
+int f21 (int x) { int a = -49152, b = -49152; return x / a < b; }
+int f22 (int x) { return x / -49152 <= -49152; }
+int f23 (int x) { int a = -49152, b = -49152; return x / a <= b; }
+int f24 (int x) { return x / -46340 > 46341; }
+int f25 (int x) { int a = -46340, b = 46341; return x / a > b; }
+int f26 (int x) { return x / -46340 < -46341; }
+int f27 (int x) { int a = -46340, b = -46341; return x / a < b; }
+int f28 (int x) { return x / -49152 == 49152; }
+int f29 (int x) { int a = -49152, b = 49152; return x / a == b; }
+int f30 (int x) { return x / -49152 == -49152; }
+int f31 (int x) { int a = -49152, b = -49152; return x / a == b; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81346-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-3.c
new file mode 100644
index 00000000000..bef64a8746a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-3.c
@@ -0,0 +1,109 @@
+/* PR tree-optimization/81346 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+
+__attribute__((noinline, noclone)) int f00 (int x) { return x / 46340 > -46341; }
+__attribute__((noinline, noclone)) int f01 (int x) { int a = 46340, b = -46341; return x / a > b; }
+__attribute__((noinline, noclone)) int f02 (int x) { return x / 46340 >= 46341; }
+__attribute__((noinline, noclone)) int f03 (int x) { int a = 46340, b = 46341; return x / a >= b; }
+__attribute__((noinline, noclone)) int f04 (int x) { return x / 46340 < 46341; }
+__attribute__((noinline, noclone)) int f05 (int x) { int a = 46340, b = 46341; return x / a < b; }
+__attribute__((noinline, noclone)) int f06 (int x) { return x / 46340 <= -46341; }
+__attribute__((noinline, noclone)) int f07 (int x) { int a = 46340, b = -46341; return x / a <= b; }
+__attribute__((noinline, noclone)) int f08 (int x) { return x / 46340 == -46341; }
+__attribute__((noinline, noclone)) int f09 (int x) { int a = 46340, b = -46341; return x / a == b; }
+__attribute__((noinline, noclone)) int f10 (int x) { return x / 46340 == 46341; }
+__attribute__((noinline, noclone)) int f11 (int x) { int a = 46340, b = 46341; return x / a == b; }
+__attribute__((noinline, noclone)) int f12 (int x) { return x / 46340 != -46341; }
+__attribute__((noinline, noclone)) int f13 (int x) { int a = 46340, b = -46341; return x / a != b; }
+__attribute__((noinline, noclone)) int f14 (int x) { return x / 46340 != 46341; }
+__attribute__((noinline, noclone)) int f15 (int x) { int a = 46340, b = 46341; return x / a != b; }
+__attribute__((noinline, noclone)) int f16 (int x) { return x / 15 > -15; }
+__attribute__((noinline, noclone)) int f17 (int x) { int a = 15, b = -15; return x / a > b; }
+__attribute__((noinline, noclone)) int f18 (int x) { return x / 15 > 15; }
+__attribute__((noinline, noclone)) int f19 (int x) { int a = 15, b = 15; return x / a > b; }
+__attribute__((noinline, noclone)) int f20 (int x) { return x / 15 >= -15; }
+__attribute__((noinline, noclone)) int f21 (int x) { int a = 15, b = -15; return x / a >= b; }
+__attribute__((noinline, noclone)) int f22 (int x) { return x / 15 >= 15; }
+__attribute__((noinline, noclone)) int f23 (int x) { int a = 15, b = 15; return x / a >= b; }
+__attribute__((noinline, noclone)) int f24 (int x) { return x / 15 < -15; }
+__attribute__((noinline, noclone)) int f25 (int x) { int a = 15, b = -15; return x / a < b; }
+__attribute__((noinline, noclone)) int f26 (int x) { return x / 15 < 15; }
+__attribute__((noinline, noclone)) int f27 (int x) { int a = 15, b = 15; return x / a < b; }
+__attribute__((noinline, noclone)) int f28 (int x) { return x / 15 <= -15; }
+__attribute__((noinline, noclone)) int f29 (int x) { int a = 15, b = -15; return x / a <= b; }
+__attribute__((noinline, noclone)) int f30 (int x) { return x / 15 <= 15; }
+__attribute__((noinline, noclone)) int f31 (int x) { int a = 15, b = 15; return x / a <= b; }
+__attribute__((noinline, noclone)) int f32 (int x) { return x / 15 == -15; }
+__attribute__((noinline, noclone)) int f33 (int x) { int a = 15, b = -15; return x / a == b; }
+__attribute__((noinline, noclone)) int f34 (int x) { return x / 15 == 15; }
+__attribute__((noinline, noclone)) int f35 (int x) { int a = 15, b = 15; return x / a == b; }
+__attribute__((noinline, noclone)) int f36 (int x) { return x / 15 != -15; }
+__attribute__((noinline, noclone)) int f37 (int x) { int a = 15, b = -15; return x / a != b; }
+__attribute__((noinline, noclone)) int f38 (int x) { return x / 15 != 15; }
+__attribute__((noinline, noclone)) int f39 (int x) { int a = 15, b = 15; return x / a != b; }
+__attribute__((noinline, noclone)) int f40 (int x) { return x / -46340 > -46341; }
+__attribute__((noinline, noclone)) int f41 (int x) { int a = -46340, b = -46341; return x / a > b; }
+__attribute__((noinline, noclone)) int f42 (int x) { return x / -46340 >= 46341; }
+__attribute__((noinline, noclone)) int f43 (int x) { int a = -46340, b = 46341; return x / a >= b; }
+__attribute__((noinline, noclone)) int f44 (int x) { return x / -46340 < 46341; }
+__attribute__((noinline, noclone)) int f45 (int x) { int a = -46340, b = 46341; return x / a < b; }
+__attribute__((noinline, noclone)) int f46 (int x) { return x / -46340 <= -46341; }
+__attribute__((noinline, noclone)) int f47 (int x) { int a = -46340, b = -46341; return x / a <= b; }
+__attribute__((noinline, noclone)) int f48 (int x) { return x / -46340 == 46341; }
+__attribute__((noinline, noclone)) int f49 (int x) { int a = -46340, b = 46341; return x / a == b; }
+__attribute__((noinline, noclone)) int f50 (int x) { return x / -46340 == -46341; }
+__attribute__((noinline, noclone)) int f51 (int x) { int a = -46340, b = -46341; return x / a == b; }
+__attribute__((noinline, noclone)) int f52 (int x) { return x / -46340 != 46341; }
+__attribute__((noinline, noclone)) int f53 (int x) { int a = -46340, b = 46341; return x / a != b; }
+__attribute__((noinline, noclone)) int f54 (int x) { return x / -46340 != -46341; }
+__attribute__((noinline, noclone)) int f55 (int x) { int a = -46340, b = -46341; return x / a != b; }
+__attribute__((noinline, noclone)) int f56 (int x) { return x / -15 > 15; }
+__attribute__((noinline, noclone)) int f57 (int x) { int a = -15, b = 15; return x / a > b; }
+__attribute__((noinline, noclone)) int f58 (int x) { return x / -15 > -15; }
+__attribute__((noinline, noclone)) int f59 (int x) { int a = -15, b = -15; return x / a > b; }
+__attribute__((noinline, noclone)) int f60 (int x) { return x / -15 >= 15; }
+__attribute__((noinline, noclone)) int f61 (int x) { int a = -15, b = 15; return x / a >= b; }
+__attribute__((noinline, noclone)) int f62 (int x) { return x / -15 >= -15; }
+__attribute__((noinline, noclone)) int f63 (int x) { int a = -15, b = -15; return x / a >= b; }
+__attribute__((noinline, noclone)) int f64 (int x) { return x / -15 < 15; }
+__attribute__((noinline, noclone)) int f65 (int x) { int a = -15, b = 15; return x / a < b; }
+__attribute__((noinline, noclone)) int f66 (int x) { return x / -15 < -15; }
+__attribute__((noinline, noclone)) int f67 (int x) { int a = -15, b = -15; return x / a < b; }
+__attribute__((noinline, noclone)) int f68 (int x) { return x / -15 <= 15; }
+__attribute__((noinline, noclone)) int f69 (int x) { int a = -15, b = 15; return x / a <= b; }
+__attribute__((noinline, noclone)) int f70 (int x) { return x / -15 <= -15; }
+__attribute__((noinline, noclone)) int f71 (int x) { int a = -15, b = -15; return x / a <= b; }
+__attribute__((noinline, noclone)) int f72 (int x) { return x / -15 == 15; }
+__attribute__((noinline, noclone)) int f73 (int x) { int a = -15, b = 15; return x / a == b; }
+__attribute__((noinline, noclone)) int f74 (int x) { return x / -15 == -15; }
+__attribute__((noinline, noclone)) int f75 (int x) { int a = -15, b = -15; return x / a == b; }
+__attribute__((noinline, noclone)) int f76 (int x) { return x / -15 != 15; }
+__attribute__((noinline, noclone)) int f77 (int x) { int a = -15, b = 15; return x / a != b; }
+__attribute__((noinline, noclone)) int f78 (int x) { return x / -15 != -15; }
+__attribute__((noinline, noclone)) int f79 (int x) { int a = -15, b = -15; return x / a != b; }
+__attribute__((noinline, noclone)) int f80 (int x) { return x / -15 > 0; }
+__attribute__((noinline, noclone)) int f81 (int x) { int a = -15, b = 0; return x / a > b; }
+__attribute__((noinline, noclone)) int f82 (int x) { return x / 15 > 0; }
+__attribute__((noinline, noclone)) int f83 (int x) { int a = 15, b = 0; return x / a > b; }
+__attribute__((noinline, noclone)) int f84 (int x) { return x / -15 >= 0; }
+__attribute__((noinline, noclone)) int f85 (int x) { int a = -15, b = 0; return x / a >= b; }
+__attribute__((noinline, noclone)) int f86 (int x) { return x / 15 >= 0; }
+__attribute__((noinline, noclone)) int f87 (int x) { int a = 15, b = 0; return x / a >= b; }
+__attribute__((noinline, noclone)) int f88 (int x) { return x / -15 < 0; }
+__attribute__((noinline, noclone)) int f89 (int x) { int a = -15, b = 0; return x / a < b; }
+__attribute__((noinline, noclone)) int f90 (int x) { return x / 15 < 0; }
+__attribute__((noinline, noclone)) int f91 (int x) { int a = 15, b = 0; return x / a < b; }
+__attribute__((noinline, noclone)) int f92 (int x) { return x / -15 <= 0; }
+__attribute__((noinline, noclone)) int f93 (int x) { int a = -15, b = 0; return x / a <= b; }
+__attribute__((noinline, noclone)) int f94 (int x) { return x / 15 <= 0; }
+__attribute__((noinline, noclone)) int f95 (int x) { int a = 15, b = 0; return x / a <= b; }
+__attribute__((noinline, noclone)) int f96 (int x) { return x / -15 == 0; }
+__attribute__((noinline, noclone)) int f97 (int x) { int a = -15, b = 0; return x / a == b; }
+__attribute__((noinline, noclone)) int f98 (int x) { return x / 15 == 0; }
+__attribute__((noinline, noclone)) int f99 (int x) { int a = 15, b = 0; return x / a == b; }
+__attribute__((noinline, noclone)) int f100 (int x) { return x / -15 != 0; }
+__attribute__((noinline, noclone)) int f101 (int x) { int a = -15, b = 0; return x / a != b; }
+__attribute__((noinline, noclone)) int f102 (int x) { return x / 15 != 0; }
+__attribute__((noinline, noclone)) int f103 (int x) { int a = 15, b = 0; return x / a != b; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81346-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-4.c
new file mode 100644
index 00000000000..f93ad468c3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-4.c
@@ -0,0 +1,79 @@
+/* PR tree-optimization/81346 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "pr81346-3.c"
+
+#define INT_MAX __INT_MAX__
+#define INT_MIN (-__INT_MAX__ - 1)
+
+extern void abort (void);
+
+int
+main ()
+{
+ if (__CHAR_BIT__ != 8 || __SIZEOF_INT__ != 4)
+ return 0;
+#define TEST(fn1, fn2, v1, v2) \
+ do { \
+ int w1 = v1; int w2 = v2; \
+ int in = 1; if (w1 > w2) { in = w1; w1 = w2; w2 = in; in = 0; } \
+ if (w1 != INT_MIN) { if (fn1 (w1 - 1) != !in || fn2 (w1 - 1) != !in) abort (); } \
+ if (fn1 (w1) != in || fn2 (w1) != in) abort (); \
+ if (fn1 (w2) != in || fn2 (w2) != in) abort (); \
+ if (w2 != INT_MAX) { if (fn1 (w2 + 1) != !in || fn2 (w2 + 1) != !in) abort (); } \
+ } while (0)
+TEST (f00, f01, -2147441939, INT_MAX);
+TEST (f02, f03, 2147441940, INT_MAX);
+TEST (f04, f05, INT_MIN, 2147441939);
+TEST (f06, f07, INT_MIN, -2147441940);
+TEST (f08, f09, INT_MIN, -2147441940);
+TEST (f10, f11, 2147441940, INT_MAX);
+TEST (f12, f13, -2147441939, INT_MAX);
+TEST (f14, f15, INT_MIN, 2147441939);
+TEST (f16, f17, -224, INT_MAX);
+TEST (f18, f19, 240, INT_MAX);
+TEST (f20, f21, -239, INT_MAX);
+TEST (f22, f23, 225, INT_MAX);
+TEST (f24, f25, INT_MIN, -240);
+TEST (f26, f27, INT_MIN, 224);
+TEST (f28, f29, INT_MIN, -225);
+TEST (f30, f31, INT_MIN, 239);
+TEST (f32, f33, -239, -225);
+TEST (f34, f35, 225, 239);
+TEST (f36, f37, -225, -239);
+TEST (f38, f39, 239, 225);
+TEST (f40, f41, INT_MIN, 2147441939);
+TEST (f42, f43, INT_MIN, -2147441940);
+TEST (f44, f45, -2147441939, INT_MAX);
+TEST (f46, f47, 2147441940, INT_MAX);
+TEST (f48, f49, INT_MIN, -2147441940);
+TEST (f50, f51, 2147441940, INT_MAX);
+TEST (f52, f53, -2147441939, INT_MAX);
+TEST (f54, f55, INT_MIN, 2147441939);
+TEST (f56, f57, INT_MIN, -240);
+TEST (f58, f59, INT_MIN, 224);
+TEST (f60, f61, INT_MIN, -225);
+TEST (f62, f63, INT_MIN, 239);
+TEST (f64, f65, -224, INT_MAX);
+TEST (f66, f67, 240, INT_MAX);
+TEST (f68, f69, -239, INT_MAX);
+TEST (f70, f71, 225, INT_MAX);
+TEST (f72, f73, -239, -225);
+TEST (f74, f75, 225, 239);
+TEST (f76, f77, -225, -239);
+TEST (f78, f79, 239, 225);
+TEST (f80, f81, INT_MIN, -15);
+TEST (f82, f83, 15, INT_MAX);
+TEST (f84, f85, INT_MIN, 14);
+TEST (f86, f87, -14, INT_MAX);
+TEST (f88, f89, 15, INT_MAX);
+TEST (f90, f91, INT_MIN, -15);
+TEST (f92, f93, -14, INT_MAX);
+TEST (f94, f95, INT_MIN, 14);
+TEST (f96, f97, -14, 14);
+TEST (f98, f99, -14, 14);
+TEST (f100, f101, 14, -14);
+TEST (f102, f103, 14, -14);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c
new file mode 100644
index 00000000000..14562a11152
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81346-5.c
@@ -0,0 +1,17 @@
+/* PR tree-optimization/81346 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\\(signed int\\) x" 10 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= 0;" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " > 0;" 5 "optimized" } } */
+
+int f1 (unsigned x) { return x - 1 <= __INT_MAX__ - 1; }
+int f2 (unsigned x) { unsigned a = 1, b = __INT_MAX__ - 1; return x - a <= b; }
+int f3 (unsigned x) { return x - 1 < __INT_MAX__; }
+int f4 (unsigned x) { unsigned a = 1, b = __INT_MAX__; return x - a < b; }
+int f5 (unsigned x) { return x >= 1 && x <= __INT_MAX__; }
+int f6 (unsigned x) { return x - 1 > __INT_MAX__ - 1; }
+int f7 (unsigned x) { unsigned a = 1, b = __INT_MAX__ - 1; return x - a > b; }
+int f8 (unsigned x) { return x - 1 >= __INT_MAX__; }
+int f9 (unsigned x) { unsigned a = 1, b = __INT_MAX__; return x - a >= b; }
+int f10 (unsigned x) { return x < 1 || x > __INT_MAX__; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81369.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81369.c
new file mode 100644
index 00000000000..b40477b0b41
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81369.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-loop-distribution" } */
+
+typedef __PTRDIFF_TYPE__ intptr_t;
+int wo;
+
+void
+sy (long int *as)
+{
+ for (;;)
+ {
+ *as = wo;
+ while (as < (long int *) (void *) 2)
+ {
+ int *y9;
+
+ if (wo != 0)
+ *y9 = (int) (intptr_t) &wo;
+ wo /= (wo != 0 && *y9 != 0);
+ ++as;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c
new file mode 100644
index 00000000000..ecfe12929cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-overflow -fdump-tree-ivcanon-details" } */
+
+void bar();
+void foo(char *dst)
+{
+ char *const end = dst;
+ do {
+ bar();
+ dst += 2;
+ } while (dst < end);
+}
+
+/* { dg-final { scan-tree-dump-times " zero if " 1 "ivcanon" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c
new file mode 100644
index 00000000000..71fd2890f3d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81388-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivcanon-details" } */
+
+void bar();
+void foo(unsigned dst)
+{
+ unsigned end = dst;
+ do {
+ bar();
+ dst += 2;
+ } while (dst < end);
+}
+
+/* { dg-final { scan-tree-dump-times " zero if " 1 "ivcanon" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c
new file mode 100644
index 00000000000..9f4a08d1c22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/81396 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef unsigned long long uint64_t;
+
+uint64_t
+foo (uint64_t word)
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_LONG_LONG__ == 8
+ const unsigned char *const ptr = (const unsigned char *) &word;
+ return ((uint64_t) ptr[0]
+ | ((uint64_t) ptr[1] << 8)
+ | ((uint64_t) ptr[2] << (8 * 2))
+ | ((uint64_t) ptr[3] << (8 * 3))
+ | ((uint64_t) ptr[4] << (8 * 4))
+ | ((uint64_t) ptr[5] << (8 * 5))
+ | ((uint64_t) ptr[6] << (8 * 6))
+ | ((uint64_t) ptr[7] << (8 * 7)));
+#else
+ return word;
+#endif
+}
+
+/* { dg-final { scan-tree-dump "return word_\[0-9]*\\(D\\);" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c
new file mode 100644
index 00000000000..d3a2339e55e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, -1, 5, -2, 11, 0};
+int result2[10] = {0, 0, -1, -2, -2, 0};
+int result3[10] = {0, 0, 0, -1, -2, -2, 0};
+int result4[10] = {0, 0, 0, 0, -1, -2, -2, 0};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, 0};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 3] = -2;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-10.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-10.c
new file mode 100644
index 00000000000..bd5575d9502
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-10.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, 3, 5, -2, 11, 0};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len, int flag)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ if (flag)
+ a[i + 1] = -1;
+ a[i + 3] = -2;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ int i;
+
+ foo (arr, 0, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1, 0);
+ check (arr, result1, 10);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump-not "Store-stores chain" "pcom"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-11.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-11.c
new file mode 100644
index 00000000000..9e496f68a12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-11.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int x[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, 0, 0, 0, 0, 0, -1, -2, -2};
+
+extern void abort (void);
+
+int __attribute__((noinline)) foo (int * __restrict__ a, int * __restrict__ b, int len, int flag)
+{
+ int i, sum = 0;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ b[i + 2] = i;
+ a[i + 1] = -1;
+ sum += b[i];
+ a[i + 3] = -2;
+ }
+ return sum;
+}
+
+void check (int *a, int *res, int len, int sum, int val)
+{
+ int i;
+
+ if (sum != val)
+ abort ();
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ int i, sum;
+
+ sum = foo (arr, x, 0, 0);
+ check (arr, result0, 10, sum, 0);
+
+ sum = foo (arr, x, 6, 0);
+ check (arr, result1, 10, sum, 11);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
+/* { dg-final { scan-tree-dump "Store-loads chain" "pcom"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c
new file mode 100644
index 00000000000..c48d438e9e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, 3, -1, -2, 11, 0};
+int result2[10] = {0, 0, -1, -1, -2, 0};
+int result3[10] = {0, 0, 0, -1, -1, -2, 0};
+int result4[10] = {0, 0, 0, 0, -1, -1, -2, 0};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -2, 0};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 2] = -1;
+ a[i + 3] = -2;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
new file mode 100644
index 00000000000..9c2736cd0ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
@@ -0,0 +1,108 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr1[105] = {2, 3, 5, 7, 11, 13, 0};
+int arr2[105] = {2, 3, 5, 7, 11, 13, 0};
+int arr3[105] = {2, 3, 5, 7, 11, 13, 0};
+int arr4[105] = {2, 3, 5, 7, 11, 13, 0};
+int result1[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, 0};
+int result2[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -2, 0};
+int result3[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, 0};
+int result4[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0};
+
+extern void abort (void);
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+void __attribute__((noinline)) foo1 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 2] = -2;
+ a[i + 3] = -3;
+ }
+}
+
+void __attribute__((noinline)) foo2 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 2] = -1;
+ a[i + 3] = -2;
+ }
+}
+
+void __attribute__((noinline)) foo3 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 3] = -2;
+ }
+}
+
+void __attribute__((noinline)) foo4 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 3] = -1;
+ }
+}
+
+int main (void)
+{
+ foo1 (arr1);
+ check (arr1, result1, 105);
+
+ foo2 (arr2);
+ check (arr2, result2, 105);
+
+ foo3 (arr3);
+ check (arr3, result3, 105);
+
+ foo4 (arr4);
+ check (arr4, result4, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump-times "Store-stores chain" 4 "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c
new file mode 100644
index 00000000000..302425a17cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, 3, 5, -1, 11, 0};
+int result2[10] = {0, 0, 5, -1, -1, 0};
+int result3[10] = {0, 0, 0, -1, -1, -1, 0};
+int result4[10] = {0, 0, 0, 0, -1, -1, -1, 0};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 3] = -1;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-5.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-5.c
new file mode 100644
index 00000000000..a13d56098be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-5.c
@@ -0,0 +1,63 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11};
+int result0[10] = {2, 3, 5, 7, 11};
+int result1[10] = {0, -1, -2, -3, 11, 0};
+int result2[10] = {0, 0, -1, -2, -3, 0};
+int result3[10] = {0, 0, 0, -1, -2, -3, 0};
+int result4[10] = {0, 0, 0, 0, -1, -2, -3, 0};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, 0};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 2] = -2;
+ a[i + 3] = -3;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-6.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-6.c
new file mode 100644
index 00000000000..63d6c8f33b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-6.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result0[10] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result1[10] = {0, -1, -2, -3, -4, -5, 17, 19};
+int result2[10] = {0, 0, -1, -2, -3, -4, -5, 19};
+int result3[10] = {0, 0, 0, -1, -2, -3, -4, -5};
+int result4[10] = {0, 0, 0, 0, -1, -2, -3, -4, -5};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, -4, -5};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 2] = -2;
+ a[i + 3] = -3;
+ a[i + 4] = -4;
+ a[i + 5] = -5;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-7.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-7.c
new file mode 100644
index 00000000000..0bde6e6dced
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-7.c
@@ -0,0 +1,63 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result0[10] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result1[10] = {0, -1, 5, -3, 11, -5, 17, 19};
+int result2[10] = {0, 0, -1, -3, -3, -5, -5, 19};
+int result3[10] = {0, 0, 0, -1, -3, -3, -5, -5};
+int result4[10] = {0, 0, 0, 0, -1, -3, -3, -5, -5};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -3, -3, -5, -5};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 3] = -3;
+ a[i + 5] = -5;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-8.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-8.c
new file mode 100644
index 00000000000..45ffd25c424
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-8.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result0[10] = {2, 3, 5, 7, 11, 13, 17, 19};
+int result1[10] = {0, 3, 5, 7, 11, -5, 17, 19};
+int result2[10] = {0, 0, 5, 7, 11, -5, -5, 19};
+int result3[10] = {0, 0, 0, 7, 11, -5, -5, -5};
+int result4[10] = {0, 0, 0, 0, 11, -5, -5, -5, -5};
+int result100[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5, -5, -5, -5, -5};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo (int *a, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 0;
+ a[i + 5] = -5;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo (arr, 0);
+ check (arr, result0, 10);
+
+ foo (arr, 1);
+ check (arr, result1, 10);
+
+ foo (arr, 2);
+ check (arr, result2, 10);
+
+ foo (arr, 3);
+ check (arr, result3, 10);
+
+ foo (arr, 4);
+ check (arr, result4, 10);
+
+ foo (arr, 100);
+ check (arr, result100, 105);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-9.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-9.c
new file mode 100644
index 00000000000..1c4e3140309
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-9.c
@@ -0,0 +1,90 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+
+int arr1[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+int arr2[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+int arr3[105] = {2, 3, 5, 7, 11, 13, 17, 19};
+
+int result1[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, -4, -5};
+int result2[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -3, -3, -5, -5};
+int result3[105] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5, -5, -5, -5, -5};
+
+extern void abort (void);
+
+void __attribute__((noinline)) foo1 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 2] = -2;
+ a[i + 3] = -3;
+ a[i + 4] = -4;
+ a[i + 5] = -5;
+ }
+}
+
+void __attribute__((noinline)) foo2 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 1] = -1;
+ a[i + 3] = -3;
+ a[i + 5] = -5;
+ }
+}
+
+void __attribute__((noinline)) foo3 (int *a)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ a[i] = 0;
+ a[i + 5] = -5;
+ }
+}
+
+void check (int *a, int *res, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (a[i] != res[i])
+ abort ();
+}
+
+int main (void)
+{
+ foo1 (arr1);
+ check (arr1, result1, 10);
+
+ foo2 (arr2);
+ check (arr2, result2, 10);
+
+ foo3 (arr3);
+ check (arr3, result3, 10);
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump "Store-stores chain" "pcom"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-35.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-35.c
index 9a7d8d5d253..0f57ea20b79 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-35.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-35.c
@@ -3,7 +3,7 @@
phi has an argument which is a parameter. */
/* { dg-do compile } */
-/* { dg-options "-O3 -fno-code-hoisting -fdump-tree-optimized" } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
int
f (int c, int i)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-36.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-36.c
index 1ab357d11c0..448d5d2cff1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-36.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-36.c
@@ -3,7 +3,7 @@
phi has an argument which is a parameter. */
/* { dg-do compile } */
-/* { dg-options "-O3 -fno-code-hoisting -fdump-tree-optimized" } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
int
f (int s, int c, int i)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c
index 17d7b4c6951..1e943b737b9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-4.c
@@ -23,13 +23,9 @@ f (int i)
foo (y);
}
-/* { dg-final { scan-tree-dump-times "\\* 4" 1 "slsr" } } */
-/* { dg-final { scan-tree-dump-times "\\* 10" 1 "slsr" } } */
-/* { dg-final { scan-tree-dump-times "\\+ 20;" 1 "slsr" } } */
+/* { dg-final { scan-tree-dump-times "\\* 40" 1 "slsr" } } */
/* { dg-final { scan-tree-dump-times "\\+ 200" 1 "slsr" } } */
-/* { dg-final { scan-tree-dump-times "\\- 16;" 1 "slsr" } } */
/* { dg-final { scan-tree-dump-times "\\- 160" 1 "slsr" } } */
-/* { dg-final { scan-tree-dump-times "\\* 4" 1 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "\\* 10" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\* 40" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\\+ 200" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\\+ 40" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c
index ece8cb2a80c..1d1fe82fda0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c
@@ -8,7 +8,7 @@ void test_bcopy (const void *s)
{
char d[33];
- /* Bcopy is transformed into memcpy and those calls are expanded
+ /* Bcopy is transformed into memmove and those calls are expanded
inline in EVRP, before DSE runs, so this test doesn't actually
verify that DSE does its job. */
__builtin_bcopy (s, d, sizeof d);
@@ -28,4 +28,4 @@ void test_bzero (void)
}
/* { dg-final { scan-tree-dump-times "builtin_memset" 1 "dse1" } } */
-/* { dg-final { scan-tree-dump-not "builtin_(bcopy|bzero|memcpy)" "dse1" } } */
+/* { dg-final { scan-tree-dump-not "builtin_(bcopy|bzero|memcpy|memmove)" "dse1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c
new file mode 100644
index 00000000000..d9d7b2394cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+int
+f (int m1, int m2, int c)
+{
+ int d = m1 > m2;
+ int e = d * c;
+ return e ? m1 : m2;
+}
+
+/* { dg-final { scan-tree-dump-times "\\? c_\[0-9\]\\(D\\) : 0" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c
index 853ee21bb8f..ed49e25f87a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-vrp1-details -fdump-tree-optimized" } */
struct rtx_def;
@@ -86,10 +86,8 @@ L7:
/* The first n_sets > 0 test can be simplfiied into n_sets == 1 since
n_sets can only have the values [0, 1] as it's the result of a
- boolean operation.
+ boolean operation. */
- The second n_sets > 0 test can also be simplified into n_sets == 1
- as the only way to reach the tests is when n_sets <= 1 and the only
- value which satisfies both conditions is n_sets == 1. */
-/* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "if " 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr81162.c b/gcc/testsuite/gcc.dg/ubsan/pr81162.c
new file mode 100644
index 00000000000..9ce98afa367
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/pr81162.c
@@ -0,0 +1,17 @@
+/* PR tree-optimization/81162 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -O2" } */
+
+short s;
+int i1 = 1;
+int i2 = 1;
+unsigned char uc = 147;
+
+int main() {
+ s = (-uc + 2147483647) << 0;
+ if (9031239389974324562ULL >= (-((i1 && i2) + uc) ^ -21096) ) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr81223.c b/gcc/testsuite/gcc.dg/ubsan/pr81223.c
new file mode 100644
index 00000000000..e7aff5243e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/pr81223.c
@@ -0,0 +1,12 @@
+/* PR sanitizer/81223 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+void bar ();
+
+void
+foo (int x)
+{
+ struct S { char a[x]; } v;
+ bar (v);
+}
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr81505.c b/gcc/testsuite/gcc.dg/ubsan/pr81505.c
new file mode 100644
index 00000000000..1cebef56172
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/pr81505.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fsanitize=signed-integer-overflow" } */
+
+int a, b, c, h;
+
+int i[5][5];
+
+void
+fn1 ()
+{
+ int l = 0;
+
+ for (a = 0; a <= 3; a++)
+ for (b = 1; b >= 0; b -= 1)
+ l |= i[0][b];
+ c = l;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
index a6c75c7c77f..0e4f1a71b6b 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr65935.c
@@ -57,4 +57,6 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp1" } } */
+/* We should also be able to use 2-lane SLP to initialize the real and
+ imaginary components in the first loop of main. */
+/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr80815-3.c b/gcc/testsuite/gcc.dg/vect/pr80815-3.c
index dae01fa7af7..50392ab1a41 100644
--- a/gcc/testsuite/gcc.dg/vect/pr80815-3.c
+++ b/gcc/testsuite/gcc.dg/vect/pr80815-3.c
@@ -42,4 +42,4 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump "improved number of alias checks from \[0-9\]* to 1" "vect" } } */
+/* { dg-final { scan-tree-dump "improved number of alias checks from \[0-9\]* to 1" "vect" { target vect_perm } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr81136.c b/gcc/testsuite/gcc.dg/vect/pr81136.c
new file mode 100644
index 00000000000..24bd8fa3b19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr81136.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+struct __attribute__((aligned (32)))
+{
+ char misaligner;
+ int foo[100];
+ int bar[100];
+} *a;
+
+void
+fn1 (int n)
+{
+ int *b = a->foo;
+ for (int i = 0; i < n; i++)
+ a->bar[i] = b[i];
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr81196.c b/gcc/testsuite/gcc.dg/vect/pr81196.c
new file mode 100644
index 00000000000..46d7a9ebc57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr81196.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_perm_short } */
+
+void f(short*p){
+ p=(short*)__builtin_assume_aligned(p,64);
+ short*q=p+256;
+ for(;p!=q;++p,--q){
+ short t=*p;*p=*q;*q=t;
+ }
+}
+void b(short*p){
+ p=(short*)__builtin_assume_aligned(p,64);
+ short*q=p+256;
+ for(;p<q;++p,--q){
+ short t=*p;*p=*q;*q=t;
+ }
+}
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr81410.c b/gcc/testsuite/gcc.dg/vect/pr81410.c
new file mode 100644
index 00000000000..8d1bd6c8efd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr81410.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vect_long_long } */
+
+#include "tree-vect.h"
+
+long long x[24];
+long long y[16];
+long long z[8];
+
+void __attribute__((noinline)) foo()
+{
+ for (int i = 0; i < 8; ++i)
+ {
+ y[2*i] = x[3*i];
+ y[2*i + 1] = x[3*i + 1];
+ z[i] = 1;
+ }
+}
+
+int main()
+{
+ check_vect ();
+
+ for (int i = 0; i < 24; ++i)
+ {
+ x[i] = i;
+ __asm__ volatile ("" : : : "memory");
+ }
+ foo ();
+ for (int i = 0; i < 8; ++i)
+ if (y[2*i] != 3*i || y[2*i+1] != 3*i + 1)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-43.c b/gcc/testsuite/gcc.dg/vect/slp-43.c
index fea3aadb341..880a2961ae1 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-43.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-43.c
@@ -4,13 +4,16 @@
#include <string.h>
#include "tree-vect.h"
+/* AVX512BW has V64QImode, make char_1 vectorizable with that. */
+#define MAX_VEC_ELEMENTS 64
+
#define FOO(T,N) \
void __attribute__((noinline,noclone)) \
foo_ ## T ## _ ## N (T * __restrict__ in_, T * __restrict__ out_, int s) \
{ \
T *in = __builtin_assume_aligned (in_, __BIGGEST_ALIGNMENT__); \
T *out = __builtin_assume_aligned (out_, __BIGGEST_ALIGNMENT__); \
- for (int i = 0; i < 16; i++) \
+ for (int i = 0; i < MAX_VEC_ELEMENTS; i++) \
{ \
for (int j = 0; j < N; ++j) \
out[j] = in[j]; \
@@ -23,9 +26,9 @@ foo_ ## T ## _ ## N (T * __restrict__ in_, T * __restrict__ out_, int s) \
do { \
memset (out, 0, 4096); \
foo_ ## T ## _ ## N ((T *)in, (T *)out, 1); \
- if (memcmp (in, out, sizeof (T) * 16 * N) != 0) \
+ if (memcmp (in, out, sizeof (T) * MAX_VEC_ELEMENTS * N) != 0) \
__builtin_abort (); \
- for (int i = sizeof (T) * 16 * N; i < 4096; ++i) \
+ for (int i = sizeof (T) * MAX_VEC_ELEMENTS * N; i < 4096; ++i) \
if (out[i] != 0) \
__builtin_abort (); \
} while (0)
diff --git a/gcc/testsuite/gcc.dg/vect/slp-45.c b/gcc/testsuite/gcc.dg/vect/slp-45.c
index a8300a44670..20a9f815292 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-45.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-45.c
@@ -4,13 +4,16 @@
#include <string.h>
#include "tree-vect.h"
+/* AVX512BW has V64QImode, make char_1 vectorizable with that. */
+#define MAX_VEC_ELEMENTS 64
+
#define FOO(T,N) \
void __attribute__((noinline,noclone)) \
foo_ ## T ## _ ## N (T * __restrict__ in_, T * __restrict__ out_, int s) \
{ \
T *in = __builtin_assume_aligned (in_, __BIGGEST_ALIGNMENT__); \
T *out = __builtin_assume_aligned (out_, __BIGGEST_ALIGNMENT__); \
- for (int i = 0; i < 16; i++) \
+ for (int i = 0; i < MAX_VEC_ELEMENTS; i++) \
{ \
for (int j = 0; j < N; ++j) \
out[j] = in[j]; \
@@ -23,9 +26,9 @@ foo_ ## T ## _ ## N (T * __restrict__ in_, T * __restrict__ out_, int s) \
do { \
memset (out, 0, 4096); \
foo_ ## T ## _ ## N ((T *)in, (T *)out, 1); \
- if (memcmp (in, out, sizeof (T) * 16 * N) != 0) \
+ if (memcmp (in, out, sizeof (T) * MAX_VEC_ELEMENTS * N) != 0) \
__builtin_abort (); \
- for (int i = sizeof (T) * 16 * N; i < 4096; ++i) \
+ for (int i = sizeof (T) * MAX_VEC_ELEMENTS * N; i < 4096; ++i) \
if (out[i] != 0) \
__builtin_abort (); \
} while (0)
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-8.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-8.c
new file mode 100644
index 00000000000..618c800e577
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-8.c
@@ -0,0 +1,48 @@
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+static int a[512], b[512];
+
+void __attribute__((noinline,noclone))
+foo (int *sum1p, int *sum2p, int *sum3p)
+{
+ int sum1 = 0;
+ int sum2 = 0;
+ int sum3 = 0;
+ /* Check that we vectorize a reduction chain and a SLP reduction
+ at the same time. */
+ for (int i = 0; i < 256; ++i)
+ {
+ sum1 += a[2*i];
+ sum1 += a[2*i + 1];
+ sum2 += b[2*i];
+ sum3 += b[2*i + 1];
+ }
+ *sum1p = sum1;
+ *sum2p = sum2;
+ *sum3p = sum3;
+}
+
+int main()
+{
+ check_vect ();
+
+ for (int i = 0; i < 256; ++i)
+ {
+ a[2*i] = i;
+ a[2*i + 1] = i/2;
+ b[2*i] = i + 1;
+ b[2*i + 1] = i/2 + 1;
+ __asm__ volatile ("" : : : "memory");
+ }
+ int sum1, sum2, sum3;
+ foo (&sum1, &sum2, &sum3);
+ if (sum1 != 48896 || sum2 != 32896 || sum3 != 16512)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-11.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-11.c
new file mode 100644
index 00000000000..29408edcfce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-11.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+int x[1024], y[1024], z[1024];
+
+int __attribute__((noinline,noclone))
+foo (int n)
+{
+ int sum = 0;
+ /* Can vectorize this. */
+ for (int i = 0; i < n; ++i)
+ sum = (y[i] - (x[i] - sum));
+ return sum;
+}
+
+int __attribute__((noinline,noclone))
+bar (int n)
+{
+ int sum = 0;
+ /* Cannot vectorize this, sum is negated. */
+ for (int i = 0; i < n; ++i)
+ sum = z[i] - (y[i] - (x[i] - sum));
+ return sum;
+}
+
+int
+main()
+{
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ x[i] = i;
+ y[i] = i + 1;
+ z[i] = 0;
+ __asm__ volatile ("" : : : "memory");
+ }
+ if (foo (1024) != 1024)
+ __builtin_abort ();
+ if (bar (1023) != -1 || bar (1024) != 0)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_2.c b/gcc/testsuite/gcc.target/aarch64/ccmp_2.c
new file mode 100644
index 00000000000..77ab0207886
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ccmp_2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int g(void);
+int h(int a, _Bool c)
+{
+ if (a != 0 && c)
+ return g();
+ return 1;
+}
+
+/* { dg-final { scan-assembler "\tccmp\t" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/cmp-2.c b/gcc/testsuite/gcc.target/aarch64/cmp-2.c
new file mode 100644
index 00000000000..12016647061
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cmp-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int lt (int x, int y)
+{
+ if ((x - y) < 0)
+ return 10;
+
+ return 0;
+}
+
+int ge (int x, int y)
+{
+ if ((x - y) >= 0)
+ return 10;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "csel\t" 2 } } */
+/* { dg-final { scan-assembler-not "sub\t" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c
new file mode 100644
index 00000000000..e8dd01db056
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-skip-if "Tiny model won't generate adrp" { *-*-* } { "-mcmodel=tiny" } { "" } } */
+
+double d0(void)
+{
+ double x = 0.0d;
+ return x;
+}
+
+double dn1(void)
+{
+ double x = -0.0d;
+ return x;
+}
+
+
+double d1(void)
+{
+ double x = 1.5d;
+ return x;
+}
+
+double d2(void)
+{
+ double x = 123256.0d;
+ return x;
+}
+
+double d3(void)
+{
+ double x = 123256123456.0d;
+ return x;
+}
+
+double d4(void)
+{
+ double x = 123456123456123456.0d;
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "movi\td\[0-9\]+, #?0" 1 } } */
+
+/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, \.LC\[0-9\]" 2 } } */
+/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+, \\\[x\[0-9\], #:lo12:\.LC\[0-9\]\\\]" 2 } } */
+
+/* { dg-final { scan-assembler-times "fmov\td\[0-9\]+, 1\\\.5e\\\+0" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, 25838523252736" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x40fe, lsl 48" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -9223372036854775808" 1 } } */
+/* { dg-final { scan-assembler-times "fmov\td\[0-9\]+, x\[0-9\]+" 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c
new file mode 100644
index 00000000000..1ed3831e139
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+
+extern __fp16 foo ();
+extern void bar (__fp16* x);
+
+void f1 ()
+{
+ volatile __fp16 a = 17.0;
+}
+
+
+void f2 (__fp16 *a)
+{
+ *a = 17.0;
+}
+
+void f3 ()
+{
+ __fp16 b = foo ();
+ b = 17.0;
+ bar (&b);
+}
+
+__fp16 f4 ()
+{
+ __fp16 a = 0;
+ __fp16 b = 1;
+ __fp16 c = 2;
+ __fp16 d = 4;
+
+ __fp16 z = a + b;
+ z = z + c;
+ z = z - d;
+ return z;
+}
+
+__fp16 f5 ()
+{
+ __fp16 a = 16;
+ bar (&a);
+ return a;
+}
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, #?19520" 3 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0xbc, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x4c, lsl 8" 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
new file mode 100644
index 00000000000..6f44821e9d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+
+#include <arm_fp16.h>
+
+float16_t f0(void)
+{
+ float16_t x = 0.0f;
+ return x;
+}
+
+float16_t fn1(void)
+{
+ float16_t x = -0.0f;
+ return x;
+}
+
+float16_t f1(void)
+{
+ float16_t x = 256.0f;
+ return x;
+}
+
+float16_t f2(void)
+{
+ float16_t x = 123256.0f;
+ return x;
+}
+
+float16_t f3(void)
+{
+ float16_t x = 17.0;
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, ?#0" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x5c, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 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 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c
new file mode 100644
index 00000000000..7b92a5ae40f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/flt_mov_immediate_1.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+float f0(void)
+{
+ float x = 0.0f;
+ return x;
+}
+
+float fn1(void)
+{
+ float x = -0.0f;
+ return x;
+}
+
+float f1(void)
+{
+ float x = 256.0f;
+ return x;
+}
+
+float f2(void)
+{
+ float x = 123256.0f;
+ return x;
+}
+
+float f3(void)
+{
+ float x = 2.0f;
+ return x;
+}
+
+float f4(void)
+{
+ float x = -20000.1;
+ return x;
+}
+
+
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, ?#0" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 24" 1 } } */
+/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.2s, 0x80, lsl 24" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 48128" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tw\[0-9\]+, 0x47f0, lsl 16" 1 } } */
+
+/* { dg-final { scan-assembler-times "fmov\ts\[0-9\]+, 2\\\.0e\\\+0" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 16435" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tw\[0-9\]+, 0xc69c, lsl 16" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c
new file mode 100644
index 00000000000..6ac9065037f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O3" } */
+
+long long f1(void)
+{
+ return 0xffff6666;
+}
+
+int f3(void)
+{
+ return 0xffff6666;
+}
+
+
+long f2(void)
+{
+ return 0x11110000ffff6666;
+}
+
+long f4(void)
+{
+ return 0x11110001ffff6666;
+}
+
+long f5(void)
+{
+ return 0x111100001ff6666;
+}
+
+long f6(void)
+{
+ return 0x00001111ffff6666;
+}
+
+long f7(void)
+{
+ return 0x000011116666ffff;
+}
+
+long f8(void)
+{
+ return 0x0f0011116666ffff;
+}
+
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, -39322" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 4294927974" 3 } } */
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 1718026239" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -2576941057" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, -39322" 1 } } */
+/* { dg-final { scan-assembler-times "mov\tx\[0-9\]+, 26214" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0xf00, lsl 48" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1111, lsl 48" 2 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1000, lsl 32" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1111, lsl 32" 3 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x111, lsl 48" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1ff, lsl 16" 1 } } */
+/* { dg-final { scan-assembler-times "movk\tx\[0-9\]+, 0x1, lsl 32" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c
index c917f81c022..114d8c1a6c3 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c
@@ -4,10 +4,10 @@
#pragma GCC target ("+nothing+simd, cmodel=small")
int
-cal (float a)
+cal (double a)
{
- float b = 1.2;
- float c = 2.2;
+ double b = 3.2;
+ double c = 2.2;
if ((a + b) != c)
return 0;
else
@@ -19,11 +19,11 @@ cal (float a)
#pragma GCC target ("cmodel=large")
int
-cal2 (float a)
+cal2 (double a)
{
- float b = 1.2;
- float c = 2.2;
+ double b = 3.2;
+ double c = 2.2;
if ((a + b) != c)
return 0;
else
@@ -33,11 +33,11 @@ cal2 (float a)
#pragma GCC pop_options
int
-cal3 (float a)
+cal3 (double a)
{
- float b = 1.2;
- float c = 2.2;
+ double b = 3.2;
+ double c = 2.2;
if ((a + b) != c)
return 0;
else
diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c
new file mode 100644
index 00000000000..a889dfdd895
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads" } */
+/* { dg-require-effective-target lp64 } */
+
+__int128
+t (void)
+{
+ return (__int128)1 << 80;
+}
+
+/* { dg-final { scan-assembler "adr" } } */
+/* { dg-final { scan-assembler-not "adrp" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr81414.C b/gcc/testsuite/gcc.target/aarch64/pr81414.C
new file mode 100644
index 00000000000..53dfc7cf800
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr81414.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=cortex-a57" } */
+
+typedef __Float32x2_t float32x2_t;
+float32x2_t
+foo1 (float32x2_t __a, float32x2_t __b, float32x2_t __c) {
+ return __b * __c + __a;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vminmaxnm_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vminmaxnm_1.c
index 192bad9879b..8fd428115ba 100644
--- a/gcc/testsuite/gcc.target/aarch64/simd/vminmaxnm_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/simd/vminmaxnm_1.c
@@ -7,12 +7,10 @@
extern void abort ();
-#define CHECK(T, N, R, E) \
+#define CHECK(R, E) \
{\
- int i = 0;\
- for (; i < N; i++)\
- if (* (T *) &R[i] != * (T *) &E[i])\
- abort ();\
+ if (__builtin_memcmp (&R, &E, sizeof (R)) != 0)\
+ abort ();\
}
int
@@ -26,8 +24,8 @@ main (int argc, char **argv)
float32x2_t f32x2_ret_minnm = vminnm_f32 (f32x2_input1, f32x2_input2);
float32x2_t f32x2_ret_maxnm = vmaxnm_f32 (f32x2_input1, f32x2_input2);
- CHECK (uint32_t, 2, f32x2_ret_minnm, f32x2_exp_minnm);
- CHECK (uint32_t, 2, f32x2_ret_maxnm, f32x2_exp_maxnm);
+ CHECK (f32x2_ret_minnm, f32x2_exp_minnm);
+ CHECK (f32x2_ret_maxnm, f32x2_exp_maxnm);
/* v{min|max}nm_f32 NaN. */
f32x2_input1 = vdup_n_f32 (__builtin_nanf (""));
@@ -37,8 +35,8 @@ main (int argc, char **argv)
f32x2_ret_minnm = vminnm_f32 (f32x2_input1, f32x2_input2);
f32x2_ret_maxnm = vmaxnm_f32 (f32x2_input1, f32x2_input2);
- CHECK (uint32_t, 2, f32x2_ret_minnm, f32x2_exp_minnm);
- CHECK (uint32_t, 2, f32x2_ret_maxnm, f32x2_exp_maxnm);
+ CHECK (f32x2_ret_minnm, f32x2_exp_minnm);
+ CHECK (f32x2_ret_maxnm, f32x2_exp_maxnm);
/* v{min|max}nmq_f32 normal. */
float32x4_t f32x4_input1 = vdupq_n_f32 (-1024.0);
@@ -48,8 +46,8 @@ main (int argc, char **argv)
float32x4_t f32x4_ret_minnm = vminnmq_f32 (f32x4_input1, f32x4_input2);
float32x4_t f32x4_ret_maxnm = vmaxnmq_f32 (f32x4_input1, f32x4_input2);
- CHECK (uint32_t, 4, f32x4_ret_minnm, f32x4_exp_minnm);
- CHECK (uint32_t, 4, f32x4_ret_maxnm, f32x4_exp_maxnm);
+ CHECK (f32x4_ret_minnm, f32x4_exp_minnm);
+ CHECK (f32x4_ret_maxnm, f32x4_exp_maxnm);
/* v{min|max}nmq_f32 NaN. */
f32x4_input1 = vdupq_n_f32 (-__builtin_nanf (""));
@@ -59,8 +57,8 @@ main (int argc, char **argv)
f32x4_ret_minnm = vminnmq_f32 (f32x4_input1, f32x4_input2);
f32x4_ret_maxnm = vmaxnmq_f32 (f32x4_input1, f32x4_input2);
- CHECK (uint32_t, 4, f32x4_ret_minnm, f32x4_exp_minnm);
- CHECK (uint32_t, 4, f32x4_ret_maxnm, f32x4_exp_maxnm);
+ CHECK (f32x4_ret_minnm, f32x4_exp_minnm);
+ CHECK (f32x4_ret_maxnm, f32x4_exp_maxnm);
/* v{min|max}nm_f64 normal. */
float64x1_t f64x1_input1 = vdup_n_f64 (1.23);
@@ -69,16 +67,16 @@ main (int argc, char **argv)
float64x1_t f64x1_exp_maxnm = vdup_n_f64 (4.56);
float64x1_t f64x1_ret_minnm = vminnm_f64 (f64x1_input1, f64x1_input2);
float64x1_t f64x1_ret_maxnm = vmaxnm_f64 (f64x1_input1, f64x1_input2);
- CHECK (uint64_t, 1, f64x1_ret_minnm, f64x1_exp_minnm);
- CHECK (uint64_t, 1, f64x1_ret_maxnm, f64x1_exp_maxnm);
+ CHECK (f64x1_ret_minnm, f64x1_exp_minnm);
+ CHECK (f64x1_ret_maxnm, f64x1_exp_maxnm);
/* v{min|max}_f64 normal. */
float64x1_t f64x1_exp_min = vdup_n_f64 (1.23);
float64x1_t f64x1_exp_max = vdup_n_f64 (4.56);
float64x1_t f64x1_ret_min = vmin_f64 (f64x1_input1, f64x1_input2);
float64x1_t f64x1_ret_max = vmax_f64 (f64x1_input1, f64x1_input2);
- CHECK (uint64_t, 1, f64x1_ret_min, f64x1_exp_min);
- CHECK (uint64_t, 1, f64x1_ret_max, f64x1_exp_max);
+ CHECK (f64x1_ret_min, f64x1_exp_min);
+ CHECK (f64x1_ret_max, f64x1_exp_max);
/* v{min|max}nmq_f64 normal. */
float64x2_t f64x2_input1 = vdupq_n_f64 (1.23);
@@ -87,8 +85,8 @@ main (int argc, char **argv)
float64x2_t f64x2_exp_maxnm = vdupq_n_f64 (4.56);
float64x2_t f64x2_ret_minnm = vminnmq_f64 (f64x2_input1, f64x2_input2);
float64x2_t f64x2_ret_maxnm = vmaxnmq_f64 (f64x2_input1, f64x2_input2);
- CHECK (uint64_t, 2, f64x2_ret_minnm, f64x2_exp_minnm);
- CHECK (uint64_t, 2, f64x2_ret_maxnm, f64x2_exp_maxnm);
+ CHECK (f64x2_ret_minnm, f64x2_exp_minnm);
+ CHECK (f64x2_ret_maxnm, f64x2_exp_maxnm);
/* v{min|max}nm_f64 NaN. */
f64x1_input1 = vdup_n_f64 (-__builtin_nanf (""));
@@ -98,8 +96,8 @@ main (int argc, char **argv)
f64x1_ret_minnm = vminnm_f64 (f64x1_input1, f64x1_input2);
f64x1_ret_maxnm = vmaxnm_f64 (f64x1_input1, f64x1_input2);
- CHECK (uint64_t, 1, f64x1_ret_minnm, f64x1_exp_minnm);
- CHECK (uint64_t, 1, f64x1_ret_maxnm, f64x1_exp_maxnm);
+ CHECK (f64x1_ret_minnm, f64x1_exp_minnm);
+ CHECK (f64x1_ret_maxnm, f64x1_exp_maxnm);
/* v{min|max}_f64 NaN. */
f64x1_input1 = vdup_n_f64 (-__builtin_nanf (""));
@@ -109,8 +107,8 @@ main (int argc, char **argv)
f64x1_ret_minnm = vmin_f64 (f64x1_input1, f64x1_input2);
f64x1_ret_maxnm = vmax_f64 (f64x1_input1, f64x1_input2);
- CHECK (uint64_t, 1, f64x1_ret_minnm, f64x1_exp_minnm);
- CHECK (uint64_t, 1, f64x1_ret_maxnm, f64x1_exp_maxnm);
+ CHECK (f64x1_ret_minnm, f64x1_exp_minnm);
+ CHECK (f64x1_ret_maxnm, f64x1_exp_maxnm);
/* v{min|max}nmq_f64 NaN. */
f64x2_input1 = vdupq_n_f64 (-__builtin_nan (""));
@@ -120,8 +118,8 @@ main (int argc, char **argv)
f64x2_ret_minnm = vminnmq_f64 (f64x2_input1, f64x2_input2);
f64x2_ret_maxnm = vmaxnmq_f64 (f64x2_input1, f64x2_input2);
- CHECK (uint64_t, 2, f64x2_ret_minnm, f64x2_exp_minnm);
- CHECK (uint64_t, 2, f64x2_ret_maxnm, f64x2_exp_maxnm);
+ CHECK (f64x2_ret_minnm, f64x2_exp_minnm);
+ CHECK (f64x2_ret_maxnm, f64x2_exp_maxnm);
return 0;
}
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmla_elem_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmla_elem_1.c
new file mode 100644
index 00000000000..df777581ab4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/vmla_elem_1.c
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+typedef short int __attribute__ ((vector_size (16))) v8hi;
+
+v8hi
+mla8hi (v8hi v0, v8hi v1, short int v2)
+{
+ /* { dg-final { scan-assembler "mla\\tv\[0-9\]\+\\.8h, v\[0-9\]\+\\.8h, v\[0-9\]\+\\.h\\\[0\\\]" } } */
+ return v0 + v1 * v2;
+}
+
+
+v8hi
+mls8hi (v8hi v0, v8hi v1, short int v2)
+{
+ /* { dg-final { scan-assembler "mls\\tv\[0-9\]\+\\.8h, v\[0-9\]\+\\.8h, v\[0-9\]\+\\.h\\\[0\\\]" } } */
+ return v0 - v1 * v2;
+}
+
+typedef short int __attribute__ ((vector_size (8))) v4hi;
+
+v4hi
+mla4hi (v4hi v0, v4hi v1, short int v2)
+{
+ /* { dg-final { scan-assembler "mla\\tv\[0-9\]\+\\.4h, v\[0-9\]\+\\.4h, v\[0-9\]\+\\.h\\\[0\\\]" } } */
+ return v0 + v1 * v2;
+}
+
+v4hi
+mls4hi (v4hi v0, v4hi v1, short int v2)
+{
+ /* { dg-final { scan-assembler "mls\\tv\[0-9\]\+\\.4h, v\[0-9\]\+\\.4h, v\[0-9\]\+\\.h\\\[0\\\]" } } */
+ return v0 - v1 * v2;
+}
+
+typedef int __attribute__ ((vector_size (16))) v4si;
+
+v4si
+mla4si (v4si v0, v4si v1, int v2)
+{
+ /* { dg-final { scan-assembler "mla\\tv\[0-9\]\+\\.4s, v\[0-9\]\+\\.4s, v\[0-9\]\+\\.s\\\[0\\\]" } } */
+ return v0 + v1 * v2;
+}
+
+v4si
+mls4si (v4si v0, v4si v1, int v2)
+{
+ /* { dg-final { scan-assembler "mls\\tv\[0-9\]\+\\.4s, v\[0-9\]\+\\.4s, v\[0-9\]\+\\.s\\\[0\\\]" } } */
+ return v0 - v1 * v2;
+}
+
+typedef int __attribute__((vector_size (8))) v2si;
+
+v2si
+mla2si (v2si v0, v2si v1, int v2)
+{
+ /* { dg-final { scan-assembler "mla\\tv\[0-9\]\+\\.2s, v\[0-9\]\+\\.2s, v\[0-9\]\+\\.s\\\[0\\\]" } } */
+ return v0 + v1 * v2;
+}
+
+v2si
+mls2si (v2si v0, v2si v1, int v2)
+{
+ /* { dg-final { scan-assembler "mls\\tv\[0-9\]\+\\.2s, v\[0-9\]\+\\.2s, v\[0-9\]\+\\.s\\\[0\\\]" } } */
+ return v0 - v1 * v2;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/stack-checking.c b/gcc/testsuite/gcc.target/aarch64/stack-checking.c
index 1d1530df62b..eaa40581c86 100644
--- a/gcc/testsuite/gcc.target/aarch64/stack-checking.c
+++ b/gcc/testsuite/gcc.target/aarch64/stack-checking.c
@@ -1,4 +1,5 @@
/* { dg-do run { target { *-*-linux* } } } */
+/* { dg-require-stack-check "" } */
/* { dg-options "-fstack-check" } */
int main(void)
diff --git a/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c
new file mode 100644
index 00000000000..33a2c0f45af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+f (unsigned char *p)
+{
+ return p[0] == 50 || p[0] == 52;
+}
+
+int
+g (unsigned char *p)
+{
+ return (p[0] >> 4 & 0xfd) == 0;
+}
+
+/* { dg-final { scan-assembler-not "and\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+.*" } } */
+/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+" } } */
+/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+, lsr 4" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/var_shift_mask_1.c b/gcc/testsuite/gcc.target/aarch64/var_shift_mask_1.c
new file mode 100644
index 00000000000..0bd326a879d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/var_shift_mask_1.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* The integer variable shift and rotate instructions truncate their
+ shift amounts by the datasize. Make sure that we don't emit a redundant
+ masking operation. */
+
+unsigned
+f1 (unsigned x, int y)
+{
+ return x << (y & 31);
+}
+
+unsigned long long
+f2 (unsigned long long x, int y)
+{
+ return x << (y & 63);
+}
+
+unsigned long long
+f3 (unsigned long long bit_addr, int y)
+{
+ unsigned long bitnumb = bit_addr & 63;
+ return (1LL << bitnumb);
+}
+
+unsigned int
+f4 (unsigned int x, unsigned int y)
+{
+ y &= 31;
+ return x >> y | (x << (32 - y));
+}
+
+unsigned long long
+f5 (unsigned long long x, unsigned long long y)
+{
+ y &= 63;
+ return x >> y | (x << (64 - y));
+}
+
+unsigned int
+f6 (unsigned int x, unsigned int y)
+{
+ return (x << (32 - (y & 31)));
+}
+
+unsigned long long
+f7 (unsigned long long x, unsigned long long y)
+{
+ return (x << (64 - (y & 63)));
+}
+
+unsigned long long
+f8 (unsigned long long x, unsigned long long y)
+{
+ return (x << -(y & 63));
+}
+
+/* { dg-final { scan-assembler-times "lsl\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "lsl\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 4 } } */
+/* { dg-final { scan-assembler-times "ror\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "ror\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-not "and\tw\[0-9\]+, w\[0-9\]+, 31" } } */
+/* { dg-final { scan-assembler-not "and\tx\[0-9\]+, x\[0-9\]+, 63" } } */
+/* { dg-final { scan-assembler-not "sub\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
index 57cb95b91fc..5fd6c360363 100644
--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
@@ -7,7 +7,7 @@
static int
id (int i)
{
- asm ("": "+Xr" (i));
+ asm ("": "+r" (i));
return i;
}
diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
index 287d96d4ee9..6ec4bc5d875 100644
--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
@@ -9,7 +9,7 @@
static int
id (int i)
{
- asm ("": "+Xr" (i));
+ asm ("": "+r" (i));
return i;
}
diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
new file mode 100644
index 00000000000..e45f433f73c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+extern void bar (int);
+
+void __attribute__((naked))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
new file mode 100644
index 00000000000..7b7262f7916
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+
+#if defined(__HS__) || defined(__EM__)
+# define ILINK "ilink"
+#else
+# define ILINK "ilink1"
+#endif
+
+extern void bar (int);
+
+void __attribute__((naked, interrupt(ILINK)))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\trtie" } } */
+/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
diff --git a/gcc/testsuite/gcc.target/arc/pic-1.c b/gcc/testsuite/gcc.target/arc/pic-1.c
new file mode 100644
index 00000000000..ab24763b67f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pic-1.c
@@ -0,0 +1,11 @@
+/* Tests how complex pic constant expressions are handled. */
+/* { dg-do assemble } */
+/* { dg-skip-if "PIC not available for ARC6xx" { arc6xx } } */
+/* { dg-options "-mno-sdata -w -Os -fpic" } */
+
+a() {
+ char *b = "";
+ char c;
+ int d = &c - " \n\t\v\b\r\f\a/\0";
+ e(b[d]);
+}
diff --git a/gcc/testsuite/gcc.target/arc/pr9000674901.c b/gcc/testsuite/gcc.target/arc/pr9000674901.c
new file mode 100644
index 00000000000..2a15c1c1478
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr9000674901.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=arc700 -O2 -fpic" } */
+
+/* Test if the compiler generates a constant address having that uses
+ a neg keyword on the pic unspec. */
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned long long int uint64_t;
+
+enum type {
+ t_undef = 0x01,
+ t_group = 0x02,
+ t_partition = 0x04,
+ t_spare = 0x08,
+ t_linear = 0x10,
+ t_raid0 = 0x20,
+ t_raid1 = 0x40,
+ t_raid4 = 0x80,
+ t_raid5_ls = 0x100,
+ t_raid5_rs = 0x200,
+ t_raid5_la = 0x400,
+ t_raid5_ra = 0x800,
+ t_raid6 = 0x1000,
+};
+
+struct raid_set {
+ enum type type;
+};
+
+void
+_find_factors (struct raid_set *rs, uint8_t * div, uint8_t * sub)
+{
+ struct factors {
+ const uint8_t level;
+ const uint8_t div, sub;
+ };
+ static struct factors factors[] = {
+ {0, 1, 0},
+ {1, 2, 0},
+ {2, 2, 0},
+ {5, 1, 1},
+ };
+ struct factors *f = (factors + (sizeof (factors) / sizeof (*factors)));
+
+ while (f-- > factors) {
+ if (rs->type == f->level) {
+ *div = f->div;
+ *sub = f->sub;
+ return;
+ }
+ }
+
+ *div = 1;
+ *sub = 0;
+}
diff --git a/gcc/testsuite/gcc.target/arc/pr9001191897.c b/gcc/testsuite/gcc.target/arc/pr9001191897.c
new file mode 100644
index 00000000000..fc3642629d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr9001191897.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=archs -Os -fpic -mno-sdata -mno-indexed-loads -w" } */
+a;
+c() {
+ static char b[25];
+ for (; a >= 0; a--)
+ if (b[a])
+ b[a] = '\0';
+}
diff --git a/gcc/testsuite/gcc.target/arm/lto/pr65837-attr_0.c b/gcc/testsuite/gcc.target/arm/lto/pr65837-attr_0.c
index ebc5f447a08..f00480b5c02 100644
--- a/gcc/testsuite/gcc.target/arm/lto/pr65837-attr_0.c
+++ b/gcc/testsuite/gcc.target/arm/lto/pr65837-attr_0.c
@@ -1,6 +1,7 @@
/* { dg-lto-do run } */
/* { dg-require-effective-target arm_neon_hw } */
-/* { dg-lto-options {{-flto}} } */
+/* { dg-require-effective-target arm_neon_ok_no_float_abi } */
+/* { dg-lto-options {{-flto -mfpu=neon}} } */
#include "arm_neon.h"
diff --git a/gcc/testsuite/gcc.target/arm/lto/pr65837_0.c b/gcc/testsuite/gcc.target/arm/lto/pr65837_0.c
index 6b2def9985d..5d7cea7b2e4 100644
--- a/gcc/testsuite/gcc.target/arm/lto/pr65837_0.c
+++ b/gcc/testsuite/gcc.target/arm/lto/pr65837_0.c
@@ -1,7 +1,7 @@
/* { dg-lto-do run } */
/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-require-effective-target arm_neon_ok_no_float_abi } */
/* { dg-lto-options {{-flto -mfpu=neon}} } */
-/* { dg-suppress-ld-options {-mfpu=neon} } */
#include "arm_neon.h"
diff --git a/gcc/testsuite/gcc.target/arm/stack-checking.c b/gcc/testsuite/gcc.target/arm/stack-checking.c
index 88a7e6e8286..4b53bedd97b 100644
--- a/gcc/testsuite/gcc.target/arm/stack-checking.c
+++ b/gcc/testsuite/gcc.target/arm/stack-checking.c
@@ -1,6 +1,6 @@
/* { dg-do run { target { *-*-linux* } } } */
+/* { dg-require-stack-check "" } */
/* { dg-options "-fstack-check" } */
-/* { dg-skip-if "" { arm_thumb1 } } */
int main(void)
{
diff --git a/gcc/testsuite/gcc.target/avr/isr-test.h b/gcc/testsuite/gcc.target/avr/isr-test.h
new file mode 100644
index 00000000000..176dbc2a15f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/isr-test.h
@@ -0,0 +1,283 @@
+#ifndef ISR_TEST_H
+#define ISR_TEST_H
+
+#include <string.h>
+
+#define ISR(N,...) \
+__attribute__ ((used, externally_visible , ## __VA_ARGS__)) \
+ void __vector_##N (void); \
+ void __vector_##N (void)
+
+#define SFR(ADDR) (*(unsigned char volatile*) (__AVR_SFR_OFFSET__ + (ADDR)))
+#define CORE_SFRS SFR (0x38)
+#define SREG SFR (0x3F)
+#define SPL SFR (0x3D)
+#define EIND SFR (0x3C)
+#define RAMPZ SFR (0x3B)
+#define RAMPY SFR (0x3A)
+#define RAMPX SFR (0x39)
+#define RAMPD SFR (0x38)
+
+#ifdef __AVR_HAVE_JMP_CALL__
+#define VEC_SIZE 4
+#else
+#define VEC_SIZE 2
+#endif
+
+#ifdef __AVR_TINY__
+#define FIRST_REG 16
+#else
+#define FIRST_REG 0
+#endif
+
+#define CR "\n\t"
+
+typedef struct
+{
+ unsigned char sfrs[8];
+ unsigned char gprs[32 - FIRST_REG];
+} regs_t;
+
+regs_t reginfo1, reginfo2;
+
+__attribute__((noinline,unused))
+static void clear_reginfo (void)
+{
+ memset (reginfo1.sfrs, 0, sizeof (reginfo1.sfrs));
+ memset (reginfo2.sfrs, 0, sizeof (reginfo2.sfrs));
+}
+
+__attribute__((noinline,unused))
+static void compare_reginfo (unsigned long gpr_ignore)
+{
+ signed char regno;
+ const unsigned char *preg1 = &reginfo1.gprs[0];
+ const unsigned char *preg2 = &reginfo2.gprs[0];
+
+ if (memcmp (&reginfo1, &reginfo2, 8))
+ __builtin_abort();
+
+ gpr_ignore >>= FIRST_REG;
+
+ for (regno = FIRST_REG; regno < 32;
+ regno++, preg1++, preg2++, gpr_ignore >>= 1)
+ {
+ if (gpr_ignore & 1)
+ continue;
+
+ if (*preg1 != *preg2)
+ {
+ static signed char volatile failed_regno;
+ (void) failed_regno;
+ failed_regno = regno;
+ __builtin_abort();
+ }
+ }
+}
+
+/* STore GPR */
+#define ST(regno,M) \
+ CR "sts %[" #M "]+8-%[first]+" #regno ", r" #regno
+
+/* STore SFR */
+#define ST_SFR(sfr, n_sfr, M) \
+ CR "in __tmp_reg__,%i[s_" #sfr "]" \
+ CR "sts %[" #M "]+" #n_sfr ", __tmp_reg__"
+
+/* Named asm OPerand for SFR */
+#define OP_SFR(sfr) \
+ , [s_ ## sfr] "n" (&(sfr))
+
+/* Write funny value to SFR */
+#define XX_SFR(sfr) \
+ CR "dec r31 $ out %i[s_" #sfr "], r31"
+
+/* Write 0 to SFR */
+#define OO_SFR(sfr) \
+ CR "out %i[s_" #sfr "], __zero_reg__"
+
+/* Macros for SREG */
+#define ST_SREG(M) ST_SFR (SREG,0,M)
+#define OP_SREG OP_SFR (SREG)
+#define XX_SREG XX_SFR (SREG)
+
+/* Macros for EIND */
+#if defined __AVR_HAVE_EIJMP_EICALL__
+#define ST_EIND(M) ST_SFR (EIND,1,M)
+#define OP_EIND OP_SFR (EIND)
+#else
+#define ST_EIND(M) /* empty */
+#define OP_EIND /* empty */
+#endif
+
+/* Macros for RAMPX */
+#if defined (__AVR_HAVE_RAMPX__)
+#define ST_RAMPX(M) ST_SFR (RAMPX,2,M)
+#define OP_RAMPX OP_SFR (RAMPX)
+#define XX_RAMPX XX_SFR (RAMPX)
+#define OO_RAMPX OO_SFR (RAMPX)
+#else
+#define ST_RAMPX(M) /* empty */
+#define OP_RAMPX /* empty */
+#define XX_RAMPX /* empty */
+#define OO_RAMPX /* empty */
+#endif
+
+/* Macros for RAMPY */
+#if defined (__AVR_HAVE_RAMPY__)
+#define ST_RAMPY(M) ST_SFR (RAMPY,3,M)
+#define OP_RAMPY OP_SFR (RAMPY)
+#define XX_RAMPY XX_SFR (RAMPY)
+#define OO_RAMPY OO_SFR (RAMPY)
+#else
+#define ST_RAMPY(M) /* empty */
+#define OP_RAMPY /* empty */
+#define XX_RAMPY /* empty */
+#define OO_RAMPY /* empty */
+#endif
+
+/* Macros for RAMPZ */
+#if defined (__AVR_HAVE_RAMPZ__)
+#define ST_RAMPZ(M) ST_SFR (RAMPZ,4,M)
+#define OP_RAMPZ OP_SFR (RAMPZ)
+#define XX_RAMPZ XX_SFR (RAMPZ)
+#define OO_RAMPZ OO_SFR (RAMPZ)
+#else
+#define ST_RAMPZ(M) /* empty */
+#define OP_RAMPZ /* empty */
+#define XX_RAMPZ /* empty */
+#define OO_RAMPZ /* empty */
+#endif
+
+/* Macros for RAMPD */
+#if defined (__AVR_HAVE_RAMPD__)
+#define ST_RAMPD(M) ST_SFR (RAMPD,5,M)
+#define OP_RAMPD OP_SFR (RAMPD)
+#else
+#define ST_RAMPD(M) /* empty */
+#define OP_RAMPD /* empty */
+#endif
+
+/* Macros for all GPRs */
+#if defined __AVR_TINY__
+#define ST_REGS_LO(M) /* empty */
+#else
+#define ST_REGS_LO(M) \
+ ST(0,M) ST(1,M) ST(2,M) ST(3,M) \
+ ST(4,M) ST(5,M) ST(6,M) ST(7,M) \
+ ST(8,M) ST(9,M) ST(10,M) ST(11,M) \
+ ST(12,M) ST(13,M) ST(14,M) ST(15,M)
+#endif /* AVR_TINY */
+
+#define ST_REGS_HI(M) \
+ ST(16,M) ST(17,M) ST(18,M) ST(19,M) \
+ ST(20,M) ST(21,M) ST(22,M) ST(23,M) \
+ ST(24,M) ST(25,M) ST(26,M) ST(27,M) \
+ ST(28,M) ST(29,M) ST(30,M) ST(31,M)
+
+__attribute__((unused,naked,noinline,noclone))
+static void host_store1 (void)
+{
+ __asm __volatile__
+ ("nop"
+ CR ".global do_stores_before"
+ CR ".type do_stores_before,@function"
+ CR "do_stores_before:"
+ /* Funny values to some SFRs */
+ CR "ldi r31, 1 + 'Z'"
+ XX_RAMPZ
+ XX_RAMPY
+ XX_RAMPX
+ CR "dec __zero_reg__"
+ CR "clr r31"
+ XX_SREG
+ /* Must set I-flag due to RETI of ISR */
+ CR "sei"
+ /* Store core regs before ISR */
+ ST_RAMPX (mem1)
+ ST_RAMPY (mem1)
+ ST_RAMPZ (mem1)
+ ST_RAMPD (mem1)
+ ST_EIND (mem1)
+ ST_SREG (mem1)
+ CR "ldi r31, 0xaa"
+ CR "mov __tmp_reg__, r31"
+ CR "ldi r31, 31"
+ ST_REGS_LO (mem1)
+ ST_REGS_HI (mem1)
+ CR "ret"
+ : /* No outputs */
+ : [mem1] "i" (&reginfo1), [first] "n" (FIRST_REG)
+ OP_RAMPX
+ OP_RAMPY
+ OP_RAMPZ
+ OP_RAMPD
+ OP_EIND
+ OP_SREG
+ : "memory", "r31");
+}
+
+__attribute__((unused,naked,noinline,noclone))
+static void host_store2 (void)
+{
+ __asm __volatile__
+ ("nop"
+ CR ".global do_stores_after"
+ CR ".type do_stores_after,@function"
+ CR "do_stores_after:"
+ /* Store core regs after ISR */
+ ST_REGS_LO (mem2)
+ ST_REGS_HI (mem2)
+ ST_RAMPX (mem2)
+ ST_RAMPY (mem2)
+ ST_RAMPZ (mem2)
+ ST_RAMPD (mem2)
+ ST_EIND (mem2)
+ ST_SREG (mem2)
+ /* Undo funny values */
+ CR "clr __zero_reg__"
+ OO_RAMPX
+ OO_RAMPY
+ OO_RAMPZ
+ CR "ret"
+ : /* No outputs */
+ : [mem2] "i" (&reginfo2), [first] "n" (FIRST_REG)
+ OP_RAMPX
+ OP_RAMPY
+ OP_RAMPZ
+ OP_RAMPD
+ OP_EIND
+ OP_SREG
+ : "memory");
+}
+
+#define MK_CALL_ISR(vecno) \
+ __asm __volatile__ \
+ (/* Funny values to some SFRs */ \
+ /* Must set I-flag due to RETI of ISR */ \
+ /* Store core regs before ISR */ \
+ CR "%~call do_stores_before" \
+ /* Execute ISR */ \
+ CR "%~call __vectors + %[vect]" \
+ /* Store core regs after ISR */ \
+ /* Undo funny values */ \
+ CR "%~call do_stores_after" \
+ : /* No outputs */ \
+ : [vect] "i" (VEC_SIZE * (vecno)) \
+ , "i" (host_store1) \
+ , "i" (host_store2) \
+ : "memory", "r31")
+
+
+#define MK_RUN_ISR(N, IGMSK) \
+ \
+__attribute__((noinline,noclone)) \
+void run_isr_ ## N (void) \
+{ \
+ clear_reginfo(); \
+ MK_CALL_ISR (N); \
+ compare_reginfo (IGMSK); \
+}
+
+#endif /* ISR_TEST_H */
+
diff --git a/gcc/testsuite/gcc.target/avr/torture/isr-01-simple.c b/gcc/testsuite/gcc.target/avr/torture/isr-01-simple.c
new file mode 100644
index 00000000000..271d0cf47e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/isr-01-simple.c
@@ -0,0 +1,98 @@
+/* { dg-do run } */
+/* { dg-options "-std=c99" } */
+
+#include "../isr-test.h"
+
+int volatile v;
+
+/**********************************************************************/
+
+ISR (1, signal)
+{
+}
+
+MK_RUN_ISR (1, 0)
+
+void test1 (void)
+{
+ run_isr_1();
+}
+
+/**********************************************************************/
+
+ISR (2, signal)
+{
+ v++;
+}
+
+MK_RUN_ISR (2, 0)
+
+void test2 (void)
+{
+ v = 0;
+ run_isr_2();
+ if (v != 1)
+ __builtin_abort();
+}
+
+
+/**********************************************************************/
+
+ISR (3, signal)
+{
+ __asm __volatile__ ("$ lds r27, v"
+ "$ swap r27"
+ "$ sts v, r27"
+ ::: "memory", "r27");
+}
+
+MK_RUN_ISR (3, 0)
+
+void test3 (void)
+{
+ run_isr_3();
+ if (v != 0x10)
+ __builtin_abort();
+}
+
+/**********************************************************************/
+
+ISR (4, signal)
+{
+ __asm __volatile__ ("sts v,__zero_reg__" ::: "memory");
+}
+
+MK_RUN_ISR (4, 0)
+
+void test4 (void)
+{
+ run_isr_4();
+ if (v != 0)
+ __builtin_abort();
+}
+
+/**********************************************************************/
+
+ISR (5, signal)
+{
+ __asm __volatile__ ("clt");
+}
+
+MK_RUN_ISR (5, 0)
+
+void test5 (void)
+{
+ run_isr_5();
+}
+
+/**********************************************************************/
+
+int main (void)
+{
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/torture/isr-02-call.c b/gcc/testsuite/gcc.target/avr/torture/isr-02-call.c
new file mode 100644
index 00000000000..be4f22ebb35
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/isr-02-call.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-std=c99" } */
+
+#include "../isr-test.h"
+
+int volatile v;
+
+__attribute__((noinline,noclone))
+void inc_v (void)
+{
+ v++;
+}
+
+/**********************************************************************/
+
+ISR (1, signal)
+{
+ inc_v();
+}
+
+MK_RUN_ISR (1, 0)
+
+void test1 (void)
+{
+ run_isr_1();
+ if (v != 1)
+ __builtin_abort();
+}
+
+/**********************************************************************/
+
+ISR (2, signal)
+{
+ if (v == 1)
+ inc_v();
+ else
+ v += 2;
+}
+
+MK_RUN_ISR (2, 0)
+
+void test2 (void)
+{
+ run_isr_2();
+ if (v != 2)
+ __builtin_abort();
+ run_isr_2();
+ if (v != 4)
+ __builtin_abort();
+}
+
+
+/**********************************************************************/
+
+int main (void)
+{
+ test1();
+ test2();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/torture/isr-03-fixed.c b/gcc/testsuite/gcc.target/avr/torture/isr-03-fixed.c
new file mode 100644
index 00000000000..5606225aebc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/isr-03-fixed.c
@@ -0,0 +1,146 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -fno-lto -fno-toplevel-reorder" } */
+
+// No LTO for now due to PR lto/68384.
+
+#ifdef __AVR_TINY__
+unsigned char reg2;
+#else
+register unsigned char reg2 __asm("r2");
+#endif
+
+#include "../isr-test.h"
+
+#define SET_REG(reg,val) \
+ do { \
+ reg = (val); \
+ __asm __volatile__("" : "+r" (reg)); \
+ } while (0) \
+
+#define GET_REG(reg) \
+ ({ \
+ __asm __volatile__("" : "+r" (reg)); \
+ reg; \
+ })
+
+/**********************************************************************/
+
+ISR (1, signal)
+{
+ reg2++;
+}
+
+MK_RUN_ISR (1, 1ul << 2)
+
+void test1 (void)
+{
+ SET_REG (reg2, 0);
+ run_isr_1();
+ if (GET_REG (reg2) != 1)
+ __builtin_abort();
+}
+
+/**********************************************************************/
+
+__attribute__((noinline,noclone))
+void inc_r2 (void)
+{
+ reg2++;
+}
+
+ISR (2, signal)
+{
+ inc_r2 ();
+}
+
+MK_RUN_ISR (2, 1ul << 2)
+
+void test2 (void)
+{
+ run_isr_2();
+ if (GET_REG (reg2) != 2)
+ __builtin_abort();
+}
+
+
+/**********************************************************************/
+
+ISR (3, signal)
+{
+#ifndef __AVR_TINY__
+ register char r4 __asm ("r4");
+ __asm __volatile ("inc %0" : "+r" (r4));
+ __asm __volatile ("inc r5" ::: "r5");
+#endif
+}
+
+MK_RUN_ISR (3, 0)
+
+void test3 (void)
+{
+ run_isr_3();
+}
+
+
+/**********************************************************************/
+
+#define CLOBB(reg) \
+ do { \
+ __asm __volatile__ ("inc " #reg ::: #reg); \
+ } while (0)
+
+ISR (4, signal)
+{
+ char volatile v;
+ v = 1;
+
+#ifndef __AVR_TINY__
+ CLOBB (r3);
+ CLOBB (r4);
+ CLOBB (r5);
+ CLOBB (r6);
+ CLOBB (r7);
+ CLOBB (r8);
+ CLOBB (r9);
+ CLOBB (r10);
+ CLOBB (r11);
+ CLOBB (r12);
+ CLOBB (r13);
+ CLOBB (r14);
+ CLOBB (r15);
+ CLOBB (r16);
+ CLOBB (r17);
+#endif
+
+ CLOBB (r18);
+ CLOBB (r19);
+ CLOBB (r20);
+ CLOBB (r21);
+ CLOBB (r22);
+ CLOBB (r23);
+ CLOBB (r24);
+ CLOBB (r25);
+ CLOBB (r26);
+ CLOBB (r27);
+ CLOBB (r30);
+ CLOBB (r31);
+}
+
+MK_RUN_ISR (4, 0)
+
+void test4 (void)
+{
+ run_isr_4();
+}
+
+
+/**********************************************************************/
+
+int main (void)
+{
+ test1();
+ test2();
+ test3();
+ test4();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c
index b1da555bc31..ddee754c962 100644
--- a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c
+++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c
@@ -44,9 +44,9 @@ adx_test (void)
sum_ref = 0x0;
/* X = 0x00000001, Y = 0x00000000, C = 0. */
- c = _subborrow_u32 (c, x, y, &x);
+ c = _subborrow_u32 (c, y, x, &x);
/* X = 0xFFFFFFFF, Y = 0x00000000, C = 1. */
- c = _subborrow_u32 (c, x, y, &x);
+ c = _subborrow_u32 (c, y, x, &x);
/* X = 0xFFFFFFFF, Y = 0xFFFFFFFF, C = 1. */
if (x != sum_ref)
diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c
index b326291bb35..287e263a9dd 100644
--- a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c
+++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c
@@ -44,9 +44,9 @@ adx_test (void)
sum_ref = 0x0LL;
/* X = 0x0000000000000001, Y = 0x0000000000000000, C = 0. */
- c = _subborrow_u64 (c, x, y, &x);
+ c = _subborrow_u64 (c, y, x, &x);
/* X = 0xFFFFFFFFFFFFFFFF, Y = 0x0000000000000000, C = 1. */
- c = _subborrow_u64 (c, x, y, &x);
+ c = _subborrow_u64 (c, y, x, &x);
/* X = 0x0000000000000000, Y = 0x0000000000000000, C = 1. */
if (x != sum_ref)
diff --git a/gcc/testsuite/gcc.target/i386/avx-1.c b/gcc/testsuite/gcc.target/i386/avx-1.c
index 8377555f815..085ba81a672 100644
--- a/gcc/testsuite/gcc.target/i386/avx-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx-1.c
@@ -233,11 +233,15 @@
#define __builtin_ia32_getexppd512_mask(A, B, C, D) __builtin_ia32_getexppd512_mask(A, B, C, 8)
#define __builtin_ia32_getexpps512_mask(A, B, C, D) __builtin_ia32_getexpps512_mask(A, B, C, 8)
#define __builtin_ia32_getexpsd128_round(A, B, C) __builtin_ia32_getexpsd128_round(A, B, 4)
+#define __builtin_ia32_getexpsd_mask_round(A, B, C, D, E) __builtin_ia32_getexpsd_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getexpss128_round(A, B, C) __builtin_ia32_getexpss128_round(A, B, 4)
+#define __builtin_ia32_getexpss_mask_round(A, B, C, D, E) __builtin_ia32_getexpss_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getmantpd512_mask(A, F, C, D, E) __builtin_ia32_getmantpd512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantps512_mask(A, F, C, D, E) __builtin_ia32_getmantps512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantsd_round(A, B, C, D) __builtin_ia32_getmantsd_round(A, B, 1, 4)
+#define __builtin_ia32_getmantsd_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsd_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_getmantss_round(A, B, C, D) __builtin_ia32_getmantss_round(A, B, 1, 4)
+#define __builtin_ia32_getmantss_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantss_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_insertf32x4_mask(A, B, F, D, E) __builtin_ia32_insertf32x4_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x4_mask(A, B, F, D, E) __builtin_ia32_insertf64x4_mask(A, B, 1, D, E)
#define __builtin_ia32_inserti32x4_mask(A, B, F, D, E) __builtin_ia32_inserti32x4_mask(A, B, 1, D, E)
diff --git a/gcc/testsuite/gcc.target/i386/avx-pr80846.c b/gcc/testsuite/gcc.target/i386/avx-pr80846.c
new file mode 100644
index 00000000000..338f01039f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-pr80846.c
@@ -0,0 +1,39 @@
+/* PR target/80846 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx -mno-avx2" } */
+
+typedef __int128 V __attribute__((vector_size (32)));
+typedef long long W __attribute__((vector_size (32)));
+typedef int X __attribute__((vector_size (16)));
+typedef __int128 Y __attribute__((vector_size (64)));
+typedef long long Z __attribute__((vector_size (64)));
+
+W f1 (__int128 x, __int128 y) { return (W) ((V) { x, y }); }
+__int128 f2 (W x) { return ((V)x)[0]; }
+__int128 f3 (W x) { return ((V)x)[1]; }
+W f4 (X x, X y) { union { X x; __int128 i; } u = { .x = x }, v = { .x = y }; return (W) ((V) { u.i, v.i }); }
+X f5 (W x) { return (X)(((V)x)[0]); }
+X f6 (W x) { return (X)(((V)x)[1]); }
+W f7 (void) { return (W) ((V) { 2, 3 }); }
+W f8 (X x) { union { X x; __int128 i; } u = { .x = x }; return (W) ((V) { u.i, 3 }); }
+W f9 (X x) { union { X x; __int128 i; } u = { .x = x }; return (W) ((V) { 2, u.i }); }
+W f10 (X x) { union { X x; __int128 i; } u = { .x = x }; return (W) ((V) { u.i, u.i }); }
+#ifdef __AVX512F__
+Z f11 (__int128 x, __int128 y, __int128 z, __int128 a) { return (Z) ((Y) { x, y, z, a }); }
+__int128 f12 (Z x) { return ((Y)x)[0]; }
+__int128 f13 (Z x) { return ((Y)x)[1]; }
+__int128 f14 (Z x) { return ((Y)x)[2]; }
+__int128 f15 (Z x) { return ((Y)x)[3]; }
+Z f16 (X x, X y, X z, X a) { union { X x; __int128 i; } u = { .x = x }, v = { .x = y }, w = { .x = z }, t = { .x = a };
+ return (Z) ((Y) { u.i, v.i, w.i, t.i }); }
+X f17 (Z x) { return (X)(((Y)x)[0]); }
+X f18 (Z x) { return (X)(((Y)x)[1]); }
+X f19 (Z x) { return (X)(((Y)x)[2]); }
+X f20 (Z x) { return (X)(((Y)x)[3]); }
+Z f21 (void) { return (Z) ((Y) { 2, 3, 4, 5 }); }
+Z f22 (X x) { union { X x; __int128 i; } u = { .x = x }; return (Z) ((Y) { u.i, 3, 4, 5 }); }
+Z f23 (X x) { union { X x; __int128 i; } u = { .x = x }; return (Z) ((Y) { 2, u.i, 4, 5 }); }
+Z f24 (X x) { union { X x; __int128 i; } u = { .x = x }; return (Z) ((Y) { 2, 3, u.i, 5 }); }
+Z f25 (X x) { union { X x; __int128 i; } u = { .x = x }; return (Z) ((Y) { 2, 3, 4, u.i }); }
+Z f26 (X x) { union { X x; __int128 i; } u = { .x = x }; return (Z) ((Y) { u.i, u.i, u.i, u.i }); }
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr80846.c b/gcc/testsuite/gcc.target/i386/avx2-pr80846.c
new file mode 100644
index 00000000000..907fd4f7b62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-pr80846.c
@@ -0,0 +1,5 @@
+/* PR target/80846 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx2 -mno-avx512f" } */
+
+#include "avx-pr80846.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr81532.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr81532.c
new file mode 100644
index 00000000000..6ebaed6f715
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr81532.c
@@ -0,0 +1,5 @@
+/* PR target/81532 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx512bw -mavx512vl -mno-avx512dq" } */
+
+#include "avx512dq-pr81532.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-pr81532.c b/gcc/testsuite/gcc.target/i386/avx512dq-pr81532.c
new file mode 100644
index 00000000000..39632a2c482
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-pr81532.c
@@ -0,0 +1,12 @@
+/* PR target/81532 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx512dq -mavx512vl -mno-avx512bw" } */
+
+typedef unsigned __int128 V __attribute__ ((vector_size (64)));
+
+V
+foo (V c)
+{
+ c >>= 0 != c;
+ return c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr80846.c b/gcc/testsuite/gcc.target/i386/avx512f-pr80846.c
new file mode 100644
index 00000000000..c32c9762cf9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-pr80846.c
@@ -0,0 +1,5 @@
+/* PR target/80846 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx512f" } */
+
+#include "avx-pr80846.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vaddsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vaddsd-3.c
new file mode 100644
index 00000000000..fbe09b1220b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vaddsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_add (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] + s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_add_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_add_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_add_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_add_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_add (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_add (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vaddss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vaddss-3.c
new file mode 100644
index 00000000000..45fb29594e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vaddss-3.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_add (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] + s2[0];
+
+ int i;
+ for (i = 1; i < SIZE; i++)
+ r[i] = s1[i];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_add_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_add_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_add_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_add_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_add (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_add (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vdivsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vdivsd-3.c
new file mode 100644
index 00000000000..0baaf75e194
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vdivsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_div (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] / s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_div_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_div_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_div_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_div_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_div (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_div (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vdivss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vdivss-3.c
new file mode 100644
index 00000000000..d337bb21182
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vdivss-3.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_div (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] / s2[0];
+ int i;
+ for (i = 1; i < SIZE; i++)
+ r[i] = s1[i];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_div_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_div_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_div_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_div_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_div (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_div (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-1.c
index 63194a38b17..226cd9665ca 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-1.c
@@ -1,15 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpsd\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
volatile __m128d x;
+volatile __mmask8 m;
void extern
avx512f_test (void)
{
x = _mm_getexp_sd (x, x);
+ x = _mm_mask_getexp_sd (x, m, x, x);
+ x = _mm_maskz_getexp_sd (m, x, x);
x = _mm_getexp_round_sd (x, x, _MM_FROUND_NO_EXC);
+ x = _mm_mask_getexp_round_sd (x, m, x, x, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getexp_round_sd (m, x, x, _MM_FROUND_NO_EXC);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-2.c
index 4f7c94db9ae..cb82448725f 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpsd-2.c
@@ -6,30 +6,61 @@
#include <math.h>
#include "avx512f-check.h"
+#include "avx512f-helper.h"
+#include "avx512f-mask-type.h"
static void
compute_vgetexpsd (double *s, double *r)
{
r[0] = floor (log (s[0]) / log (2));
+ r[1] = s[1];
}
void static
avx512f_test (void)
{
int i;
- union128d res1, s1;
+ union128d res1, res2, res3, res4, res5, res6, s1;
+ MASK_TYPE mask = MASK_VALUE;
double res_ref[SIZE];
for (i = 0; i < SIZE; i++)
{
s1.a[i] = 5.0 - i;
- res_ref[i] = s1.a[i];
+ res2.a[i] = DEFAULT_VALUE;
+ res5.a[i] = DEFAULT_VALUE;
}
res1.x = _mm_getexp_sd (s1.x, s1.x);
+ res2.x = _mm_mask_getexp_sd (res2.x, mask, s1.x, s1.x);
+ res3.x = _mm_maskz_getexp_sd (mask, s1.x, s1.x);
+ res4.x = _mm_getexp_round_sd (s1.x, s1.x, _MM_FROUND_NO_EXC);
+ res5.x = _mm_mask_getexp_round_sd (res5.x, mask, s1.x, s1.x, _MM_FROUND_NO_EXC);
+ res6.x = _mm_maskz_getexp_round_sd (mask, s1.x, s1.x, _MM_FROUND_NO_EXC);
compute_vgetexpsd (s1.a, res_ref);
if (check_fp_union128d (res1, res_ref))
abort ();
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_fp_union128d (res2, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_fp_union128d (res3, res_ref))
+ abort ();
+
+ compute_vgetexpsd (s1.a, res_ref);
+
+ if (check_fp_union128d (res4, res_ref))
+ abort ();
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_fp_union128d (res5, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_fp_union128d (res6, res_ref))
+ abort ();
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-1.c
index 9103e6ad84f..495b93c9c6a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-1.c
@@ -1,15 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -O2" } */
/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+\, %xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetexpss\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
volatile __m128 x;
+volatile __mmask8 m;
void extern
avx512f_test (void)
{
x = _mm_getexp_ss (x, x);
+ x = _mm_mask_getexp_ss (x, m, x, x);
+ x = _mm_maskz_getexp_ss (m, x, x);
x = _mm_getexp_round_ss (x, x, _MM_FROUND_NO_EXC);
+ x = _mm_mask_getexp_round_ss (x, m, x, x, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getexp_round_ss (m, x, x, _MM_FROUND_NO_EXC);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-2.c
index 926f4d87ffb..ed193af78d4 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetexpss-2.c
@@ -6,30 +6,63 @@
#include <math.h>
#include "avx512f-check.h"
+#include "avx512f-helper.h"
+#include "avx512f-mask-type.h"
static void
compute_vgetexpss (float *s, float *r)
{
+ int i;
r[0] = floor (log (s[0]) / log (2));
+ for(i = 1; i < SIZE; i++)
+ r[i] = s[i];
}
void static
avx512f_test (void)
{
int i;
- union128 res1, s1;
+ union128 res1, res2, res3, res4, res5, res6, s1;
+ MASK_TYPE mask = MASK_VALUE;
float res_ref[SIZE];
for (i = 0; i < SIZE; i++)
{
s1.a[i] = 5.0 - i;
- res_ref[i] = s1.a[i];
+ res2.a[i] = DEFAULT_VALUE;
+ res5.a[i] = DEFAULT_VALUE;
}
res1.x = _mm_getexp_ss (s1.x, s1.x);
+ res2.x = _mm_mask_getexp_ss (res2.x, mask, s1.x, s1.x);
+ res3.x = _mm_maskz_getexp_ss (mask, s1.x, s1.x);
+ res4.x = _mm_getexp_round_ss (s1.x, s1.x, _MM_FROUND_NO_EXC);
+ res5.x = _mm_mask_getexp_round_ss (res5.x, mask, s1.x, s1.x, _MM_FROUND_NO_EXC);
+ res6.x = _mm_maskz_getexp_round_ss (mask, s1.x, s1.x, _MM_FROUND_NO_EXC);
compute_vgetexpss (s1.a, res_ref);
if (check_fp_union128 (res1, res_ref))
abort ();
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_fp_union128 (res2, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_fp_union128 (res3, res_ref))
+ abort ();
+
+ compute_vgetexpss (s1.a, res_ref);
+
+ if (check_fp_union128 (res4, res_ref))
+ abort ();
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_fp_union128 (res5, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_fp_union128 (res6, res_ref))
+ abort ();
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-1.c
index c501ba6729e..25a64202ea7 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-1.c
@@ -1,16 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f" } */
/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantsd\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
volatile __m128d x, y, z;
+volatile __mmask8 m;
void extern
avx512f_test (void)
{
x = _mm_getmant_sd (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
- x = _mm_getmant_round_sd (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src,
- _MM_FROUND_NO_EXC);
+ x = _mm_mask_getmant_sd (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_maskz_getmant_sd (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_getmant_round_sd (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src,_MM_FROUND_NO_EXC);
+ x = _mm_mask_getmant_round_sd (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getmant_round_sd (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c
index 3a34ca4f05d..45875b4a921 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c
@@ -5,6 +5,10 @@
#include "avx512f-check.h"
#include <math.h>
+#include "avx512f-helper.h"
+
+#define SIZE (128/64)
+#include "avx512f-mask-type.h"
union fp_int_t
{
@@ -76,18 +80,51 @@ compute_vgetmantsd (double *r, double *s1, double *s2, int interv,
static void
avx512f_test (void)
{
- union128d res1, src1, src2;
+ union128d res1, res2, res3, res4, res5, res6, src1, src2;
double res_ref[2];
- int interv = _MM_MANT_NORM_p5_1;
- int signctrl = _MM_MANT_SIGN_src;
+ MASK_TYPE mask = MASK_VALUE;
src1.x = _mm_set_pd (-3.0, 111.111);
src2.x = _mm_set_pd (222.222, -2.0);
+
+ int i;
+ for (i = 0; i < SIZE; i++)
+ {
+ res2.a[i] = DEFAULT_VALUE;
+ res5.a[i] = DEFAULT_VALUE;
+ }
- res1.x = _mm_getmant_sd (src1.x, src2.x, interv, signctrl);
+ res1.x = _mm_getmant_sd (src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res2.x = _mm_mask_getmant_sd (res2.x, mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res3.x = _mm_maskz_getmant_sd (mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res4.x = _mm_getmant_round_sd (src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ res5.x = _mm_mask_getmant_round_sd (res5.x, mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ res6.x = _mm_maskz_getmant_round_sd (mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
- compute_vgetmantsd (res_ref, src1.a, src2.a, interv, signctrl);
+ compute_vgetmantsd (res_ref, src1.a, src2.a, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
if (check_union128d (res1, res_ref))
abort ();
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ compute_vgetmantsd (res_ref, src1.a, src2.a, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+
+ if (check_union128d (res4, res_ref))
+ abort ();
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res5, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res6, res_ref))
+ abort ();
+
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-1.c
index 8ce9d467806..00a055ffeee 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-1.c
@@ -1,16 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f" } */
/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vgetmantss\[ \\t\]+\[^\n\]*\{sae\}\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
volatile __m128 x, y, z;
+volatile __mmask8 m;
void extern
avx512f_test (void)
{
x = _mm_getmant_ss (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
- x = _mm_getmant_round_ss (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src,
- _MM_FROUND_NO_EXC);
+ x = _mm_mask_getmant_ss (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_maskz_getmant_ss (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src);
+ x = _mm_getmant_round_ss (y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm_mask_getmant_round_ss (x, m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ x = _mm_maskz_getmant_round_ss (m, y, z, _MM_MANT_NORM_p75_1p5, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c
index 7c30ea7d8e6..bcd449b4ae2 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c
@@ -5,6 +5,10 @@
#include "avx512f-check.h"
#include <math.h>
+#include "avx512f-helper.h"
+
+#define SIZE (128/32)
+#include "avx512f-mask-type.h"
union fp_int_t
{
@@ -72,7 +76,7 @@ compute_vgetmantss (float *r, float *s1, float *s2, int interv,
{
int i;
r[0] = get_norm_mant (s2[0], signctrl, interv);
- for (i = 1; i < 4; i++)
+ for (i = 1; i < SIZE; i++)
{
r[i] = s1[i];
}
@@ -81,18 +85,50 @@ compute_vgetmantss (float *r, float *s1, float *s2, int interv,
static void
avx512f_test (void)
{
- union128 res1, src1, src2;
+ union128 res1, res2, res3, res4, res5, res6, src1, src2;
float res_ref[4];
- int interv = _MM_MANT_NORM_p5_1;
- int signctrl = _MM_MANT_SIGN_src;
+ MASK_TYPE mask = MASK_VALUE;
src1.x = _mm_set_ps (-24.043, 68.346, -43.35, 546.46);
src2.x = _mm_set_ps (222.222, 333.333, 444.444, -2.0);
- res1.x = _mm_getmant_ss (src1.x, src2.x, interv, signctrl);
+ int i;
+ for (i = 0; i < SIZE; i++)
+ {
+ res2.a[i] = DEFAULT_VALUE;
+ res5.a[i] = DEFAULT_VALUE;
+ }
+
+ res1.x = _mm_getmant_ss (src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res2.x = _mm_mask_getmant_ss (res2.x, mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res3.x = _mm_maskz_getmant_ss (mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+ res4.x = _mm_getmant_round_ss (src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ res5.x = _mm_mask_getmant_round_ss (res5.x, mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
+ res6.x = _mm_maskz_getmant_round_ss (mask, src1.x, src2.x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src, _MM_FROUND_NO_EXC);
- compute_vgetmantss (res_ref, src1.a, src2.a, interv, signctrl);
+ compute_vgetmantss (res_ref, src1.a, src2.a, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
if (check_union128 (res1, res_ref))
abort ();
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ compute_vgetmantss (res_ref, src1.a, src2.a, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
+
+ if (check_union128 (res4, res_ref))
+ abort ();
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res5, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res6, res_ref))
+ abort ();
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmaxsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vmaxsd-3.c
new file mode 100644
index 00000000000..95c9c6335af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmaxsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_max (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] > s2[0] ? s1[0] : s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_max_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_max_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_max_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_max_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_max (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_max (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmaxss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vmaxss-3.c
new file mode 100644
index 00000000000..e40c891001b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmaxss-3.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_max (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] > s2[0] ? s1[0] : s2[0];
+ int i;
+ for (i = 1; i < SIZE; i++)
+ {
+ r[i] = s1[i];
+ }
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_max_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_max_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_max_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_max_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_max (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_max (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vminsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vminsd-3.c
new file mode 100644
index 00000000000..eac806b0f23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vminsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_min (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] < s2[0] ? s1[0] : s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_min_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_min_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_min_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_min_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_min (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_min (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vminss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vminss-3.c
new file mode 100644
index 00000000000..0ecddd6803e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vminss-3.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_min (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] < s2[0] ? s1[0] : s2[0];
+ int i;
+ for (i = 1; i < SIZE; i++)
+ {
+ r[i] = s1[i];
+ }
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_min_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_min_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_min_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_min_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_min (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_min (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmulsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vmulsd-3.c
new file mode 100644
index 00000000000..f6afb693e68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmulsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_mul (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] * s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_mul_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_mul_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_mul_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_mul_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_mul (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_mul (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmulss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vmulss-3.c
new file mode 100644
index 00000000000..3d579905bae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vmulss-3.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_mul (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] * s2[0];
+ int i;
+ for (i = 1; i < SIZE; i++)
+ r[i] = s1[i];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_mul_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_mul_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_mul_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_mul_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_mul (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_mul (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpermd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vpermd-2.c
index dbd4544c39e..b36a9c2da0a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpermd-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpermd-2.c
@@ -41,18 +41,14 @@ TEST (void)
res3.a[i] = DEFAULT_VALUE;
}
-#if AVX512F_LEN == 512
res1.x = INTRINSIC (_permutexvar_epi32) (src1.x, src2.x);
-#endif
res2.x = INTRINSIC (_maskz_permutexvar_epi32) (mask, src1.x, src2.x);
res3.x = INTRINSIC (_mask_permutexvar_epi32) (res3.x, mask, src1.x, src2.x);
CALC (src1.a, src2.a, res_ref);
-#if AVX512F_LEN == 512
if (UNION_CHECK (AVX512F_LEN, i_d) (res1, res_ref))
abort ();
-#endif
MASK_ZERO (i_d) (res_ref, mask, SIZE);
if (UNION_CHECK (AVX512F_LEN, i_d) (res2, res_ref))
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpermq-imm-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vpermq-imm-2.c
index 770d5623f5f..dd88cd46c0b 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpermq-imm-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpermq-imm-2.c
@@ -40,18 +40,14 @@ TEST (void)
res3.a[i] = DEFAULT_VALUE;
}
-#if AVX512F_LEN == 512
res1.x = INTRINSIC (_permutex_epi64) (src1.x, IMM_MASK);
-#endif
res2.x = INTRINSIC (_maskz_permutex_epi64) (mask, src1.x, IMM_MASK);
res3.x = INTRINSIC (_mask_permutex_epi64) (res3.x, mask, src1.x, IMM_MASK);
CALC (src1.a, IMM_MASK, res_ref);
-#if AVX512F_LEN == 512
if (UNION_CHECK (AVX512F_LEN, i_q) (res1, res_ref))
abort ();
-#endif
MASK_ZERO (i_q) (res_ref, mask, SIZE);
if (UNION_CHECK (AVX512F_LEN, i_q) (res2, res_ref))
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpermq-var-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vpermq-var-2.c
index c596b1d9c40..6c222888e88 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vpermq-var-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vpermq-var-2.c
@@ -41,18 +41,14 @@ TEST (void)
res3.a[i] = DEFAULT_VALUE;
}
-#if AVX512F_LEN == 512
res1.x = INTRINSIC (_permutexvar_epi64) (src1.x, src2.x);
-#endif
res2.x = INTRINSIC (_maskz_permutexvar_epi64) (mask, src1.x, src2.x);
res3.x = INTRINSIC (_mask_permutexvar_epi64) (res3.x, mask, src1.x, src2.x);
CALC (src1.a, src2.a, res_ref);
-#if AVX512F_LEN == 512
if (UNION_CHECK (AVX512F_LEN, i_q) (res1, res_ref))
abort ();
-#endif
MASK_ZERO (i_q) (res_ref, mask, SIZE);
if (UNION_CHECK (AVX512F_LEN, i_q) (res2, res_ref))
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vsubsd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vsubsd-3.c
new file mode 100644
index 00000000000..d9f79133937
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vsubsd-3.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+static void
+calc_sub (double *r, double *s1, double *s2)
+{
+ r[0] = s1[0] - s2[0];
+ r[1] = s1[1];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128d res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ double res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_sub_sd (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_sub_sd (mask, src1.x, src2.x);
+ res3.x = _mm_mask_sub_round_sd (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_sub_round_sd (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_sub (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res1, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res2, res_ref))
+ abort ();
+
+ calc_sub (res_ref, src1.a, src2.a);
+
+ MASK_MERGE (d) (res_ref, mask, 1);
+ if (check_union128d (res3, res_ref))
+ abort ();
+
+ MASK_ZERO (d) (res_ref, mask, 1);
+ if (check_union128d (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vsubss-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vsubss-3.c
new file mode 100644
index 00000000000..bd597c959a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vsubss-3.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#include "avx512f-check.h"
+
+#include "avx512f-helper.h"
+
+#define SIZE (128 / 32)
+#include "avx512f-mask-type.h"
+
+static void
+calc_sub (float *r, float *s1, float *s2)
+{
+ r[0] = s1[0] - s2[0];
+ int i;
+ for (i = 1; i < SIZE; i++)
+ r[i] = s1[i];
+}
+
+void
+avx512f_test (void)
+{
+ int i, sign;
+ union128 res1, res2, res3, res4, src1, src2;
+ MASK_TYPE mask = 0;
+ float res_ref[SIZE];
+
+ sign = -1;
+ for (i = 0; i < SIZE; i++)
+ {
+ src1.a[i] = 1.5 + 34.67 * i * sign;
+ src2.a[i] = -22.17 * i * sign + 1.0;
+ res1.a[i] = DEFAULT_VALUE;
+ res3.a[i] = DEFAULT_VALUE;
+ sign = sign * -1;
+ }
+
+ res1.x = _mm_mask_sub_ss (res1.x, mask, src1.x, src2.x);
+ res2.x = _mm_maskz_sub_ss (mask, src1.x, src2.x);
+ res3.x = _mm_mask_sub_round_ss (res3.x, mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+ res4.x = _mm_maskz_sub_round_ss (mask, src1.x, src2.x, _MM_FROUND_NO_EXC);
+
+ calc_sub (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res1, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res2, res_ref))
+ abort ();
+
+ calc_sub (res_ref, src1.a, src2.a);
+
+ MASK_MERGE () (res_ref, mask, 1);
+ if (check_union128 (res3, res_ref))
+ abort ();
+
+ MASK_ZERO () (res_ref, mask, 1);
+ if (check_union128 (res4, res_ref))
+ abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpermd-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpermd-1.c
index fa1aaa390ab..069bb5d6c63 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpermd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpermd-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vpermd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
@@ -11,6 +12,7 @@ volatile __mmask8 m;
void extern
avx512vl_test (void)
{
+ x = _mm256_permutexvar_epi32 (x, x);
x = _mm256_maskz_permutexvar_epi32 (m, x, x);
x = _mm256_mask_permutexvar_epi32 (x, m, x, x);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-imm-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-imm-1.c
index c74c8ce96c7..2340a6d9993 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-imm-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-imm-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
@@ -11,6 +12,7 @@ volatile __mmask8 m;
void extern
avx512vl_test (void)
{
+ x = _mm256_permutex_epi64 (x, 13);
x = _mm256_mask_permutex_epi64 (x, m, x, 13);
x = _mm256_maskz_permutex_epi64 (m, x, 13);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-var-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-var-1.c
index 43ccad3d6c1..69185e50f76 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-var-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpermq-var-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -O2" } */
+/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\](?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpermq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
@@ -11,6 +12,7 @@ volatile __mmask8 m;
void extern
avx512vl_test (void)
{
+ x = _mm256_permutexvar_epi64 (x, x);
x = _mm256_maskz_permutexvar_epi64 (m, x, x);
x = _mm256_mask_permutexvar_epi64 (x, m, x, x);
}
diff --git a/gcc/testsuite/gcc.target/i386/cmov7.c b/gcc/testsuite/gcc.target/i386/cmov7.c
index 8d637504fd7..e648fed8b2a 100644
--- a/gcc/testsuite/gcc.target/i386/cmov7.c
+++ b/gcc/testsuite/gcc.target/i386/cmov7.c
@@ -10,7 +10,7 @@
(set (reg:DF) (float_extend:DF (mem:SF (symbol_ref...)))). */
double
-sgn (double __x)
+foo (double __x)
{
- return __x >= 0.0 ? 1.0 : -1.0;
+ return __x >= 1.0 ? 0.0 : -1.0;
}
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-5.c b/gcc/testsuite/gcc.target/i386/interrupt-5.c
index 803c0636299..5742b6f4743 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-5.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-5.c
@@ -7,12 +7,21 @@ extern void link_error (void);
typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+struct interrupt_frame
+{
+ uword_t ip;
+ uword_t cs;
+ uword_t flags;
+ uword_t sp;
+ uword_t ss;
+};
+
__attribute__ ((used, interrupt))
void
-foo (void *frame, uword_t error)
+foo (struct interrupt_frame *frame, uword_t error)
{
void *ra = __builtin_return_address (0);
- if ((uintptr_t) ra != (uintptr_t) error)
+ if ((uintptr_t) ra != (uintptr_t) frame->ip)
link_error ();
}
diff --git a/gcc/testsuite/gcc.target/i386/mvc2.c b/gcc/testsuite/gcc.target/i386/mvc2.c
index 9635ec83fac..34a777c1d5e 100644
--- a/gcc/testsuite/gcc.target/i386/mvc2.c
+++ b/gcc/testsuite/gcc.target/i386/mvc2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
__attribute__((target_clones("avx","arch=slm","arch=core-avx2")))
int foo ();
diff --git a/gcc/testsuite/gcc.target/i386/mvc3.c b/gcc/testsuite/gcc.target/i386/mvc3.c
index f940cdbbf55..1c7755fabbe 100644
--- a/gcc/testsuite/gcc.target/i386/mvc3.c
+++ b/gcc/testsuite/gcc.target/i386/mvc3.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
__attribute__((target_clones("avx","arch=slm","arch=core-avx2")))
int foo (); /* { dg-error "default target was not set" } */
diff --git a/gcc/testsuite/gcc.target/i386/mvc6.c b/gcc/testsuite/gcc.target/i386/mvc6.c
index d584f573328..af631394980 100644
--- a/gcc/testsuite/gcc.target/i386/mvc6.c
+++ b/gcc/testsuite/gcc.target/i386/mvc6.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
/* { dg-options "-O3" } */
/* { dg-final { scan-assembler "vpshufb" } } */
/* { dg-final { scan-assembler "punpcklbw" } } */
diff --git a/gcc/testsuite/gcc.target/i386/naked-1.c b/gcc/testsuite/gcc.target/i386/naked-1.c
new file mode 100644
index 00000000000..440dbe9ee7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/naked-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+/* Verify that __attribute__((naked)) produces a naked function
+ that does not use ret to return but traps at the end. */
+void
+__attribute__((naked))
+foo (void)
+{
+ __asm__ ("# naked");
+}
+/* { dg-final { scan-assembler "# naked" } } */
+/* { dg-final { scan-assembler "ud2" } } */
+/* { dg-final { scan-assembler-not "ret" } } */
diff --git a/gcc/testsuite/gcc.target/i386/naked-2.c b/gcc/testsuite/gcc.target/i386/naked-2.c
new file mode 100644
index 00000000000..adcd7121541
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/naked-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+/* Verify that __attribute__((naked)) produces a naked function
+ that does not construct a frame. */
+void
+__attribute__((naked))
+foo (void)
+{
+ __asm__ ("# naked");
+}
+/* { dg-final { scan-assembler "# naked" } } */
+/* { dg-final { scan-assembler-not "push" } } */
+/* { dg-final { scan-assembler-not "pop" } } */
diff --git a/gcc/testsuite/gcc.target/i386/naked-3.c b/gcc/testsuite/gcc.target/i386/naked-3.c
new file mode 100644
index 00000000000..845300d6e4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/naked-3.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2" } */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int data;
+
+/* Verify that naked function traps at the end. */
+
+void
+__attribute__((naked, noinline, noclone))
+naked (void)
+{
+ if (data == 0x12345678)
+ return;
+ asm ("ret");
+}
+
+void handler (int i)
+{
+ exit (0);
+}
+
+int main ()
+{
+ struct sigaction s;
+
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = handler;
+ s.sa_flags = 0;
+ sigaction (SIGILL, &s, NULL);
+
+ data = 0x12345678;
+ naked ();
+
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr48723.c b/gcc/testsuite/gcc.target/i386/pr48723.c
index ad102090e9f..222c075fbf7 100644
--- a/gcc/testsuite/gcc.target/i386/pr48723.c
+++ b/gcc/testsuite/gcc.target/i386/pr48723.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-stack-check "" } */
/* { dg-options "-fstack-check -mavx" } */
struct S0
diff --git a/gcc/testsuite/gcc.target/i386/pr55672.c b/gcc/testsuite/gcc.target/i386/pr55672.c
index 6f1c898c748..f7b0d717e01 100644
--- a/gcc/testsuite/gcc.target/i386/pr55672.c
+++ b/gcc/testsuite/gcc.target/i386/pr55672.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-stack-check "generic" } */
/* { dg-options "-O -fstack-check=generic" } */
int main ()
diff --git a/gcc/testsuite/gcc.target/i386/pr67265-2.c b/gcc/testsuite/gcc.target/i386/pr67265-2.c
index a9f2eb460ef..690a7845557 100644
--- a/gcc/testsuite/gcc.target/i386/pr67265-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr67265-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-stack-check "" } */
/* { dg-options "-O -fstack-check" } */
void foo (int n)
diff --git a/gcc/testsuite/gcc.target/i386/pr67265.c b/gcc/testsuite/gcc.target/i386/pr67265.c
index 7827685fe5f..2671acc043a 100644
--- a/gcc/testsuite/gcc.target/i386/pr67265.c
+++ b/gcc/testsuite/gcc.target/i386/pr67265.c
@@ -2,6 +2,7 @@
/* Reduced testcase by Johannes Dewender <gnu@JonnyJD.net> */
/* { dg-do compile } */
+/* { dg-require-stack-check "" } */
/* { dg-options "-O -fstack-check -fPIC" } */
int a, b, c, d, e;
diff --git a/gcc/testsuite/gcc.target/i386/pr69255-2.c b/gcc/testsuite/gcc.target/i386/pr69255-2.c
index ebe6828e188..af3be6c31a2 100644
--- a/gcc/testsuite/gcc.target/i386/pr69255-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr69255-2.c
@@ -12,7 +12,8 @@ __attribute__ ((__vector_size__ (16))) int b;
void
foo (const long long *p)
{
- __builtin_ia32_gather3siv4di (a, p, b, 1, 1); /* { dg-error "needs isa option -m32 -mavx512vl" } */
+ volatile __attribute__ ((__vector_size__ (32))) long long c;
+ c = __builtin_ia32_gather3siv4di (a, p, b, 1, 1); /* { dg-error "needs isa option -m32 -mavx512vl" } */
/* { dg-warning "AVX vector return without AVX enabled changes the ABI" "" { target *-*-* } .-1 } */
/* { dg-warning "AVX vector argument without AVX enabled changes the ABI" "" { target *-*-* } .-2 } */
}
diff --git a/gcc/testsuite/gcc.target/i386/pr79793-1.c b/gcc/testsuite/gcc.target/i386/pr79793-1.c
new file mode 100644
index 00000000000..a382fe9c5e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79793-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -mgeneral-regs-only" } */
+
+void
+ __attribute__ ((interrupt))
+fn1 (void *frame)
+{
+ char fxsave_region [512] __attribute__((aligned(16)));
+ __builtin_ia32_fxsave64 (fxsave_region);
+}
+
+/* { dg-final { scan-assembler-times "sub\[lq\]\[\t \]*\\\$400,\[\t \]*%\[re\]sp" 1 } } */
+/* { dg-final { scan-assembler-times "fxsave64\[\t \]*-120\\(%\[re\]sp\\)" 1 } } */
+/* { dg-final { scan-assembler-times "add\[lq\]\[\t \]*\\\$400,\[\t \]*%\[re\]sp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr79793-2.c b/gcc/testsuite/gcc.target/i386/pr79793-2.c
new file mode 100644
index 00000000000..f6ae5aed33a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79793-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -mgeneral-regs-only" } */
+
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+
+void
+ __attribute__ ((interrupt))
+fn1 (void *frame, uword_t error)
+{
+ char fxsave_region [512] __attribute__((aligned(16)));
+ __builtin_ia32_fxsave64 (fxsave_region);
+}
+
+/* { dg-final { scan-assembler-times "sub\[lq\]\[\t \]*\\\$392,\[\t \]*%\[re\]sp" 1 } } */
+/* { dg-final { scan-assembler-times "fxsave64\[\t \]*-120\\(%\[re\]sp\\)" 1 } } */
+/* { dg-final { scan-assembler-times "add\[lq\]\[\t \]*\\\$400,\[\t \]*%\[re\]sp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr80569.c b/gcc/testsuite/gcc.target/i386/pr80569.c
new file mode 100644
index 00000000000..8e11c40bb08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr80569.c
@@ -0,0 +1,9 @@
+/* PR target/80569 */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -m16 -march=haswell" } */
+
+void load_kernel(void *setup_addr)
+{
+ unsigned int seg = (unsigned int)setup_addr >> 4;
+ asm("movl %0, %%es" : : "r"(seg));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr80833-3.c b/gcc/testsuite/gcc.target/i386/pr80833-3.c
new file mode 100644
index 00000000000..6d5b8bb6b69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr80833-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -mavx512dq -mavx512vl -mno-avx512bw -mtune=intel" } */
+
+__int128 test (__int128 a)
+{
+ asm ("" : "+v" (a) : : "xmm0", "xmm1", "xmm2", "xmm3",
+ "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11",
+ "xmm12", "xmm13", "xmm14", "xmm15");
+ return a;
+}
+
+/* { dg-final { scan-assembler "pinsrq" } } */
+/* { dg-final { scan-assembler "pextrq" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81128.c b/gcc/testsuite/gcc.target/i386/pr81128.c
new file mode 100644
index 00000000000..90a567ad690
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81128.c
@@ -0,0 +1,65 @@
+/* PR ipa/81128 */
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+/* { dg-require-ifunc "" } */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+int resolver_fn = 0;
+int resolved_fn = 0;
+
+static inline void
+do_it_right_at_runtime_A ()
+{
+ resolved_fn++;
+}
+
+static inline void
+do_it_right_at_runtime_B ()
+{
+ resolved_fn++;
+}
+
+static inline void do_it_right_at_runtime (void);
+
+void do_it_right_at_runtime (void)
+ __attribute__ ((ifunc ("resolve_do_it_right_at_runtime")));
+
+static void (*resolve_do_it_right_at_runtime (void)) (void)
+{
+ srand (time (NULL));
+ int r = rand ();
+ resolver_fn++;
+
+ /* Use intermediate variable to get a warning for non-matching
+ * prototype. */
+ typeof(do_it_right_at_runtime) *func;
+ if (r & 1)
+ func = do_it_right_at_runtime_A;
+ else
+ func = do_it_right_at_runtime_B;
+
+ return (void *) func;
+}
+
+int
+main (void)
+{
+ const unsigned int ITERS = 10;
+
+ for (int i = ITERS; i > 0; i--)
+ {
+ do_it_right_at_runtime ();
+ }
+
+ if (resolver_fn != 1)
+ __builtin_abort ();
+
+ if (resolved_fn != 10)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81214.c b/gcc/testsuite/gcc.target/i386/pr81214.c
new file mode 100644
index 00000000000..2584decdb3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81214.c
@@ -0,0 +1,14 @@
+/* PR ipa/81214. */
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("avx","arch=slm","arch=core-avx2","default")))
+int
+foo ()
+{
+ return -2;
+}
+
+/* { dg-final { scan-assembler "\t.globl\tfoo" } } */
+/* { dg-final { scan-assembler "foo.resolver:" } } */
+/* { dg-final { scan-assembler "foo, @gnu_indirect_function" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81225.c b/gcc/testsuite/gcc.target/i386/pr81225.c
new file mode 100644
index 00000000000..db95e941c14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81225.c
@@ -0,0 +1,14 @@
+/* PR target/81225 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512ifma -O3 -ffloat-store" } */
+
+long a[24];
+float b[4], c[24];
+int d;
+
+void
+foo ()
+{
+ for (d = 0; d < 24; d++)
+ c[d] = (float) d ? : b[a[d]];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81294-1.c b/gcc/testsuite/gcc.target/i386/pr81294-1.c
new file mode 100644
index 00000000000..6a15ed0a410
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81294-1.c
@@ -0,0 +1,29 @@
+/* PR target/81294 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include <x86intrin.h>
+
+int
+main ()
+{
+ volatile unsigned char c;
+ unsigned int x;
+ volatile unsigned int y, sum_ref;
+
+ c = 0;
+ x = 1;
+ y = 0;
+ sum_ref = 0x0;
+
+ /* X = 0x00000001, Y = 0x00000000, C = 0. */
+ c = _subborrow_u32 (c, y, x, &x);
+ /* X = 0xFFFFFFFF, Y = 0x00000000, C = 1. */
+ c = _subborrow_u32 (c, y, x, &x);
+ /* X = 0xFFFFFFFF, Y = 0xFFFFFFFF, C = 1. */
+
+ if (x != sum_ref)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81294-2.c b/gcc/testsuite/gcc.target/i386/pr81294-2.c
new file mode 100644
index 00000000000..3e3bdb44139
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81294-2.c
@@ -0,0 +1,28 @@
+/* PR target/81294 */
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+#include <x86intrin.h>
+
+int main ()
+{
+ volatile unsigned char c;
+ unsigned long long x;
+ volatile unsigned long long y, sum_ref;
+
+ c = 0;
+ x = 1LL;
+ y = 0LL;
+ sum_ref = 0x0LL;
+
+ /* X = 0x0000000000000001, Y = 0x0000000000000000, C = 0. */
+ c = _subborrow_u64 (c, y, x, &x);
+ /* X = 0xFFFFFFFFFFFFFFFF, Y = 0x0000000000000000, C = 1. */
+ c = _subborrow_u64 (c, y, x, &x);
+ /* X = 0x0000000000000000, Y = 0x0000000000000000, C = 1. */
+
+ if (x != sum_ref)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81300.c b/gcc/testsuite/gcc.target/i386/pr81300.c
new file mode 100644
index 00000000000..11eb55fed8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81300.c
@@ -0,0 +1,30 @@
+/* PR target/81300 */
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+int
+__attribute__((noinline, noclone))
+foo (void)
+{
+ unsigned long long _discard = 0, zero = 0, maxull = 0;
+ unsigned char zero1 = __builtin_ia32_addcarryx_u64 (0, 0, 0, &_discard);
+ unsigned char zero2 = __builtin_ia32_addcarryx_u64 (zero1, 0, 0, &zero);
+ __builtin_ia32_sbb_u64 (0x0, 2, -1, &_discard);
+ unsigned char one = __builtin_ia32_sbb_u64 (0, zero, 1, &maxull);
+ unsigned long long x = __builtin_ia32_sbb_u64 (one, zero2, 0, &_discard);
+
+ unsigned long long z1 = 0;
+ __asm__ ("mov{q}\t{%1, %0|%0, %1}" : "+r" (z1) : "r" (x));
+ unsigned long long z2 = 3;
+ __asm__ ("mov{q}\t{%1, %0|%0, %1}" : "+r" (z2) : "r" (x));
+
+ return 1 - (z1 | z2);
+}
+
+int main ()
+{
+ if (foo ())
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81313-1.c b/gcc/testsuite/gcc.target/i386/pr81313-1.c
new file mode 100644
index 00000000000..f7650035cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81313-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-accumulate-outgoing-args -mincoming-stack-boundary=4 -mpreferred-stack-boundary=6" } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
+
+/* { dg-final { scan-assembler-not "lea\[lq\]?\[\\t \]*\[0-9\]*\\(%\[er\]sp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81313-2.c b/gcc/testsuite/gcc.target/i386/pr81313-2.c
new file mode 100644
index 00000000000..2cdc645dbcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81313-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mno-accumulate-outgoing-args -mincoming-stack-boundary=4 -mpreferred-stack-boundary=6 -mno-iamcu" } */
+
+extern void foo (int, int, int);
+
+void
+bar (void)
+{
+ foo (1, 2, 3);
+}
+
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*\[0-9\]*\\(%esp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81313-3.c b/gcc/testsuite/gcc.target/i386/pr81313-3.c
new file mode 100644
index 00000000000..9c1b2326616
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81313-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mno-accumulate-outgoing-args -mincoming-stack-boundary=4 -mpreferred-stack-boundary=6" } */
+
+extern void foo (int, int, int) __attribute__ ((regparm(3)));
+
+void
+bar (int i1, int i2, int i3, int i4)
+{
+ foo (i1, i2, i3);
+}
+
+/* { dg-final { scan-assembler-not "lea\[l\]?\[\\t \]*\[0-9\]*\\(%esp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81313-4.c b/gcc/testsuite/gcc.target/i386/pr81313-4.c
new file mode 100644
index 00000000000..bad0b3c27db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81313-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-accumulate-outgoing-args -mincoming-stack-boundary=4 -mpreferred-stack-boundary=6" } */
+
+extern void foo (int, int, int, int, int, int, int);
+
+void
+bar (void)
+{
+ foo (1, 2, 3, 4, 5, 6, 7);
+}
+
+/* { dg-final { scan-assembler "lea\[lq\]?\[\\t \]*\[0-9\]*\\(%\[er\]sp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81313-5.c b/gcc/testsuite/gcc.target/i386/pr81313-5.c
new file mode 100644
index 00000000000..51a543ca57e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81313-5.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-accumulate-outgoing-args -mincoming-stack-boundary=4 -mpreferred-stack-boundary=6" } */
+
+extern void foo (int, int, int, int, int, int);
+
+void
+bar (int i1, int i2, int i3, int i4, int i5, int i6, int i7)
+{
+ foo (i1, i2, i3, i4, i5, i6);
+}
+
+/* { dg-final { scan-assembler-not "lea\[lq\]?\[\\t \]*\[0-9\]*\\(%\[er\]sp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81375.c b/gcc/testsuite/gcc.target/i386/pr81375.c
new file mode 100644
index 00000000000..256a79df719
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81375.c
@@ -0,0 +1,8 @@
+/* PR target/81375 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-mno-80387 -mno-sse -mfpmath=sse" } */
+
+float foo (float a, float b)
+{
+ return a / b;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81471.c b/gcc/testsuite/gcc.target/i386/pr81471.c
new file mode 100644
index 00000000000..68b4497c9f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81471.c
@@ -0,0 +1,13 @@
+/* PR target/81471 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi2" } */
+
+static inline unsigned int rotl (unsigned int x, int k)
+{
+ return (x << k) | (x >> (32 - k));
+}
+
+unsigned long long test (unsigned int z)
+{
+ return rotl (z, 55);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81502.c b/gcc/testsuite/gcc.target/i386/pr81502.c
new file mode 100644
index 00000000000..d28791aacd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81502.c
@@ -0,0 +1,34 @@
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -msse2" } */
+
+#include <emmintrin.h>
+
+#define SIZE (sizeof (void *))
+
+static int foo(unsigned char (*foo)[SIZE])
+{
+ __m128i acc = _mm_set_epi32(0, 0, 0, 0);
+ size_t i = 0;
+ for(; i + sizeof(__m128i) <= SIZE; i += sizeof(__m128i)) {
+ __m128i word;
+ __builtin_memcpy(&word, foo + i, sizeof(__m128i));
+ acc = _mm_add_epi32(word, acc);
+ }
+ if (i != SIZE) {
+ __m128i word = _mm_set_epi32(0, 0, 0, 0);
+ __builtin_memcpy(&word, foo + i, SIZE - i); // (1)
+ acc = _mm_add_epi32(word, acc);
+ }
+ int res;
+ __builtin_memcpy(&res, &acc, sizeof(res));
+ return res;
+}
+
+int bar(void *ptr)
+{
+ unsigned char buf[SIZE];
+ __builtin_memcpy(buf, &ptr, SIZE);
+ return foo((unsigned char(*)[SIZE])buf);
+}
+
+/* { dg-final { scan-assembler-times "mov" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81563.c b/gcc/testsuite/gcc.target/i386/pr81563.c
new file mode 100644
index 00000000000..ebfd583daf5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81563.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -maccumulate-outgoing-args -mincoming-stack-boundary=2 -mpreferred-stack-boundary=3 -mregparm=3 -mtune-ctrl=epilogue_using_move" } */
+
+extern void bar (long long int, int);
+
+long long int
+fn1 (long long int x)
+{
+ bar (x, 1);
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "movl\[\\t \]*-8\\(%ebp\\),\[\\t \]*%esi" 1 } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%edi" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index 79879d7cc16..c5c43b12611 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -250,11 +250,15 @@
#define __builtin_ia32_getexppd512_mask(A, B, C, D) __builtin_ia32_getexppd512_mask(A, B, C, 8)
#define __builtin_ia32_getexpps512_mask(A, B, C, D) __builtin_ia32_getexpps512_mask(A, B, C, 8)
#define __builtin_ia32_getexpsd128_round(A, B, C) __builtin_ia32_getexpsd128_round(A, B, 4)
+#define __builtin_ia32_getexpsd_mask_round(A, B, C, D, E) __builtin_ia32_getexpsd_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getexpss128_round(A, B, C) __builtin_ia32_getexpss128_round(A, B, 4)
+#define __builtin_ia32_getexpss_mask_round(A, B, C, D, E) __builtin_ia32_getexpss_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getmantpd512_mask(A, F, C, D, E) __builtin_ia32_getmantpd512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantps512_mask(A, F, C, D, E) __builtin_ia32_getmantps512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantsd_round(A, B, C, D) __builtin_ia32_getmantsd_round(A, B, 1, 4)
+#define __builtin_ia32_getmantsd_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsd_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_getmantss_round(A, B, C, D) __builtin_ia32_getmantss_round(A, B, 1, 4)
+#define __builtin_ia32_getmantss_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantss_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_insertf32x4_mask(A, B, F, D, E) __builtin_ia32_insertf32x4_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x4_mask(A, B, F, D, E) __builtin_ia32_insertf64x4_mask(A, B, 1, D, E)
#define __builtin_ia32_inserti32x4_mask(A, B, F, D, E) __builtin_ia32_inserti32x4_mask(A, B, 1, D, E)
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index 547314aef07..c2a19b3ccef 100644
--- a/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -244,7 +244,9 @@ test_2 (_mm512_maskz_extractf64x4_pd, __m256d, __mmask8, __m512d, 1)
test_2 (_mm512_maskz_extracti32x4_epi32, __m128i, __mmask8, __m512i, 1)
test_2 (_mm512_maskz_extracti64x4_epi64, __m256i, __mmask8, __m512i, 1)
test_2 (_mm512_maskz_getexp_round_pd, __m512d, __mmask8, __m512d, 8)
+test_3 (_mm_maskz_getexp_round_sd, __m128d, __mmask8, __m128d, __m128d, 8)
test_2 (_mm512_maskz_getexp_round_ps, __m512, __mmask16, __m512, 8)
+test_3 (_mm_maskz_getexp_round_ss, __m128, __mmask8, __m128, __m128, 8)
test_2y (_mm512_maskz_getmant_round_pd, __m512d, __mmask8, __m512d, 1, 1, 8)
test_2y (_mm512_maskz_getmant_round_ps, __m512, __mmask16, __m512, 1, 1, 8)
test_2 (_mm512_maskz_permute_pd, __m512d, __mmask8, __m512d, 1)
@@ -300,7 +302,11 @@ test_2 (_mm_div_round_ss, __m128, __m128, __m128, 9)
test_2 (_mm_getexp_round_sd, __m128d, __m128d, __m128d, 8)
test_2 (_mm_getexp_round_ss, __m128, __m128, __m128, 8)
test_2y (_mm_getmant_round_sd, __m128d, __m128d, __m128d, 1, 1, 8)
+test_4y (_mm_mask_getmant_round_sd, __m128d, __m128d, __mmask8, __m128d, __m128d, 1, 1, 8)
+test_3y (_mm_maskz_getmant_round_sd, __m128d, __mmask8, __m128d, __m128d, 1, 1, 8)
test_2y (_mm_getmant_round_ss, __m128, __m128, __m128, 1, 1, 8)
+test_4y (_mm_mask_getmant_round_ss, __m128, __m128, __mmask8, __m128, __m128, 1, 1, 8)
+test_3y (_mm_maskz_getmant_round_ss, __m128, __mmask8, __m128, __m128, 1, 1, 8)
test_2 (_mm_mul_round_sd, __m128d, __m128d, __m128d, 9)
test_2 (_mm_mul_round_ss, __m128, __m128, __m128, 9)
test_2 (_mm_scalef_round_sd, __m128d, __m128d, __m128d, 9)
@@ -356,7 +362,9 @@ test_3 (_mm512_mask_extractf64x4_pd, __m256d, __m256d, __mmask8, __m512d, 1)
test_3 (_mm512_mask_extracti32x4_epi32, __m128i, __m128i, __mmask8, __m512i, 1)
test_3 (_mm512_mask_extracti64x4_epi64, __m256i, __m256i, __mmask8, __m512i, 1)
test_3 (_mm512_mask_getexp_round_pd, __m512d, __m512d, __mmask8, __m512d, 8)
+test_4 (_mm_mask_getexp_round_sd, __m128d, __m128d, __mmask8, __m128d, __m128d, 8)
test_3 (_mm512_mask_getexp_round_ps, __m512, __m512, __mmask16, __m512, 8)
+test_4 (_mm_mask_getexp_round_ss, __m128, __m128, __mmask8, __m128, __m128, 8)
test_3y (_mm512_mask_getmant_round_pd, __m512d, __m512d, __mmask8, __m512d, 1, 1, 8)
test_3y (_mm512_mask_getmant_round_ps, __m512, __m512, __mmask16, __m512, 1, 1, 8)
test_3 (_mm512_mask_permute_pd, __m512d, __m512d, __mmask8, __m512d, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index b8a35d11c45..cd8945be1cb 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -399,7 +399,9 @@ test_2 (_mm512_maskz_extracti64x4_epi64, __m256i, __mmask8, __m512i, 1)
test_2 (_mm512_maskz_getexp_round_pd, __m512d, __mmask8, __m512d, 8)
test_2 (_mm512_maskz_getexp_round_ps, __m512, __mmask16, __m512, 8)
test_2y (_mm512_maskz_getmant_round_pd, __m512d, __mmask8, __m512d, 1, 1, 8)
+test_3y (_mm_maskz_getmant_round_sd, __m128d, __mmask8, __m128d, __m128d, 1, 1, 8)
test_2y (_mm512_maskz_getmant_round_ps, __m512, __mmask16, __m512, 1, 1, 8)
+test_3y (_mm_maskz_getmant_round_ss, __m128, __mmask8, __m128, __m128, 1, 1, 8)
test_2 (_mm512_maskz_permute_pd, __m512d, __mmask8, __m512d, 1)
test_2 (_mm512_maskz_permute_ps, __m512, __mmask16, __m512, 1)
test_2 (_mm512_maskz_permutex_epi64, __m512i, __mmask8, __m512i, 1)
@@ -491,7 +493,9 @@ test_3 (_mm512_mask_extracti64x4_epi64, __m256i, __m256i, __mmask8, __m512i, 1)
test_3 (_mm512_mask_getexp_round_pd, __m512d, __m512d, __mmask8, __m512d, 8)
test_3 (_mm512_mask_getexp_round_ps, __m512, __m512, __mmask16, __m512, 8)
test_3y (_mm512_mask_getmant_round_pd, __m512d, __m512d, __mmask8, __m512d, 1, 1, 8)
+test_4y (_mm_mask_getmant_round_sd, __m128d, __m128d, __mmask8, __m128d, __m128d, 1, 1, 8)
test_3y (_mm512_mask_getmant_round_ps, __m512, __m512, __mmask16, __m512, 1, 1, 8)
+test_4y (_mm_mask_getmant_round_ss, __m128, __m128, __mmask8, __m128, __m128, 1, 1, 8)
test_3 (_mm512_mask_permute_pd, __m512d, __m512d, __mmask8, __m512d, 1)
test_3 (_mm512_mask_permute_ps, __m512, __m512, __mmask16, __m512, 1)
test_3 (_mm512_mask_permutex_epi64, __m512i, __m512i, __mmask8, __m512i, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index 96c663b64d3..fc339a51e63 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -251,11 +251,15 @@
#define __builtin_ia32_getexppd512_mask(A, B, C, D) __builtin_ia32_getexppd512_mask(A, B, C, 8)
#define __builtin_ia32_getexpps512_mask(A, B, C, D) __builtin_ia32_getexpps512_mask(A, B, C, 8)
#define __builtin_ia32_getexpsd128_round(A, B, C) __builtin_ia32_getexpsd128_round(A, B, 4)
+#define __builtin_ia32_getexpsd_mask_round(A, B, C, D, E) __builtin_ia32_getexpsd_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getexpss128_round(A, B, C) __builtin_ia32_getexpss128_round(A, B, 4)
+#define __builtin_ia32_getexpss_mask_round(A, B, C, D, E) __builtin_ia32_getexpss_mask_round(A, B, C, D, 4)
#define __builtin_ia32_getmantpd512_mask(A, F, C, D, E) __builtin_ia32_getmantpd512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantps512_mask(A, F, C, D, E) __builtin_ia32_getmantps512_mask(A, 1, C, D, 8)
#define __builtin_ia32_getmantsd_round(A, B, C, D) __builtin_ia32_getmantsd_round(A, B, 1, 4)
+#define __builtin_ia32_getmantsd_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantsd_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_getmantss_round(A, B, C, D) __builtin_ia32_getmantss_round(A, B, 1, 4)
+#define __builtin_ia32_getmantss_mask_round(A, B, C, W, U, D) __builtin_ia32_getmantss_mask_round(A, B, 1, W, U, 4)
#define __builtin_ia32_insertf32x4_mask(A, B, F, D, E) __builtin_ia32_insertf32x4_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x4_mask(A, B, F, D, E) __builtin_ia32_insertf64x4_mask(A, B, 1, D, E)
#define __builtin_ia32_inserti32x4_mask(A, B, F, D, E) __builtin_ia32_inserti32x4_mask(A, B, 1, D, E)
diff --git a/gcc/testsuite/gcc.target/i386/testimm-10.c b/gcc/testsuite/gcc.target/i386/testimm-10.c
index c2bf0dbabd1..d0e9b42f2fe 100644
--- a/gcc/testsuite/gcc.target/i386/testimm-10.c
+++ b/gcc/testsuite/gcc.target/i386/testimm-10.c
@@ -191,5 +191,9 @@ test4bit (void) {
m512 = _mm512_maskz_getmant_ps (mmask16, m512, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
m128d = _mm_getmant_sd (m128d, m128d, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
+ m128d = _mm_mask_getmant_sd (m128d, mmask8, m128d, m128d, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
+ m128d = _mm_maskz_getmant_sd (mmask8, m128d, m128d, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
m128 = _mm_getmant_ss (m128, m128, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
+ m128 = _mm_mask_getmant_ss (m128, mmask8, m128, m128, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
+ m128 = _mm_maskz_getmant_ss (mmask8, m128, m128, 1, 64); /* { dg-error "the immediate argument must be a 4-bit immediate" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/testround-1.c b/gcc/testsuite/gcc.target/i386/testround-1.c
index 2c1338164f5..d5ab95c208e 100644
--- a/gcc/testsuite/gcc.target/i386/testround-1.c
+++ b/gcc/testsuite/gcc.target/i386/testround-1.c
@@ -249,7 +249,11 @@ test_round (void)
m128d = _mm_cvt_roundss_sd (m128d, m128, 7); /* { dg-error "incorrect rounding operand" } */
m128 = _mm_getexp_round_ss (m128, m128, 7); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_mask_getexp_round_ss (m128, mmask8, m128, m128, 7); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_maskz_getexp_round_ss (mmask8, m128, m128, 7); /* { dg-error "incorrect rounding operand" } */
m128d = _mm_getexp_round_sd (m128d, m128d, 7); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_mask_getexp_round_sd (m128d, mmask8, m128d, m128d, 7); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_maskz_getexp_round_sd (mmask8, m128d, m128d, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_getexp_round_ps (m512, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_mask_getexp_round_ps (m512, mmask16, m512, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_maskz_getexp_round_ps (mmask16, m512, 7); /* { dg-error "incorrect rounding operand" } */
@@ -263,7 +267,11 @@ test_round (void)
m512 = _mm512_mask_getmant_round_ps (m512, mmask16, m512, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_maskz_getmant_round_ps (mmask16, m512, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
m128d = _mm_getmant_round_sd (m128d, m128d, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_mask_getmant_round_sd (m128d, mmask8, m128d, m128d, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_maskz_getmant_round_sd (mmask8, m128d, m128d, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
m128 = _mm_getmant_round_ss (m128, m128, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_mask_getmant_round_ss (m128, mmask8, m128, m128, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_maskz_getmant_round_ss (mmask8, m128, m128, 0, 0, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_roundscale_round_ps (m512, 4, 7); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_mask_roundscale_round_ps (m512, mmask16, m512, 4, 7); /* { dg-error "incorrect rounding operand" } */
@@ -524,7 +532,11 @@ test_sae_only (void)
m128d = _mm_cvt_roundss_sd (m128d, m128, 3); /* { dg-error "incorrect rounding operand" } */
m128 = _mm_getexp_round_ss (m128, m128, 3); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_mask_getexp_round_ss (m128, mmask8, m128, m128, 3); /* { dg-error "incorrect rounding operand" } */
+ m128 = _mm_maskz_getexp_round_ss (mmask8, m128, m128, 3); /* { dg-error "incorrect rounding operand" } */
m128d = _mm_getexp_round_sd (m128d, m128d, 3); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_mask_getexp_round_sd (m128d, mmask8, m128d, m128d, 5); /* { dg-error "incorrect rounding operand" } */
+ m128d = _mm_maskz_getexp_round_sd (mmask8, m128d, m128d, 5); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_getexp_round_ps (m512, 3); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_mask_getexp_round_ps (m512, mmask16, m512, 3); /* { dg-error "incorrect rounding operand" } */
m512 = _mm512_maskz_getexp_round_ps (mmask16, m512, 3); /* { dg-error "incorrect rounding operand" } */
diff --git a/gcc/testsuite/gcc.target/i386/umod-3.c b/gcc/testsuite/gcc.target/i386/umod-3.c
index e1fb988263a..609ab520712 100644
--- a/gcc/testsuite/gcc.target/i386/umod-3.c
+++ b/gcc/testsuite/gcc.target/i386/umod-3.c
@@ -9,9 +9,11 @@ int
main ()
{
unsigned char cy;
-
- cy = cx / 6; if (cy != 1) exit (1);
- cy = cx % 6; if (cy != 1) exit (1);
+ unsigned char cz = 1;
+ asm ("" : "+q" (cz));
+
+ cy = cx / 6; if (cy != cz) exit (1);
+ cy = cx % 6; if (cy != cz) exit (1);
exit(0);
}
diff --git a/gcc/testsuite/gcc.target/i386/vect-insert-1.c b/gcc/testsuite/gcc.target/i386/vect-insert-1.c
new file mode 100644
index 00000000000..55cc52334c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-insert-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -msse2 -fdump-tree-ccp1" } */
+
+typedef int v4si __attribute__((vector_size(16)));
+
+float f;
+
+v4si foo (v4si a)
+{
+ __builtin_memcpy ((char *)&a + 4, &f, 4);
+ return a;
+}
+
+/* { dg-final { scan-tree-dump "Now a gimple register: a" "ccp1" } } */
+/* { dg-final { scan-tree-dump "BIT_INSERT_EXPR <a" "ccp1" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/decl-init.c b/gcc/testsuite/gcc.target/nvptx/decl-init.c
index e9af9075756..23008fb209c 100644
--- a/gcc/testsuite/gcc.target/nvptx/decl-init.c
+++ b/gcc/testsuite/gcc.target/nvptx/decl-init.c
@@ -37,7 +37,7 @@ struct five five2[2] = {{12, 13}, {14, 15}};
/* { dg-final { scan-assembler ".align 1 .u8 five2\\\[10\\\] = { 12, 13, 0, 0, 0, 14, 15, 0, 0, 0 };" } } */
int __attribute__((vector_size(16))) vi = {16, 17, 18, 19};
-/* { dg-final { scan-assembler ".align 8 .u32 vi\\\[4\\\] = { 16, 17, 18, 19 };" } } */
+/* { dg-final { scan-assembler ".align 16 .u32 vi\\\[4\\\] = { 16, 17, 18, 19 };" } } */
typedef int __attribute ((mode(TI))) ti_t;
diff --git a/gcc/testsuite/gcc.target/nvptx/slp-2-run.c b/gcc/testsuite/gcc.target/nvptx/slp-2-run.c
new file mode 100644
index 00000000000..f9841a6b11a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/slp-2-run.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-slp-vectorize" } */
+
+#include "slp-2.c"
+
+int
+main(void)
+{
+ unsigned int i;
+ for (i = 0; i < 1000; i += 1)
+ {
+ p[i] = i;
+ p2[i] = 0;
+ }
+
+ foo ();
+
+ for (i = 0; i < 1000; i += 1)
+ if (p2[i] != i)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/slp-2.c b/gcc/testsuite/gcc.target/nvptx/slp-2.c
new file mode 100644
index 00000000000..66394918d63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/slp-2.c
@@ -0,0 +1,25 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -ftree-slp-vectorize -save-temps" } */
+
+long long int p[1000] __attribute__((aligned(16)));
+long long int p2[1000] __attribute__((aligned(16)));
+
+void __attribute__((noinline, noclone))
+foo ()
+{
+ long long int a, b;
+
+ unsigned int i;
+ for (i = 0; i < 1000; i += 2)
+ {
+ a = p[i];
+ b = p[i+1];
+
+ p2[i] = a;
+ p2[i+1] = b;
+ }
+}
+
+/* { dg-final { scan-assembler "ld.v2.u64" } } */
+/* { dg-final { scan-assembler "st.v2.u64" } } */
+
diff --git a/gcc/testsuite/gcc.target/nvptx/slp-run.c b/gcc/testsuite/gcc.target/nvptx/slp-run.c
new file mode 100644
index 00000000000..dedec471bb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/slp-run.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-slp-vectorize" } */
+
+#include "slp.c"
+
+int
+main(void)
+{
+ unsigned int i;
+ for (i = 0; i < 1000; i += 1)
+ {
+ p[i] = i;
+ p2[i] = 0;
+ }
+
+ foo ();
+
+ for (i = 0; i < 1000; i += 1)
+ if (p2[i] != i)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/slp.c b/gcc/testsuite/gcc.target/nvptx/slp.c
new file mode 100644
index 00000000000..5dee147af9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/slp.c
@@ -0,0 +1,25 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -ftree-slp-vectorize -save-temps" } */
+
+int p[1000] __attribute__((aligned(8)));
+int p2[1000] __attribute__((aligned(8)));
+
+void __attribute__((noinline, noclone))
+foo ()
+{
+ int a, b;
+
+ unsigned int i;
+ for (i = 0; i < 1000; i += 2)
+ {
+ a = p[i];
+ b = p[i+1];
+
+ p2[i] = a;
+ p2[i+1] = b;
+ }
+}
+
+/* { dg-final { scan-assembler "ld.v2.u32" } } */
+/* { dg-final { scan-assembler "st.v2.u32" } } */
+
diff --git a/gcc/testsuite/gcc.target/nvptx/v2di.c b/gcc/testsuite/gcc.target/nvptx/v2di.c
new file mode 100644
index 00000000000..f63ad35d816
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/v2di.c
@@ -0,0 +1,12 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -save-temps" } */
+
+typedef long long int __v2di __attribute__((__vector_size__(16)));
+
+#define TYPE __v2di
+#include "vec.inc"
+
+/* { dg-final { scan-assembler ".reg\\.v2\\.u64" } } */
+/* { dg-final { scan-assembler "ld\\.v2\\.u64" } } */
+/* { dg-final { scan-assembler "st\\.v2\\.u64" } } */
+/* { dg-final { scan-assembler "mov\\.v2\\.u64.*\\{ 1, 2 \\}" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/v2si-cvt.c b/gcc/testsuite/gcc.target/nvptx/v2si-cvt.c
new file mode 100644
index 00000000000..73f86bcfa9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/v2si-cvt.c
@@ -0,0 +1,39 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -save-temps" } */
+
+typedef int __v2si __attribute__((__vector_size__(8)));
+
+int __attribute__((unused))
+vector_cvt (__v2si arg)
+{
+ __v2si val4 = arg;
+ char *p = (char*)&val4;
+
+ if (p[0] != 1)
+ return 1;
+ if (p[1] != 2)
+ return 1;
+ if (p[2] != 3)
+ return 1;
+
+ return 0;
+}
+
+int
+vector_cvt_2 (__v2si val, __v2si val2)
+{
+ char *p = (char*)&val;
+ char *p2 = (char*)&val2;
+
+ if (p[0] != p2[0])
+ return 1;
+ if (p[4] != p2[4])
+ return 1;
+
+ return 0;
+}
+
+/* We want to test for 'mov.t' here, but given PR80845 we test for cvt.t.t
+ instead.
+ { dg-final { scan-assembler "(?n)cvt\\.u32\\.u32.*\\.x" } } */
+/* { dg-final { scan-assembler "(?n)cvt\\.u16\\.u32.*\\.x" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/v2si-run.c b/gcc/testsuite/gcc.target/nvptx/v2si-run.c
new file mode 100644
index 00000000000..5821a5a95d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/v2si-run.c
@@ -0,0 +1,83 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "v2si.c"
+
+void __attribute__((noinline, noclone))
+init_val ( __v2si *p)
+{
+ char *p2 = (char*)p;
+ p2[0] = 8;
+ p2[1] = 7;
+ p2[2] = 6;
+ p2[3] = 5;
+ p2[4] = 4;
+ p2[5] = 3;
+ p2[6] = 2;
+ p2[7] = 1;
+}
+
+int
+main (void)
+{
+ {
+ __v2si val;
+ __v2si val2;
+ __v2si val3;
+
+ init_val(&val);
+
+ /* Copy val to val2. */
+ vector_store (&val2, val);
+
+ /* Copy val2 to val3. */
+ val3 = vector_load (&val2);
+
+ /* Compare val to val3. */
+ {
+ char *p = (char*)&val;
+ char *p2 = (char*)&val3;
+
+ if (p[0] != p2[0])
+ return 1;
+ if (p[1] != p2[1])
+ return 1;
+ if (p[2] != p2[2])
+ return 1;
+ if (p[3] != p2[3])
+ return 1;
+ if (p[4] != p2[4])
+ return 1;
+ if (p[5] != p2[5])
+ return 1;
+ if (p[6] != p2[6])
+ return 1;
+ if (p[7] != p2[7])
+ return 1;
+ }
+ }
+
+ {
+ __v2si val4 = vector_const ();
+ char *p = (char*)&val4;
+
+ if (p[0] != 1)
+ return 1;
+ if (p[1] != 0)
+ return 1;
+ if (p[2] != 0)
+ return 1;
+ if (p[3] != 0)
+ return 1;
+ if (p[4] != 2)
+ return 1;
+ if (p[5] != 0)
+ return 1;
+ if (p[6] != 0)
+ return 1;
+ if (p[7] != 0)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/v2si.c b/gcc/testsuite/gcc.target/nvptx/v2si.c
new file mode 100644
index 00000000000..ce423d82c2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/v2si.c
@@ -0,0 +1,12 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -save-temps" } */
+
+typedef int __v2si __attribute__((__vector_size__(8)));
+
+#define TYPE __v2si
+#include "vec.inc"
+
+/* { dg-final { scan-assembler ".reg\\.v2\\.u32" } } */
+/* { dg-final { scan-assembler "ld\\.v2\\.u32" } } */
+/* { dg-final { scan-assembler "st\\.v2\\.u32" } } */
+/* { dg-final { scan-assembler "(?n)mov\\.v2\\.u32.*\\{ 1, 2 \\}" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/vec.inc b/gcc/testsuite/gcc.target/nvptx/vec.inc
new file mode 100644
index 00000000000..269a9749e26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/vec.inc
@@ -0,0 +1,18 @@
+TYPE __attribute__((noinline, noclone))
+vector_load (TYPE *p)
+{
+ return *p;
+}
+
+void __attribute__((noinline, noclone))
+vector_store (TYPE *p, TYPE val)
+{
+ *p = val;
+}
+
+TYPE __attribute__((noinline, noclone))
+vector_const ()
+{
+ TYPE res = {1, 2};
+ return res;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-3.c
new file mode 100644
index 00000000000..e069fb49af9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-3.c
@@ -0,0 +1,32 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+int
+compare_exponents_eq (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ return scalar_cmp_exp_eq (exponent1, exponent2);
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (!compare_exponents_eq (&x, &y))
+ abort ();
+ if (compare_exponents_eq (&x, &z))
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-4.c
new file mode 100644
index 00000000000..800c32c6e07
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-4.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+char
+compare_exponents_eq (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ if (scalar_cmp_exp_eq (exponent1, exponent2))
+ return 't';
+ else
+ return 'f';
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_eq (&x, &y) == 'f')
+ abort ();
+ if (compare_exponents_eq (&x, &z) == 't')
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-3.c
new file mode 100644
index 00000000000..c0cedecaa7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-3.c
@@ -0,0 +1,31 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+int
+compare_exponents_gt (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ return scalar_cmp_exp_gt (exponent1, exponent2);
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_gt (&x, &y))
+ abort ();
+ if (!compare_exponents_gt (&x, &z))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-4.c
new file mode 100644
index 00000000000..1e24355d7f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-4.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+char
+compare_exponents_gt (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ if (scalar_cmp_exp_gt (exponent1, exponent2))
+ return 't';
+ else
+ return 'f';
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_gt (&x, &y) == 't')
+ abort ();
+ if (compare_exponents_gt (&x, &z) == 'f')
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-3.c
new file mode 100644
index 00000000000..acc24b5658e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-3.c
@@ -0,0 +1,31 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+int
+compare_exponents_lt (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ return scalar_cmp_exp_lt (exponent1, exponent2);
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_lt (&x, &y))
+ abort ();
+ if (!compare_exponents_lt (&z, &x))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-4.c
new file mode 100644
index 00000000000..b8bd278dce5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-4.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+char
+compare_exponents_lt (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ if (scalar_cmp_exp_lt (exponent1, exponent2))
+ return 't';
+ else
+ return 'f';
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_lt (&x, &y) == 't')
+ abort ();
+ if (compare_exponents_lt (&z, &x) == 'f')
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-3.c
new file mode 100644
index 00000000000..79900c21b5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-3.c
@@ -0,0 +1,36 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+int
+compare_exponents_unordered (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ /* This test succeeds if either exponent1 or exponent2 is NaN. */
+ return scalar_cmp_exp_unordered (exponent1, exponent2);
+}
+
+int
+main ()
+{
+ /* NaN is denoted by exponent = 2047 and fraction != 0 */
+ unsigned long long int nan_image = 0x7ff0000000000003LL;
+ double *nan_ptr = (double *) &nan_image;
+
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (!compare_exponents_unordered (&x, nan_ptr))
+ abort ();
+ if (compare_exponents_unordered (&x, &z))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-4.c
new file mode 100644
index 00000000000..4371946a6d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-4.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on 32-bit and 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+char
+compare_exponents_unordered (double *exponent1_p, double *exponent2_p)
+{
+ double exponent1 = *exponent1_p;
+ double exponent2 = *exponent2_p;
+
+ /* This test succeeds if either exponent1 or exponent2 is NaN. */
+ if (scalar_cmp_exp_unordered (exponent1, exponent2))
+ return 't';
+ else
+ return 'f';
+}
+
+int
+main ()
+{
+ /* NaN is denoted by exponent = 2047 and fraction != 0 */
+ unsigned long long int nan_image = 0x7ff0000000000003LL;
+ double *nan_ptr = (double *) &nan_image;
+
+ double x = (double) (0x1100LL << 50);
+ double y = (double) (0x1101LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (compare_exponents_unordered (&x, nan_ptr) == 'f')
+ abort ();
+ if (compare_exponents_unordered (&x, &z) == 't')
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-3.c
new file mode 100644
index 00000000000..9e6fb085d47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+unsigned long long int
+get_exponent (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_extract_exp (source);
+}
+
+/* { dg-final { scan-assembler "xsxexpqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c
new file mode 100644
index 00000000000..502241581d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+unsigned long long int
+get_exponent (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return __builtin_vec_scalar_extract_exp (source); /* { dg-error "Builtin function __builtin_vsx_scalar_extract_expq requires" } */
+}
+
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
new file mode 100644
index 00000000000..07e0c1de7e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test only runs on 32-bit configurations, where a compiler error
+ should be issued because this builtin is not available on
+ 32-bit configurations. */
+
+#include <altivec.h>
+
+unsigned long long int
+get_exponent (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_extract_exp (source); /* { dg-error "Builtin function __builtin_vec_scalar_extract_exp not supported in this compiler configuration" } */
+}
+
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-6.c
new file mode 100644
index 00000000000..a5e31bf51ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-6.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+unsigned int
+get_unbiased_exponent (double *p)
+{
+ double source = *p;
+
+ return scalar_extract_exp (source) - 1023;
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (get_unbiased_exponent (&x) != 62)
+ abort ();
+ if (get_unbiased_exponent (&z) != 49)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-7.c
new file mode 100644
index 00000000000..3920594b657
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-7.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+unsigned long long int
+get_unbiased_exponent (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_extract_exp (source) - 16383;
+}
+
+int
+main ()
+{
+ __ieee128 x = (__ieee128) (((__int128) 0x1100LL) << 114);
+ __ieee128 z = (__ieee128) (((__int128) 0x1101LL) << 112);
+
+ if (get_unbiased_exponent (&x) != 126)
+ abort ();
+ if (get_unbiased_exponent (&z) != 124)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-3.c
new file mode 100644
index 00000000000..093ba337785
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+unsigned __int128
+get_significand (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_extract_sig (source);
+}
+
+/* { dg-final { scan-assembler "xsxsigqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c
new file mode 100644
index 00000000000..0c2ec4739f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+unsigned __int128
+get_significand (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return __builtin_vec_scalar_extract_sig (source); /* { dg-error "Builtin function __builtin_vsx_scalar_extract_sigq requires" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
new file mode 100644
index 00000000000..19ca4c4a09a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test only runs on 32-bit configurations, producing a compiler
+ error because the builtin requires 64 bits. */
+#include <altivec.h>
+
+unsigned __int128 /* { dg-error "'__int128' is not supported on this target" } */
+get_significand (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return __builtin_vec_scalar_extract_sig (source); /* { dg-error "Builtin function __builtin_vec_scalar_extract_sig not supported in this compiler configuration" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-6.c
new file mode 100644
index 00000000000..298268dadf4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-6.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+unsigned long long int
+get_significand (double *p)
+{
+ double source = *p;
+
+ return scalar_extract_sig (source);
+}
+
+int
+main ()
+{
+ double x = (double) (0x1100LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (get_significand (&x) != 0x11000000000000ULL)
+ abort ();
+ if (get_significand (&z) != 0x11010000000000ULL)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-7.c
new file mode 100644
index 00000000000..52081310ac5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-7.c
@@ -0,0 +1,36 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+unsigned __int128
+get_significand (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_extract_sig (source);
+}
+
+int
+main ()
+{
+ __ieee128 x = (__ieee128) (((__int128) 0x1100LL) << 114);
+ __ieee128 z = (__ieee128) (((__int128) 0x1101LL) << 112);
+
+ /* 113 bits in the significand */
+ /* our constant mantissas have 13 bits */
+
+ unsigned __int128 first_anticipated_result = ((__int128) 0x1100LL) << 100;
+ unsigned __int128 second_anticipated_result = ((__int128) 0x1101LL) << 100;
+
+ if (get_significand (&x) != first_anticipated_result)
+ abort ();
+ if (get_significand (&z) != second_anticipated_result)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c
new file mode 100644
index 00000000000..e730556c5c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+__ieee128
+insert_exponent (__ieee128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ __ieee128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "Builtin function __builtin_vsx_scalar_insert_exp_qp requires" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
new file mode 100644
index 00000000000..d44e6ccec5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-11.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test only runs on 32-bit configurations, where a compiler error
+ should be issued because this builtin is not available on
+ 32-bit configurations. */
+
+#include <altivec.h>
+
+__ieee128
+insert_exponent (__ieee128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ __ieee128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent); /* { dg-error "Builtin function __builtin_vec_scalar_insert_exp not supported in this compiler configuration" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-12.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-12.c
new file mode 100644
index 00000000000..b76c9c81145
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-12.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+double
+insert_exponent (unsigned long long int *significand_p,
+ unsigned long long int *exponent_p)
+{
+ unsigned long long int significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+#define BIAS_FOR_DOUBLE_EXP 1023
+
+int
+main ()
+{
+ unsigned long long int significand_1 = 0x18000000000000LL;
+ unsigned long long int significand_2 = 0x1a000000000000LL;
+ unsigned long long int exponent_1 = 62 + BIAS_FOR_DOUBLE_EXP;
+ unsigned long long int exponent_2 = 49 + BIAS_FOR_DOUBLE_EXP;
+
+ double x = (double) (0x1800ULL << 50);
+ double z = (double) (0x1a00ULL << 37);
+
+
+ if (insert_exponent (&significand_1, &exponent_1) != x)
+ abort ();
+ if (insert_exponent (&significand_2, &exponent_2) != z)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-13.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-13.c
new file mode 100644
index 00000000000..212563c84b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-13.c
@@ -0,0 +1,43 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+double
+insert_exponent (double *significand_p,
+ unsigned long long int *exponent_p)
+{
+ double significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+#define BIAS_FOR_DOUBLE_EXP 1023
+
+int
+main ()
+{
+ unsigned long long int significand_1 = 0x11000000000000LL;
+ unsigned long long int significand_2 = 0x11010000000000LL;
+ unsigned long long int exponent_1 = 62 + BIAS_FOR_DOUBLE_EXP;
+ unsigned long long int exponent_2 = 49 + BIAS_FOR_DOUBLE_EXP;
+
+ double *significand_1_ptr = (double *) &significand_1;
+ double *significand_2_ptr = (double *) &significand_2;
+
+
+ double x = (double) (0x1100LL << 50);
+ double z = (double) (0x1101LL << 37);
+
+ if (insert_exponent (significand_1_ptr, &exponent_1) != x)
+ abort ();
+ if (insert_exponent (significand_2_ptr, &exponent_2) != z)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-14.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-14.c
new file mode 100644
index 00000000000..fc6c3817b98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-14.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+__ieee128
+insert_exponent (unsigned __int128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ unsigned __int128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+#define BIAS_FOR_QUAD_EXP 16383
+
+int
+main ()
+{
+ /* most-significant bit @13, shift it to position 113 */
+ unsigned __int128 significand_1 = ((__int128) 0x1100) << 100;
+ unsigned __int128 significand_2 = ((__int128) 0x1101) << 100;
+ unsigned long long int exponent_1 = 126 + BIAS_FOR_QUAD_EXP;
+ unsigned long long int exponent_2 = 124 + BIAS_FOR_QUAD_EXP;
+
+ __ieee128 x = (__ieee128) (((__int128) 0x1100LL) << 114);
+ __ieee128 z = (__ieee128) (((__int128) 0x1101LL) << 112);
+
+ if (insert_exponent (&significand_1, &exponent_1) != x)
+ abort ();
+ if (insert_exponent (&significand_2, &exponent_2) != z)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-15.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-15.c
new file mode 100644
index 00000000000..5843880d382
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-15.c
@@ -0,0 +1,43 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+#include <stdlib.h>
+
+__ieee128
+insert_exponent (__ieee128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ __ieee128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+#define BIAS_FOR_QUAD_EXP 16383
+
+int
+main ()
+{
+ /* most-significant bit @13, shift it to position 113 */
+ unsigned __int128 significand_1 = ((unsigned __int128) 0x1100) << 100;
+ unsigned __int128 significand_2 = ((unsigned __int128) 0x1101) << 100;
+ unsigned long long int exponent_1 = 126 + BIAS_FOR_QUAD_EXP;
+ unsigned long long int exponent_2 = 124 + BIAS_FOR_QUAD_EXP;
+
+ __ieee128 *significand_1_ptr = (__ieee128 *) &significand_1;
+ __ieee128 *significand_2_ptr = (__ieee128 *) &significand_2;
+
+ __ieee128 x = (__ieee128) (((__int128) 0x1100LL) << 114);
+ __ieee128 z = (__ieee128) (((__int128) 0x1101LL) << 112);
+
+ if (insert_exponent (significand_1_ptr, &exponent_1) != x)
+ abort ();
+ if (insert_exponent (significand_2_ptr, &exponent_2) != z)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-6.c
new file mode 100644
index 00000000000..d896fa5d7b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+__ieee128
+insert_exponent (unsigned __int128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ unsigned __int128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+/* { dg-final { scan-assembler "xsiexpqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c
new file mode 100644
index 00000000000..fe565c8f416
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+__ieee128
+insert_exponent (unsigned __int128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ unsigned __int128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "Builtin function __builtin_vsx_scalar_insert_exp_q requires" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c
new file mode 100644
index 00000000000..3a3f1c4aa82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test only runs on 32-bit configurations, where a compiler error
+ should be issued because this builtin is not available on
+ 32-bit configurations. */
+
+#include <altivec.h>
+
+__ieee128
+insert_exponent (unsigned __int128 *significand_p, /* { dg-error "'__int128' is not supported on this target" } */
+ unsigned long long int *exponent_p)
+{
+ unsigned __int128 significand = *significand_p; /* { dg-error "'__int128' is not supported on this target" } */
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent); /* { dg-error "Builtin function __builtin_vec_scalar_insert_exp not supported in this compiler configuration" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-9.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-9.c
new file mode 100644
index 00000000000..dca5c0ab5b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-9.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations. */
+#include <altivec.h>
+
+__ieee128
+insert_exponent (__ieee128 *significand_p,
+ unsigned long long int *exponent_p)
+{
+ __ieee128 significand = *significand_p;
+ unsigned long long int exponent = *exponent_p;
+
+ return scalar_insert_exp (significand, exponent);
+}
+
+/* { dg-final { scan-assembler "xsiexpqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-10.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-10.c
new file mode 100644
index 00000000000..32fd8b1deee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-10.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_data_class (__ieee128 *p, const int condition_flag)
+{
+ __ieee128 source = *p;
+
+ return scalar_test_data_class (source, condition_flag); /* { dg-error "argument 2 must be a 7-bit unsigned literal" } */
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c
new file mode 100644
index 00000000000..0065b77746a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_data_class (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "Builtin function __builtin_vsx_scalar_test_data_class_qp requires" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-12.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-12.c
new file mode 100644
index 00000000000..46c4fd22735
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-12.c
@@ -0,0 +1,44 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_denormal (double *p)
+{
+ double source = *p;
+
+ /*
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal
+ */
+ return scalar_test_data_class (source, 3);
+}
+
+int
+main ()
+{
+ /* A Denormal number has a biased exponent value of zero and a
+ * non-zero fraction value. */
+ double denormal_plus = scalar_insert_exp (0x0008000000000000ULL, 0x0ULL);
+ double denormal_minus = scalar_insert_exp (0x8008000000000000ULL, 0x0ULL);
+ double not_denormal = scalar_insert_exp (0x8000000000000000ULL, 1023ULL);
+
+ if (!test_denormal (&denormal_plus))
+ abort ();
+ if (!test_denormal (&denormal_minus))
+ abort ();
+ if (test_denormal (&not_denormal))
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-13.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-13.c
new file mode 100644
index 00000000000..0beb66ae643
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-13.c
@@ -0,0 +1,47 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_zero (float *p)
+{
+ float source = *p;
+
+ /*
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal
+ */
+ return scalar_test_data_class (source, 12);
+}
+
+int
+main ()
+{
+ /* A Zero value has a biased exponent value of zero and a zero
+ * fraction value. The sign may be either positive or negative. */
+ unsigned int zero_plus_image = 0x0;
+ unsigned int zero_minus_image = 0x80000000;
+ unsigned int non_zero_image = 0x60000000;
+
+ float *zero_plus_p = (float *) &zero_plus_image;
+ float *zero_minus_p = (float *) &zero_minus_image;
+ float *not_zero_p = (float *) &non_zero_image;
+
+ if (!test_zero (zero_plus_p))
+ abort ();
+ if (!test_zero (zero_minus_p))
+ abort ();
+ if (test_zero (not_zero_p))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-14.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-14.c
new file mode 100644
index 00000000000..90dd64637c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-14.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_nan (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ /*
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal
+ */
+ return scalar_test_data_class (source, 0x40);
+}
+
+int
+main ()
+{
+ /* NaN is represented with the maximum biased exponent value and a
+ * non-zero fraction value. The sign bit ignored. If the
+ * high-order bit of the fraction field is 0, then the NaN is a
+ * Signaling NaN. Otherwise, it is a Quiet NaN. */
+ __int128 signal_significand = (__int128) 0xffffffff;
+ __int128 quiet_significand = (((__int128) 0x1) << 112) | 0xffffffff;
+ __int128 a_number_significand = (((__int128) 0x1) << 112);
+ unsigned long long int nan_exponent = 0x7fff;
+ unsigned long long int a_number_exponent = 16383;
+
+ __ieee128 signaling_nan =
+ scalar_insert_exp (signal_significand, nan_exponent);
+ __ieee128 quiet_nan =
+ scalar_insert_exp (quiet_significand, nan_exponent);
+ __ieee128 a_number =
+ scalar_insert_exp (a_number_significand, a_number_exponent);
+
+ if (!test_nan (&signaling_nan))
+ abort ();
+ if (!test_nan (&quiet_nan))
+ abort ();
+ if (test_nan (&a_number))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-15.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-15.c
new file mode 100644
index 00000000000..5da7a3fe1b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-15.c
@@ -0,0 +1,56 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_infinity (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ /*
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal
+ */
+ return scalar_test_data_class (source, 0x30);
+}
+
+int
+main ()
+{
+ /* Infinity is represented by a biased exponent value of:
+ * 255 in single format
+ * 2047 in double format
+ * 32767 in ieee128 format
+ * and a zero fraction value. */
+ __int128 plus_significand = (__int128) 0;
+ __int128 minus_significand = ((__int128) 0x1) << 127;
+ __int128 a_number_significand = (((__int128) 0x1) << 112);
+
+ unsigned long long int infinite_exponent = 0x7fff;
+ unsigned long long int a_number_exponent = 16383;
+
+ __ieee128 plus_infinity =
+ scalar_insert_exp (plus_significand, infinite_exponent);
+ __ieee128 minus_infinity =
+ scalar_insert_exp (minus_significand, infinite_exponent);
+ __ieee128 a_number =
+ scalar_insert_exp (a_number_significand, a_number_exponent);
+
+ if (!test_infinity (&plus_infinity))
+ abort ();
+ if (!test_infinity (&minus_infinity))
+ abort ();
+ if (test_infinity (&a_number))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-8.c
new file mode 100644
index 00000000000..25192506992
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-8.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_data_class (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_test_data_class (source, 3);
+}
+
+/* { dg-final { scan-assembler "xststdcqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-9.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-9.c
new file mode 100644
index 00000000000..28c1e090ce5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-9.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_data_class (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_test_data_class (source, 256); /* { dg-error "argument 2 must be a 7-bit unsigned literal" } */
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-4.c
new file mode 100644
index 00000000000..13fee32cdf8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_neg (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_test_neg (source);
+}
+
+/* { dg-final { scan-assembler "xststdcqp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c
new file mode 100644
index 00000000000..041a4a1c820
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power8" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+
+bool
+test_neg (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return __builtin_vec_scalar_test_neg_qp (source); /* { dg-error "Builtin function __builtin_vsx_scalar_test_neg_qp requires" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-6.c
new file mode 100644
index 00000000000..497ac7b14aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-6.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_neg (double *p)
+{
+ double source = *p;
+
+ return scalar_test_neg (source);
+}
+
+int
+main ()
+{
+ double neg_number = (double) -1;
+ double plus_number = (double) 1;
+
+ if (!test_neg (&neg_number))
+ abort ();
+ if (test_neg (&plus_number))
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-7.c
new file mode 100644
index 00000000000..f7dfb5f9ed6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-7.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_neg (float *p)
+{
+ float source = *p;
+
+ return scalar_test_neg (source);
+}
+
+int
+main ()
+{
+ float neg_number = (float) -1;
+ float plus_number = (float) 1;
+
+ if (!test_neg (&neg_number))
+ abort ();
+ if (test_neg (&plus_number))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-8.c
new file mode 100644
index 00000000000..fff837ace70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-8.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool
+test_neg (__ieee128 *p)
+{
+ __ieee128 source = *p;
+
+ return scalar_test_neg (source);
+}
+
+int
+main ()
+{
+ __ieee128 neg_number = (__ieee128) -1;
+ __ieee128 plus_number = (__ieee128) 1;
+
+ if (!test_neg (&neg_number))
+ abort ();
+ if (test_neg (&plus_number))
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-4.c
new file mode 100644
index 00000000000..ab0e05e17c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-4.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector unsigned int
+get_exponents (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_extract_exp (source);
+}
+
+unsigned int bias_float_exp (int unbiased_exp)
+{
+ return (unsigned int) (unbiased_exp + 127);
+}
+
+int
+main ()
+{
+ __vector float argument;
+ __vector unsigned int result;
+
+ argument[0] = (float) (0x1 << 10);
+ argument[1] = (float) (0x1 << 9);
+ argument[2] = (float) (0x1 << 8);
+ argument[3] = (float) (0x1 << 7);
+
+ result = get_exponents (&argument);
+ if ((result[0] != bias_float_exp (10)) ||
+ (result[1] != bias_float_exp (9)) ||
+ (result[2] != bias_float_exp (8)) || (result[3] != bias_float_exp (7)))
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-5.c
new file mode 100644
index 00000000000..1dabd6cf2c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-5.c
@@ -0,0 +1,37 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector unsigned long long int
+get_exponents (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_extract_exp (source);
+}
+
+unsigned long long int
+bias_double_exp (long long int unbiased_exp)
+{
+ return (unsigned long long int) (unbiased_exp + 1023);
+}
+
+int
+main ()
+{
+ __vector double argument;
+ __vector unsigned long long int result;
+
+ argument[0] = (double) (0x1 << 22);
+ argument[1] = (double) (0x1 << 23);
+
+ result = get_exponents (&argument);
+ if ((result[0] != bias_double_exp (22)) ||
+ (result[1] != bias_double_exp (23)))
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-4.c
new file mode 100644
index 00000000000..6d4a9277f18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-4.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector unsigned int
+get_significands (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_extract_sig (source);
+}
+
+int
+main ()
+{
+ __vector float argument;
+ __vector unsigned int result;
+
+ argument[0] = (float) (0x1234 << 10);
+ argument[1] = (float) (0x4321 << 9);
+ argument[2] = (float) (0xbabe << 8);
+ argument[3] = (float) (0xcafe << 7);
+
+ result = get_significands (&argument);
+ if ((result[0] != 0x91a000) || (result[1] != 0x864200) ||
+ (result[2] != 0xbabe00) || (result[3] != 0xcafe00))
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-5.c
new file mode 100644
index 00000000000..ff2ca48798f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-5.c
@@ -0,0 +1,31 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector unsigned long long int
+get_significands (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_extract_sig (source);
+}
+
+int
+main ()
+{
+ __vector double argument;
+ __vector unsigned long long int result;
+
+ argument[0] = (double) (0xbabeLL << 22);
+ argument[1] = (double) (0xcafeLL << 23);
+
+ result = get_significands (&argument);
+ if ((result[0] != (0xbabeULL << 37)) || (result[1] != (0xcafeULL << 37)))
+ abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-10.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-10.c
new file mode 100644
index 00000000000..020d09abe13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-10.c
@@ -0,0 +1,44 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector float
+make_floats (__vector float *significands_p,
+ __vector unsigned int *exponents_p)
+{
+ __vector float significands = *significands_p;
+ __vector unsigned int exponents = *exponents_p;
+
+ return vec_insert_exp (significands, exponents);
+}
+
+int
+main ()
+{
+ __vector unsigned int significands;
+ __vector float *significands_p = (__vector float *) &significands;
+ __vector unsigned int exponents;
+ __vector float result;
+
+ /* 24 bits in significand, plus the sign bit: 0x80ffffff */
+ significands[0] = 0x00800000; /* 1.0 */
+ significands[1] = 0x00c00000; /* 1.5 */
+ significands[2] = 0x80e00000; /* -1.75 */
+ significands[3] = 0x80c00000; /* -1.5 */
+
+ exponents[0] = 127; /* exp = 0: 1.0 */
+ exponents[1] = 128; /* exp = 1: 3.0 */
+ exponents[2] = 129; /* exp = 2: -7.0 */
+ exponents[3] = 125; /* exp = -2: -0.375 */
+
+ result = make_floats (significands_p, &exponents);
+ if ((result[0] != 1.0f) ||
+ (result[1] != 3.0f) || (result[2] != -7.0f) || (result[3] != -0.375f))
+ abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-11.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-11.c
new file mode 100644
index 00000000000..5bf2c9cfdaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-11.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector double
+make_doubles (__vector double *significands_p,
+ __vector unsigned long long int *exponents_p)
+{
+ __vector double significands = *significands_p;
+ __vector unsigned long long int exponents = *exponents_p;
+
+ return vec_insert_exp (significands, exponents);
+}
+
+int
+main ()
+{
+ __vector unsigned long long int significands;
+ __vector double *significands_p = (__vector double *) &significands;
+ __vector unsigned long long int exponents;
+ __vector double result;
+
+ /* 53 bits in significand, plus the sign bit: 0x8000_0000_0000_0000 */
+ significands[0] = 0x0010000000000000; /* 1.0 */
+ significands[1] = 0x801c000000000000; /* -1.75 */
+
+ exponents[0] = 1023; /* exp = 0: 1.0 */
+ exponents[1] = 1021; /* exp = -2: -0.4375 (7/16) */
+
+ result = make_doubles (significands_p, &exponents);
+ if ((result[0] != 1.0) || (result[1] != -0.4375))
+ abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-8.c
new file mode 100644
index 00000000000..3f9bd988aad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-8.c
@@ -0,0 +1,43 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector float
+make_floats (__vector unsigned int *significands_p,
+ __vector unsigned int *exponents_p)
+{
+ __vector unsigned int significands = *significands_p;
+ __vector unsigned int exponents = *exponents_p;
+
+ return vec_insert_exp (significands, exponents);
+}
+
+int
+main ()
+{
+ __vector unsigned int significands;
+ __vector unsigned int exponents;
+ __vector float result;
+
+ /* 24 bits in significand, plus the sign bit: 0x80ffffff */
+ significands[0] = 0x00800000; /* 1.0 */
+ significands[1] = 0x00c00000; /* 1.5 */
+ significands[2] = 0x80e00000; /* -1.75 */
+ significands[3] = 0x80c00000; /* -1.5 */
+
+ exponents[0] = 127; /* exp = 0: 1.0 */
+ exponents[1] = 128; /* exp = 1: 3.0.0 */
+ exponents[2] = 129; /* exp = 2: -7.0 */
+ exponents[3] = 125; /* exp = -2: -0.375 */
+
+ result = make_floats (&significands, &exponents);
+ if ((result[0] != 1.0f) ||
+ (result[1] != 3.0f) || (result[2] != -7.0f) || (result[3] != -0.375f))
+ abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-9.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-9.c
new file mode 100644
index 00000000000..5dc71951aee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-9.c
@@ -0,0 +1,38 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+__vector double
+make_doubles (__vector unsigned long long int *significands_p,
+ __vector unsigned long long int *exponents_p)
+{
+ __vector unsigned long long int significands = *significands_p;
+ __vector unsigned long long int exponents = *exponents_p;
+
+ return vec_insert_exp (significands, exponents);
+}
+
+int
+main ()
+{
+ __vector unsigned long long int significands;
+ __vector unsigned long long int exponents;
+ __vector double result;
+
+ /* 53 bits in significand, plus the sign bit: 0x8000_0000_0000_0000 */
+ significands[0] = 0x0010000000000000; /* 1.0 */
+ significands[1] = 0x801c000000000000; /* -1.75 */
+
+ exponents[0] = 1023; /* exp = 0: 1.0 */
+ exponents[1] = 1021; /* exp = -2: -0.4375 (7/16) */
+
+ result = make_doubles (&significands, &exponents);
+ if ((result[0] != 1.0) || (result[1] != -0.4375))
+ abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-8.c
new file mode 100644
index 00000000000..636a3012612
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-8.c
@@ -0,0 +1,112 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+/* Flags to select tests:
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal */
+
+__vector bool int
+test_nan (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_test_data_class (source, 0x40);
+}
+
+__vector bool int
+test_infinity (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_test_data_class (source, 0x30);
+}
+
+__vector bool int
+test_zero (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_test_data_class (source, 0x0c);
+}
+
+__vector bool int
+test_denormal (__vector float *p)
+{
+ __vector float source = *p;
+
+ return vec_test_data_class (source, 0x03);
+}
+
+float
+float_scalar_insert_exp (unsigned int significand, unsigned int exponent)
+{
+ float result;
+ unsigned int *result_as_uip = (unsigned int *) &result;
+
+ *result_as_uip = (significand & ~0x800000) | ((exponent & 0xff) << 23);
+ return result;
+}
+
+int
+main ()
+{
+ __vector float argument;
+ __vector bool result;
+
+ unsigned int signaling_significand = 0x00a00000;
+ unsigned int quiet_significand = 0x00c00000;
+ unsigned int one_significand = 0x00800000;
+ unsigned int three_significand = 0x00c00000;
+ unsigned int five_significand = 0x00a00000;
+ unsigned int zero_significand = 0x00000000;
+ unsigned int minus_zero_significand = 0x80000000;
+
+ /* A NaN is represented with the maximum biased exponent value and a
+ * non-zero fraction value. The sign bit ignored. If the
+ * high-order bit of the fraction field is 0, then the NaN
+ * is a Signaling NaN. Otherwise, it is a Quiet NaN. */
+ argument[0] = float_scalar_insert_exp (signaling_significand, 255);
+ argument[1] = float_scalar_insert_exp (quiet_significand, 255);
+ argument[2] = 1.0f;
+ argument[3] = -0.07f;
+ result = test_nan (&argument);
+ if (!result[0] || !result[1] || result[2] || result[3])
+ abort ();
+
+ /* Infinity is represented by a biased exponent value of:
+ * 255 in single format
+ * 2047 in double format
+ * and a zero fraction value. The difference between +infinity and
+ * -infinity is the value of the sign bit. */
+ argument[2] = float_scalar_insert_exp (zero_significand, 255);
+ argument[3] = float_scalar_insert_exp (minus_zero_significand, 255);
+ result = test_infinity (&argument);
+ if (result[0] || result[1] || !result[2] || !result[3])
+ abort ();
+
+ /* A Zero value has a biased exponent value of zero and a zero
+ * fraction value. The sign may be either positive or negative. */
+ argument[1] = float_scalar_insert_exp (minus_zero_significand, 0);
+ argument[2] = float_scalar_insert_exp (zero_significand, 0);
+ result = test_zero (&argument);
+ if (result[0] || !result[1] || !result[2] || result[3])
+ abort ();
+
+ /* A Denormal number has a biased exponent value of zero and a
+ * non-zero fraction value. */
+ argument[0] = float_scalar_insert_exp (five_significand, 0);
+ argument[3] = float_scalar_insert_exp (three_significand, 0);
+ result = test_denormal (&argument);
+ if (!result[0] || result[1] || result[2] || !result[3])
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-9.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-9.c
new file mode 100644
index 00000000000..5ccac12df87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-9.c
@@ -0,0 +1,125 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target p9vector_hw } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+#include <stdlib.h>
+
+/* Flags to select tests:
+ 0x40 Test for NaN
+ 0x20 Test for +Infinity
+ 0x10 Test for -Infinity
+ 0x08 Test for +Zero
+ 0x04 Test for -Zero
+ 0x02 Test for +Denormal
+ 0x01 Test for -Denormal */
+
+__vector bool long long int
+test_nan (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_test_data_class (source, 0x40);
+}
+
+__vector bool long long int
+test_infinity (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_test_data_class (source, 0x30);
+}
+
+__vector bool long long int
+test_zero (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_test_data_class (source, 0x0c);
+}
+
+__vector bool long long int
+test_denormal (__vector double *p)
+{
+ __vector double source = *p;
+
+ return vec_test_data_class (source, 0x03);
+}
+
+int
+main ()
+{
+ __vector double special_argument;
+ __vector double nonspecial_argument;
+ __vector bool long long int result;
+
+ unsigned long long int signaling_significand =
+ 0x0017000000000000ULL;
+ unsigned long long int quiet_significand =
+ 0x001f000000000000ULL;
+ unsigned long long int one_significand =
+ 0x0010000000000000ULL;
+ unsigned long long int three_significand =
+ 0x0018000000000000ULL;
+ unsigned long long int five_significand =
+ 0x0014000000000000ULL;
+ unsigned long long int zero_significand =
+ 0x0000000000000000ULL;
+ unsigned long long int minus_zero_significand =
+ 0x8000000000000000ULL;
+
+ nonspecial_argument[0] = -3.825;
+ nonspecial_argument[1] = 3.14159;
+
+ /* A NaN is represented with the maximum biased exponent value and a
+ * non-zero fraction value. The sign bit ignored. If the
+ * high-order bit of the fraction field is 0, then the NaN
+ * is a Signaling NaN. Otherwise, it is a Quiet NaN. */
+ special_argument[0] = scalar_insert_exp (signaling_significand, 2047);
+ special_argument[1] = scalar_insert_exp (quiet_significand, 2047);
+ result = test_nan (&special_argument);
+ if (!result[0] || !result[1])
+ abort ();
+ result = test_nan (&nonspecial_argument);
+ if (result[0] || result[1])
+ abort ();
+
+ /* Infinity is represented by a biased exponent value of:
+ * 255 in single format
+ * 2047 in double format
+ * and a zero fraction value. The difference between +infinity and
+ * -infinity is the value of the sign bit. */
+ special_argument[0] = scalar_insert_exp (zero_significand, 2047);
+ special_argument[1] = scalar_insert_exp (minus_zero_significand, 2047);
+ result = test_infinity (&special_argument);
+ if (!result[0] || !result[1])
+ abort ();
+ result = test_infinity (&nonspecial_argument);
+ if (result[0] || result[1])
+ abort ();
+
+ /* A Zero value has a biased exponent value of zero and a zero
+ * fraction value. The sign may be either positive or negative. */
+ special_argument[0] = scalar_insert_exp (minus_zero_significand, 0);
+ special_argument[1] = scalar_insert_exp (zero_significand, 0);
+ result = test_zero (&special_argument);
+ if (!result[0] || !result[1])
+ abort ();
+ result = test_zero (&nonspecial_argument);
+ if (result[0] || result[1])
+ abort ();
+
+ /* A Denormal number has a biased exponent value of zero and a
+ * non-zero fraction value. */
+ special_argument[0] = scalar_insert_exp (five_significand, 0);
+ special_argument[1] = scalar_insert_exp (three_significand, 0);
+ result = test_denormal (&special_argument);
+ if (!result[0] || !result[1])
+ abort ();
+ result = test_denormal (&nonspecial_argument);
+ if (result[0] || result[1])
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-andn-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-andn-1.c
index 8d8d643e088..3702bdd77fe 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-andn-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-andn-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-andn-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-andn-2.c
index a4260b51b79..a6f5d5084c9 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-andn-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-andn-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-1.c
index f532c6a3bb5..45e5bdd8510 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O2 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-2.c
index b3515259fca..52f78df1267 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-4.c b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-4.c
index 8701d9fbd1d..3ca56665033 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-4.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-5.c b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-5.c
index 2835adedced..e43e2da422a 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-bextr-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-bextr-5.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsi-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsi-1.c
index 418d336b43e..345a7eb9def 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsi-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsi-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsi-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsi-2.c
index 1d51b5a75bb..f2e1a58f5ed 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsi-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsi-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-1.c
index df34d53ab86..481b09f77ce 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-2.c
index e5fe12d4ee0..3ba7e97dd47 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsmsk-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsr-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsr-1.c
index 645e00f05ee..c383b7914e2 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsr-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsr-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-blsr-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-blsr-2.c
index f290b838001..61d962b9150 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-blsr-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-blsr-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-check.h b/gcc/testsuite/gcc.target/powerpc/bmi-check.h
index 35a2ac29bc3..1a9ad13f38c 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-check.h
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-check.h
@@ -13,6 +13,7 @@ do_test (void)
int
main ()
{
+#ifdef __BUILTIN_CPU_SUPPORTS__
/* Need 64-bit for 64-bit longs as single instruction. */
if ( __builtin_cpu_supports ("ppc64") )
{
@@ -25,6 +26,6 @@ main ()
else
printf ("SKIPPED\n");
#endif
-
+#endif /* __BUILTIN_CPU_SUPPORTS__ */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-1.c b/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-1.c
index 25b096ad0bc..25ba3dc238e 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-2.c b/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-2.c
index 75397e53eb6..1b80ccbdaa9 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi-tzcnt-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3 -fno-inline" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi32-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi32-1.c
index b2a6d4d74ea..f0943d7f974 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi32-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi32-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi64-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi64-1.c
index a09d5d24b51..33f1748b44e 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi64-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-bzhi64-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-check.h b/gcc/testsuite/gcc.target/powerpc/bmi2-check.h
index fa7d4c02a45..ab032eaa7ca 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-check.h
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-check.h
@@ -13,6 +13,7 @@ do_test (void)
int
main ()
{
+#ifdef __BUILTIN_CPU_SUPPORTS__
/* The BMI2 test for pext test requires the Bit Permute doubleword
(bpermd) instruction added in PowerISA 2.06 along with the VSX
facility. So we can test for arch_2_06. */
@@ -27,7 +28,7 @@ main ()
else
printf ("SKIPPED\n");
#endif
-
+#endif /* __BUILTIN_CPU_SUPPORTS__ */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-1.c
index eda74690589..870679c779f 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include "bmi2-check.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-2.c b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-2.c
index a6fc38cbf55..b8327741c3a 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx32-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-1.c
index 5334de20fc5..b1e4a13c2af 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include "bmi2-check.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-2.c b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-2.c
index ff119262c64..d57f05503c5 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-mulx64-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-pdep32-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-pdep32-1.c
index 12cf92eec2c..a07567389d0 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-pdep32-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-pdep32-1.c
@@ -3,6 +3,7 @@
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target vsx_hw } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-pdep64-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-pdep64-1.c
index 01e1fdaf538..1268239e61f 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-pdep64-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-pdep64-1.c
@@ -3,6 +3,7 @@
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target vsx_hw } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-pext32-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-pext32-1.c
index 9450ef56aed..762ed1b0325 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-pext32-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-pext32-1.c
@@ -3,6 +3,7 @@
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target vsx_hw } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/bmi2-pext64-1.c b/gcc/testsuite/gcc.target/powerpc/bmi2-pext64-1.c
index b76ae81b5bc..5e269ec47de 100644
--- a/gcc/testsuite/gcc.target/powerpc/bmi2-pext64-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/bmi2-pext64-1.c
@@ -3,6 +3,7 @@
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target vsx_hw } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
#define NO_WARN_X86_INTRINSICS 1
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1-p9-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-1-p9-runnable.c
new file mode 100644
index 00000000000..acaebb60f1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-1-p9-runnable.c
@@ -0,0 +1,26 @@
+/* { dg-do run { target { powerpc*-*-linux* && { lp64 && p9vector_hw } } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mcpu=power9" } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+
+#include <altivec.h>
+
+void abort (void);
+
+int main() {
+ int i;
+ vector float vfa, vfb;
+ vector unsigned short vur, vuexpt;
+
+ vfa = (vector float){3.4, 5.0, 20.0, 50.9 };
+ vfb = (vector float){10.0, 40.0, 70.0, 100.0 };
+ vuexpt = (vector unsigned short){ 3, 5, 20, 50,
+ 10, 40, 70, 100};
+
+ vur = vec_pack_to_short_fp32 (vfa, vfb);
+
+ for(i = 0; i< 8; i++) {
+ if (vur[i] != vuexpt[i])
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-2-p9-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-2-p9-runnable.c
new file mode 100644
index 00000000000..2f317077fcb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-2-p9-runnable.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target { powerpc64*-*-* && { lp64 && p9vector_hw } } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+#include <altivec.h> // vector
+
+void abort (void);
+
+int main() {
+ int i;
+ vector int vsia;
+ vector unsigned int vsir, vsiexpt;
+ vector unsigned int vuia, vuir, vuiexpt;
+ vector signed long long vslla;
+ vector unsigned long long vsllr, vsllexpt;
+ vector unsigned long long vulla, vullr, vullexpt;
+ vector __int128_t vs128a;
+ vector __uint128_t vs128r, vs128expt;
+ vector __uint128_t vu128a, vu128r, vu128expt;
+
+ /* Returns a vector with each element containing the parity of the low-order
+ bit of each of the bytes in that element. Note results are always
+ returned in an unsinged type, per the ABI spec. */
+ vsia = (vector int) {0x10101010, 0x10101011, 0x10101111, 0x10111111};
+ vsiexpt = (vector unsigned int){0x0, 0x1, 0x0, 0x1};
+
+ vuia = (vector unsigned int) {0x000010000, 0x00010001,
+ 0x10100000, 0x000010101};
+ vuiexpt = (vector unsigned int){0x1, 0x0, 0x0, 0x1};
+
+ vslla = (vector long long) {0x0000000000010000, 0x0001000100010000};
+ vsllexpt = (vector unsigned long long){0x1, 0x1};
+
+ vulla = (vector unsigned long long) {0x0000000000000001,
+ 0x0001000000000001};
+ vullexpt = (vector unsigned long long){0x1, 0x0};
+
+ vs128a = (vector __int128_t) {0x0000000000001};
+ vs128expt = (vector __uint128_t) {0x1};
+ vu128a = (vector __uint128_t) {0x1000000000001};
+ vu128expt = (vector __uint128_t) {0x0};
+
+ vsir = vec_parity_lsbb(vsia);
+ vuir = vec_parity_lsbb(vuia);
+ vsllr = vec_parity_lsbb(vslla);
+ vullr = vec_parity_lsbb(vulla);
+ vs128r = vec_parity_lsbb(vs128a);
+ vu128r = vec_parity_lsbb(vu128a);
+
+ for(i = 0; i< 4; i++) {
+ if (vsir[i] != vsiexpt[i])
+ abort();
+
+ if (vuir[i] != vuiexpt[i])
+ abort();
+ }
+
+ for(i = 0; i< 2; i++) {
+ if (vsllr[i] != vsllexpt[i])
+ abort();
+
+ if (vullr[i] != vullexpt[i])
+ abort();
+ }
+
+ if (vs128r[0] != vs128expt[0])
+ abort();
+
+ if (vu128r[0] != vu128expt[0])
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3-p9-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-3-p9-runnable.c
new file mode 100644
index 00000000000..24589b55639
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3-p9-runnable.c
@@ -0,0 +1,35 @@
+/* { dg-do run { target { powerpc64*-*-* && { lp64 && p9vector_hw } } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+
+#include <altivec.h> // vector
+
+void abort (void);
+
+int main() {
+ int i;
+ vector float vfr, vfexpt;
+ vector unsigned short vusha;
+
+ /* 1.0, -2.0, 0.0, 8.5, 1.5, 0.5, 1.25, -0.25 */
+ vusha = (vector unsigned short){0B011110000000000, 0B1100000000000000,
+ 0B000000000000000, 0B0100100001000000,
+ 0B011111000000000, 0B0011100000000000,
+ 0B011110100000000, 0B1011010000000000};
+
+ vfexpt = (vector float){1.0, -2.0, 0.0, 8.5};
+ vfr = vec_extract_fp_from_shorth(vusha);
+
+ for (i=0; i<4; i++) {
+ if (vfr[i] != vfexpt[i])
+ abort();
+ }
+
+ vfexpt = (vector float){1.5, 0.5, 1.25, -0.25};
+ vfr = vec_extract_fp_from_shortl(vusha);
+
+ for (i=0; i<4; i++) {
+ if (vfr[i] != vfexpt[i])
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-3-runnable.c
index 08b7a5395d2..17bb9b3225b 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-3-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3-runnable.c
@@ -5,53 +5,181 @@
#include <altivec.h> // vector
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
#define ALL 1
#define EVEN 2
#define ODD 3
void abort (void);
-void test_result_sp(int check, vector float vec_result, vector float vec_expected)
+void test_int_result(int check, vector int vec_result, vector int vec_expected)
{
int i;
- for(i = 0; i<4; i++) {
- switch (check) {
- case ALL:
- break;
- case EVEN:
- if (i%2 == 0)
+ for (i = 0; i < 4; i++) {
+ switch (check) {
+ case ALL:
break;
- else
- continue;
- case ODD:
- if (i%2 != 0)
+ case EVEN:
+ if (i%2 == 0)
+ break;
+ else
+ continue;
+ case ODD:
+ if (i%2 != 0)
+ break;
+ else
+ continue;
+ }
+
+ if (vec_result[i] != vec_expected[i]) {
+#ifdef DEBUG
+ printf("Test_int_result: ");
+ printf("vec_result[%d] (%d) != vec_expected[%d] (%d)\n",
+ i, vec_result[i], i, vec_expected[i]);
+#else
+ abort();
+#endif
+ }
+ }
+}
+
+void test_unsigned_int_result(int check, vector unsigned int vec_result,
+ vector unsigned int vec_expected)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ switch (check) {
+ case ALL:
break;
- else
- continue;
+ case EVEN:
+ if (i%2 == 0)
+ break;
+ else
+ continue;
+ case ODD:
+ if (i%2 != 0)
+ break;
+ else
+ continue;
+ }
+
+ if (vec_result[i] != vec_expected[i]) {
+#ifdef DEBUG
+ printf("Test_unsigned int_result: ");
+ printf("vec_result[%d] (%d) != vec_expected[%d] (%d)\n",
+ i, vec_result[i], i, vec_expected[i]);
+#else
+ abort();
+#endif
+ }
+
}
+}
- if (vec_result[i] != vec_expected[i])
- abort();
+void test_ll_int_result(vector long long int vec_result,
+ vector long long int vec_expected)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ if (vec_result[i] != vec_expected[i]) {
+#ifdef DEBUG
+ printf("Test_ll_int_result: ");
+ printf("vec_result[%d] (%lld) != vec_expected[%d] (%lld)\n",
+ i, vec_result[i], i, vec_expected[i]);
+#else
+ abort();
+#endif
+ }
+}
+
+void test_ll_unsigned_int_result(vector long long unsigned int vec_result,
+ vector long long unsigned int vec_expected)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ if (vec_result[i] != vec_expected[i]) {
+#ifdef DEBUG
+ printf("Test_ll_unsigned_int_result: ");
+ printf("vec_result[%d] (%lld) != vec_expected[%d] (%lld)\n",
+ i, vec_result[i], i, vec_expected[i]);
+#else
+ abort();
+#endif
+ }
+}
+
+void test_result_sp(int check, vector float vec_result,
+ vector float vec_expected)
+{
+ int i;
+ for(i = 0; i<4; i++) {
+
+ switch (check) {
+ case ALL:
+ break;
+ case EVEN:
+ if (i%2 == 0)
+ break;
+ else
+ continue;
+ case ODD:
+ if (i%2 != 0)
+ break;
+ else
+ continue;
+ }
+
+ if (vec_result[i] != vec_expected[i]) {
+#ifdef DEBUG
+ printf("Test_result_sp: ");
+ printf("vec_result[%d] (%lld) != vec_expected[%d] (%lld)\n",
+ i, vec_result[i], i, vec_expected[i]);
+#else
+ abort();
+#endif
+ }
}
}
void test_result_dp(vector double vec_result, vector double vec_expected)
{
- if (vec_result[0] != vec_expected[0])
+ if (vec_result[0] != vec_expected[0]) {
+#ifdef DEBUG
+ printf("Test_result_dp: ");
+ printf("vec_result[0] (%lld) != vec_expected[0] (%lld)\n",
+ vec_result[0], vec_expected[0]);
+#else
abort();
+#endif
+ }
- if (vec_result[1] != vec_expected[1])
+ if (vec_result[1] != vec_expected[1]) {
+#ifdef DEBUG
+ printf("Test_result_dp: ");
+ printf("vec_result[1] (%lld) != vec_expected[1] (%lld)\n",
+ vec_result[1], vec_expected[1]);
+#else
abort();
+#endif
+ }
}
int main()
{
int i;
- vector unsigned int vec_unint;
- vector signed int vec_int;
+ vector unsigned int vec_unint, vec_uns_int_expected, vec_uns_int_result;
+ vector signed int vec_int, vec_int_expected, vec_int_result;
vector long long int vec_ll_int0, vec_ll_int1;
+ vector long long int vec_ll_int_expected, vec_ll_int_result;
vector long long unsigned int vec_ll_uns_int0, vec_ll_uns_int1;
+ vector long long unsigned int vec_ll_uns_int_expected, vec_ll_uns_int_result;
vector float vec_flt, vec_flt_result, vec_flt_expected;
vector double vec_dble0, vec_dble1, vec_dble_result, vec_dble_expected;
@@ -163,4 +291,67 @@ int main()
vec_flt_expected = (vector float){0.00, 34.00, 0.00, 97.00};
vec_flt_result = vec_floato (vec_dble0);
test_result_sp(ODD, vec_flt_result, vec_flt_expected);
+
+ /* Convert single precision float to int */
+ vec_flt = (vector float){-14.30, 34.00, 22.00, 97.00};
+ vec_int_expected = (vector signed int){-14, 34, 22, 97};
+ vec_int_result = vec_signed (vec_flt);
+ test_int_result (ALL, vec_int_result, vec_int_expected);
+
+ /* Convert double precision float to long long int */
+ vec_dble0 = (vector double){-124.930, 81234.49};
+ vec_ll_int_expected = (vector long long signed int){-124, 81234};
+ vec_ll_int_result = vec_signed (vec_dble0);
+ test_ll_int_result (vec_ll_int_result, vec_ll_int_expected);
+
+ /* Convert two double precision vector float to vector int */
+ vec_dble0 = (vector double){-124.930, 81234.49};
+ vec_dble1 = (vector double){-24.370, 8354.99};
+ vec_int_expected = (vector signed int){-124, 81234, -24, 8354};
+ vec_int_result = vec_signed2 (vec_dble0, vec_dble1);
+ test_int_result (ALL, vec_int_result, vec_int_expected);
+
+ /* Convert double precision vector float to vector int, even words */
+ vec_dble0 = (vector double){-124.930, 81234.49};
+ vec_int_expected = (vector signed int){-124, 0, 81234, 0};
+ vec_int_result = vec_signede (vec_dble0);
+ test_int_result (EVEN, vec_int_result, vec_int_expected);
+
+ /* Convert double precision vector float to vector int, odd words */
+ vec_dble0 = (vector double){-124.930, 81234.49};
+ vec_int_expected = (vector signed int){0, -124, 0, 81234};
+ vec_int_result = vec_signedo (vec_dble0);
+ test_int_result (ODD, vec_int_result, vec_int_expected);
+
+ /* Convert double precision float to long long unsigned int */
+ vec_dble0 = (vector double){124.930, 8134.49};
+ vec_ll_uns_int_expected = (vector long long unsigned int){124, 8134};
+ vec_ll_uns_int_result = vec_unsigned (vec_dble0);
+ test_ll_unsigned_int_result (vec_ll_uns_int_result,
+ vec_ll_uns_int_expected);
+
+ /* Convert two double precision vector float to vector unsigned int */
+ vec_dble0 = (vector double){124.930, 8134.49};
+ vec_dble1 = (vector double){24.370, 834.99};
+ vec_uns_int_expected = (vector unsigned int){124, 8134, 24, 834};
+ vec_uns_int_result = vec_unsigned2 (vec_dble0, vec_dble1);
+ test_unsigned_int_result (ALL, vec_uns_int_result,
+ vec_uns_int_expected);
+
+ /* Convert double precision vector float to vector unsigned int,
+ even words */
+ vec_dble0 = (vector double){3124.930, 8234.49};
+ vec_uns_int_expected = (vector unsigned int){3124, 0, 8234, 0};
+ vec_uns_int_result = vec_unsignede (vec_dble0);
+ test_unsigned_int_result (EVEN, vec_uns_int_result,
+ vec_uns_int_expected);
+
+ /* Convert double precision vector float to vector unsigned int,
+ odd words */
+ vec_dble0 = (vector double){1924.930, 81234.49};
+ vec_uns_int_expected = (vector unsigned int){0, 1924, 0, 81234};
+ vec_uns_int_result = vec_unsignedo (vec_dble0);
+ test_unsigned_int_result (ODD, vec_uns_int_result,
+ vec_uns_int_expected);
}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3-vec_reve-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-3-vec_reve-runnable.c
new file mode 100644
index 00000000000..f7c3c3d9138
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3-vec_reve-runnable.c
@@ -0,0 +1,393 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-O2 -mvsx -mcpu=power7" } */
+
+#include <altivec.h> // vector
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#define VBC 0
+#define VSC 1
+#define VUC 2
+#define VBS 3
+#define VSS 4
+#define VUS 5
+#define VBI 6
+#define VI 7
+#define VUI 8
+#define VLLB 9
+#define VLLI 10
+#define VLLUI 11
+#define VF 12
+#define VD 13
+
+union vector_value
+{
+ vector bool char vbc;
+ vector signed char vsc;
+ vector unsigned char vuc;
+ vector bool short vbs;
+ vector signed short vss;
+ vector unsigned short vus;
+ vector bool int vbi;
+ vector signed int vi;
+ vector unsigned int vui;
+ vector bool long long vllb;
+ vector long long signed int vlli;
+ vector long long unsigned int vllui;
+ vector float vf;
+ vector double vd;
+} vec_element;
+
+struct vector_struct
+{
+ int vector_id;
+ int element_size; // element size in bytes
+ union vector_value vec;
+} vec;
+
+void abort (void);
+
+void test_results(struct vector_struct *vec_result,
+ struct vector_struct *vec_expected)
+{
+ int i;
+ int num_elements;
+ if (vec_result->element_size != vec_expected->element_size)
+#ifdef DEBUG
+ printf("vec_result->element_size != vec_expected->element_size\n");
+#else
+ abort();
+#endif
+
+ if (vec_result->vector_id != vec_expected->vector_id)
+#ifdef DEBUG
+ printf("vec_result->vector_id != vec_expected->vector_id\n");
+#else
+ abort();
+#endif
+
+ num_elements = 16 / vec_result->element_size;
+
+ for (i = 0; i<num_elements; i++) {
+ switch (vec_result->vector_id) {
+ case VBC:
+ if (vec_result->vec.vbc[i] != vec_expected->vec.vbc[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vbc[%d] (%d) != ",
+ i, vec_result->vec.vbc[i]);
+ printf("vec_expected->vec.vbc[%d] (%d)\n",
+ i, vec_expected->vec.vbc[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VSC:
+ if (vec_result->vec.vsc[i] != vec_expected->vec.vsc[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vsc[%d] (%d) != ",
+ i, vec_result->vec.vsc[i]);
+ printf("vec_expected->vec.vsc[%d] (%d)\n",
+ i, vec_expected->vec.vsc[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VUC:
+ if (vec_result->vec.vuc[i] != vec_expected->vec.vuc[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vuc[%d] (%d) != ",
+ i, vec_result->vec.vuc[i]);
+ printf("vec_expected->vec.vuc[%d] (%d)\n",
+ i, vec_expected->vec.vuc[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VBS:
+ if (vec_result->vec.vbs[i] != vec_expected->vec.vbs[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vbs[%d] (%d) != ",
+ i, vec_result->vec.vbs[i]);
+ printf("vec_expected->vec.vbs[%d] (%d)\n",
+ i, vec_expected->vec.vbs[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VSS:
+ if (vec_result->vec.vss[i] != vec_expected->vec.vss[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vss[%d] (%d) != ",
+ i, vec_result->vec.vss[i]);
+ printf("vec_expected->vec.vss[%d] (%d)\n",
+ i, vec_expected->vec.vss[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VUS:
+ if (vec_result->vec.vus[i] != vec_expected->vec.vus[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vus[%d] (%d) != ",
+ i, vec_expected->vec.vus[i]);
+ printf("vec_expected->vec.vus[%d] (%d)\n",
+ i, vec_expected->vec.vus[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VBI:
+ if (vec_result->vec.vbi[i] != vec_expected->vec.vbi[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vbi[%d] (%d) != ",
+ i, vec_result->vec.vbi[i]);
+ printf("vec_expected->vec.vbi[%d] (%d)\n",
+ i, vec_expected->vec.vbi[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VI:
+ if (vec_result->vec.vi[i] != vec_expected->vec.vi[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vi[%d] (%d) != ",
+ i, vec_result->vec.vi[i]);
+ printf("vec_expected->vec.vi[%d] (%d)\n",
+ i, vec_expected->vec.vi[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VUI:
+ if (vec_result->vec.vui[i] != vec_expected->vec.vui[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vui[%d] (%u) != ",
+ i, vec_result->vec.vui[i]);
+ printf("vec_expected->vec.vui[%u] (%d)\n",
+ i, vec_expected->vec.vui[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VLLB:
+ if (vec_result->vec.vllb[i] != vec_expected->vec.vllb[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vllb[%d] (%lld != ",
+ i, vec_result->vec.vllb[i]);
+ printf("vec_expected->vec.vllb[%lld] (%d)\n",
+ i, vec_expected->vec.vllb[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VLLI:
+ if (vec_result->vec.vlli[i] != vec_expected->vec.vlli[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vlli[%d] (%d) != ",
+ i, vec_result->vec.vlli[i]);
+ printf("vec_expected->vec.vlli[%d] (%d)\n",
+ i, vec_expected->vec.vlli[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VLLUI:
+ if (vec_result->vec.vllui[i] != vec_expected->vec.vllui[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vllui[%d] (%llu) != ",
+ i, vec_result->vec.vllui[i]);
+ printf("vec_expected->vec.vllui[%d] (%llu)\n",
+ i, vec_expected->vec.vllui[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VF:
+ if (vec_result->vec.vf[i] != vec_expected->vec.vf[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vf[%d] (%f) != ",
+ i, vec_result->vec.vf[i]);
+ printf("vec_expected->vec.vf[%d] (%f)\n",
+ i, vec_expected->vec.vf[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ case VD:
+ if (vec_result->vec.vd[i] != vec_expected->vec.vd[i])
+ {
+#ifdef DEBUG
+ printf("vec_result->vec.vd[%d] (%f) != ",
+ i, vec_result->vec.vd[i]);
+ printf("vec_expected->vec.vd[%d] (%f)\n",
+ i, vec_expected->vec.vd[i]);
+#else
+ abort();
+#endif
+ }
+ break;
+
+ default:
+#ifdef DEBUG
+ printf("Unknown case.\n");
+#else
+ abort();
+#endif
+ }
+ }
+}
+
+int main()
+{
+ int i;
+ struct vector_struct vec_src, vec_expected, vec_result;
+
+ vec_src.vec.vbc = (vector bool char){ 0, 1, 0, 0, 1, 1, 0, 0,
+ 0, 1, 1, 1, 0, 0, 0, 0 };
+ vec_expected.vec.vbc = (vector bool char){ 0, 0, 0, 0, 1, 1, 1, 0,
+ 0, 0, 1, 1, 0, 0, 1, 0 };
+ vec_result.element_size = vec_expected.element_size = 1;
+ vec_result.vector_id = vec_expected.vector_id = VBC;
+ vec_result.vec.vbc = vec_reve (vec_src.vec.vbc);
+ test_results(&vec_result, &vec_expected);
+
+ vec_src.vec.vsc = (vector signed char){ 0, 1, -2, -3, 4, 5, -6, -7, 8,
+ 9, -10, -11, 12, 13, -14, -15 };
+ vec_expected.vec.vsc = (vector signed char){ -15, -14, 13, 12, -11, -10,
+ 9, 8, -7, -6, 5, 4, -3, -2,
+ 1, 0 };
+ vec_result.element_size = vec_expected.element_size = 1;
+ vec_result.vector_id = vec_expected.vector_id = VSC;
+ vec_result.vec.vsc = vec_reve (vec_src.vec.vsc);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vuc = (vector unsigned char){ 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25 };
+ vec_expected.vec.vuc = (vector unsigned char){ 25, 24, 23, 22, 21, 20,
+ 19, 18, 17, 16, 15, 14, 13,
+ 12, 11, 10 };
+ vec_result.element_size = vec_expected.element_size = 1;
+ vec_result.vector_id = vec_expected.vector_id = VUC;
+ vec_result.vec.vuc = vec_reve (vec_src.vec.vuc);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vbs = (vector bool short){ 0, 0, 1, 1, 0, 1, 0, 1 };
+ vec_expected.vec.vbs = (vector bool short){ 1, 0, 1, 0, 1, 1, 0, 0 };
+ vec_result.element_size = vec_expected.element_size = 2;
+ vec_result.vector_id = vec_expected.vector_id = VBS;
+ vec_result.vec.vbs = vec_reve (vec_src.vec.vbs);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vss = (vector signed short){ -1, -2, 3, 4, -5, -6, 7, 8 };
+ vec_expected.vec.vss = (vector signed short){ 8, 7, -6, -5, 4, 3, -2, -1 };
+ vec_result.element_size = vec_expected.element_size = 2;
+ vec_result.vector_id = vec_expected.vector_id = VSS;
+ vec_result.vec.vss = vec_reve (vec_src.vec.vss);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vus = (vector unsigned short){ 11, 22, 33, 44, 55, 66, 77, 88 };
+ vec_expected.vec.vus = (vector unsigned short){ 88, 77, 66, 55,
+ 44, 33, 22, 11 };
+ vec_result.element_size = vec_expected.element_size = 2;
+ vec_result.vector_id = vec_expected.vector_id = VUS;
+ vec_result.vec.vus = vec_reve (vec_src.vec.vus);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vbi = (vector bool int){ 0, 1, 1, 1 };
+ vec_expected.vec.vbi = (vector bool int){ 1, 1, 1, 0 };
+ vec_result.element_size = vec_expected.element_size = 4;
+ vec_result.vector_id = vec_expected.vector_id = VBI;
+ vec_result.vec.vbi = vec_reve (vec_src.vec.vbi);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vi = (vector signed int){ -1, 3, -5, 1234567 };
+ vec_expected.vec.vi = (vector signed int){1234567, -5, 3, -1};
+ vec_result.element_size = vec_expected.element_size = 4;
+ vec_result.vector_id = vec_expected.vector_id = VI;
+ vec_result.vec.vi = vec_reve (vec_src.vec.vi);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vui = (vector unsigned int){ 9, 11, 15, 2468013579 };
+ vec_expected.vec.vui = (vector unsigned int){2468013579, 15, 11, 9};
+ vec_result.element_size = vec_expected.element_size = 4;
+ vec_result.vector_id = vec_expected.vector_id = VUI;
+ vec_result.vec.vui = vec_reve (vec_src.vec.vui);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vllb = (vector bool long long ){ 0, 1 };
+ vec_expected.vec.vllb = (vector bool long long){1, 0};
+ vec_result.element_size = vec_expected.element_size = 8;
+ vec_result.vector_id = vec_expected.vector_id = VLLB;
+ vec_result.vec.vllb = vec_reve (vec_src.vec.vllb);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vlli = (vector long long int){ -12, -12345678901234 };
+ vec_expected.vec.vlli = (vector long long int){-12345678901234, -12};
+ vec_result.element_size = vec_expected.element_size = 8;
+ vec_result.vector_id = vec_expected.vector_id = VLLI;
+ vec_result.vec.vlli = vec_reve (vec_src.vec.vlli);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vllui = (vector unsigned long long int){ 102, 9753108642 };
+ vec_expected.vec.vllui = (vector unsigned long long int){9753108642, 102};
+ vec_result.element_size = vec_expected.element_size = 8;
+ vec_result.vector_id = vec_expected.vector_id = VLLUI;
+ vec_result.vec.vllui = vec_reve (vec_src.vec.vllui);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vf = (vector float){ -21., 3.5, -53., 78. };
+ vec_expected.vec.vf = (vector float){78., -53, 3.5, -21};
+ vec_result.element_size = vec_expected.element_size = 4;
+ vec_result.vector_id = vec_expected.vector_id = VF;
+ vec_result.vec.vf = vec_reve (vec_src.vec.vf);
+ test_results (&vec_result, &vec_expected);
+
+ vec_src.vec.vd = (vector double){ 34.0, 97.0 };
+ vec_expected.vec.vd = (vector double){97.0, 34.0};
+ vec_result.element_size = vec_expected.element_size = 8;
+ vec_result.vector_id = vec_expected.vector_id = VD;
+ vec_result.vec.vd = vec_reve (vec_src.vec.vd);
+ test_results (&vec_result, &vec_expected);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-4-p9-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-4-p9-runnable.c
new file mode 100644
index 00000000000..8e8fcabbe82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-4-p9-runnable.c
@@ -0,0 +1,95 @@
+/* { dg-do run { target { powerpc*-*-* && { p9vector_hw } } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2 " } */
+
+#include <altivec.h> // vector
+
+void abort (void);
+
+int main() {
+ int i;
+
+ vector signed char vsca, vscr, vscexpt;
+ vector unsigned char vuca, vucr, vucexpt;
+ vector signed short int vssa, vssr, vssexpt;
+ vector unsigned short int vusa, vusr, vusexpt;
+ vector signed int vsia, vsir, vsiexpt;
+ vector unsigned int vuia, vuir, vuiexpt;
+ vector signed long long vslla, vsllr, vsllexpt;
+ vector unsigned long long vulla, vullr, vullexpt;
+
+ vsca = (vector signed char) {0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15};
+
+ vscexpt = (vector signed char) {8, 0, 1, 0, 2, 0, 1, 0,
+ 3, 0, 1, 0, 2, 0, 1, 0};
+
+ vuca = (vector unsigned char) {'0', '3', '6', '9', 'A', 'B', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'};
+
+ vucexpt = (vector unsigned char) {4, 0, 1, 0, 0, 1, 0, 1,
+ 0, 3, 0, 1, 0, 2, 0, 1};
+
+ vssa = (vector short int) {0x1, 0x10, 0x100, 0x1000,
+ 0x2, 0x20, 0x200, 0x2000};
+
+ vssexpt = (vector short int) {0, 4, 8, 12, 1, 5, 9, 13};
+
+ vusa = (vector unsigned short int) {0x4, 0x40, 0x400, 0x4000,
+ 0x8, 0x80, 0x800, 0x8000};
+ vusexpt = (vector unsigned short int) {2, 6, 10, 14, 3, 7, 11, 15};
+
+ vsia = (vector int) {0x10000, 0x100000, 0x1000000, 0x10000000};
+ vsiexpt = (vector int){16, 20, 24, 28};
+
+ vuia = (vector unsigned int) {0x2, 0x20, 0x200, 0x2000};
+ vuiexpt = (vector unsigned int){1, 5, 9, 13};
+
+ vslla = (vector long long) {0x0000000000010000LL, 0x0001000100010000LL};
+ vsllexpt = (vector long long){16, 16};
+
+ vulla = (vector unsigned long long) {0x0000400000000000LL, 0x0080000000000000ULL};
+
+ vullexpt = (vector unsigned long long) {46, 55};
+
+ vscr = vec_cnttz (vsca);
+ vucr = vec_cnttz (vuca);
+ vssr = vec_cnttz (vssa);
+ vusr = vec_cnttz (vusa);
+ vsir = vec_cnttz (vsia);
+ vuir = vec_cnttz (vuia);
+ vsllr = vec_cnttz (vslla);
+ vullr = vec_cnttz (vulla);
+
+ for (i=0; i<16; i++) {
+ if (vscr[i] != vscexpt[i])
+ abort();
+
+ if (vucr[i] != vucexpt[i])
+ abort();
+ }
+
+ for (i=0; i<8; i++) {
+ if (vssr[i] != vssexpt[i])
+ abort();
+
+ if (vusr[i] != vusexpt[i])
+ abort();
+ }
+
+ for (i=0; i<4; i++) {
+ if (vsir[i] != vsiexpt[i])
+ abort();
+
+ if (vuir[i] != vuiexpt[i])
+ abort();
+ }
+
+ for (i=0; i<2; i++) {
+ if (vsllr[i] != vsllexpt[i])
+ abort();
+
+ if (vullr[i] != vullexpt[i])
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/clone1.c b/gcc/testsuite/gcc.target/powerpc/clone1.c
index 5c69db8e217..eb13a7b2dbd 100644
--- a/gcc/testsuite/gcc.target/powerpc/clone1.c
+++ b/gcc/testsuite/gcc.target/powerpc/clone1.c
@@ -2,6 +2,7 @@
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-options "-mcpu=power8 -O2" } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
/* Power9 (aka, ISA 3.0) has a MODSD instruction to do modulus, while Power8
(aka, ISA 2.07) has to do modulus with divide and multiply. Make sure
diff --git a/gcc/testsuite/gcc.target/powerpc/clone2.c b/gcc/testsuite/gcc.target/powerpc/clone2.c
new file mode 100644
index 00000000000..ecad5eb8e29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/clone2.c
@@ -0,0 +1,31 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-options "-mvsx -O2" } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-require-effective-target ppc_cpu_supports_hw } */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+/* Power9 (aka, ISA 3.0) has a MODSD instruction to do modulus, while Power8
+ (aka, ISA 2.07) has to do modulus with divide and multiply. Make sure that
+ the basic support for target_clones runs.
+
+ Restrict ourselves to Linux, since IFUNC might not be supported in other
+ operating systems. */
+
+__attribute__((__target_clones__("cpu=power9,default")))
+long mod_func (long a, long b)
+{
+ return a % b;
+}
+
+#define X 53L
+#define Y 7L
+int
+main (void)
+{
+ if (mod_func (X, Y) != (X % Y))
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c
index 684c0f6d17d..c190f246231 100644
--- a/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/cpu-builtin-1.c
@@ -4,6 +4,11 @@
void
use_cpu_is_builtins (unsigned int *p)
{
+ /* If GCC was configured to use an old GLIBC (before 2.23), the
+ __builtin_cpu_is and __builtin_cpu_supports built-in functions return 0,
+ and the compiler issues a warning that you need a newer glibc to use them.
+ Use #ifdef to avoid the warning. */
+#ifdef __BUILTIN_CPU_SUPPORTS__
p[0] = __builtin_cpu_is ("power9");
p[1] = __builtin_cpu_is ("power8");
p[2] = __builtin_cpu_is ("power7");
@@ -19,11 +24,15 @@ use_cpu_is_builtins (unsigned int *p)
p[12] = __builtin_cpu_is ("ppc440");
p[13] = __builtin_cpu_is ("ppc405");
p[14] = __builtin_cpu_is ("ppc-cell-be");
+#else
+ p[0] = 0;
+#endif
}
void
use_cpu_supports_builtins (unsigned int *p)
{
+#ifdef __BUILTIN_CPU_SUPPORTS__
p[0] = __builtin_cpu_supports ("4xxmac");
p[1] = __builtin_cpu_supports ("altivec");
p[2] = __builtin_cpu_supports ("arch_2_05");
@@ -62,4 +71,9 @@ use_cpu_supports_builtins (unsigned int *p)
p[35] = __builtin_cpu_supports ("ucache");
p[36] = __builtin_cpu_supports ("vcrypto");
p[37] = __builtin_cpu_supports ("vsx");
+ p[38] = __builtin_cpu_supports ("darn");
+ p[39] = __builtin_cpu_supports ("scv");
+#else
+ p[0] = 0;
+#endif
}
diff --git a/gcc/testsuite/gcc.target/powerpc/dform-1.c b/gcc/testsuite/gcc.target/powerpc/dform-1.c
index 12623f20262..37a30d1c92f 100644
--- a/gcc/testsuite/gcc.target/powerpc/dform-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/dform-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -mpower9-dform -O2 -mlra" } */
+/* { dg-options "-mcpu=power9 -mpower9-dform -O2" } */
#ifndef TYPE
#define TYPE double
diff --git a/gcc/testsuite/gcc.target/powerpc/dform-2.c b/gcc/testsuite/gcc.target/powerpc/dform-2.c
index 86d65b5b1fd..b4c4199c0b3 100644
--- a/gcc/testsuite/gcc.target/powerpc/dform-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/dform-2.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -mpower9-dform -O2 -mlra" } */
+/* { dg-options "-mcpu=power9 -mpower9-dform -O2" } */
#ifndef TYPE
#define TYPE float
diff --git a/gcc/testsuite/gcc.target/powerpc/dform-3.c b/gcc/testsuite/gcc.target/powerpc/dform-3.c
index b1c481fbf6d..c261c4e6f5d 100644
--- a/gcc/testsuite/gcc.target/powerpc/dform-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/dform-3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -mpower9-dform -O2 -mlra" } */
+/* { dg-options "-mcpu=power9 -mpower9-dform -O2" } */
#ifndef TYPE
#define TYPE vector double
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-missing-lhs.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-missing-lhs.c
new file mode 100644
index 00000000000..6add9038288
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-missing-lhs.c
@@ -0,0 +1,24 @@
+/* This test is meant to verify that the gimple-folding does not
+ occur when the LHS portion of an expression is missing.
+ The intent of this test is to verify that we do not generate an ICE.
+ This was noticed during debug of PR81317. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <altivec.h>
+
+vector signed short
+test1_nolhs (vector bool short x, vector signed short y)
+{
+ vec_add (x, y);
+ return vec_add (x, y);
+}
+
+vector signed short
+test2_nolhs (vector signed short x, vector bool short y)
+{
+ vec_add (x, y);
+ return vec_add (x, y);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-check.h b/gcc/testsuite/gcc.target/powerpc/mmx-check.h
new file mode 100644
index 00000000000..e08077f6d80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-check.h
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+static void mmx_test (void);
+
+static void
+__attribute__ ((noinline))
+do_test (void)
+{
+ mmx_test ();
+}
+
+int
+main ()
+ {
+#ifdef __BUILTIN_CPU_SUPPORTS__
+ /* Many MMX intrinsics are simpler / faster to implement by
+ transferring the __m64 (long int) to vector registers for SIMD
+ operations. To be efficient we also need the direct register
+ transfer instructions from POWER8. So we can test for
+ arch_2_07. */
+ if ( __builtin_cpu_supports ("arch_2_07") )
+ {
+ do_test ();
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+ }
+#ifdef DEBUG
+ else
+ printf ("SKIPPED\n");
+#endif
+#endif /* __BUILTIN_CPU_SUPPORTS__ */
+ return 0;
+ }
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-packs.c b/gcc/testsuite/gcc.target/powerpc/mmx-packs.c
new file mode 100644
index 00000000000..18faa5a18eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-packs.c
@@ -0,0 +1,91 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#include <mmintrin.h>
+#include "mmx-check.h"
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+static void
+__attribute__ ((noinline))
+check_packs_pu16 (unsigned long long int src1, unsigned long long int src2,
+ unsigned long long int res_ref)
+{
+ unsigned long long int res;
+
+ res = (unsigned long long int) _mm_packs_pu16 ((__m64 ) src1, (__m64 ) src2);
+
+ if (res != res_ref)
+ abort ();
+}
+
+static void
+__attribute__ ((noinline))
+check_packs_pi16 (unsigned long long int src1, unsigned long long int src2,
+ unsigned long long int res_ref)
+{
+ unsigned long long int res;
+
+ res = (unsigned long long int) _mm_packs_pi16 ((__m64 ) src1, (__m64 ) src2);
+
+
+ if (res != res_ref)
+ abort ();
+}
+
+static void
+__attribute__ ((noinline))
+check_packs_pi32 (unsigned long long int src1, unsigned long long int src2,
+ unsigned long long int res_ref)
+{
+ unsigned long long int res;
+
+ res = (unsigned long long int) _mm_packs_pi32 ((__m64 ) src1, (__m64 ) src2);
+
+ if (res != res_ref)
+ abort ();
+}
+
+static unsigned long long int src1[] =
+ { 0xffff0000fffe0000UL, 0x0001000000020000UL, 0xfffffffffffffffeUL,
+ 0x0000000100000002UL, 0x0001000200030004UL, 0xfffffffefffdfffcUL,
+ 0x0100020003000400UL, 0xff00fe01fe02fe03UL };
+
+static unsigned long long int src2[] =
+ { 0xfffffffdfffffffcUL, 0x0000000200000003UL, 0xfffffffdfffffffcUL,
+ 0x0000000300000004UL, 0x0005000600070008UL, 0xfffbfffafff9fff8UL,
+ 0x0005000600070008UL, 0xfffbfffafff9fff8UL };
+
+static unsigned long long int res_pi16[] =
+ { 0xfffdfffcff00fe00UL, 0x0002000301000200UL, 0xfffdfffcfffffffeUL,
+ 0x0003000400010002UL, 0x0506070801020304UL, 0xfbfaf9f8fffefdfcUL,
+ 0x050607087f7f7f7fUL, 0xfbfaf9f880808080UL };
+
+static unsigned long long int res_pi32[] =
+ { 0xfffdfffc80008000UL, 0x000200037fff7fffUL, 0xfffdfffcfffffffeUL,
+ 0x0003000400010002UL, 0x7fff7fff7fff7fffUL, 0x80008000fffe8000UL,
+ 0x7fff7fff7fff7fffUL, 0x8000800080008000UL };
+
+static unsigned long long int res_pu16[] =
+ { 0x0000000000000000UL, 0x0002000301000200UL, 0x0000000000000000UL,
+ 0x0003000400010002UL, 0x0506070801020304UL, 0x000000000000000UL,
+ 0x5060708ffffffffUL, 0x0000000000000000UL };
+
+static void
+TEST ()
+{
+ long i;
+
+ for (i = 0; i < 8; i++)
+ {
+ check_packs_pu16 (src1[i], src2[i], res_pu16[i]);
+ check_packs_pi16 (src1[i], src2[i], res_pi16[i]);
+ check_packs_pi32 (src1[i], src2[i], res_pi32[i]);
+ }
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-packssdw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-packssdw-1.c
new file mode 100644
index 00000000000..8698d55f012
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-packssdw-1.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_packs_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union s1, s2;
+ __m64_union u;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi32 (2134, -128);
+ s2.as_m64 = _mm_set_pi32 (41124, 234);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ {
+ if (s1.as_int[i] > 32767)
+ e.as_short[i] = 32767;
+ else if (s1.as_int[i] < -32768)
+ e.as_short[i] = -32768;
+ else
+ e.as_short[i] = s1.as_int[i];
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (s2.as_int[i] > 32767)
+ e.as_short[i+2] = 32767;
+ else if (s2.as_int[i] < -32768)
+ e.as_short[i+2] = -32768;
+ else
+ e.as_short[i+2] = s2.as_int[i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-packsswb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-packsswb-1.c
new file mode 100644
index 00000000000..96bea7b81ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-packsswb-1.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_packs_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union s1, s2;
+ __m64_union u;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (2134, -128, 1234, 6354);
+ s2.as_m64 = _mm_set_pi16 (41124, 234, 2344, 2354);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ if (s1.as_short[i] > 127)
+ e.as_char[i] = 127;
+ else if (s1.as_short[i] < -128)
+ e.as_char[i] = -128;
+ else
+ e.as_char[i] = s1.as_short[i];
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ if (s2.as_short[i] > 127)
+ e.as_char[i+4] = 127;
+ else if (s2.as_short[i] < -128)
+ e.as_char[i+4] = -128;
+ else
+ e.as_char[i+4] = s2.as_short[i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-packuswb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-packuswb-1.c
new file mode 100644
index 00000000000..029d5687d71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-packuswb-1.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_packs_pu16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union s1, s2;
+ __m64_union u;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (1, 2, 3, 4);
+ s2.as_m64 = _mm_set_pi16 (-9, -10, -11, -12);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i=0; i<4; i++)
+ {
+ tmp = s1.as_short[i]<0 ? 0 : s1.as_short[i];
+ tmp = tmp>255 ? 255 : tmp;
+ e.as_char[i] = tmp;
+
+ tmp = s2.as_short[i]<0 ? 0 : s2.as_short[i];
+ tmp = tmp>255 ? 255 : tmp;
+ e.as_char[i+4] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddb-1.c
new file mode 100644
index 00000000000..46b0584549e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddb-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_add_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 33, 22, 11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ e.as_char[i] = s1.as_char[i] + s2.as_char[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddd-1.c
new file mode 100644
index 00000000000..a006dda0ee4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddd-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_add_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi32 (30, 90);
+ s2.as_m64 = _mm_set_pi32 (76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = s1.as_int[i] + s2.as_int[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddsb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddsb-1.c
new file mode 100644
index 00000000000..5722302095e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddsb-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_adds_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 33, 22, 11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp = s1.as_signed_char[i] + s2.as_signed_char[i];
+
+ if (tmp > 127)
+ tmp = 127;
+ if (tmp < -128)
+ tmp = -128;
+
+ e.as_signed_char[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddsw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddsw-1.c
new file mode 100644
index 00000000000..f7518b4dbae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddsw-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_adds_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (1, 2, 3, 4);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = s1.as_short[i] + s2.as_short[i];
+
+ if (tmp > 32767)
+ tmp = 32767;
+ if (tmp < -32768)
+ tmp = -32768;
+
+ e.as_short[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddusb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddusb-1.c
new file mode 100644
index 00000000000..a209e3e30dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddusb-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_adds_pu8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi8 (30, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 33, 22, 11, 98, 76, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp = s1.as_char[i] + s2.as_char[i];
+
+ if (tmp > 255)
+ tmp = -1;
+ if (tmp < 0)
+ tmp = 0;
+
+ e.as_char[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddusw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddusw-1.c
new file mode 100644
index 00000000000..b46b7f636bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddusw-1.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_adds_pu16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (1, 2, 3, 4);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = (unsigned short)s1.as_short[i] + (unsigned short)s2.as_short[i];
+
+ if (tmp > 65535)
+ tmp = -1;
+
+ if (tmp < 0)
+ tmp = 0;
+
+ e.as_short[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-paddw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-paddw-1.c
new file mode 100644
index 00000000000..748fe2b5703
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-paddw-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_add_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = s1.as_short[i] + s2.as_short[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqb-1.c
new file mode 100644
index 00000000000..c779b26e691
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqb-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpeq_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 3, 22, 11, 98, 30, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ e.as_char[i] = (s1.as_char[i] == s2.as_char[i]) ? -1:0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqd-1.c
new file mode 100644
index 00000000000..a7807a2fdd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqd-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpeq_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi32 (98, 25);
+ s2.as_m64 = _mm_set_pi32 (98, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = (s1.as_int[i] == s2.as_int[i]) ? -1:0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqw-1.c
new file mode 100644
index 00000000000..e25fd54c6b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpeqw-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpeq_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (20, 30, 90, 80);
+ s2.as_m64 = _mm_set_pi16 (34, 78, 90, 6);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = (s1.as_short[i] == s2.as_short[i]) ? -1:0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtb-1.c
new file mode 100644
index 00000000000..7f841b0b26e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtb-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpgt_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 3, 22, 11, 98, 28, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ e.as_char[i] = (s1.as_char[i] > s2.as_char[i]) ? -1 : 0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtd-1.c
new file mode 100644
index 00000000000..9f503b5ec9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtd-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpgt_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi32 (99, 25);
+ s2.as_m64 = _mm_set_pi32 (98, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = (s1.as_int[i] > s2.as_int[i]) ? -1:0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtw-1.c
new file mode 100644
index 00000000000..85716937e0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pcmpgtw-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_cmpgt_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (20, 30, 90, 80);
+ s2.as_m64 = _mm_set_pi16 (34, 78, 90, 6);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = (s1.as_short[i] > s2.as_short[i]) ? -1:0;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pmaddwd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pmaddwd-1.c
new file mode 100644
index 00000000000..220b4f65209
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pmaddwd-1.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_madd_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (2134, 3334, 1234, 6354);
+ s2.as_m64 = _mm_set_pi16 (1, 3, 4, 5);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = (s1.as_short[i * 2] * s2.as_short[i * 2])
+ + (s1.as_short[(i * 2) + 1] * s2.as_short[(i * 2) + 1]);
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pmulhw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pmulhw-1.c
new file mode 100644
index 00000000000..79b7c7b1838
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pmulhw-1.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_mulhi_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (10, 2067, -3033, 90);
+ s2.as_m64 = _mm_set_pi16 (11, 9834, 7444, -10222);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = s1.as_short[i] * s2.as_short[i];
+
+ e.as_short[i] = (tmp & 0xffff0000)>>16;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pmullw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pmullw-1.c
new file mode 100644
index 00000000000..6d041691772
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pmullw-1.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_mullo_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (10, 2067, -3033, 90);
+ s2.as_m64 = _mm_set_pi16 (11, 9834, 7444, -10222);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = s1.as_short[i] * s2.as_short[i];
+
+ e.as_short[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-pslld-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-pslld-1.c
new file mode 100644
index 00000000000..af687cd1e96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-pslld-1.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_sll_pi32 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi32 (1, -2);
+ u.as_m64 = test (s1.as_m64);
+
+
+ if (N < 16)
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = s1.as_int[i] << N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psllw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psllw-1.c
new file mode 100644
index 00000000000..415f6a84176
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psllw-1.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_sll_pi16 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi16 (1, 2, 0x7000, 0x9000);
+ u.as_m64 = test (s1.as_m64);
+
+
+ if (N < 16)
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = s1.as_short[i] << N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psrad-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psrad-1.c
new file mode 100644
index 00000000000..eaaf214292e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psrad-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_sra_pi32 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi32 (1000, -20000);
+ u.as_m64 = test (s1.as_m64);
+
+ if (N < 16)
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = s1.as_int[i] >> N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psraw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psraw-1.c
new file mode 100644
index 00000000000..eb7c3aec150
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psraw-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_sra_pi16 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi16 (1, -2, 0x7000, 0x9000);
+ u.as_m64 = test (s1.as_m64);
+
+ if (N < 16)
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = s1.as_short[i] >> N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psrld-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psrld-1.c
new file mode 100644
index 00000000000..1eb9d2897a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psrld-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_srl_pi32 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi32 (1000, -20000);
+ u.as_m64 = test (s1.as_m64);
+
+ if (N < 16)
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = (unsigned int)s1.as_int[i] >> N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psrlw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psrlw-1.c
new file mode 100644
index 00000000000..d066159e8eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psrlw-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#define N 0xb
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1)
+{
+ return _mm_srl_pi16 (s1, N);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi16 (1, -2, 0x7000, 0x9000);
+ u.as_m64 = test (s1.as_m64);
+
+ if (N < 16)
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = (unsigned short)s1.as_short[i] >> N;
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubb-2.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubb-2.c
new file mode 100644
index 00000000000..c64204afa41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubb-2.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_sub_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 3, 22, 11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ e.as_char[i] = s1.as_char[i] - s2.as_char[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubd-2.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubd-2.c
new file mode 100644
index 00000000000..3260f611748
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubd-2.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_sub_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_setr_pi32 (30, 90);
+ s2.as_m64 = _mm_setr_pi32 (76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ e.as_int[i] = s1.as_int[i] - s2.as_int[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubsb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubsb-1.c
new file mode 100644
index 00000000000..3f0fb2af899
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubsb-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_subs_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi8 (1, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 3, 22, 11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp = s1.as_signed_char[i] - s2.as_signed_char[i];
+
+ if (tmp > 127)
+ tmp = 127;
+ if (tmp < -128)
+ tmp = -128;
+
+ e.as_signed_char[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubsw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubsw-1.c
new file mode 100644
index 00000000000..ae819e19c25
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubsw-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_subs_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (10, 20, 30, 00);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = s1.as_short[i] - s2.as_short[i];
+
+ if (tmp > 32767)
+ tmp = 32767;
+ if (tmp < -32768)
+ tmp = -32768;
+
+ e.as_short[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubusb-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubusb-1.c
new file mode 100644
index 00000000000..bbdc0977109
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubusb-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_subs_pu8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi8 (30, 2, 3, 4, 10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi8 (88, 44, 3, 22, 11, 98, 76, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp = s1.as_char[i] - s2.as_char[i];
+
+ if (tmp > 255)
+ tmp = -1;
+ if (tmp < 0)
+ tmp = 0;
+
+ e.as_char[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubusw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubusw-1.c
new file mode 100644
index 00000000000..e26c380daee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubusw-1.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_subs_pu16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i, tmp;
+
+ s1.as_m64 = _mm_set_pi16 (10, 20, 30, 40);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, 100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = (unsigned short)s1.as_short[i] - (unsigned short)s2.as_short[i];
+
+ if (tmp > 65535)
+ tmp = -1;
+
+ if (tmp < 0)
+ tmp = 0;
+
+ e.as_short[i] = tmp;
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-psubw-2.c b/gcc/testsuite/gcc.target/powerpc/mmx-psubw-2.c
new file mode 100644
index 00000000000..39e4cdea04a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-psubw-2.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_sub_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2;
+ __m64_union e;
+ int i;
+
+ s1.as_m64 = _mm_set_pi16 (10, 20, 30, 90);
+ s2.as_m64 = _mm_set_pi16 (11, 98, 76, -100);
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ e.as_short[i] = s1.as_short[i] - s2.as_short[i];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpckhbw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhbw-1.c
new file mode 100644
index 00000000000..dba56ca205b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhbw-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpackhi_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+ int i;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ e.as_char[2*i] = s1.as_char[4+i];
+ e.as_char[2*i + 1] = s2.as_char[4+i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpckhdq-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhdq-1.c
new file mode 100644
index 00000000000..f2f53c434c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhdq-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpackhi_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ e.as_int[0] = s1.as_int[1];
+ e.as_int[1] = s2.as_int[1];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpckhwd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhwd-1.c
new file mode 100644
index 00000000000..f0264463a81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpckhwd-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpackhi_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+ int i;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ {
+ e.as_short[2*i] = s1.as_short[2+i];
+ e.as_short[2*i + 1] = s2.as_short[2+i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpcklbw-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpcklbw-1.c
new file mode 100644
index 00000000000..36cf241ab19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpcklbw-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpacklo_pi8 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+ int i;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 4; i++)
+ {
+ e.as_char[2*i] = s1.as_char[i];
+ e.as_char[2*i + 1] = s2.as_char[i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpckldq-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpckldq-1.c
new file mode 100644
index 00000000000..8fb0251560a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpckldq-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpacklo_pi32 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ e.as_int[0] = s1.as_int[0];
+ e.as_int[1] = s2.as_int[0];
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/mmx-punpcklwd-1.c b/gcc/testsuite/gcc.target/powerpc/mmx-punpcklwd-1.c
new file mode 100644
index 00000000000..37b6b6ff8c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mmx-punpcklwd-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target p8vector_hw } */
+
+#define NO_WARN_X86_INTRINSICS 1
+#ifndef CHECK_H
+#define CHECK_H "mmx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST mmx_test
+#endif
+
+#include CHECK_H
+
+#include <mmintrin.h>
+
+static __m64
+__attribute__((noinline, unused))
+test (__m64 s1, __m64 s2)
+{
+ return _mm_unpacklo_pi16 (s1, s2);
+}
+
+static void
+TEST (void)
+{
+ __m64_union u, s1, s2, e;
+ int i;
+
+ s1.as_m64 = 0x0706050403020100UL;
+ s2.as_m64 = 0x1716151413121110UL;
+ u.as_m64 = test (s1.as_m64, s2.as_m64);
+
+ for (i = 0; i < 2; i++)
+ {
+ e.as_short[2*i] = s1.as_short[i];
+ e.as_short[2*i + 1] = s2.as_short[i];
+ }
+
+ if (u.as_m64 != e.as_m64)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c
index 33347740d0c..4b0370bb863 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c
@@ -11,7 +11,8 @@ vector unsigned char vuca, vucb, vucc;
vector bool char vbca, vbcb;
vector unsigned short vusa, vusb;
vector bool short vbsa, vbsb;
-vector unsigned int vuia, vuib;
+vector signed int vsia, vsib, vsic;
+vector unsigned int vuia, vuib, vuic;
vector bool int vbia, vbib;
vector signed long long vsla, vslb;
vector unsigned long long vula, vulb, vulc;
@@ -24,6 +25,7 @@ void foo (vector unsigned char *vucr,
vector bool char *vbcr,
vector unsigned short *vusr,
vector bool short *vbsr,
+ vector signed int *vsir,
vector unsigned int *vuir,
vector bool int *vbir,
vector unsigned long long *vulr,
@@ -32,10 +34,16 @@ void foo (vector unsigned char *vucr,
vector unsigned __int128 *vuxr,
vector double *vdr)
{
+ *vsir++ = vec_addc (vsia, vsib);
+ *vuir++ = vec_addc (vuia, vuib);
*vsxr++ = vec_addc (vsxa, vsxb);
*vuxr++ = vec_addc (vuxa, vuxb);
+ *vsir++ = vec_adde (vsia, vsib, vsic);
+ *vuir++ = vec_adde (vuia, vuib, vuic);
*vsxr++ = vec_adde (vsxa, vsxb, vsxc);
*vuxr++ = vec_adde (vuxa, vuxb, vuxc);
+ *vsir++ = vec_addec (vsia, vsib, vsic);
+ *vuir++ = vec_addec (vuia, vuib, vuic);
*vsxr++ = vec_addec (vsxa, vsxb, vsxc);
*vuxr++ = vec_addec (vuxa, vuxb, vuxc);
*vucr++ = vec_bperm (vuca, vucb);
@@ -60,11 +68,30 @@ void foo (vector unsigned char *vucr,
*vuxr++ = vec_pmsum_be (vula, vulb);
*vuir++ = vec_shasigma_be (vuia, 0, 1);
*vulr++ = vec_shasigma_be (vula, 0, 1);
+ *vsir++ = vec_subc (vsia, vsib);
+ *vuir++ = vec_subc (vuia, vuib);
+ *vsxr++ = vec_subc (vsxa, vsxb);
+ *vuxr++ = vec_subc (vuxa, vuxb);
+ *vsir++ = vec_sube (vsia, vsib, vsic);
+ *vuir++ = vec_sube (vuia, vuib, vuic);
+ *vsxr++ = vec_sube (vsxa, vsxb, vsxc);
+ *vuxr++ = vec_sube (vuxa, vuxb, vuxc);
+ *vsir++ = vec_subec (vsia, vsib, vsic);
+ *vuir++ = vec_subec (vuia, vuib, vuic);
+ *vsxr++ = vec_subec (vsxa, vsxb, vsxc);
+ *vuxr++ = vec_subec (vuxa, vuxb, vuxc);
}
/* { dg-final { scan-assembler-times "vaddcuq" 2 } } */
/* { dg-final { scan-assembler-times "vaddeuqm" 2 } } */
/* { dg-final { scan-assembler-times "vaddecuq" 2 } } */
+/* { dg-final { scan-assembler-times "vaddcuw" 6 } } */
+/* { dg-final { scan-assembler-times "vadduwm" 4 } } */
+/* { dg-final { scan-assembler-times "vsubcuq" 2 } } */
+/* { dg-final { scan-assembler-times "vsubeuqm" 2 } } */
+/* { dg-final { scan-assembler-times "vsubecuq" 2 } } */
+/* { dg-final { scan-assembler-times "vsubcuw" 4 } } */
+/* { dg-final { scan-assembler-times "vsubuwm" 4 } } */
/* { dg-final { scan-assembler-times "vbpermq" 2 } } */
/* { dg-final { scan-assembler-times "xxleqv" 4 } } */
/* { dg-final { scan-assembler-times "vgbbd" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
index 17b73bbc7b3..7b30e4c4e23 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf -fno-math-errno" } */
+/* { dg-options "-mcpu=power8 -O2 -fno-math-errno" } */
float abs_sf (float *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-int128-1.c b/gcc/testsuite/gcc.target/powerpc/p8vector-int128-1.c
index 23663b96da6..992ed225d5f 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-int128-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-int128-1.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O3 -mvsx-timode -mlra" } */
+/* { dg-options "-mcpu=power8 -O3 -mvsx-timode" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
index 58e1f4485be..e683d614d62 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf" } */
+/* { dg-options "-mcpu=power8 -O2" } */
float
load_store_sf (unsigned long num,
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c b/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
index c29b69d3e9e..64f0e31fb00 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power9 -O2" } */
/* Verify P9 changes to allow DImode into Altivec registers, and generate
constants using XXSPLTIB. */
@@ -43,8 +43,8 @@ p9_minus_1 (void)
return ret;
}
-/* { dg-final { scan-assembler "\[ \t\]xxspltib" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]mtvsrd" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]lfd" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]ld" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]lxsd" } } */
+/* { dg-final { scan-assembler {\mxxspltib\M} } } */
+/* { dg-final { scan-assembler-not {\mmtvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mlfd\M} } } */
+/* { dg-final { scan-assembler-not {\mld\M} } } */
+/* { dg-final { scan-assembler-not {\mlxsd\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c b/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
index f33d18c6078..9e27936d748 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power9 -O2" } */
/* Verify that large integer constants are loaded via direct move instead of being
loaded from memory. */
@@ -21,7 +21,7 @@ p9_large (void)
return ret;
}
-/* { dg-final { scan-assembler "\[ \t\]mtvsrd" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]ld" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]lfd" } } */
-/* { dg-final { scan-assembler-not "\[ \t\]lxsd" } } */
+/* { dg-final { scan-assembler {\mmtvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mld\M} } } */
+/* { dg-final { scan-assembler-not {\mlfd\M} } } */
+/* { dg-final { scan-assembler-not {\mlxsd\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-vparity.c b/gcc/testsuite/gcc.target/powerpc/p9-vparity.c
index af5b5905a6f..6e49606fe0b 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-vparity.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-vparity.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mlra -mvsx-timode" } */
+/* { dg-options "-mcpu=power9 -O2 -mvsx-timode" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-xxbr-1.c b/gcc/testsuite/gcc.target/powerpc/p9-xxbr-1.c
index cd4ba7384de..164f11f6ea3 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-xxbr-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-xxbr-1.c
@@ -13,6 +13,12 @@ rev_char (vector char a)
return vec_revb (a); /* XXBRQ. */
}
+vector bool char
+rev_bool_char (vector bool char a)
+{
+ return vec_revb (a); /* XXBRQ. */
+}
+
vector signed char
rev_schar (vector signed char a)
{
@@ -31,6 +37,12 @@ rev_short (vector short a)
return vec_revb (a); /* XXBRH. */
}
+vector bool short
+rev_bool_short (vector bool short a)
+{
+ return vec_revb (a); /* XXBRH. */
+}
+
vector unsigned short
rev_ushort (vector unsigned short a)
{
@@ -43,6 +55,12 @@ rev_int (vector int a)
return vec_revb (a); /* XXBRW. */
}
+vector bool int
+rev_bool_int (vector bool int a)
+{
+ return vec_revb (a); /* XXBRW. */
+}
+
vector unsigned int
rev_uint (vector unsigned int a)
{
@@ -62,6 +80,6 @@ rev_double (vector double a)
}
/* { dg-final { scan-assembler-times "xxbrd" 1 } } */
-/* { dg-final { scan-assembler-times "xxbrh" 2 } } */
-/* { dg-final { scan-assembler-times "xxbrq" 3 } } */
-/* { dg-final { scan-assembler-times "xxbrw" 3 } } */
+/* { dg-final { scan-assembler-times "xxbrh" 3 } } */
+/* { dg-final { scan-assembler-times "xxbrq" 4 } } */
+/* { dg-final { scan-assembler-times "xxbrw" 4 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-xxbr-2.c b/gcc/testsuite/gcc.target/powerpc/p9-xxbr-2.c
index 97f6186bf91..a4a19390d7b 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-xxbr-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-xxbr-2.c
@@ -20,6 +20,18 @@ rev_ulong (vector unsigned long a)
return vec_revb (a); /* XXBRD. */
}
+vector long long
+rev_long_long (vector long long a)
+{
+ return vec_revb (a); /* XXBRD. */
+}
+
+vector unsigned long long
+rev_ulong_ulong (vector unsigned long long a)
+{
+ return vec_revb (a); /* XXBRD. */
+}
+
vector __int128_t
rev_int128 (vector __int128_t a)
{
@@ -32,5 +44,5 @@ rev_uint128 (vector __uint128_t a)
return vec_revb (a); /* XXBRQ. */
}
-/* { dg-final { scan-assembler-times "xxbrd" 2 } } */
+/* { dg-final { scan-assembler-times "xxbrd" 4 } } */
/* { dg-final { scan-assembler-times "xxbrq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-1.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-1.c
index 2efa952a239..de508b784c9 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-1.c
@@ -2,15 +2,13 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O2 -mcpu=power7 -ffast-math -mno-upper-regs-df" } */
-/* { dg-final { scan-assembler-times "lfiwax" 2 } } */
-/* { dg-final { scan-assembler-times "lfiwzx" 2 } } */
-/* { dg-final { scan-assembler-times "fcfids " 3 } } */
-/* { dg-final { scan-assembler-times "fcfidus " 1 } } */
-/* { dg-final { scan-assembler-times "fcfid " 3 } } */
-/* { dg-final { scan-assembler-times "fcfidu " 1 } } */
-/* { dg-final { scan-assembler-not "xscvdpsxds" } } */
-/* { dg-final { scan-assembler-not "xscvdpuxds" } } */
+/* { dg-options "-O2 -mcpu=power7 -ffast-math" } */
+/* { dg-final { scan-assembler-times {\mlfiwax\M|\mlxsiwax\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mlfiwzx\M|\mlxsiwzx\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfcfids\M|\mxscvsxdsp\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mfcfidus\M|\mxscvuxdsp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mfcfid\M|\mxscvsxddp\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mfcfidu\M|\mxscvuxddp\M} 1 } } */
void int_to_float (float *dest, int *src)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-10.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-10.c
index 9e192d13398..cb6dea41b06 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-10.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-10.c
@@ -2,8 +2,8 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O2 -mcpu=power7 -ffast-math -mno-upper-regs-df" } */
-/* { dg-final { scan-assembler "friz" } } */
+/* { dg-options "-O2 -mcpu=power7 -ffast-math" } */
+/* { dg-final { scan-assembler {\mfriz\M|\mxsrdpiz\M} } } */
double round_double_llong (double a)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c
index b59cac3a5bb..6bffa164fcd 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c
@@ -2,13 +2,11 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O3 -mcpu=power7 -ffast-math -mno-upper-regs-df" } */
-/* { dg-final { scan-assembler-times "fctiwz " 2 } } */
-/* { dg-final { scan-assembler-times "fctiwuz " 2 } } */
-/* { dg-final { scan-assembler-times "fctidz " 2 } } */
-/* { dg-final { scan-assembler-times "fctiduz " 2 } } */
-/* { dg-final { scan-assembler-not "xscvdpsxds" } } */
-/* { dg-final { scan-assembler-not "xscvdpuxds" } } */
+/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */
+/* { dg-final { scan-assembler-times {\mfctiwz\M|\mxscvdpsxws\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfctiwuz\M|\mxscvdpuxws\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfctidz\M|\mxscvdpsxds\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfctiduz\M|\mxscvdpuxds\M} 2 } } */
void float_to_int (int *dest, float src) { *dest = (int) src; }
void double_to_int (int *dest, double src) { *dest = (int) src; }
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c
index 372b2334686..d376936a750 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c
@@ -2,12 +2,12 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O3 -mcpu=power7 -ffast-math -mno-upper-regs-df" } */
-/* { dg-final { scan-assembler-times "fctidz" 2 } } */
-/* { dg-final { scan-assembler-not "lwz" } } */
-/* { dg-final { scan-assembler-not "stw" } } */
-/* { dg-final { scan-assembler-not "ld " } } */
-/* { dg-final { scan-assembler-not "std" } } */
+/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */
+/* { dg-final { scan-assembler-times {\mfctidz\M|\mxscvdpsxds\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlwz\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
+/* { dg-final { scan-assembler-not {\mld\M} } } */
+/* { dg-final { scan-assembler-not {\mstd\M} } } */
void float_to_llong (long long *dest, float src) { *dest = (long long) src; }
void double_to_llong (long long *dest, double src) { *dest = (long long) src; }
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-round.c b/gcc/testsuite/gcc.target/powerpc/ppc-round.c
index 0cfa0da2a72..50ab078f55a 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-round.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-round.c
@@ -2,15 +2,15 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O2 -mcpu=power7 -mno-upper-regs-df" } */
-/* { dg-final { scan-assembler-times "stfiwx" 4 } } */
-/* { dg-final { scan-assembler-times "lfiwax" 2 } } */
-/* { dg-final { scan-assembler-times "lfiwzx" 2 } } */
-/* { dg-final { scan-assembler-times "fctiwz " 2 } } */
-/* { dg-final { scan-assembler-times "fctiwuz " 2 } } */
-/* { dg-final { scan-assembler-times "fcfids " 2 } } */
-/* { dg-final { scan-assembler-not "lwz" } } */
-/* { dg-final { scan-assembler-not "stw" } } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler-times {\mstfiwx\M|\mstxsiwx\M} 4 } } */
+/* { dg-final { scan-assembler-times {\mlfiwax\M|\mlxsiwax\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mlfiwzx\M|\mlxsiwzx\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfctiwz\M|\mxscvdpsxws\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfctiwuz\M|\mxscvdpuxws\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mfcfids\M|\mxscvsxdsp\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlwz\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
/* Make sure we don't have loads/stores to the GPR unit. */
double
diff --git a/gcc/testsuite/gcc.target/powerpc/pr63491.c b/gcc/testsuite/gcc.target/powerpc/pr63491.c
index a1518912308..be6a40eb32d 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr63491.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr63491.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-options "-O1 -mcpu=power8 -mlra" } */
+/* { dg-options "-O1 -mcpu=power8" } */
typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
typedef unsigned long long scalar_64_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr65849-1.c b/gcc/testsuite/gcc.target/powerpc/pr65849-1.c
deleted file mode 100644
index 288fdeed2ca..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr65849-1.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-mcpu=power7 -O2 -mno-upper-regs-df" } */
-
-/* Test whether we can enable the -mupper-regs-df with target pragmas. Make
- sure double values are allocated to the Altivec registers as well as the
- traditional FPR registers. */
-
-#ifndef TYPE
-#define TYPE double
-#endif
-
-#ifndef MASK_TYPE
-#define MASK_TYPE unsigned long long
-#endif
-
-#define MASK_ONE ((MASK_TYPE)1)
-#define ZERO ((TYPE) 0.0)
-
-#pragma GCC target ("upper-regs-df")
-TYPE
-test_add (const MASK_TYPE *add_mask, const TYPE *add_values,
- const MASK_TYPE *sub_mask, const TYPE *sub_values,
- const MASK_TYPE *mul_mask, const TYPE *mul_values,
- const MASK_TYPE *div_mask, const TYPE *div_values,
- const MASK_TYPE *eq0_mask, int *eq0_ptr)
-{
- TYPE value;
- TYPE value00 = ZERO;
- TYPE value01 = ZERO;
- TYPE value02 = ZERO;
- TYPE value03 = ZERO;
- TYPE value04 = ZERO;
- TYPE value05 = ZERO;
- TYPE value06 = ZERO;
- TYPE value07 = ZERO;
- TYPE value08 = ZERO;
- TYPE value09 = ZERO;
- TYPE value10 = ZERO;
- TYPE value11 = ZERO;
- TYPE value12 = ZERO;
- TYPE value13 = ZERO;
- TYPE value14 = ZERO;
- TYPE value15 = ZERO;
- TYPE value16 = ZERO;
- TYPE value17 = ZERO;
- TYPE value18 = ZERO;
- TYPE value19 = ZERO;
- TYPE value20 = ZERO;
- TYPE value21 = ZERO;
- TYPE value22 = ZERO;
- TYPE value23 = ZERO;
- TYPE value24 = ZERO;
- TYPE value25 = ZERO;
- TYPE value26 = ZERO;
- TYPE value27 = ZERO;
- TYPE value28 = ZERO;
- TYPE value29 = ZERO;
- TYPE value30 = ZERO;
- TYPE value31 = ZERO;
- TYPE value32 = ZERO;
- TYPE value33 = ZERO;
- TYPE value34 = ZERO;
- TYPE value35 = ZERO;
- TYPE value36 = ZERO;
- TYPE value37 = ZERO;
- TYPE value38 = ZERO;
- TYPE value39 = ZERO;
- MASK_TYPE mask;
- int eq0;
-
- while ((mask = *add_mask++) != 0)
- {
- value = *add_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 += value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 += value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 += value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 += value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 += value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 += value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 += value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 += value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 += value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 += value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 += value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 += value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 += value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 += value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 += value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 += value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 += value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 += value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 += value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 += value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 += value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 += value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 += value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 += value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 += value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 += value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 += value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 += value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 += value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 += value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 += value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 += value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 += value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 += value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 += value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 += value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 += value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 += value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 += value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 += value;
- }
-
- while ((mask = *sub_mask++) != 0)
- {
- value = *sub_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 -= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 -= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 -= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 -= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 -= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 -= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 -= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 -= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 -= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 -= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 -= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 -= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 -= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 -= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 -= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 -= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 -= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 -= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 -= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 -= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 -= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 -= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 -= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 -= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 -= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 -= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 -= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 -= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 -= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 -= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 -= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 -= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 -= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 -= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 -= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 -= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 -= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 -= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 -= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 -= value;
- }
-
- while ((mask = *mul_mask++) != 0)
- {
- value = *mul_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 *= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 *= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 *= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 *= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 *= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 *= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 *= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 *= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 *= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 *= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 *= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 *= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 *= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 *= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 *= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 *= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 *= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 *= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 *= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 *= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 *= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 *= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 *= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 *= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 *= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 *= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 *= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 *= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 *= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 *= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 *= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 *= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 *= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 *= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 *= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 *= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 *= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 *= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 *= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 *= value;
- }
-
- while ((mask = *div_mask++) != 0)
- {
- value = *div_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 /= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 /= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 /= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 /= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 /= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 /= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 /= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 /= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 /= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 /= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 /= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 /= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 /= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 /= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 /= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 /= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 /= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 /= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 /= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 /= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 /= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 /= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 /= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 /= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 /= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 /= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 /= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 /= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 /= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 /= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 /= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 /= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 /= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 /= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 /= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 /= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 /= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 /= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 /= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 /= value;
- }
-
- while ((mask = *eq0_mask++) != 0)
- {
- eq0 = 0;
-
- if ((mask & (MASK_ONE << 0)) != 0)
- eq0 |= (value00 == ZERO);
-
- if ((mask & (MASK_ONE << 1)) != 0)
- eq0 |= (value01 == ZERO);
-
- if ((mask & (MASK_ONE << 2)) != 0)
- eq0 |= (value02 == ZERO);
-
- if ((mask & (MASK_ONE << 3)) != 0)
- eq0 |= (value03 == ZERO);
-
- if ((mask & (MASK_ONE << 4)) != 0)
- eq0 |= (value04 == ZERO);
-
- if ((mask & (MASK_ONE << 5)) != 0)
- eq0 |= (value05 == ZERO);
-
- if ((mask & (MASK_ONE << 6)) != 0)
- eq0 |= (value06 == ZERO);
-
- if ((mask & (MASK_ONE << 7)) != 0)
- eq0 |= (value07 == ZERO);
-
- if ((mask & (MASK_ONE << 8)) != 0)
- eq0 |= (value08 == ZERO);
-
- if ((mask & (MASK_ONE << 9)) != 0)
- eq0 |= (value09 == ZERO);
-
- if ((mask & (MASK_ONE << 10)) != 0)
- eq0 |= (value10 == ZERO);
-
- if ((mask & (MASK_ONE << 11)) != 0)
- eq0 |= (value11 == ZERO);
-
- if ((mask & (MASK_ONE << 12)) != 0)
- eq0 |= (value12 == ZERO);
-
- if ((mask & (MASK_ONE << 13)) != 0)
- eq0 |= (value13 == ZERO);
-
- if ((mask & (MASK_ONE << 14)) != 0)
- eq0 |= (value14 == ZERO);
-
- if ((mask & (MASK_ONE << 15)) != 0)
- eq0 |= (value15 == ZERO);
-
- if ((mask & (MASK_ONE << 16)) != 0)
- eq0 |= (value16 == ZERO);
-
- if ((mask & (MASK_ONE << 17)) != 0)
- eq0 |= (value17 == ZERO);
-
- if ((mask & (MASK_ONE << 18)) != 0)
- eq0 |= (value18 == ZERO);
-
- if ((mask & (MASK_ONE << 19)) != 0)
- eq0 |= (value19 == ZERO);
-
- if ((mask & (MASK_ONE << 20)) != 0)
- eq0 |= (value20 == ZERO);
-
- if ((mask & (MASK_ONE << 21)) != 0)
- eq0 |= (value21 == ZERO);
-
- if ((mask & (MASK_ONE << 22)) != 0)
- eq0 |= (value22 == ZERO);
-
- if ((mask & (MASK_ONE << 23)) != 0)
- eq0 |= (value23 == ZERO);
-
- if ((mask & (MASK_ONE << 24)) != 0)
- eq0 |= (value24 == ZERO);
-
- if ((mask & (MASK_ONE << 25)) != 0)
- eq0 |= (value25 == ZERO);
-
- if ((mask & (MASK_ONE << 26)) != 0)
- eq0 |= (value26 == ZERO);
-
- if ((mask & (MASK_ONE << 27)) != 0)
- eq0 |= (value27 == ZERO);
-
- if ((mask & (MASK_ONE << 28)) != 0)
- eq0 |= (value28 == ZERO);
-
- if ((mask & (MASK_ONE << 29)) != 0)
- eq0 |= (value29 == ZERO);
-
- if ((mask & (MASK_ONE << 30)) != 0)
- eq0 |= (value30 == ZERO);
-
- if ((mask & (MASK_ONE << 31)) != 0)
- eq0 |= (value31 == ZERO);
-
- if ((mask & (MASK_ONE << 32)) != 0)
- eq0 |= (value32 == ZERO);
-
- if ((mask & (MASK_ONE << 33)) != 0)
- eq0 |= (value33 == ZERO);
-
- if ((mask & (MASK_ONE << 34)) != 0)
- eq0 |= (value34 == ZERO);
-
- if ((mask & (MASK_ONE << 35)) != 0)
- eq0 |= (value35 == ZERO);
-
- if ((mask & (MASK_ONE << 36)) != 0)
- eq0 |= (value36 == ZERO);
-
- if ((mask & (MASK_ONE << 37)) != 0)
- eq0 |= (value37 == ZERO);
-
- if ((mask & (MASK_ONE << 38)) != 0)
- eq0 |= (value38 == ZERO);
-
- if ((mask & (MASK_ONE << 39)) != 0)
- eq0 |= (value39 == ZERO);
-
- *eq0_ptr++ = eq0;
- }
-
- return ( value00 + value01 + value02 + value03 + value04
- + value05 + value06 + value07 + value08 + value09
- + value10 + value11 + value12 + value13 + value14
- + value15 + value16 + value17 + value18 + value19
- + value20 + value21 + value22 + value23 + value24
- + value25 + value26 + value27 + value28 + value29
- + value30 + value31 + value32 + value33 + value34
- + value35 + value36 + value37 + value38 + value39);
-}
-
-/* { dg-final { scan-assembler "fadd" } } */
-/* { dg-final { scan-assembler "fsub" } } */
-/* { dg-final { scan-assembler "fmul" } } */
-/* { dg-final { scan-assembler "fdiv" } } */
-/* { dg-final { scan-assembler "fcmpu" } } */
-/* { dg-final { scan-assembler "xsadddp" } } */
-/* { dg-final { scan-assembler "xssubdp" } } */
-/* { dg-final { scan-assembler "xsmuldp" } } */
-/* { dg-final { scan-assembler "xsdivdp" } } */
-/* { dg-final { scan-assembler "xscmpudp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr65849-2.c b/gcc/testsuite/gcc.target/powerpc/pr65849-2.c
deleted file mode 100644
index 0af6a4a51c7..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr65849-2.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-sf" } */
-
-/* Test whether we can enable the -mupper-regs-sf with target pragmas. Make
- sure float values are allocated to the Altivec registers as well as the
- traditional FPR registers. */
-
-#ifndef TYPE
-#define TYPE float
-#endif
-
-#ifndef MASK_TYPE
-#define MASK_TYPE unsigned long long
-#endif
-
-#define MASK_ONE ((MASK_TYPE)1)
-#define ZERO ((TYPE) 0.0)
-
-#pragma GCC target ("upper-regs-sf")
-TYPE
-test_add (const MASK_TYPE *add_mask, const TYPE *add_values,
- const MASK_TYPE *sub_mask, const TYPE *sub_values,
- const MASK_TYPE *mul_mask, const TYPE *mul_values,
- const MASK_TYPE *div_mask, const TYPE *div_values,
- const MASK_TYPE *eq0_mask, int *eq0_ptr)
-{
- TYPE value;
- TYPE value00 = ZERO;
- TYPE value01 = ZERO;
- TYPE value02 = ZERO;
- TYPE value03 = ZERO;
- TYPE value04 = ZERO;
- TYPE value05 = ZERO;
- TYPE value06 = ZERO;
- TYPE value07 = ZERO;
- TYPE value08 = ZERO;
- TYPE value09 = ZERO;
- TYPE value10 = ZERO;
- TYPE value11 = ZERO;
- TYPE value12 = ZERO;
- TYPE value13 = ZERO;
- TYPE value14 = ZERO;
- TYPE value15 = ZERO;
- TYPE value16 = ZERO;
- TYPE value17 = ZERO;
- TYPE value18 = ZERO;
- TYPE value19 = ZERO;
- TYPE value20 = ZERO;
- TYPE value21 = ZERO;
- TYPE value22 = ZERO;
- TYPE value23 = ZERO;
- TYPE value24 = ZERO;
- TYPE value25 = ZERO;
- TYPE value26 = ZERO;
- TYPE value27 = ZERO;
- TYPE value28 = ZERO;
- TYPE value29 = ZERO;
- TYPE value30 = ZERO;
- TYPE value31 = ZERO;
- TYPE value32 = ZERO;
- TYPE value33 = ZERO;
- TYPE value34 = ZERO;
- TYPE value35 = ZERO;
- TYPE value36 = ZERO;
- TYPE value37 = ZERO;
- TYPE value38 = ZERO;
- TYPE value39 = ZERO;
- MASK_TYPE mask;
- int eq0;
-
- while ((mask = *add_mask++) != 0)
- {
- value = *add_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 += value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 += value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 += value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 += value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 += value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 += value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 += value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 += value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 += value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 += value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 += value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 += value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 += value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 += value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 += value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 += value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 += value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 += value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 += value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 += value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 += value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 += value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 += value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 += value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 += value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 += value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 += value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 += value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 += value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 += value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 += value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 += value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 += value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 += value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 += value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 += value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 += value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 += value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 += value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 += value;
- }
-
- while ((mask = *sub_mask++) != 0)
- {
- value = *sub_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 -= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 -= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 -= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 -= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 -= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 -= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 -= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 -= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 -= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 -= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 -= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 -= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 -= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 -= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 -= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 -= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 -= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 -= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 -= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 -= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 -= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 -= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 -= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 -= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 -= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 -= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 -= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 -= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 -= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 -= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 -= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 -= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 -= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 -= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 -= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 -= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 -= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 -= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 -= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 -= value;
- }
-
- while ((mask = *mul_mask++) != 0)
- {
- value = *mul_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 *= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 *= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 *= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 *= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 *= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 *= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 *= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 *= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 *= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 *= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 *= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 *= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 *= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 *= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 *= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 *= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 *= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 *= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 *= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 *= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 *= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 *= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 *= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 *= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 *= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 *= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 *= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 *= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 *= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 *= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 *= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 *= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 *= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 *= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 *= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 *= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 *= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 *= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 *= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 *= value;
- }
-
- while ((mask = *div_mask++) != 0)
- {
- value = *div_values++;
-
- __asm__ (" #reg %0" : "+d" (value));
-
- if ((mask & (MASK_ONE << 0)) != 0)
- value00 /= value;
-
- if ((mask & (MASK_ONE << 1)) != 0)
- value01 /= value;
-
- if ((mask & (MASK_ONE << 2)) != 0)
- value02 /= value;
-
- if ((mask & (MASK_ONE << 3)) != 0)
- value03 /= value;
-
- if ((mask & (MASK_ONE << 4)) != 0)
- value04 /= value;
-
- if ((mask & (MASK_ONE << 5)) != 0)
- value05 /= value;
-
- if ((mask & (MASK_ONE << 6)) != 0)
- value06 /= value;
-
- if ((mask & (MASK_ONE << 7)) != 0)
- value07 /= value;
-
- if ((mask & (MASK_ONE << 8)) != 0)
- value08 /= value;
-
- if ((mask & (MASK_ONE << 9)) != 0)
- value09 /= value;
-
- if ((mask & (MASK_ONE << 10)) != 0)
- value10 /= value;
-
- if ((mask & (MASK_ONE << 11)) != 0)
- value11 /= value;
-
- if ((mask & (MASK_ONE << 12)) != 0)
- value12 /= value;
-
- if ((mask & (MASK_ONE << 13)) != 0)
- value13 /= value;
-
- if ((mask & (MASK_ONE << 14)) != 0)
- value14 /= value;
-
- if ((mask & (MASK_ONE << 15)) != 0)
- value15 /= value;
-
- if ((mask & (MASK_ONE << 16)) != 0)
- value16 /= value;
-
- if ((mask & (MASK_ONE << 17)) != 0)
- value17 /= value;
-
- if ((mask & (MASK_ONE << 18)) != 0)
- value18 /= value;
-
- if ((mask & (MASK_ONE << 19)) != 0)
- value19 /= value;
-
- if ((mask & (MASK_ONE << 20)) != 0)
- value20 /= value;
-
- if ((mask & (MASK_ONE << 21)) != 0)
- value21 /= value;
-
- if ((mask & (MASK_ONE << 22)) != 0)
- value22 /= value;
-
- if ((mask & (MASK_ONE << 23)) != 0)
- value23 /= value;
-
- if ((mask & (MASK_ONE << 24)) != 0)
- value24 /= value;
-
- if ((mask & (MASK_ONE << 25)) != 0)
- value25 /= value;
-
- if ((mask & (MASK_ONE << 26)) != 0)
- value26 /= value;
-
- if ((mask & (MASK_ONE << 27)) != 0)
- value27 /= value;
-
- if ((mask & (MASK_ONE << 28)) != 0)
- value28 /= value;
-
- if ((mask & (MASK_ONE << 29)) != 0)
- value29 /= value;
-
- if ((mask & (MASK_ONE << 30)) != 0)
- value30 /= value;
-
- if ((mask & (MASK_ONE << 31)) != 0)
- value31 /= value;
-
- if ((mask & (MASK_ONE << 32)) != 0)
- value32 /= value;
-
- if ((mask & (MASK_ONE << 33)) != 0)
- value33 /= value;
-
- if ((mask & (MASK_ONE << 34)) != 0)
- value34 /= value;
-
- if ((mask & (MASK_ONE << 35)) != 0)
- value35 /= value;
-
- if ((mask & (MASK_ONE << 36)) != 0)
- value36 /= value;
-
- if ((mask & (MASK_ONE << 37)) != 0)
- value37 /= value;
-
- if ((mask & (MASK_ONE << 38)) != 0)
- value38 /= value;
-
- if ((mask & (MASK_ONE << 39)) != 0)
- value39 /= value;
- }
-
- while ((mask = *eq0_mask++) != 0)
- {
- eq0 = 0;
-
- if ((mask & (MASK_ONE << 0)) != 0)
- eq0 |= (value00 == ZERO);
-
- if ((mask & (MASK_ONE << 1)) != 0)
- eq0 |= (value01 == ZERO);
-
- if ((mask & (MASK_ONE << 2)) != 0)
- eq0 |= (value02 == ZERO);
-
- if ((mask & (MASK_ONE << 3)) != 0)
- eq0 |= (value03 == ZERO);
-
- if ((mask & (MASK_ONE << 4)) != 0)
- eq0 |= (value04 == ZERO);
-
- if ((mask & (MASK_ONE << 5)) != 0)
- eq0 |= (value05 == ZERO);
-
- if ((mask & (MASK_ONE << 6)) != 0)
- eq0 |= (value06 == ZERO);
-
- if ((mask & (MASK_ONE << 7)) != 0)
- eq0 |= (value07 == ZERO);
-
- if ((mask & (MASK_ONE << 8)) != 0)
- eq0 |= (value08 == ZERO);
-
- if ((mask & (MASK_ONE << 9)) != 0)
- eq0 |= (value09 == ZERO);
-
- if ((mask & (MASK_ONE << 10)) != 0)
- eq0 |= (value10 == ZERO);
-
- if ((mask & (MASK_ONE << 11)) != 0)
- eq0 |= (value11 == ZERO);
-
- if ((mask & (MASK_ONE << 12)) != 0)
- eq0 |= (value12 == ZERO);
-
- if ((mask & (MASK_ONE << 13)) != 0)
- eq0 |= (value13 == ZERO);
-
- if ((mask & (MASK_ONE << 14)) != 0)
- eq0 |= (value14 == ZERO);
-
- if ((mask & (MASK_ONE << 15)) != 0)
- eq0 |= (value15 == ZERO);
-
- if ((mask & (MASK_ONE << 16)) != 0)
- eq0 |= (value16 == ZERO);
-
- if ((mask & (MASK_ONE << 17)) != 0)
- eq0 |= (value17 == ZERO);
-
- if ((mask & (MASK_ONE << 18)) != 0)
- eq0 |= (value18 == ZERO);
-
- if ((mask & (MASK_ONE << 19)) != 0)
- eq0 |= (value19 == ZERO);
-
- if ((mask & (MASK_ONE << 20)) != 0)
- eq0 |= (value20 == ZERO);
-
- if ((mask & (MASK_ONE << 21)) != 0)
- eq0 |= (value21 == ZERO);
-
- if ((mask & (MASK_ONE << 22)) != 0)
- eq0 |= (value22 == ZERO);
-
- if ((mask & (MASK_ONE << 23)) != 0)
- eq0 |= (value23 == ZERO);
-
- if ((mask & (MASK_ONE << 24)) != 0)
- eq0 |= (value24 == ZERO);
-
- if ((mask & (MASK_ONE << 25)) != 0)
- eq0 |= (value25 == ZERO);
-
- if ((mask & (MASK_ONE << 26)) != 0)
- eq0 |= (value26 == ZERO);
-
- if ((mask & (MASK_ONE << 27)) != 0)
- eq0 |= (value27 == ZERO);
-
- if ((mask & (MASK_ONE << 28)) != 0)
- eq0 |= (value28 == ZERO);
-
- if ((mask & (MASK_ONE << 29)) != 0)
- eq0 |= (value29 == ZERO);
-
- if ((mask & (MASK_ONE << 30)) != 0)
- eq0 |= (value30 == ZERO);
-
- if ((mask & (MASK_ONE << 31)) != 0)
- eq0 |= (value31 == ZERO);
-
- if ((mask & (MASK_ONE << 32)) != 0)
- eq0 |= (value32 == ZERO);
-
- if ((mask & (MASK_ONE << 33)) != 0)
- eq0 |= (value33 == ZERO);
-
- if ((mask & (MASK_ONE << 34)) != 0)
- eq0 |= (value34 == ZERO);
-
- if ((mask & (MASK_ONE << 35)) != 0)
- eq0 |= (value35 == ZERO);
-
- if ((mask & (MASK_ONE << 36)) != 0)
- eq0 |= (value36 == ZERO);
-
- if ((mask & (MASK_ONE << 37)) != 0)
- eq0 |= (value37 == ZERO);
-
- if ((mask & (MASK_ONE << 38)) != 0)
- eq0 |= (value38 == ZERO);
-
- if ((mask & (MASK_ONE << 39)) != 0)
- eq0 |= (value39 == ZERO);
-
- *eq0_ptr++ = eq0;
- }
-
- return ( value00 + value01 + value02 + value03 + value04
- + value05 + value06 + value07 + value08 + value09
- + value10 + value11 + value12 + value13 + value14
- + value15 + value16 + value17 + value18 + value19
- + value20 + value21 + value22 + value23 + value24
- + value25 + value26 + value27 + value28 + value29
- + value30 + value31 + value32 + value33 + value34
- + value35 + value36 + value37 + value38 + value39);
-}
-
-/* { dg-final { scan-assembler "fadds" } } */
-/* { dg-final { scan-assembler "fsubs" } } */
-/* { dg-final { scan-assembler "fmuls" } } */
-/* { dg-final { scan-assembler "fdivs" } } */
-/* { dg-final { scan-assembler "fcmpu" } } */
-/* { dg-final { scan-assembler "xsaddsp" } } */
-/* { dg-final { scan-assembler "xssubsp" } } */
-/* { dg-final { scan-assembler "xsmulsp" } } */
-/* { dg-final { scan-assembler "xsdivsp" } } */
-/* { dg-final { scan-assembler "xscmpudp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr67808.c b/gcc/testsuite/gcc.target/powerpc/pr67808.c
index 16b309c151e..3ee8003bebc 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr67808.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr67808.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O1 -mvsx -mlra -mcpu=power7 -mlong-double-128" } */
+/* { dg-options "-O1 -mvsx -mcpu=power7 -mlong-double-128" } */
/* PR 67808: LRA ICEs on simple double to long double conversion test case */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr68805.c b/gcc/testsuite/gcc.target/powerpc/pr68805.c
index 5510811107d..f4454a9e2d2 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr68805.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr68805.c
@@ -1,6 +1,6 @@
/* { dg-do compile { target powerpc64le-*-* } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-O2 -mvsx-timode -mcpu=power8 -mlra" } */
+/* { dg-options "-O2 -mvsx-timode -mcpu=power8" } */
typedef struct bar {
void *a;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr69461.c b/gcc/testsuite/gcc.target/powerpc/pr69461.c
index 406e7049d29..f693a5f0146 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr69461.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr69461.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -mlra" } */
+/* { dg-options "-O3" } */
extern void _setjmp (void);
typedef struct {
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71656-1.c b/gcc/testsuite/gcc.target/powerpc/pr71656-1.c
index fa6b4ffb816..1cb809f8b2a 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71656-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71656-1.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-O1 -mcpu=power9 -mpower9-dform-vector -mno-lra" } */
+/* { dg-options "-O1 -mcpu=power9 -mpower9-dform-vector" } */
typedef __attribute__((altivec(vector__))) int type_t;
type_t
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71656-2.c b/gcc/testsuite/gcc.target/powerpc/pr71656-2.c
index 99855fa1667..f953ebe4f9e 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71656-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71656-2.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-O3 -mcpu=power9 -mpower9-dform-vector -mno-lra -funroll-loops -fno-aggressive-loop-optimizations" } */
+/* { dg-options "-O3 -mcpu=power9 -mpower9-dform-vector -funroll-loops -fno-aggressive-loop-optimizations" } */
typedef double vec[3];
struct vec_t
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71680.c b/gcc/testsuite/gcc.target/powerpc/pr71680.c
index fe5260f73d9..cdb7b5143ed 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71680.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71680.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O1 -mlra" } */
+/* { dg-options "-mcpu=power8 -O1" } */
#pragma pack(1)
struct
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71698.c b/gcc/testsuite/gcc.target/powerpc/pr71698.c
index c752f64e1c7..eba47b0951f 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71698.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71698.c
@@ -3,7 +3,7 @@
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-require-effective-target dfp } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-O1 -mcpu=power9 -mno-lra" } */
+/* { dg-options "-O1 -mcpu=power9" } */
extern void testvad128 (int n, ...);
void
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71720.c b/gcc/testsuite/gcc.target/powerpc/pr71720.c
index a0c330db931..732daf97595 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71720.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71720.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power9 -O2" } */
/* Verify that we generate xxspltw <reg>,<reg>,0 for V4SFmode splat. */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr72853.c b/gcc/testsuite/gcc.target/powerpc/pr72853.c
index 8a086087088..9dc1bd2344c 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr72853.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr72853.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O3 -mupper-regs-df -mupper-regs-sf -funroll-loops" } */
+/* { dg-options "-mcpu=power9 -O3 -funroll-loops" } */
/* derived from 20021120-1.c, compiled for -mcpu=power9. */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr77289.c b/gcc/testsuite/gcc.target/powerpc/pr77289.c
index 295aa27acdc..474bdbf0b16 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr77289.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr77289.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O3 -mcpu=power7 -funroll-loops -ffast-math -mlra -mupdate -fno-auto-inc-dec" } */
+/* { dg-options "-O3 -mcpu=power7 -funroll-loops -ffast-math -mupdate -fno-auto-inc-dec" } */
/* PR 77289: LRA ICEs due to invalid constraint checking. */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr78458.c b/gcc/testsuite/gcc.target/powerpc/pr78458.c
index 777ac43bcad..a27876375af 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr78458.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr78458.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=8548 -mspe -mabi=spe -mlra" } */
+/* { dg-options "-mcpu=8548 -mspe -mabi=spe" } */
/* { dg-skip-if "not an SPE target" { ! powerpc_spe_nocache } } */
extern void bar (void);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr78543.c b/gcc/testsuite/gcc.target/powerpc/pr78543.c
index 0421344d3ce..13b34e58a0b 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr78543.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr78543.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O1 -mno-lra" } */
+/* { dg-options "-mcpu=power8 -O1" } */
typedef long a;
enum c { e, f, g, h, i, ab } j();
diff --git a/gcc/testsuite/gcc.target/powerpc/pr78953.c b/gcc/testsuite/gcc.target/powerpc/pr78953.c
index 34a3083918d..fd26f073499 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr78953.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr78953.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power9 -O2" } */
#include <altivec.h>
@@ -16,4 +16,4 @@ foo (vector int *vp, int *ip)
ip[4] = vec_extract (v, 0);
}
-/* { dg-final { scan-assembler "xxextractuw\|vextuw\[lr\]x" } } */
+/* { dg-final { scan-assembler {\mxxextractuw\M|\mvextuw[lr]x\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr79907.c b/gcc/testsuite/gcc.target/powerpc/pr79907.c
index c0e669b3264..240a1f46713 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr79907.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr79907.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O3 -mno-upper-regs-df" } */
+/* { dg-options "-mcpu=power8 -O3" } */
int foo (short a[], int x)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80099-1.c b/gcc/testsuite/gcc.target/powerpc/pr80099-1.c
deleted file mode 100644
index 9f34c5fbef8..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr80099-1.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-sf" } */
-
-/* PR target/80099: compiler internal error if -mno-upper-regs-sf used. */
-
-int a;
-int int_from_mem (vector float *c)
-{
- return __builtin_vec_extract (*c, a);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80099-2.c b/gcc/testsuite/gcc.target/powerpc/pr80099-2.c
deleted file mode 100644
index 5800db63212..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr80099-2.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-sf" } */
-
-/* PR target/80099 was an issue with -mno-upper-regs-sf. Test for all variable
- extract types with various -mno-upper-regs-* options. */
-
-double
-d_extract_arg_n (vector double v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-float
-f_extract_arg_n (vector float v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-long
-sl_extract_arg_n (vector long v, unsigned long n)
-{
- return (long) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ul_extract_arg_n (vector unsigned long v, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (v, n);
-}
-
-long
-si_extract_arg_n (vector int v, unsigned long n)
-{
- return (int) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ui_extract_arg_n (vector unsigned int v, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (v, n);
-}
-
-long
-ss_extract_arg_n (vector short v, unsigned long n)
-{
- return (short) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-us_extract_arg_n (vector unsigned short v, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (v, n);
-}
-
-long
-sc_extract_arg_n (vector signed char v, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-uc_extract_arg_n (vector unsigned char v, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (v, n);
-}
-
-
-double
-d_extract_mem_n (vector double *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-float
-f_extract_mem_n (vector float *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-long
-sl_extract_mem_n (vector long *p, unsigned long n)
-{
- return (long) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ul_extract_mem_n (vector unsigned long *p, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (*p, n);
-}
-
-long
-si_extract_mem_n (vector int *p, unsigned long n)
-{
- return (int) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ui_extract_mem_n (vector unsigned int *p, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (*p, n);
-}
-
-long
-ss_extract_mem_n (vector short *p, unsigned long n)
-{
- return (short) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-us_extract_mem_n (vector unsigned short *p, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (*p, n);
-}
-
-long
-sc_extract_mem_n (vector signed char *p, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-uc_extract_mem_n (vector unsigned char *p, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (*p, n);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80099-3.c b/gcc/testsuite/gcc.target/powerpc/pr80099-3.c
deleted file mode 100644
index 71c2b40b0d1..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr80099-3.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-df" } */
-
-/* PR target/80099 was an issue with -mno-upper-regs-sf. Test for all variable
- extract types with various -mno-upper-regs-* options. */
-
-double
-d_extract_arg_n (vector double v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-float
-f_extract_arg_n (vector float v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-long
-sl_extract_arg_n (vector long v, unsigned long n)
-{
- return (long) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ul_extract_arg_n (vector unsigned long v, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (v, n);
-}
-
-long
-si_extract_arg_n (vector int v, unsigned long n)
-{
- return (int) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ui_extract_arg_n (vector unsigned int v, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (v, n);
-}
-
-long
-ss_extract_arg_n (vector short v, unsigned long n)
-{
- return (short) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-us_extract_arg_n (vector unsigned short v, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (v, n);
-}
-
-long
-sc_extract_arg_n (vector signed char v, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-uc_extract_arg_n (vector unsigned char v, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (v, n);
-}
-
-
-double
-d_extract_mem_n (vector double *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-float
-f_extract_mem_n (vector float *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-long
-sl_extract_mem_n (vector long *p, unsigned long n)
-{
- return (long) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ul_extract_mem_n (vector unsigned long *p, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (*p, n);
-}
-
-long
-si_extract_mem_n (vector int *p, unsigned long n)
-{
- return (int) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ui_extract_mem_n (vector unsigned int *p, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (*p, n);
-}
-
-long
-ss_extract_mem_n (vector short *p, unsigned long n)
-{
- return (short) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-us_extract_mem_n (vector unsigned short *p, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (*p, n);
-}
-
-long
-sc_extract_mem_n (vector signed char *p, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-uc_extract_mem_n (vector unsigned char *p, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (*p, n);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80099-4.c b/gcc/testsuite/gcc.target/powerpc/pr80099-4.c
deleted file mode 100644
index 145dd1724af..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr80099-4.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs-di" } */
-
-/* PR target/80099 was an issue with -mno-upper-regs-sf. Test for all variable
- extract types with various -mno-upper-regs-* options. */
-
-double
-d_extract_arg_n (vector double v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-float
-f_extract_arg_n (vector float v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-long
-sl_extract_arg_n (vector long v, unsigned long n)
-{
- return (long) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ul_extract_arg_n (vector unsigned long v, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (v, n);
-}
-
-long
-si_extract_arg_n (vector int v, unsigned long n)
-{
- return (int) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ui_extract_arg_n (vector unsigned int v, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (v, n);
-}
-
-long
-ss_extract_arg_n (vector short v, unsigned long n)
-{
- return (short) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-us_extract_arg_n (vector unsigned short v, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (v, n);
-}
-
-long
-sc_extract_arg_n (vector signed char v, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-uc_extract_arg_n (vector unsigned char v, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (v, n);
-}
-
-
-double
-d_extract_mem_n (vector double *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-float
-f_extract_mem_n (vector float *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-long
-sl_extract_mem_n (vector long *p, unsigned long n)
-{
- return (long) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ul_extract_mem_n (vector unsigned long *p, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (*p, n);
-}
-
-long
-si_extract_mem_n (vector int *p, unsigned long n)
-{
- return (int) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ui_extract_mem_n (vector unsigned int *p, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (*p, n);
-}
-
-long
-ss_extract_mem_n (vector short *p, unsigned long n)
-{
- return (short) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-us_extract_mem_n (vector unsigned short *p, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (*p, n);
-}
-
-long
-sc_extract_mem_n (vector signed char *p, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-uc_extract_mem_n (vector unsigned char *p, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (*p, n);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80099-5.c b/gcc/testsuite/gcc.target/powerpc/pr80099-5.c
deleted file mode 100644
index 9ebc0fe466d..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr80099-5.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mno-upper-regs" } */
-
-/* PR target/80099 was an issue with -mno-upper-regs-sf. Test for all variable
- extract types with various -mno-upper-regs-* options. */
-
-double
-d_extract_arg_n (vector double v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-float
-f_extract_arg_n (vector float v, unsigned long n)
-{
- return __builtin_vec_extract (v, n);
-}
-
-long
-sl_extract_arg_n (vector long v, unsigned long n)
-{
- return (long) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ul_extract_arg_n (vector unsigned long v, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (v, n);
-}
-
-long
-si_extract_arg_n (vector int v, unsigned long n)
-{
- return (int) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-ui_extract_arg_n (vector unsigned int v, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (v, n);
-}
-
-long
-ss_extract_arg_n (vector short v, unsigned long n)
-{
- return (short) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-us_extract_arg_n (vector unsigned short v, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (v, n);
-}
-
-long
-sc_extract_arg_n (vector signed char v, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (v, n);
-}
-
-unsigned long
-uc_extract_arg_n (vector unsigned char v, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (v, n);
-}
-
-
-double
-d_extract_mem_n (vector double *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-float
-f_extract_mem_n (vector float *p, unsigned long n)
-{
- return __builtin_vec_extract (*p, n);
-}
-
-long
-sl_extract_mem_n (vector long *p, unsigned long n)
-{
- return (long) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ul_extract_mem_n (vector unsigned long *p, unsigned long n)
-{
- return (unsigned long) __builtin_vec_extract (*p, n);
-}
-
-long
-si_extract_mem_n (vector int *p, unsigned long n)
-{
- return (int) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-ui_extract_mem_n (vector unsigned int *p, unsigned long n)
-{
- return (unsigned int) __builtin_vec_extract (*p, n);
-}
-
-long
-ss_extract_mem_n (vector short *p, unsigned long n)
-{
- return (short) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-us_extract_mem_n (vector unsigned short *p, unsigned long n)
-{
- return (unsigned short) __builtin_vec_extract (*p, n);
-}
-
-long
-sc_extract_mem_n (vector signed char *p, unsigned long n)
-{
- return (signed char) __builtin_vec_extract (*p, n);
-}
-
-unsigned long
-uc_extract_mem_n (vector unsigned char *p, unsigned long n)
-{
- return (unsigned char) __builtin_vec_extract (*p, n);
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80103-1.c b/gcc/testsuite/gcc.target/powerpc/pr80103-1.c
index 35d48c4d8ce..bbec707df20 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80103-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80103-1.c
@@ -12,5 +12,5 @@
int a;
void b (__attribute__ ((__vector_size__ (16))) char c)
{
- a = ((__attributes__ ((__vector_size__ (2 * sizeof (long)))) long) c)[0];
+ a = ((__attribute__ ((__vector_size__ (2 * sizeof (long)))) long) c)[0];
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr81348.c b/gcc/testsuite/gcc.target/powerpc/pr81348.c
new file mode 100644
index 00000000000..e8e10bb598b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr81348.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9 -Og" } */
+
+/* PR target/81348: Compiler died in doing short->float conversion due to using
+ the wrong register in a define_split. */
+
+int a;
+short b;
+float ***c;
+
+void d(void)
+{
+ int e = 3;
+
+ if (a)
+ e = b;
+
+ ***c = e;
+}
+
+/* { dg-final { scan-assembler {\mlxsihzx\M} } } */
+/* { dg-final { scan-assembler {\mvextsh2d\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/upper-regs-df.c b/gcc/testsuite/gcc.target/powerpc/upper-regs-df.c
index 17f01bfbfca..0df579797ad 100644
--- a/gcc/testsuite/gcc.target/powerpc/upper-regs-df.c
+++ b/gcc/testsuite/gcc.target/powerpc/upper-regs-df.c
@@ -2,10 +2,10 @@
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power7 -O2 -mupper-regs-df" } */
+/* { dg-options "-mcpu=power7 -O2" } */
-/* Test for the -mupper-regs-df option to make sure double values are allocated
- to the Altivec registers as well as the traditional FPR registers. */
+/* Test to make sure double values are allocated to the Altivec registers as
+ well as the traditional FPR registers. */
#ifndef TYPE
#define TYPE double
diff --git a/gcc/testsuite/gcc.target/powerpc/upper-regs-sf.c b/gcc/testsuite/gcc.target/powerpc/upper-regs-sf.c
index 8c246796805..fd29fb5fd6e 100644
--- a/gcc/testsuite/gcc.target/powerpc/upper-regs-sf.c
+++ b/gcc/testsuite/gcc.target/powerpc/upper-regs-sf.c
@@ -2,10 +2,10 @@
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf" } */
+/* { dg-options "-mcpu=power8 -O2" } */
-/* Test for the -mupper-regs-df option to make sure double values are allocated
- to the Altivec registers as well as the traditional FPR registers. */
+/* Test make sure single precision values are allocated to the Altivec
+ registers as well as the traditional FPR registers. */
#ifndef TYPE
#define TYPE float
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-extract-1.c b/gcc/testsuite/gcc.target/powerpc/vec-extract-1.c
index 2f9624d4c86..9c8e6f3a684 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-extract-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-extract-1.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-di" } */
+/* { dg-options "-mcpu=power8 -O2" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-init-3.c b/gcc/testsuite/gcc.target/powerpc/vec-init-3.c
index d6d546942da..f4a536a2ea9 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-init-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-init-3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power9 -O2" } */
vector long
merge (long a, long b)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-init-6.c b/gcc/testsuite/gcc.target/powerpc/vec-init-6.c
index 14e605ca435..8d610e158cc 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-init-6.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-init-6.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power8 -O2" } */
vector int
merge (int a, int b, int c, int d)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-init-7.c b/gcc/testsuite/gcc.target/powerpc/vec-init-7.c
index b5e531ea7f1..c44fa9b2a3d 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-init-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-init-7.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -mupper-regs-di" } */
+/* { dg-options "-mcpu=power8 -O2" } */
vector int
splat (int a)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-set-char.c b/gcc/testsuite/gcc.target/powerpc/vec-set-char.c
index 2da79ef9e9d..5df260ded29 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-set-char.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-set-char.c
@@ -3,7 +3,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
vector char
insert_0_0 (vector char v)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-set-int.c b/gcc/testsuite/gcc.target/powerpc/vec-set-int.c
index dc97ac9d4d3..deaa6acfa6e 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-set-int.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-set-int.c
@@ -3,7 +3,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
vector int
insert_0_0 (vector int v)
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-set-short.c b/gcc/testsuite/gcc.target/powerpc/vec-set-short.c
index d82760955fd..eabcf3488de 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-set-short.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-set-short.c
@@ -3,7 +3,7 @@
/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
vector short
insert_0_0 (vector short v)
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-himode.c b/gcc/testsuite/gcc.target/powerpc/vsx-himode.c
index 8f710e5c5bd..2a4e610de72 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-himode.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-himode.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
double load_asm_d_constraint (short *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-himode2.c b/gcc/testsuite/gcc.target/powerpc/vsx-himode2.c
index e6f26a8e014..6ee08cf109a 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-himode2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-himode2.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
unsigned int foo (unsigned short u)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-himode3.c b/gcc/testsuite/gcc.target/powerpc/vsx-himode3.c
index 3c0e66d14ca..972be677dd6 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-himode3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-himode3.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
double load_asm_v_constraint (short *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-qimode.c b/gcc/testsuite/gcc.target/powerpc/vsx-qimode.c
index a252457f314..1c224cb1b61 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-qimode.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-qimode.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
double load_asm_d_constraint (signed char *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-qimode2.c b/gcc/testsuite/gcc.target/powerpc/vsx-qimode2.c
index d321970d0ac..478c9da3051 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-qimode2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-qimode2.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
unsigned int foo (unsigned char u)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-qimode3.c b/gcc/testsuite/gcc.target/powerpc/vsx-qimode3.c
index 50142e8d86d..6537d8b80a0 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-qimode3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-qimode3.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-mcpu=power9 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power9 -O2" } */
double load_asm_v_constraint (signed char *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-simode.c b/gcc/testsuite/gcc.target/powerpc/vsx-simode.c
index 91d55bb8791..77049008845 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-simode.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-simode.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power8 -O2" } */
double load_asm_d_constraint (int *p)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-simode2.c b/gcc/testsuite/gcc.target/powerpc/vsx-simode2.c
index 56793a16222..92053d9ac35 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-simode2.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-simode2.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power8 -O2" } */
unsigned int foo (unsigned int u)
{
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-simode3.c b/gcc/testsuite/gcc.target/powerpc/vsx-simode3.c
index a35e6db0b79..62f5ab46c04 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-simode3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-simode3.c
@@ -2,7 +2,7 @@
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2 -mvsx-small-integer" } */
+/* { dg-options "-mcpu=power8 -O2" } */
double load_asm_v_constraint (int *p)
{
diff --git a/gcc/testsuite/gcc.target/s390/nodatarel-1.c b/gcc/testsuite/gcc.target/s390/nodatarel-1.c
new file mode 100644
index 00000000000..1d589a10947
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nodatarel-1.c
@@ -0,0 +1,83 @@
+/* Test -mno-pic-data-is-text-relative option. No relative addressing
+ of elements in .data and .bss are allowed with that option. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-optimize-sibling-calls -fpic -mno-pic-data-is-text-relative -march=z10 -mtune=z9-109 -mzarch" } */
+
+static int a = 3;
+
+/* With -mno-pic-data-is-text-relative these must be addressed via
+ GOT. */
+
+int __attribute__((noinline,noclone))
+foo ()
+{
+ return a;
+}
+
+static int __attribute__((noinline,noclone))
+foostatic (void)
+{
+ return a;
+}
+
+/* Just to make a potentially modified. */
+
+void
+bar (int b)
+{
+ a = b;
+}
+
+/* { dg-final { scan-assembler-times "a@GOTENT" 3 } } */
+
+/* The exrl target is a label_ref which should not be affected at
+ all. */
+
+void
+mymemcpy (char *dst, char *src, long size)
+{
+ __builtin_memcpy (dst, src, size);
+}
+
+/* { dg-final { scan-assembler "exrl" } } */
+
+
+/* PLT slots can still be addressed relatively. */
+
+int
+callfoo ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "foo@PLT" 1 } } */
+
+
+/* GOT entries can still be addressed relatively. */
+
+void *
+fooptr ()
+{
+ return &foo;
+}
+
+/* { dg-final { scan-assembler-times "foo@GOTENT" 1 } } */
+
+
+/* A static function can be addressed relatively. */
+
+int
+callfoostatic ()
+{
+ return foostatic ();
+}
+
+void *
+foostaticptr ()
+{
+ return &foostatic;
+}
+
+
+/* { dg-final { scan-assembler-not "foostatic@" } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr81534.c b/gcc/testsuite/gcc.target/s390/pr81534.c
new file mode 100644
index 00000000000..0e1bd99b9cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr81534.c
@@ -0,0 +1,17 @@
+/* PR81534 This testcase used to fail because the HI/QI
+ "atomic_fetch_<atomic><mode>" expander accepted symbolic references
+ and emitted CAS patterns whose insn definition rejected them. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=zEC12" } */
+
+struct {
+ short b;
+ long c;
+} a = {};
+
+void
+d ()
+{
+ __atomic_fetch_add(&a.b, 0, 5);
+}
diff --git a/gcc/testsuite/gcc.target/sparc/dictunpack.c b/gcc/testsuite/gcc.target/sparc/dictunpack.c
new file mode 100644
index 00000000000..4334dee2b2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/dictunpack.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis4b" } */
+
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+typedef short vec16 __attribute__((vector_size(8)));
+typedef int vec32 __attribute__((vector_size(8)));
+
+vec8 test_dictunpack8 (double a)
+{
+ return __builtin_vis_dictunpack8 (a, 6);
+}
+
+vec16 test_dictunpack16 (double a)
+{
+ return __builtin_vis_dictunpack16 (a, 14);
+}
+
+vec32 test_dictunpack32 (double a)
+{
+ return __builtin_vis_dictunpack32 (a, 30);
+}
+
+/* { dg-final { scan-assembler "dictunpack\t%" } } */
+/* { dg-final { scan-assembler "dictunpack\t%" } } */
+/* { dg-final { scan-assembler "dictunpack\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpcmpdeshl.c b/gcc/testsuite/gcc.target/sparc/fpcmpdeshl.c
new file mode 100644
index 00000000000..3e3daa6e99f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fpcmpdeshl.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis4b" } */
+
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+typedef short vec16 __attribute__((vector_size(8)));
+typedef int vec32 __attribute__((vector_size(8)));
+
+long test_fpcmpde8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpde8shl (a, b, 2);
+}
+
+long test_fpcmpde16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpde16shl (a, b, 2);
+}
+
+long test_fpcmpde32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpde32shl (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "fpcmpde8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpde16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpde32shl\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpcmpshl.c b/gcc/testsuite/gcc.target/sparc/fpcmpshl.c
new file mode 100644
index 00000000000..0985251cbfd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fpcmpshl.c
@@ -0,0 +1,81 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis4b" } */
+
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+typedef short vec16 __attribute__((vector_size(8)));
+typedef int vec32 __attribute__((vector_size(8)));
+
+long test_fpcmple8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmple8shl (a, b, 2);
+}
+
+long test_fpcmpgt8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpgt8shl (a, b, 2);
+}
+
+long test_fpcmpeq8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpeq8shl (a, b, 2);
+}
+
+long test_fpcmpne8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpne8shl (a, b, 2);
+}
+
+long test_fpcmple16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmple16shl (a, b, 2);
+}
+
+long test_fpcmpgt16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpgt16shl (a, b, 2);
+}
+
+long test_fpcmpeq16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpeq16shl (a, b, 2);
+}
+
+long test_fpcmpne16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpne16shl (a, b, 2);
+}
+
+long test_fpcmple32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmple32shl (a, b, 2);
+}
+
+long test_fpcmpgt32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpgt32shl (a, b, 2);
+}
+
+long test_fpcmpeq32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpeq32shl (a, b, 2);
+}
+
+long test_fpcmpne32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpne32shl (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "fpcmple8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpgt8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpeq8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpne8shl\t%" } } */
+
+/* { dg-final { scan-assembler "fpcmple16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpgt16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpeq16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpne16shl\t%" } } */
+
+/* { dg-final { scan-assembler "fpcmple32shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpgt32shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpeq32shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpne32shl\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpcmpurshl.c b/gcc/testsuite/gcc.target/sparc/fpcmpurshl.c
new file mode 100644
index 00000000000..db74e01b5f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fpcmpurshl.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis4b" } */
+
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+typedef short vec16 __attribute__((vector_size(8)));
+typedef int vec32 __attribute__((vector_size(8)));
+
+long test_fpcmpur8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpur8shl (a, b, 2);
+}
+
+long test_fpcmpur16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpur16shl (a, b, 2);
+}
+
+long test_fpcmpur32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpur32shl (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "fpcmpur8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpur16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpur32shl\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpcmpushl.c b/gcc/testsuite/gcc.target/sparc/fpcmpushl.c
new file mode 100644
index 00000000000..fc58deddb45
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fpcmpushl.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis4b" } */
+
+typedef unsigned char vec8 __attribute__((vector_size(8)));
+typedef short vec16 __attribute__((vector_size(8)));
+typedef int vec32 __attribute__((vector_size(8)));
+
+long test_fpcmpule8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpule8shl (a, b, 2);
+}
+
+long test_fpcmpugt8shl (vec8 a, vec8 b)
+{
+ return __builtin_vis_fpcmpugt8shl (a, b, 2);
+}
+
+long test_fpcmpule16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpule16shl (a, b, 2);
+}
+
+long test_fpcmpugt16shl (vec16 a, vec16 b)
+{
+ return __builtin_vis_fpcmpugt16shl (a, b, 2);
+}
+
+long test_fpcmpule32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpule32shl (a, b, 2);
+}
+
+long test_fpcmpugt32shl (vec32 a, vec32 b)
+{
+ return __builtin_vis_fpcmpugt32shl (a, b, 2);
+}
+
+/* { dg-final { scan-assembler "fpcmpule8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpugt8shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpule16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpugt16shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpule32shl\t%" } } */
+/* { dg-final { scan-assembler "fpcmpugt32shl\t%" } } */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/do-test.S b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/do-test.S
index 1395235fd1e..ffe011bcc68 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/do-test.S
+++ b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/do-test.S
@@ -23,141 +23,101 @@ 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/>. */
-#ifdef __x86_64__
-
-# ifdef __ELF__
-# define ELFFN_BEGIN(fn) .type fn,@function
-# define ELFFN_END(fn) .size fn,.-fn
-# else
-# define ELFFN_BEGIN(fn)
-# define ELFFN_END(fn)
-# endif
-
-# define FUNC(fn) \
- .global fn; \
- ELFFN_BEGIN(fn); \
-fn:
-
-#define FUNC_END(fn) ELFFN_END(fn)
-
-# ifdef __AVX__
-# define MOVAPS vmovaps
-# else
-# define MOVAPS movaps
-# endif
-
-/* TODO: Is there a cleaner way to provide these offsets? */
- .struct 0
-test_data_save:
-
- .struct test_data_save + 224
-test_data_input:
-
- .struct test_data_save + 448
-test_data_output:
-
- .struct test_data_save + 672
-test_data_fn:
-
- .struct test_data_save + 680
-test_data_retaddr:
+#if defined(__x86_64__) && defined(__SSE2__)
+
+/* These macros currently support GNU/Linux, Solaris and Darwin. */
+
+#ifdef __ELF__
+# define FN_TYPE(fn) .type fn,@function
+# define FN_SIZE(fn) .size fn,.-fn
+#else
+# define FN_TYPE(fn)
+# define FN_SIZE(fn)
+#endif
+
+#ifdef __USER_LABEL_PREFIX__
+# define ASMNAME2(prefix, name) prefix ## name
+# define ASMNAME1(prefix, name) ASMNAME2(prefix, name)
+# define ASMNAME(name) ASMNAME1(__USER_LABEL_PREFIX__, name)
+#else
+# define ASMNAME(name) name
+#endif
+
+#define FUNC_BEGIN(fn) \
+ .globl ASMNAME(fn); \
+ FN_TYPE (ASMNAME(fn)); \
+ASMNAME(fn):
+
+#define FUNC_END(fn) FN_SIZE(ASMNAME(fn))
+
+#ifdef __AVX__
+# define MOVAPS vmovaps
+#else
+# define MOVAPS movaps
+#endif
.text
-regs_to_mem:
- MOVAPS %xmm6, (%rax)
- MOVAPS %xmm7, 0x10(%rax)
- MOVAPS %xmm8, 0x20(%rax)
- MOVAPS %xmm9, 0x30(%rax)
- MOVAPS %xmm10, 0x40(%rax)
- MOVAPS %xmm11, 0x50(%rax)
- MOVAPS %xmm12, 0x60(%rax)
- MOVAPS %xmm13, 0x70(%rax)
- MOVAPS %xmm14, 0x80(%rax)
- MOVAPS %xmm15, 0x90(%rax)
- mov %rsi, 0xa0(%rax)
- mov %rdi, 0xa8(%rax)
- mov %rbx, 0xb0(%rax)
- mov %rbp, 0xb8(%rax)
- mov %r12, 0xc0(%rax)
- mov %r13, 0xc8(%rax)
- mov %r14, 0xd0(%rax)
- mov %r15, 0xd8(%rax)
+FUNC_BEGIN(regs_to_mem)
+ MOVAPS %xmm6, (%r10)
+ MOVAPS %xmm7, 0x10(%r10)
+ MOVAPS %xmm8, 0x20(%r10)
+ MOVAPS %xmm9, 0x30(%r10)
+ MOVAPS %xmm10, 0x40(%r10)
+ MOVAPS %xmm11, 0x50(%r10)
+ MOVAPS %xmm12, 0x60(%r10)
+ MOVAPS %xmm13, 0x70(%r10)
+ MOVAPS %xmm14, 0x80(%r10)
+ MOVAPS %xmm15, 0x90(%r10)
+ mov %rsi, 0xa0(%r10)
+ mov %rdi, 0xa8(%r10)
+ mov %rbx, 0xb0(%r10)
+ mov %rbp, 0xb8(%r10)
+ mov %r12, 0xc0(%r10)
+ mov %r13, 0xc8(%r10)
+ mov %r14, 0xd0(%r10)
+ mov %r15, 0xd8(%r10)
retq
-
-mem_to_regs:
- MOVAPS (%rax), %xmm6
- MOVAPS 0x10(%rax),%xmm7
- MOVAPS 0x20(%rax),%xmm8
- MOVAPS 0x30(%rax),%xmm9
- MOVAPS 0x40(%rax),%xmm10
- MOVAPS 0x50(%rax),%xmm11
- MOVAPS 0x60(%rax),%xmm12
- MOVAPS 0x70(%rax),%xmm13
- MOVAPS 0x80(%rax),%xmm14
- MOVAPS 0x90(%rax),%xmm15
- mov 0xa0(%rax),%rsi
- mov 0xa8(%rax),%rdi
- mov 0xb0(%rax),%rbx
- mov 0xb8(%rax),%rbp
- mov 0xc0(%rax),%r12
- mov 0xc8(%rax),%r13
- mov 0xd0(%rax),%r14
- mov 0xd8(%rax),%r15
+FUNC_END(regs_to_mem)
+
+FUNC_BEGIN(mem_to_regs)
+ MOVAPS (%r10), %xmm6
+ MOVAPS 0x10(%r10),%xmm7
+ MOVAPS 0x20(%r10),%xmm8
+ MOVAPS 0x30(%r10),%xmm9
+ MOVAPS 0x40(%r10),%xmm10
+ MOVAPS 0x50(%r10),%xmm11
+ MOVAPS 0x60(%r10),%xmm12
+ MOVAPS 0x70(%r10),%xmm13
+ MOVAPS 0x80(%r10),%xmm14
+ MOVAPS 0x90(%r10),%xmm15
+ mov 0xa0(%r10),%rsi
+ mov 0xa8(%r10),%rdi
+ mov 0xb0(%r10),%rbx
+ mov 0xb8(%r10),%rbp
+ mov 0xc0(%r10),%r12
+ mov 0xc8(%r10),%r13
+ mov 0xd0(%r10),%r14
+ mov 0xd8(%r10),%r15
retq
+FUNC_END(mem_to_regs)
# NOTE: Not MT safe
-FUNC(do_test_unaligned)
- .cfi_startproc
+FUNC_BEGIN(do_test_unaligned)
# The below alignment checks are to verify correctness of the test
# its self.
# Verify that incoming stack is aligned + 8
- pushf
- test $0x8, %rsp
- jne L0
+ test $0xf, %rsp
+ je ASMNAME(do_test_body)
int $3 # Stack not unaligned
+FUNC_END(do_test_unaligned)
-FUNC(do_test_aligned)
+FUNC_BEGIN(do_test_aligned)
# Verify that incoming stack is aligned
- pushf
- test $0xf, %rsp
- je L0
+ test $0x8, %rsp
+ jne ASMNAME(do_test_body)
int $3 # Stack not aligned
-L0:
- popf
-
- # Save registers
- lea test_data(%rip), %rax
- call regs_to_mem
-
- # Load register with random data
- lea test_data + test_data_input(%rip), %rax
- call mem_to_regs
-
- # Save original return address
- pop %rax
- movq %rax, test_data + test_data_retaddr(%rip)
-
- # Call the test function
- call *test_data + test_data_fn(%rip)
-
- # Restore the original return address
- movq test_data + test_data_retaddr(%rip), %rcx
- push %rcx
-
- # Save test function return value and store resulting register values
- push %rax
- lea test_data + test_data_output(%rip), %rax
- call regs_to_mem
-
- # Restore registers
- lea test_data(%rip), %rax
- call mem_to_regs
- pop %rax
- retq
- .cfi_endproc
FUNC_END(do_test_aligned)
-FUNC_END(do_test_unaligned)
#endif /* __x86_64__ */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c
index 2a011f5103d..5fdd1e20674 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c
@@ -46,6 +46,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
is then called. After the function returns, the value of all volatile
registers is verified against the random data and then restored. */
+/* { dg-do run } */
+/* { dg-additional-sources "do-test.S" } */
+/* { dg-additional-options "-Wall" } */
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -58,8 +62,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <errno.h>
#include <ctype.h>
-#ifndef __x86_64__
-# error Test only valid on x86_64
+#if !defined(__x86_64__) || !defined(__SSE2__)
+# error Test only valid on x86_64 with -msse2
#endif
enum reg_data_sets
@@ -144,6 +148,72 @@ static __attribute__((ms_abi)) long
static int arbitrarily_fail;
static const char *argv0;
+
+#define PASTE_STR2(a) #a
+#define PASTE_STR1(a, b) PASTE_STR2(a ## b)
+#define PASTE_STR(a, b) PASTE_STR1(a, b)
+
+#ifdef __USER_LABEL_PREFIX__
+# define ASMNAME(name) PASTE_STR(__USER_LABEL_PREFIX__, name)
+#else
+# define ASMNAME(name) #name
+#endif
+
+#ifdef __MACH__
+# define LOAD_TEST_DATA_ADDR(dest) \
+ " mov " ASMNAME(test_data) "@GOTPCREL(%%rip), " dest "\n"
+#else
+# define LOAD_TEST_DATA_ADDR(dest) \
+ " lea " ASMNAME(test_data) "(%%rip), " dest "\n"
+#endif
+
+#define TEST_DATA_OFFSET(f) ((int)__builtin_offsetof(struct test_data, f))
+
+void __attribute__((naked))
+do_test_body (void)
+{__asm__ (
+ " # rax, r10 and r11 are usable here.\n"
+ "\n"
+ " # Save registers.\n"
+ LOAD_TEST_DATA_ADDR("%%rax")
+ " lea %p0(%%rax), %%r10\n"
+ " call " ASMNAME(regs_to_mem) "\n"
+ "\n"
+ " # Load registers with random data.\n"
+ " lea %p1(%%rax), %%r10\n"
+ " call " ASMNAME(mem_to_regs) "\n"
+ "\n"
+ " # Pop and save original return address.\n"
+ " pop %%r10\n"
+ " mov %%r10, %p4(%%rax)\n"
+ "\n"
+ " # Call the test function, after which rcx, rdx and r8-11\n"
+ " # become usable.\n"
+ " lea %p3(%%rax), %%rax\n"
+ " call *(%%rax)\n"
+ "\n"
+ " # Store resulting register values.\n"
+ LOAD_TEST_DATA_ADDR("%%rcx")
+ " lea %p2(%%rcx), %%r10\n"
+ " call " ASMNAME(regs_to_mem) "\n"
+ "\n"
+ " # Push the original return address.\n"
+ " lea %p4(%%rcx), %%r10\n"
+ " push (%%r10)\n"
+ "\n"
+ " # Restore registers.\n"
+ " lea %p0(%%rcx), %%r10\n"
+ " call " ASMNAME(mem_to_regs) "\n"
+ "\n"
+ " retq\n"
+ ::
+ "i"(TEST_DATA_OFFSET(regdata[REG_SET_SAVE])),
+ "i"(TEST_DATA_OFFSET(regdata[REG_SET_INPUT])),
+ "i"(TEST_DATA_OFFSET(regdata[REG_SET_OUTPUT])),
+ "i"(TEST_DATA_OFFSET(fn)),
+ "i"(TEST_DATA_OFFSET(retaddr)) : "memory");
+}
+
static void __attribute__((noinline))
init_test (void *fn, const char *name, enum alignment_option alignment,
enum shrink_wrap_option shrink_wrap, long ret_expected)
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 26777e0b59f..87f81690bc7 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
@@ -56,52 +56,48 @@ proc host_supports_c++11 {} {
# Exit immediately if this isn't a native x86_64 target.
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
- || ![is-effective-target lp64] || ![isnative]
- || ![host_supports_c++11] } then {
- unsupported "$subdir"
+ || ![is-effective-target lp64] || ![isnative]
+ || ![host_supports_c++11] } then {
+
+ # Gate "unsupported" message return value of first runtest_file_p call.
+ if [runtest_file_p $runtests "$srcdir/$subdir/ms-sysv.c"] {
+ unsupported "$subdir"
+ }
return
}
-global GCC_RUNTEST_PARALLELIZE_DIR
-
proc runtest_ms_sysv { cflags generator_args } {
global GCC_UNDER_TEST HOSTCXX HOSTCXXFLAGS tmpdir srcdir subdir \
- parallel_dir next_test
+ TEST_ALWAYS_FLAGS runtests
set objdir "$tmpdir/ms-sysv"
set generator "$tmpdir/ms-sysv-generate.exe"
set generated_header "$objdir/ms-sysv-generated.h"
- set do_test_o "$objdir/do-test.o"
- set ms_sysv_o "$objdir/ms-sysv.o"
- set ms_sysv_exe "$objdir/ms-sysv.exe"
set status 0
set warn_flags "-Wall"
- set this_test $next_test
- incr next_test
-
- # Do parallelization here
- if [catch {set fd [open "$parallel_dir/$this_test" \
- [list RDWR CREAT EXCL]]} ] {
- if { [lindex $::errorCode 1] eq "EEXIST" } then {
- # Another job is running this test
- return
- } else {
- error "Failed to open $parallel_dir/$this_test: $::errorCode"
- set status 1
- }
- } else {
- close $fd
- }
# Detect when hard frame pointers are enabled (or required) so we know not
# to generate bp clobbers.
- if [regexp "^(.+ +| *)-(O0|fno-omit-frame-pointer|p|pg)( +.*)?$" \
- $cflags match] then {
+ if { [regexp "(^| )-(O0|fno-omit-frame-pointer|p|pg)( |$)" \
+ "$TEST_ALWAYS_FLAGS $cflags" match]
+ || [istarget *-*-solaris*] } then {
set generator_args "$generator_args --omit-rbp-clobbers"
}
- set descr "$subdir CFLAGS=\"$cflags\" generator_args=\"$generator_args\""
- verbose "$tmpdir: Running test $descr" 1
+ # Add all other flags
+ set escaped_generator_args [regsub -all " " $generator_args "\\ "]
+ set cflags "$cflags\"-DGEN_ARGS=$escaped_generator_args\""
+
+ gcc_parallel_test_enable 1
+ if ![runtest_file_p $runtests "$srcdir/$subdir/ms-sysv.c"] then {
+ return
+ }
+
+ #verbose "runtest_ms_sysv $cflags" 0
+
+ # Make sure there's no previous header file so that we can't accidentally
+ # pass if generation fails.
+ file delete -force $generated_header
# Cleanup any previous test in objdir
file delete -force $objdir
@@ -109,18 +105,16 @@ proc runtest_ms_sysv { cflags generator_args } {
# Build the generator (only needs to be done once).
set src "$srcdir/$subdir/gen.cc"
- if { $status == 0 } then {
- if { (![file exists "$generator"]) || ([file mtime "$generator"]
- < [file mtime "$src"]) } {
- # Temporarily switch to the environment for the host compiler.
- restore_ld_library_path_env_vars
- 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
- if { $status != 0 } then {
- warning "Could not build $subdir generator"
- }
+ if { (![file exists "$generator"]) || ([file mtime "$generator"]
+ < [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 status [remote_exec host "$cxx -o $generator $src"]
+ set status [lindex $status 0]
+ set_ld_library_path_env_vars
+ if { $status != 0 } then {
+ warning "Could not build $subdir generator"
}
}
@@ -133,75 +127,26 @@ proc runtest_ms_sysv { cflags generator_args } {
}
}
- set cc "$GCC_UNDER_TEST -I$objdir -I$srcdir/$subdir $cflags $warn_flags"
-
- # Assemble do-test.S
- set src "$srcdir/$subdir/do-test.S"
- if { $status == 0 } then {
- set status [remote_exec build "$cc -c -o $do_test_o $src"]
- set status [lindex $status 0]
- if { $status != 0 } then {
- warning "Could not assemble $src"
- }
- }
-
- # Build ms-sysv.c
- set src "$srcdir/$subdir/ms-sysv.c"
- if { $status == 0 } then {
- set status [remote_exec build "$cc -c -o $ms_sysv_o $src" "" "" "" 1200]
- set status [lindex $status 0]
- if { $status != 0 } then {
- warning "Could not build $src."
- }
- }
-
- # Link
- if { $status == 0 } then {
- set status [remote_exec build "$cc -o $ms_sysv_exe $ms_sysv_o $do_test_o"]
- set status [lindex $status 0]
- if { $status != 0 } then {
- warning "Link failed."
- }
- }
-
- # Execute
- if { $status == 0 } then {
- set status [remote_exec build "$ms_sysv_exe"]
- set status [lindex $status 0]
- }
-
- if { $status != 0 } then {
- fail $descr
- } else {
- pass $descr
- }
+ gcc_parallel_test_enable 0
+ dg-runtest $srcdir/$subdir/ms-sysv.c "$cflags" "-I$objdir -I$srcdir/$subdir $warn_flags"
+ gcc_parallel_test_enable 1
}
dg-init
-# Setup parallelization
-set next_test 0
-set parallel_dir "$env(GCC_RUNTEST_PARALLELIZE_DIR)/abi-ms-sysv"
-file mkdir "$env(GCC_RUNTEST_PARALLELIZE_DIR)"
-file mkdir "$parallel_dir"
-
-if { ![file isdirectory "$parallel_dir"] } then {
- error "Failed to create directory $parallel_dir: $::errorCode"
- return
-}
+# Standard test parameters.
+set gen_pcount_opts [list "-p0" "-p1" "-p5"]
+set base_cflags_arr [list " -O2 " " -O0 -g3 "]
-set gen_opts "-p0-5"
-set all_options [list "-O2" "-O0 -g3"]
+foreach gen_opts $gen_pcount_opts {
+ foreach cflags $base_cflags_arr {
+ # Run without -mcall-ms2sysv-xlogues always
+ runtest_ms_sysv "$cflags" "$gen_opts"
-# Run without -mcall-ms2sysv-xlogues always
-foreach opt $all_options {
- runtest_ms_sysv "$opt" "$gen_opts"
-}
-
-# Skip -mcall-ms2sysv-xlogues on Windows (not supported)
-if { ![istarget *-*-cygwin*] && ![istarget *-*-mingw*] } {
- foreach opt $all_options {
- runtest_ms_sysv "-mcall-ms2sysv-xlogues $opt" "$gen_opts"
+ # Skip unsupported -mcall-ms2sysv-xlogues on Windows
+ if { ![istarget *-*-cygwin*] && ![istarget *-*-mingw*] } {
+ runtest_ms_sysv "-mcall-ms2sysv-xlogues$cflags" "$gen_opts"
+ }
}
}
diff --git a/gcc/testsuite/gfortran.dg/array_temporaries_4.f90 b/gcc/testsuite/gfortran.dg/array_temporaries_4.f90
new file mode 100644
index 00000000000..d022ce88557
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/array_temporaries_4.f90
@@ -0,0 +1,59 @@
+! { dg-do compile }
+! { dg-options "-Warray-temporaries" }
+! Tests the fix for PR80164, in which the compiler segfaulted on this
+! when using -Warray-temporaries
+!
+!******************************************************************************
+module global
+ type :: a
+ integer :: b
+ character(8):: c
+ end type a
+ interface assignment(=)
+ module procedure a_to_a, c_to_a, a_to_c
+ end interface
+ interface operator(.ne.)
+ module procedure a_ne_a
+ end interface
+
+ type(a) :: x(4), y(4)
+ logical :: l1(4), t = .true., f= .false.
+contains
+!******************************************************************************
+ elemental subroutine a_to_a (m, n)
+ type(a), intent(in) :: n
+ type(a), intent(out) :: m
+ m%b = len ( trim(n%c))
+ m%c = n%c
+ end subroutine a_to_a
+ elemental subroutine c_to_a (m, n)
+ character(8), intent(in) :: n
+ type(a), intent(out) :: m
+ m%b = m%b + 1
+ m%c = n
+ end subroutine c_to_a
+ elemental subroutine a_to_c (m, n)
+ type(a), intent(in) :: n
+ character(8), intent(out) :: m
+ m = n%c
+ end subroutine a_to_c
+!******************************************************************************
+ elemental logical function a_ne_a (m, n)
+ type(a), intent(in) :: n
+ type(a), intent(in) :: m
+ a_ne_a = (m%b .ne. n%b) .or. (m%c .ne. n%c)
+ end function a_ne_a
+!******************************************************************************
+ elemental function foo (m)
+ type(a) :: foo
+ type(a), intent(in) :: m
+ foo%b = 0
+ foo%c = m%c
+ end function foo
+end module global
+!******************************************************************************
+program test
+ use global
+ x = (/a (0, "one"),a (0, "two"),a (0, "three"),a (0, "four")/) ! { dg-warning "Creating array temporary" }
+ y = x
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_44.f90 b/gcc/testsuite/gfortran.dg/coarray_44.f90
new file mode 100644
index 00000000000..15fb8c76ce4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_44.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+! PR fortran/70071
+! Based on testcases by Gerhard Steinmetz
+
+program pr70071
+ implicit none
+ integer, allocatable :: z(:)[:,:]
+ allocate (z(2)[1::2,*]) ! { dg-error "Bad array dimension" }
+ allocate (z(1::2)[2,*]) ! { dg-error "Bad array specification in ALLOCATE" }
+end program pr70071
diff --git a/gcc/testsuite/gfortran.dg/coarray_event_2.f08 b/gcc/testsuite/gfortran.dg/coarray_event_2.f08
new file mode 100644
index 00000000000..20a37f332fb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_event_2.f08
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -lcaf_single" }
+
+! Check that pr79866 is really fixed.
+
+ use iso_fortran_env
+ type(event_type) :: x ! { dg-error "of type EVENT_TYPE or with subcomponent of type EVENT_TYPE must be a coarray" }
+
+contains
+ subroutine exchange
+ event post (x[1]) ! { dg-error "Syntax error in EVENT POST statement at .1." }
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/dim_sum_1.f90 b/gcc/testsuite/gfortran.dg/dim_sum_1.f90
new file mode 100644
index 00000000000..b2fb94312d3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dim_sum_1.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+! { dg-shouldfail "Dim argument incorrect in SUM intrinsic: is 5, should be between 1 and 2" }
+
+program summation
+
+ integer, parameter :: n1=5, n2=7
+ integer, dimension(1:n1,1:n2) :: arr
+ integer, dimension(1:n1) :: r2
+ integer, dimension(1:n2) :: r1
+ integer :: i,j
+ character(len=80) :: c1, c2
+ character(len=50) :: fmt = '(10I5)'
+ do j=1,n2
+ do i=1,n1
+ arr(i,j) = i+j*10
+ end do
+ end do
+
+ r1 = sum(arr,dim=1)
+ write (unit=c2, fmt=fmt) r1
+ call print_sum(1,c1)
+ if (c1 /= c2) call abort
+ r2 = sum(arr,dim=2)
+ write (unit=c2, fmt=fmt) r2
+ call print_sum(2,c1)
+ if (c1 /= c2) call abort
+ call print_sum(5,c1)
+
+contains
+
+ subroutine print_sum(d, c)
+ integer, intent(in) :: d
+ character(len=80), intent(out) :: c
+ write (unit=c, fmt=fmt) sum(arr,dim=d)
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dim_sum_2.f90 b/gcc/testsuite/gfortran.dg/dim_sum_2.f90
new file mode 100644
index 00000000000..6290444a81d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dim_sum_2.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+! { dg-shouldfail "Dim argument incorrect in SUM intrinsic: is 5, should be between 1 and 2" }
+
+program summation
+
+ integer, parameter :: n1=5, n2=7
+ integer, dimension(1:n1,1:n2) :: arr
+ integer, dimension(1:n1) :: r2
+ integer, dimension(1:n2) :: r1
+ integer :: i,j
+ character(len=80) :: c1, c2
+ character(len=50) :: fmt = '(10I5)'
+ do j=1,n2
+ do i=1,n1
+ arr(i,j) = i+j*10
+ end do
+ end do
+
+ r1 = sum(arr,dim=1,mask=arr>23)
+ write (unit=c2, fmt=fmt) r1
+ call print_sum(1,c1)
+ if (c1 /= c2) call abort
+ r2 = sum(arr,dim=2,mask=arr>23)
+ write (unit=c2, fmt=fmt) r2
+ call print_sum(2,c1)
+ if (c1 /= c2) call abort
+ call print_sum(5,c1)
+
+contains
+
+ subroutine print_sum(d, c)
+ integer, intent(in) :: d
+ character(len=80), intent(out) :: c
+ write (unit=c, fmt=fmt) sum(arr,dim=d,mask=arr>23)
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dim_sum_3.f90 b/gcc/testsuite/gfortran.dg/dim_sum_3.f90
new file mode 100644
index 00000000000..2661b3700fd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dim_sum_3.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+! { dg-shouldfail "Dim argument incorrect in SUM intrinsic: is 5, should be between 1 and 2" }
+
+program summation
+
+ integer, parameter :: n1=5, n2=7
+ integer, dimension(1:n1,1:n2) :: arr
+ integer, dimension(1:n1) :: r2
+ integer, dimension(1:n2) :: r1
+ integer :: i,j
+ character(len=80) :: c1, c2
+ character(len=50) :: fmt = '(10I5)'
+ do j=1,n2
+ do i=1,n1
+ arr(i,j) = i+j*10
+ end do
+ end do
+
+ r1 = sum(arr,dim=1,mask=.true.)
+ write (unit=c2, fmt=fmt) r1
+ call print_sum(1,c1)
+ if (c1 /= c2) call abort
+ r2 = sum(arr,dim=2,mask=.true.)
+ write (unit=c2, fmt=fmt) r2
+ call print_sum(2,c1)
+ if (c1 /= c2) call abort
+ call print_sum(5,c1)
+
+contains
+
+ subroutine print_sum(d, c)
+ integer, intent(in) :: d
+ character(len=80), intent(out) :: c
+ write (unit=c, fmt=fmt) sum(arr,dim=d,mask=.true.)
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/eoshift_3.f90 b/gcc/testsuite/gfortran.dg/eoshift_3.f90
new file mode 100644
index 00000000000..d1087aa8654
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eoshift_3.f90
@@ -0,0 +1,178 @@
+! { dg-do run }
+! Check that eoshift works for three-dimensional arrays.
+module x
+ implicit none
+contains
+ subroutine eoshift_0 (array, shift, boundary, dim, res)
+ real, dimension(:,:,:), intent(in) :: array
+ real, dimension(:,:,:), intent(out) :: res
+ integer, value :: shift
+ real, optional, intent(in) :: boundary
+ integer, optional, intent(in) :: dim
+ integer :: s1, s2, s3
+ integer :: n1, n2, n3
+
+ real :: b
+ integer :: d
+ if (present(boundary)) then
+ b = boundary
+ else
+ b = 0.0
+ end if
+
+ if (present(dim)) then
+ d = dim
+ else
+ d = 1
+ end if
+
+ n1 = size(array,1)
+ n2 = size(array,2)
+ n3 = size(array,3)
+
+ select case(dim)
+ case(1)
+ if (shift > 0) then
+ shift = min(shift, n1)
+ do s3=1,n3
+ do s2=1,n2
+ do s1= 1, n1 - shift
+ res(s1,s2,s3) = array(s1+shift,s2,s3)
+ end do
+ do s1 = n1 - shift + 1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+
+ else
+ shift = max(shift, -n1)
+ do s3=1,n3
+ do s2=1,n2
+ do s1=1,-shift
+ res(s1,s2,s3) = b
+ end do
+ do s1= 1-shift,n1
+ res(s1,s2,s3) = array(s1+shift,s2,s3)
+ end do
+ end do
+ end do
+ end if
+
+ case(2)
+ if (shift > 0) then
+ shift = min(shift, n2)
+ do s3=1,n3
+ do s2=1, n2 - shift
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2+shift,s3)
+ end do
+ end do
+ do s2=n2 - shift + 1, n2
+ do s1=1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ else
+ shift = max(shift, -n2)
+ do s3=1,n3
+ do s2=1,-shift
+ do s1=1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ do s2=1-shift,n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2+shift,s3)
+ end do
+ end do
+ end do
+ end if
+
+ case(3)
+ if (shift > 0) then
+ shift = min(shift, n3)
+ do s3=1,n3 - shift
+ do s2=1, n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2,s3+shift)
+ end do
+ end do
+ end do
+ do s3=n3 - shift + 1, n3
+ do s2=1, n2
+ do s1=1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ else
+ shift = max(shift, -n3)
+ do s3=1,-shift
+ do s2=1,n2
+ do s1=1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ do s3=1-shift,n3
+ do s2=1,n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2,s3+shift)
+ end do
+ end do
+ end do
+ end if
+
+ case default
+ stop "Illegal dim"
+ end select
+ end subroutine eoshift_0
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n1=2,n2=4,n3=2
+ real, dimension(n1,n2,n3) :: a,b,c
+ integer :: dim, shift, shift_lim
+ call random_number(a)
+
+ do dim=1,3
+ if (dim == 1) then
+ shift_lim = n1 + 1
+ else if (dim == 2) then
+ shift_lim = n2 + 1
+ else
+ shift_lim = n3 + 1
+ end if
+ do shift=-shift_lim, shift_lim
+ b = eoshift(a,shift,dim=dim)
+ call eoshift_0 (a, shift=shift, dim=dim, res=c)
+ if (any (b /= c)) then
+ print *,"dim = ", dim, "shift = ", shift
+ call abort
+ end if
+ end do
+ end do
+ call random_number(b)
+ c = b
+
+ do dim=1,3
+ if (dim == 1) then
+ shift_lim = n1/2 + 1
+ else if (dim == 2) then
+ shift_lim = n2/2 + 1
+ else
+ shift_lim = n3/2 + 1
+ end if
+
+ do shift=-shift_lim, shift_lim
+ b(1:n1:2,:,:) = eoshift(a(1:n1/2,:,:),shift,dim=dim)
+ call eoshift_0 (a(1:n1/2,:,:), shift=shift, dim=dim, res=c(1:n1:2,:,:))
+ if (any (b /= c)) call abort
+ end do
+ end do
+
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eoshift_4.f90 b/gcc/testsuite/gfortran.dg/eoshift_4.f90
new file mode 100644
index 00000000000..6d1a28a8479
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eoshift_4.f90
@@ -0,0 +1,187 @@
+! { dg-do run }
+! Check that eoshift works for three-dimensional arrays.
+module x
+ implicit none
+contains
+ subroutine eoshift_2 (array, shift, boundary, dim, res)
+ real, dimension(:,:,:), intent(in) :: array
+ real, dimension(:,:,:), intent(out) :: res
+ integer, value :: shift
+ real, optional, dimension(:,:), intent(in) :: boundary
+ integer, optional, intent(in) :: dim
+ integer :: s1, s2, s3
+ integer :: n1, n2, n3
+
+ real :: b
+ integer :: d
+
+ if (present(dim)) then
+ d = dim
+ else
+ d = 1
+ end if
+
+ n1 = size(array,1)
+ n2 = size(array,2)
+ n3 = size(array,3)
+
+ select case(dim)
+ case(1)
+ if (shift > 0) then
+ shift = min(shift, n1)
+ do s3=1,n3
+ do s2=1,n2
+ b = boundary(s2,s3)
+ do s1= 1, n1 - shift
+ res(s1,s2,s3) = array(s1+shift,s2,s3)
+ end do
+ do s1 = n1 - shift + 1,n1
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+
+ else
+ shift = max(shift, -n1)
+ do s3=1,n3
+ do s2=1,n2
+ b = boundary(s2,s3)
+ do s1=1,-shift
+ res(s1,s2,s3) = b
+ end do
+ do s1= 1-shift,n1
+ res(s1,s2,s3) = array(s1+shift,s2,s3)
+ end do
+ end do
+ end do
+ end if
+
+ case(2)
+ if (shift > 0) then
+ shift = min(shift, n2)
+ do s3=1,n3
+ do s2=1, n2 - shift
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2+shift,s3)
+ end do
+ end do
+ do s2=n2 - shift + 1, n2
+ do s1=1,n1
+ b = boundary(s1,s3)
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ else
+ shift = max(shift, -n2)
+ do s3=1,n3
+ do s2=1,-shift
+ do s1=1,n1
+ b = boundary(s1,s3)
+ res(s1,s2,s3) = b
+ end do
+ end do
+ do s2=1-shift,n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2+shift,s3)
+ end do
+ end do
+ end do
+ end if
+
+ case(3)
+ if (shift > 0) then
+ shift = min(shift, n3)
+ do s3=1,n3 - shift
+ do s2=1, n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2,s3+shift)
+ end do
+ end do
+ end do
+ do s3=n3 - shift + 1, n3
+ do s2=1, n2
+ do s1=1,n1
+ b = boundary(s1,s2)
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ else
+ shift = max(shift, -n3)
+ do s3=1,-shift
+ do s2=1,n2
+ do s1=1,n1
+ b = boundary(s1,s2)
+ res(s1,s2,s3) = b
+ end do
+ end do
+ end do
+ do s3=1-shift,n3
+ do s2=1,n2
+ do s1=1,n1
+ res(s1,s2,s3) = array(s1,s2,s3+shift)
+ end do
+ end do
+ end do
+ end if
+
+ case default
+ stop "Illegal dim"
+ end select
+ end subroutine eoshift_2
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n1=20,n2=30,n3=40
+ real, dimension(n1,n2,n3) :: a,b,c
+ real, dimension(2*n1,n2,n3) :: a2,c2
+ integer :: dim, shift, shift_lim
+ real, dimension(n2,n3), target :: b1
+ real, dimension(n1,n3), target :: b2
+ real, dimension(n1,n2), target :: b3
+ real, dimension(:,:), pointer :: bp
+
+ call random_number(a)
+ call random_number (b1)
+ call random_number (b2)
+ call random_number (b3)
+ do dim=1,3
+ if (dim == 1) then
+ shift_lim = n1 + 1
+ bp => b1
+ else if (dim == 2) then
+ shift_lim = n2 + 1
+ bp => b2
+ else
+ shift_lim = n3 + 1
+ bp => b3
+ end if
+ do shift=-shift_lim, shift_lim
+ b = eoshift(a,shift,dim=dim, boundary=bp)
+ call eoshift_2 (a, shift=shift, dim=dim, boundary=bp, res=c)
+ if (any (b /= c)) then
+ print *,"dim = ", dim, "shift = ", shift
+ print *,b
+ print *,c
+ call abort
+ end if
+ a2 = 42.
+ a2(1:2*n1:2,:,:) = a
+ b = eoshift(a2(1:2*n1:2,:,:), shift, dim=dim, boundary=bp)
+ if (any (b /= c)) then
+ call abort
+ end if
+ c2 = 43.
+ c2(1:2*n1:2,:,:) = eoshift(a,shift,dim=dim, boundary=bp)
+ if (any(c2(1:2*n1:2,:,:) /= c)) then
+ call abort
+ end if
+ if (any(c2(2:2*n1:2,:,:) /= 43)) then
+ call abort
+ end if
+ end do
+ end do
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eoshift_5.f90 b/gcc/testsuite/gfortran.dg/eoshift_5.f90
new file mode 100644
index 00000000000..a8c2494ad76
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eoshift_5.f90
@@ -0,0 +1,182 @@
+! { dg-do run }
+! Check that eoshift works for three-dimensional arrays.
+module x
+ implicit none
+contains
+ subroutine eoshift_1 (array, shift, boundary, dim, res)
+ real, dimension(:,:,:), intent(in) :: array
+ real, dimension(:,:,:), intent(out) :: res
+ integer, dimension(:,:), intent(in) :: shift
+ real, optional, intent(in) :: boundary
+ integer, optional, intent(in) :: dim
+ integer :: s1, s2, s3
+ integer :: n1, n2, n3
+ integer :: sh
+ real :: b
+ integer :: d
+
+ if (present(boundary)) then
+ b = boundary
+ else
+ b = 0.0
+ end if
+
+ if (present(dim)) then
+ d = dim
+ else
+ d = 1
+ end if
+
+ n1 = size(array,1)
+ n2 = size(array,2)
+ n3 = size(array,3)
+
+ select case(dim)
+ case(1)
+ do s3=1,n3
+ do s2=1,n2
+ sh = shift(s2,s3)
+ if (sh > 0) then
+ sh = min(sh, n1)
+ do s1= 1, n1 - sh
+ res(s1,s2,s3) = array(s1+sh,s2,s3)
+ end do
+ do s1 = n1 - sh + 1,n1
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n1)
+ do s1=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s1= 1-sh,n1
+ res(s1,s2,s3) = array(s1+sh,s2,s3)
+ end do
+ end if
+ end do
+ end do
+ case(2)
+ do s3=1,n3
+ do s1=1,n1
+ sh = shift(s1,s3)
+ if (sh > 0) then
+ sh = min (sh, n2)
+ do s2=1, n2 - sh
+ res(s1,s2,s3) = array(s1,s2+sh,s3)
+ end do
+ do s2=n2 - sh + 1, n2
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n2)
+ do s2=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s2=1-sh,n2
+ res(s1,s2,s3) = array(s1,s2+sh,s3)
+ end do
+ end if
+ end do
+ end do
+
+ case(3)
+ do s2=1, n2
+ do s1=1,n1
+ sh = shift(s1, s2)
+ if (sh > 0) then
+ sh = min(sh, n3)
+ do s3=1,n3 - sh
+ res(s1,s2,s3) = array(s1,s2,s3+sh)
+ end do
+ do s3=n3 - sh + 1, n3
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n3)
+ do s3=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s3=1-sh,n3
+ res(s1,s2,s3) = array(s1,s2,s3+sh)
+ end do
+ end if
+ end do
+ end do
+
+ case default
+ stop "Illegal dim"
+ end select
+ end subroutine eoshift_1
+ subroutine fill_shift(x, n)
+ integer, intent(out), dimension(:,:) :: x
+ integer, intent(in) :: n
+ integer :: n1, n2, s1, s2
+ integer :: v
+ v = -n - 1
+ n1 = size(x,1)
+ n2 = size(x,2)
+ do s2=1,n2
+ do s1=1,n1
+ x(s1,s2) = v
+ v = v + 1
+ if (v > n + 1) v = -n - 1
+ end do
+ end do
+ end subroutine fill_shift
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n1=20,n2=30,n3=40
+ real, dimension(n1,n2,n3) :: a,b,c
+ real, dimension(2*n1,n2,n3) :: a2, c2
+ integer :: dim
+ integer, dimension(n2,n3), target :: sh1
+ integer, dimension(n1,n3), target :: sh2
+ integer, dimension(n1,n2), target :: sh3
+ real, dimension(n2,n3), target :: b1
+ real, dimension(n1,n3), target :: b2
+ real, dimension(n1,n2), target :: b3
+
+ integer, dimension(:,:), pointer :: sp
+ real, dimension(:,:), pointer :: bp
+
+ call random_number(a)
+ call fill_shift(sh1, n1)
+ call fill_shift(sh2, n2)
+ call fill_shift(sh3, n3)
+
+ do dim=1,3
+ if (dim == 1) then
+ sp => sh1
+ else if (dim == 2) then
+ sp => sh2
+ else
+ sp => sh3
+ end if
+ b = eoshift(a,shift=sp,dim=dim,boundary=-0.5)
+ call eoshift_1 (a, shift=sp, dim=dim, boundary=-0.5,res=c)
+ if (any (b /= c)) then
+ print *,"dim = ", dim
+ print *,"sp = ", sp
+ print '(99F8.4)',b
+ print '(99F8.4)',c
+ call abort
+ end if
+ a2 = 42.
+ a2(1:2*n1:2,:,:) = a
+ b = eoshift(a2(1:2*n1:2,:,:), shift=sp, dim=dim, boundary=-0.5)
+ if (any(b /= c)) then
+ call abort
+ end if
+ c2 = 43.
+ c2(1:2*n1:2,:,:) = eoshift(a, shift=sp, dim=dim, boundary=-0.5)
+ if (any(c2(1:2*n1:2,:,:) /= c)) then
+ call abort
+ end if
+ if (any(c2(2:2*n1:2,:,:) /= 43.)) then
+ call abort
+ end if
+ end do
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eoshift_6.f90 b/gcc/testsuite/gfortran.dg/eoshift_6.f90
new file mode 100644
index 00000000000..f3f833cc941
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eoshift_6.f90
@@ -0,0 +1,181 @@
+! { dg-do run }
+! Check that eoshift works for three-dimensional arrays.
+module x
+ implicit none
+contains
+ subroutine eoshift_3 (array, shift, boundary, dim, res)
+ real, dimension(:,:,:), intent(in) :: array
+ real, dimension(:,:,:), intent(out) :: res
+ integer, dimension(:,:), intent(in) :: shift
+ real, optional, dimension(:,:), intent(in) :: boundary
+ integer, optional, intent(in) :: dim
+ integer :: s1, s2, s3
+ integer :: n1, n2, n3
+ integer :: sh
+ real :: b
+ integer :: d
+
+ if (present(dim)) then
+ d = dim
+ else
+ d = 1
+ end if
+
+ n1 = size(array,1)
+ n2 = size(array,2)
+ n3 = size(array,3)
+
+ select case(dim)
+ case(1)
+ do s3=1,n3
+ do s2=1,n2
+ sh = shift(s2,s3)
+ b = boundary(s2,s3)
+ if (sh > 0) then
+ sh = min(sh, n1)
+ do s1= 1, n1 - sh
+ res(s1,s2,s3) = array(s1+sh,s2,s3)
+ end do
+ do s1 = n1 - sh + 1,n1
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n1)
+ do s1=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s1= 1-sh,n1
+ res(s1,s2,s3) = array(s1+sh,s2,s3)
+ end do
+ end if
+ end do
+ end do
+ case(2)
+ do s3=1,n3
+ do s1=1,n1
+ sh = shift(s1,s3)
+ b = boundary(s1,s3)
+ if (sh > 0) then
+ sh = min (sh, n2)
+ do s2=1, n2 - sh
+ res(s1,s2,s3) = array(s1,s2+sh,s3)
+ end do
+ do s2=n2 - sh + 1, n2
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n2)
+ do s2=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s2=1-sh,n2
+ res(s1,s2,s3) = array(s1,s2+sh,s3)
+ end do
+ end if
+ end do
+ end do
+
+ case(3)
+ do s2=1, n2
+ do s1=1,n1
+ sh = shift(s1, s2)
+ b = boundary(s1, s2)
+ if (sh > 0) then
+ sh = min(sh, n3)
+ do s3=1,n3 - sh
+ res(s1,s2,s3) = array(s1,s2,s3+sh)
+ end do
+ do s3=n3 - sh + 1, n3
+ res(s1,s2,s3) = b
+ end do
+ else
+ sh = max(sh, -n3)
+ do s3=1,-sh
+ res(s1,s2,s3) = b
+ end do
+ do s3=1-sh,n3
+ res(s1,s2,s3) = array(s1,s2,s3+sh)
+ end do
+ end if
+ end do
+ end do
+
+ case default
+ stop "Illegal dim"
+ end select
+ end subroutine eoshift_3
+ subroutine fill_shift(x, n)
+ integer, intent(out), dimension(:,:) :: x
+ integer, intent(in) :: n
+ integer :: n1, n2, s1, s2
+ integer :: v
+ v = -n - 1
+ n1 = size(x,1)
+ n2 = size(x,2)
+ do s2=1,n2
+ do s1=1,n1
+ x(s1,s2) = v
+ v = v + 1
+ if (v > n + 1) v = -n - 1
+ end do
+ end do
+ end subroutine fill_shift
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n1=10,n2=30,n3=40
+ real, dimension(n1,n2,n3) :: a,b,c
+ real, dimension(2*n1,n2,n3) :: a2, c2
+ integer :: dim
+ integer, dimension(n2,n3), target :: sh1
+ integer, dimension(n1,n3), target :: sh2
+ integer, dimension(n1,n2), target :: sh3
+ real, dimension(n2,n3), target :: b1
+ real, dimension(n1,n3), target :: b2
+ real, dimension(n1,n2), target :: b3
+
+ integer, dimension(:,:), pointer :: sp
+ real, dimension(:,:), pointer :: bp
+
+ call random_number(a)
+ call random_number(b1)
+ call random_number(b2)
+ call random_number(b3)
+ call fill_shift(sh1, n1)
+ call fill_shift(sh2, n2)
+ call fill_shift(sh3, n3)
+
+ do dim=1,3
+ if (dim == 1) then
+ sp => sh1
+ bp => b1
+ else if (dim == 2) then
+ sp => sh2
+ bp => b2
+ else
+ sp => sh3
+ bp => b3
+ end if
+ b = eoshift(a,shift=sp,dim=dim,boundary=bp)
+ call eoshift_3 (a, shift=sp, dim=dim, boundary=bp,res=c)
+ if (any (b /= c)) then
+ call abort
+ end if
+ a2 = 42.
+ a2(1:2*n1:2,:,:) = a
+ b = eoshift(a2(1:2*n1:2,:,:), shift=sp, dim=dim, boundary=bp)
+ if (any(b /= c)) then
+ call abort
+ end if
+ c2 = 43.
+ c2(1:2*n1:2,:,:) = eoshift(a, shift=sp, dim=dim, boundary=bp)
+ if (any(c2(1:2*n1:2,:,:) /= c)) then
+ call abort
+ end if
+ if (any(c2(2:2*n1:2,:,:) /= 43.)) then
+ call abort
+ end if
+ end do
+end program main
diff --git a/gcc/testsuite/gfortran.dg/goacc/pr77765.f90 b/gcc/testsuite/gfortran.dg/goacc/pr77765.f90
new file mode 100644
index 00000000000..3819cf70c04
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/pr77765.f90
@@ -0,0 +1,19 @@
+! Test the presence of an ACC ROUTINE directive inside a function
+! containg an error.
+
+! { dg-do compile }
+
+module m
+contains
+ recursive function f(x)
+ end function f
+ recursive function f(x)
+ !$acc routine (f)
+ end function f
+end module m
+
+! { dg-error "Procedure 'f' at .1. is already defined" "" { target *-*-* } 8 }
+! { dg-error "Duplicate RECURSIVE attribute specified" "" { target *-*-* } 8 }
+! { dg-error ".1." "" { target *-*-* } 10 }
+! { dg-error "Unexpected ..ACC ROUTINE" "" { target *-*-* } 11 }
+! { dg-error "Expecting END MODULE statement" "" { target *-*-* } 12 }
diff --git a/gcc/testsuite/gfortran.dg/namelist_3.f90 b/gcc/testsuite/gfortran.dg/namelist_3.f90
index f37946d53c9..3f20ea400c4 100644
--- a/gcc/testsuite/gfortran.dg/namelist_3.f90
+++ b/gcc/testsuite/gfortran.dg/namelist_3.f90
@@ -4,5 +4,5 @@
program namelist_3
integer,pointer :: x
allocate (x)
- namelist /n/ x ! { dg-error "NAMELIST attribute with POINTER attribute" }
+ namelist /n/ x ! { dg-error "NAMELIST attribute conflicts with POINTER attribute" }
end program namelist_3
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_2.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_2.f90
index 692570339a3..02f91b80495 100644
--- a/gcc/testsuite/gfortran.dg/pointer_intent_2.f90
+++ b/gcc/testsuite/gfortran.dg/pointer_intent_2.f90
@@ -14,6 +14,6 @@ program test
call a(p) ! { dg-error "Type mismatch in argument" }
contains
subroutine a(p)! { dg-error "has no IMPLICIT type" }
- integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute with INTENT attribute" }
+ integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute conflicts with INTENT attribute" }
end subroutine
end program
diff --git a/gcc/testsuite/gfortran.dg/pr81175.f b/gcc/testsuite/gfortran.dg/pr81175.f
new file mode 100644
index 00000000000..130ba9c1632
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr81175.f
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! { dg-options "-Ofast -fwrapv" }
+! { dg-additional-options "-march=broadwell" { target x86_64-*-* i?86-*-* } }
+ SUBROUTINE ECPDRA(IC4C,FP,FQ,G)
+ IMPLICIT DOUBLE PRECISION (A-H,O-Z)
+ DIMENSION FP(*),FQ(*),G(*)
+ DIMENSION CKLU(23,12,12)
+!
+ DO 240 I=IAMIN,IAMAX
+ DO 240 J=JAMIN,MMAX
+ DO 230 K=1,NPNP
+ DO 230 L=1,K
+ DO 230 MU=1,2*L-1
+ CKLTEM= CKLU(MU,L,K)
+ IF(IC4C.LE.0) THEN
+ IF(ABS(CKLTEM).GT.TOL) SUM= SUM+FP(N)*CKLTEM
+ ELSE
+ IF(ABS(CKLTEM).GT.TOL) SUM= SUM+FQ(N)*CKLTEM
+ END IF
+ 230 N= N+1
+ G(NN)= G(NN)+DUMJ*SUM
+ 240 NN= NN+1
+ END
diff --git a/gcc/testsuite/gfortran.dg/pr81464.f90 b/gcc/testsuite/gfortran.dg/pr81464.f90
new file mode 100644
index 00000000000..425cae9470c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr81464.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! { dg-options "--param parloops-chunk-size=2 -ftree-parallelize-loops=2 -O1" }
+
+program main
+ implicit none
+ real, dimension(:,:),allocatable :: a, b, c
+ real :: sm
+
+ allocate (a(2,2), b(2,2), c(2,2))
+
+ call random_number(a)
+ call random_number(b)
+
+ c = matmul(a,b)
+ sm = sum(c)
+
+ deallocate(a,b,c)
+
+end program main
diff --git a/gcc/testsuite/gfortran.dg/pr81529.f90 b/gcc/testsuite/gfortran.dg/pr81529.f90
new file mode 100644
index 00000000000..92e3d48e727
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr81529.f90
@@ -0,0 +1,32 @@
+! { dg-do compile }
+! { dg-options "-std=gnu -fno-tree-scev-cprop -Ofast" }
+
+subroutine CalcCgr(C,rmax,ordgr_max)
+ integer, intent(in) :: rmax,ordgr_max
+ double complex :: Zadj(2,2), Zadj2(2,2)
+ double complex, intent(out) :: C(0:rmax,0:rmax,0:rmax)
+ double complex, allocatable :: Cexpgr(:,:,:,:)
+ double complex :: Caux
+ integer :: rmaxB,rmaxExp,r,n0,n1,n2,k,l,i,j,m,n,nn
+
+ rmaxB = 2*rmax
+ rmaxExp = rmaxB
+ allocate(Cexpgr(0:rmaxExp/2,0:rmaxExp,0:rmaxExp,0:ordgr_max))
+
+ rloop: do r=0,rmaxExp/2
+ do n0=r,1,-1
+ do nn=r-n0,0,-1
+ do i=1,2
+ Caux = Caux - Zadj(i,l)
+ end do
+ Cexpgr(n0,0,0,0) = Caux/(2*(nn+1))
+ end do
+ end do
+ do n1=0,r
+ n2 = r-n1
+ if (r.le.rmax) then
+ C(0,n1,n2) = Cexpgr(0,n1,n2,0)
+ end if
+ end do
+ end do rloop
+end subroutine CalcCgr
diff --git a/gcc/testsuite/gfortran.dg/realloc_on_assign_28.f90 b/gcc/testsuite/gfortran.dg/realloc_on_assign_28.f90
new file mode 100644
index 00000000000..2e338e470fd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/realloc_on_assign_28.f90
@@ -0,0 +1,40 @@
+! { dg-do run }
+!
+! PR fortran/66102
+!
+! Contributed by Vladimir Fuka <vladimir.fuka@gmail.com>
+!
+ type t
+ integer,allocatable :: i
+ end type
+
+ type(t) :: e
+ type(t), allocatable, dimension(:) :: a, b
+ integer :: chksum = 0
+
+ do i=1,3 ! Was 100 in original
+ e%i = i
+ chksum = chksum + i
+ if (.not.allocated(a)) then
+ a = [e]
+ b = first_arg([e], [e])
+ else
+ call foo
+ end if
+ end do
+
+ if (sum ([(a(i)%i, i=1,size(a))]) .ne. chksum) call abort
+ if (any([(a(i)%i, i=1,size(a))] /= [(i, i=1,size(a))])) call abort
+ if (size(a) /= size(b)) call abort
+ if (any([(b(i)%i, i=1,size(b))] /= [(i, i=1,size(b))])) call abort
+contains
+ subroutine foo
+ b = first_arg([b, e], [a, e])
+ a = [a, e]
+ end subroutine
+ elemental function first_arg(arg1, arg2)
+ type(t), intent(in) :: arg1, arg2
+ type(t) :: first_arg
+ first_arg = arg1
+ end function first_arg
+end
diff --git a/gcc/testsuite/gfortran.dg/vect/pr60510.f b/gcc/testsuite/gfortran.dg/vect/pr60510.f
new file mode 100644
index 00000000000..5e2c085d761
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr60510.f
@@ -0,0 +1,30 @@
+! { dg-do run }
+! { dg-require-effective-target vect_double }
+! { dg-additional-options "-fno-inline -ffast-math" }
+ subroutine foo(a,x,y,n)
+ implicit none
+ integer n,i
+
+ real*8 y(n),x(n),a
+
+ do i=1,n
+ a=a+x(i)*y(i)+x(i)
+ enddo
+
+ return
+ end
+
+ program test
+ real*8 x(1024),y(1024),a
+ do i=1,1024
+ x(i) = i
+ y(i) = i+1
+ enddo
+ call foo(a,x,y,1024)
+ if (a.ne.359488000.0) call abort()
+ end
+! If there's no longer a reduction chain detected this doesn't test what
+! it was supposed to test, vectorizing a reduction chain w/o SLP.
+! { dg-final { scan-tree-dump "reduction chain" "vect" } }
+! We should vectorize the reduction in foo and the induction in test.
+! { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } }
diff --git a/gcc/testsuite/gfortran.dg/vect/pr61171.f b/gcc/testsuite/gfortran.dg/vect/pr61171.f
new file mode 100644
index 00000000000..f94b8f31283
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr61171.f
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-additional-options "-Ofast" }
+ SUBROUTINE GAUBON(NV,PTS,PP)
+ IMPLICIT DOUBLE PRECISION(A-H,O-Z)
+ PARAMETER (MXSP=250)
+ DIMENSION PTS(3,10),PP(3)
+ COMMON /PCMPLY/ XE(MXSP),YE(MXSP),ZE(MXSP)
+ DATA PI/3.141592653589793D+00/
+ DATA ZERO/0.0D+00/
+ DO I = 1, NV
+ PP(1) = PP(1) + (PTS(1,I)-XE(NS))
+ PP(2) = PP(2) + (PTS(2,I)-YE(NS))
+ PP(3) = PP(3) + (PTS(3,I)-ZE(NS))
+ ENDDO
+ END
diff --git a/gcc/testsuite/gnat.dg/opt49.adb b/gcc/testsuite/gnat.dg/opt49.adb
index 4b91973a19d..42ab953a2e0 100644
--- a/gcc/testsuite/gnat.dg/opt49.adb
+++ b/gcc/testsuite/gnat.dg/opt49.adb
@@ -1,4 +1,5 @@
-- { dg-do run }
+-- { dg-require-stack-check "" }
-- { dg-options "-O -fstack-check" }
procedure Opt49 is
diff --git a/gcc/testsuite/gnat.dg/opt65.adb b/gcc/testsuite/gnat.dg/opt65.adb
new file mode 100644
index 00000000000..7b429b6b1a3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt65.adb
@@ -0,0 +1,30 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Ada.Command_Line; use Ada.Command_Line;
+
+procedure Opt65 is
+
+ procedure Check_Version_And_Help (Version_String : String) is
+ Help_Switch_Present : Boolean := False;
+ Next_Arg : Natural := 1;
+ begin
+ while Next_Arg <= Argument_Count loop
+ declare
+ Next_Argv : constant String := Argument (Next_Arg);
+ begin
+ if Next_Argv = "--help" then
+ Help_Switch_Present := True;
+ end if;
+ Next_Arg := Next_Arg + 1;
+ end;
+ end loop;
+
+ if Help_Switch_Present then
+ raise Program_Error;
+ end if;
+ end;
+
+begin
+ Check_Version_And_Help ("version");
+end;
diff --git a/gcc/testsuite/gnat.dg/opt66.adb b/gcc/testsuite/gnat.dg/opt66.adb
new file mode 100644
index 00000000000..94a1790737c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt66.adb
@@ -0,0 +1,13 @@
+-- { dg-do compile }
+-- { dg-options "-O" }
+
+procedure Opt66 (I : Integer) is
+ E : exception;
+begin
+ if I = 0 then
+ raise E;
+ end if;
+ Opt66 (I - I / abs (I));
+exception
+ when others => null;
+end;
diff --git a/gcc/testsuite/gnat.dg/stack_check1.adb b/gcc/testsuite/gnat.dg/stack_check1.adb
index 51ee1a633b3..eaad745bdf6 100644
--- a/gcc/testsuite/gnat.dg/stack_check1.adb
+++ b/gcc/testsuite/gnat.dg/stack_check1.adb
@@ -1,4 +1,5 @@
-- { dg-do run }
+-- { dg-require-stack-check "" }
-- { dg-options "-fstack-check" }
-- This test requires architecture- and OS-specific support code for unwinding
diff --git a/gcc/testsuite/gnat.dg/stack_check2.adb b/gcc/testsuite/gnat.dg/stack_check2.adb
index 4a3008ba02b..f34d647c862 100644
--- a/gcc/testsuite/gnat.dg/stack_check2.adb
+++ b/gcc/testsuite/gnat.dg/stack_check2.adb
@@ -1,4 +1,5 @@
-- { dg-do run }
+-- { dg-require-stack-check "" }
-- { dg-options "-fstack-check" }
-- This test requires architecture- and OS-specific support code for unwinding
diff --git a/gcc/testsuite/gnat.dg/stack_check3.adb b/gcc/testsuite/gnat.dg/stack_check3.adb
index 734ed422733..3bb859c82f8 100644
--- a/gcc/testsuite/gnat.dg/stack_check3.adb
+++ b/gcc/testsuite/gnat.dg/stack_check3.adb
@@ -1,4 +1,5 @@
-- { dg-do compile }
+-- { dg-require-stack-check "" }
-- { dg-options "-O -fstack-check" }
package body Stack_Check3 is
diff --git a/gcc/testsuite/gnat.dg/vect15.adb b/gcc/testsuite/gnat.dg/vect15.adb
index ad66836a401..b19a2240409 100644
--- a/gcc/testsuite/gnat.dg/vect15.adb
+++ b/gcc/testsuite/gnat.dg/vect15.adb
@@ -5,8 +5,9 @@ package body Vect15 is
procedure Add (X, Y : Sarray; R : out Sarray) is
begin
- for I in Sarray'Range loop
- R(I) := X(I) + Y(I);
+ R(1) := X(5) + Y(5);
+ for I in 1 .. 4 loop
+ R(I + 1) := X(I) + Y(I);
end loop;
end;
diff --git a/gcc/testsuite/gnat.dg/vect15.ads b/gcc/testsuite/gnat.dg/vect15.ads
index 91375127deb..5c813246087 100644
--- a/gcc/testsuite/gnat.dg/vect15.ads
+++ b/gcc/testsuite/gnat.dg/vect15.ads
@@ -1,6 +1,6 @@
package Vect15 is
- type Sarray is array (1 .. 4) of Long_Float;
+ type Sarray is array (1 .. 5) of Long_Float;
for Sarray'Alignment use 16;
procedure Add (X, Y : Sarray; R : out Sarray);
diff --git a/gcc/testsuite/gnat.dg/vect16.adb b/gcc/testsuite/gnat.dg/vect16.adb
index 99fe32081de..9ef5e32449c 100644
--- a/gcc/testsuite/gnat.dg/vect16.adb
+++ b/gcc/testsuite/gnat.dg/vect16.adb
@@ -5,9 +5,11 @@ package body Vect16 is
procedure Add_Sub (X, Y : Sarray; R,S : out Sarray) is
begin
- for I in Sarray'Range loop
- R(I) := X(I) + Y(I);
- S(I) := X(I) - Y(I);
+ R(1) := X(5) + Y(5);
+ S(1) := X(5) - Y(5);
+ for I in 1 .. 4 loop
+ R(I + 1) := X(I) + Y(I);
+ S(I + 1) := X(I) - Y(I);
end loop;
end;
diff --git a/gcc/testsuite/gnat.dg/vect16.ads b/gcc/testsuite/gnat.dg/vect16.ads
index 0192dccb13e..882bf2a740c 100644
--- a/gcc/testsuite/gnat.dg/vect16.ads
+++ b/gcc/testsuite/gnat.dg/vect16.ads
@@ -1,6 +1,6 @@
package Vect16 is
- type Sarray is array (1 .. 4) of Long_Float;
+ type Sarray is array (1 .. 5) of Long_Float;
for Sarray'Alignment use 16;
procedure Add_Sub (X, Y : Sarray; R,S : out Sarray);
diff --git a/gcc/testsuite/gnat.dg/vect17.adb b/gcc/testsuite/gnat.dg/vect17.adb
index f574ea22157..76b6fc7de5a 100644
--- a/gcc/testsuite/gnat.dg/vect17.adb
+++ b/gcc/testsuite/gnat.dg/vect17.adb
@@ -5,8 +5,9 @@ package body Vect17 is
procedure Add (X, Y : aliased Sarray; R : aliased out Sarray) is
begin
- for I in Sarray'Range loop
- R(I) := X(I) + Y(I);
+ R(1) := X(5) + Y(5);
+ for I in 1 .. 4 loop
+ R(I + 1) := X(I) + Y(I);
end loop;
end;
diff --git a/gcc/testsuite/gnat.dg/vect17.ads b/gcc/testsuite/gnat.dg/vect17.ads
index 5c26157924e..3a6ab660f89 100644
--- a/gcc/testsuite/gnat.dg/vect17.ads
+++ b/gcc/testsuite/gnat.dg/vect17.ads
@@ -1,6 +1,6 @@
package Vect17 is
- type Sarray is array (1 .. 4) of Long_Float;
+ type Sarray is array (1 .. 5) of Long_Float;
for Sarray'Alignment use 16;
procedure Add (X, Y : aliased Sarray; R : aliased out Sarray);
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index e55557491bc..cb5d1843c92 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -43,6 +43,9 @@ if { [ishost "*-*-cygwin*"] } {
setenv LANG C.ASCII
}
+# Avoid sporadic data-losses with expect
+match_max -d 10000
+
# Ensure GCC_COLORS is unset, for the rare testcases that verify
# how output is colorized.
if [info exists ::env(GCC_COLORS) ] {
diff --git a/gcc/testsuite/lib/profopt.exp b/gcc/testsuite/lib/profopt.exp
index 0ea8e7a048e..93bb23ce93f 100644
--- a/gcc/testsuite/lib/profopt.exp
+++ b/gcc/testsuite/lib/profopt.exp
@@ -285,7 +285,7 @@ proc auto-profopt-execute { src } {
if { ! [check_profiling_available "-fauto-profile"] } {
regsub "(?q)$srcdir/" $src "" testcase
- unsupported "$src -fauto-profile"
+ unsupported "$testcase -fauto-profile"
return
}
set profile_wrapper [profopt-perf-wrapper]
@@ -451,7 +451,7 @@ proc profopt-execute { src } {
verbose "Running $cmd"
set id [remote_spawn "" $cmd]
if { $id < 0 } {
- unsupported "$src -fauto-profile: cannot run create_gcov"
+ unsupported "$testcase -fauto-profile: cannot run create_gcov"
set status "fail"
return
}
diff --git a/gcc/testsuite/lib/target-supports-dg.exp b/gcc/testsuite/lib/target-supports-dg.exp
index 6400d643409..d50d8b07ada 100644
--- a/gcc/testsuite/lib/target-supports-dg.exp
+++ b/gcc/testsuite/lib/target-supports-dg.exp
@@ -265,6 +265,21 @@ proc dg-require-linker-plugin { args } {
}
}
+# If this target does not support the "stack-check" option, skip this
+# test.
+
+proc dg-require-stack-check { args } {
+ set stack_check_available [ check_stack_check_available [lindex $args 1 ] ]
+ if { $stack_check_available == -1 } {
+ upvar name name
+ unresolved "$name"
+ }
+ if { $stack_check_available != 1 } {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ }
+}
+
# Add any target-specific flags needed for accessing the given list
# of features. This must come after all dg-options.
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 502986e71fb..5a6562794b2 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1063,6 +1063,17 @@ proc check_effective_target_fstack_protector {} {
} "-fstack-protector"]
}
+# Return 1 if the target supports -fstack-check or -fstack-check=$stack_kind
+proc check_stack_check_available { stack_kind } {
+ if [string match "" $stack_kind] then {
+ set stack_opt "-fstack-check"
+ } else { set stack_opt "-fstack-check=$stack_kind" }
+
+ return [check_no_compiler_messages stack_check_$stack_kind executable {
+ int main (void) { return 0; }
+ } "$stack_opt"]
+}
+
# Return 1 if compilation with -freorder-blocks-and-partition is error-free
# for trivial code, 0 otherwise. As some targets (ARM for example) only
# warn when -fprofile-use is also supplied we test that combination too.
@@ -1930,6 +1941,37 @@ proc check_effective_target_powerpc64_no_dm { } {
} {-O2}]
}
+# Return 1 if the target supports the __builtin_cpu_supports built-in,
+# including having a new enough library to support the test. Cache the result.
+# Require at least a power7 to run on.
+
+proc check_ppc_cpu_supports_hw_available { } {
+ return [check_cached_effective_target ppc_cpu_supports_hw_available {
+ # Some simulators are known to not support VSX/power8 instructions.
+ # For now, disable on Darwin
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mvsx"
+ check_runtime_nocache ppc_cpu_supports_hw_available {
+ int main()
+ {
+ #ifdef __MACH__
+ asm volatile ("xxlor vs0,vs0,vs0");
+ #else
+ asm volatile ("xxlor 0,0,0");
+ #endif
+ if (!__builtin_cpu_supports ("vsx"))
+ return 1;
+ return 0;
+ }
+ } $options
+ }
+ }]
+}
+
# Return 1 if the target supports executing power8 vector instructions, 0
# otherwise. Cache the result.
@@ -2943,7 +2985,7 @@ proc check_effective_target_vect_int { } {
|| [istarget alpha*-*-*]
|| [istarget ia64-*-*]
|| [istarget aarch64*-*-*]
- || [check_effective_target_arm32]
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& ([et-is-effective-target mips_loongson]
|| [et-is-effective-target mips_msa])) } {
@@ -2971,8 +3013,7 @@ proc check_effective_target_vect_intfloat_cvt { } {
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
|| ([istarget powerpc*-*-*]
&& ![istarget powerpc-*-linux*paired*])
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa]) } {
set et_vect_intfloat_cvt_saved($et_index) 1
@@ -3014,8 +3055,7 @@ proc check_effective_target_vect_uintfloat_cvt { } {
|| ([istarget powerpc*-*-*]
&& ![istarget powerpc-*-linux*paired*])
|| [istarget aarch64*-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa]) } {
set et_vect_uintfloat_cvt_saved($et_index) 1
@@ -3043,8 +3083,7 @@ proc check_effective_target_vect_floatint_cvt { } {
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
|| ([istarget powerpc*-*-*]
&& ![istarget powerpc-*-linux*paired*])
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa]) } {
set et_vect_floatint_cvt_saved($et_index) 1
@@ -3070,8 +3109,7 @@ proc check_effective_target_vect_floatuint_cvt { } {
set et_vect_floatuint_cvt_saved($et_index) 0
if { ([istarget powerpc*-*-*]
&& ![istarget powerpc-*-linux*paired*])
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa]) } {
set et_vect_floatuint_cvt_saved($et_index) 1
@@ -3398,7 +3436,7 @@ proc add_options_for_arm_v8_1a_neon { flags } {
return "$flags"
}
global et_arm_v8_1a_neon_flags
- return "$flags $et_arm_v8_1a_neon_flags -march=armv8.1-a"
+ return "$flags $et_arm_v8_1a_neon_flags"
}
# Add the options needed for ARMv8.2 with the scalar FP16 extension.
@@ -3461,8 +3499,9 @@ proc check_effective_target_arm_neon_ok_nocache { } {
global et_arm_neon_flags
set et_arm_neon_flags ""
if { [check_effective_target_arm32] } {
- foreach flags {"" "-mfloat-abi=softfp" "-mfpu=neon" "-mfpu=neon -mfloat-abi=softfp" "-mfpu=neon -mfloat-abi=softfp -march=armv7-a"} {
+ foreach flags {"" "-mfloat-abi=softfp" "-mfpu=neon" "-mfpu=neon -mfloat-abi=softfp" "-mfpu=neon -mfloat-abi=softfp -march=armv7-a" "-mfloat-abi=hard" "-mfpu=neon -mfloat-abi=hard" "-mfpu=neon -mfloat-abi=hard -march=armv7-a"} {
if { [check_no_compiler_messages_nocache arm_neon_ok object {
+ #include <arm_neon.h>
int dummy;
#ifndef __ARM_NEON__
#error not NEON
@@ -3487,6 +3526,38 @@ proc check_effective_target_arm_neon_ok { } {
check_effective_target_arm_neon_ok_nocache]
}
+# Return 1 if this is an ARM target supporting -mfpu=neon without any
+# -mfloat-abi= option. Useful in tests where add_options is not
+# supported (such as lto tests).
+
+proc check_effective_target_arm_neon_ok_no_float_abi_nocache { } {
+ if { [check_effective_target_arm32] } {
+ foreach flags {"-mfpu=neon"} {
+ if { [check_no_compiler_messages_nocache arm_neon_ok_no_float_abi object {
+ #include <arm_neon.h>
+ int dummy;
+ #ifndef __ARM_NEON__
+ #error not NEON
+ #endif
+ /* Avoid the case where a test adds -mfpu=neon, but the toolchain is
+ configured for -mcpu=arm926ej-s, for example. */
+ #if __ARM_ARCH < 7 || __ARM_ARCH_PROFILE == 'M'
+ #error Architecture does not support NEON.
+ #endif
+ } "$flags"] } {
+ return 1
+ }
+ }
+ }
+
+ return 0
+}
+
+proc check_effective_target_arm_neon_ok_no_float_abi { } {
+ return [check_cached_effective_target arm_neon_ok_no_float_abi \
+ check_effective_target_arm_neon_ok_no_float_abi_nocache]
+}
+
proc check_effective_target_arm_crc_ok_nocache { } {
global et_arm_crc_flags
set et_arm_crc_flags "-march=armv8-a+crc"
@@ -3830,7 +3901,8 @@ foreach { armfunc armflag armdefs } {
v8_2a "-march=armv8.2a" __ARM_ARCH_8A__
v8m_base "-march=armv8-m.base -mthumb -mfloat-abi=soft"
__ARM_ARCH_8M_BASE__
- v8m_main "-march=armv8-m.main -mthumb" __ARM_ARCH_8M_MAIN__ } {
+ v8m_main "-march=armv8-m.main -mthumb" __ARM_ARCH_8M_MAIN__
+ v8r "-march=armv8-r" __ARM_ARCH_8R__ } {
eval [string map [list FUNC $armfunc FLAG $armflag DEFS $armdefs ] {
proc check_effective_target_arm_arch_FUNC_ok { } {
if { [ string match "*-marm*" "FLAG" ] &&
@@ -4055,13 +4127,15 @@ proc check_effective_target_arm_v8_1a_neon_ok_nocache { } {
# since AArch64 only needs the -march setting.
foreach flags {"" "-mfpu=neon-fp-armv8" "-mfloat-abi=softfp" \
"-mfpu=neon-fp-armv8 -mfloat-abi=softfp"} {
- if { [check_no_compiler_messages_nocache arm_v8_1a_neon_ok object {
- #if !defined (__ARM_FEATURE_QRDMX)
- #error "__ARM_FEATURE_QRDMX not defined"
- #endif
- } "$flags -march=armv8.1-a"] } {
- set et_arm_v8_1a_neon_flags "$flags -march=armv8.1-a"
- return 1
+ foreach arches { "-march=armv8-a+rdma" "-march=armv8.1-a" } {
+ if { [check_no_compiler_messages_nocache arm_v8_1a_neon_ok object {
+ #if !defined (__ARM_FEATURE_QRDMX)
+ #error "__ARM_FEATURE_QRDMX not defined"
+ #endif
+ } "$flags $arches"] } {
+ set et_arm_v8_1a_neon_flags "$flags $arches"
+ return 1
+ }
}
}
@@ -4914,7 +4988,7 @@ proc check_effective_target_vect_shift { } {
|| [istarget ia64-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget aarch64*-*-*]
- || [check_effective_target_arm32]
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& ([et-is-effective-target mips_msa]
|| [et-is-effective-target mips_loongson])) } {
@@ -4932,7 +5006,7 @@ proc check_effective_target_whole_vector_shift { } {
|| [istarget ia64-*-*]
|| [istarget aarch64*-*-*]
|| [istarget powerpc64*-*-*]
- || ([check_effective_target_arm32]
+ || ([is-effective-target arm_neon]
&& [check_effective_target_arm_little_endian])
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_loongson]) } {
@@ -4956,8 +5030,7 @@ proc check_effective_target_vect_bswap { } {
} else {
set et_vect_bswap_saved($et_index) 0
if { [istarget aarch64*-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon])
+ || [is-effective-target arm_neon]
} {
set et_vect_bswap_saved($et_index) 1
}
@@ -4980,7 +5053,7 @@ proc check_effective_target_vect_shift_char { } {
set et_vect_shift_char_saved($et_index) 0
if { ([istarget powerpc*-*-*]
&& ![istarget powerpc-*-linux*paired*])
- || [check_effective_target_arm32]
+ || [is-effective-target arm_neon]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa]) } {
set et_vect_shift_char_saved($et_index) 1
@@ -4998,10 +5071,10 @@ proc check_effective_target_vect_shift_char { } {
proc check_effective_target_vect_long { } {
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || (([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
+ || (([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
&& [check_effective_target_ilp32])
- || [check_effective_target_arm32]
+ || [is-effective-target arm_neon]
|| ([istarget sparc*-*-*] && [check_effective_target_ilp32])
|| [istarget aarch64*-*-*]
|| ([istarget mips*-*-*]
@@ -5036,7 +5109,7 @@ proc check_effective_target_vect_float { } {
|| [istarget aarch64*-*-*]
|| ([istarget mips*-*-*]
&& [et-is-effective-target mips_msa])
- || [check_effective_target_arm32] } {
+ || [is-effective-target arm_neon] } {
set et_vect_float_saved($et_index) 1
}
}
@@ -5185,7 +5258,7 @@ proc check_effective_target_vect_perm { } {
verbose "check_effective_target_vect_perm: using cached result" 2
} else {
set et_vect_perm_saved($et_index) 0
- if { [is-effective-target arm_neon_ok]
+ if { [is-effective-target arm_neon]
|| [istarget aarch64*-*-*]
|| [istarget powerpc*-*-*]
|| [istarget spu-*-*]
@@ -5214,7 +5287,7 @@ proc check_effective_target_vect_perm_byte { } {
verbose "check_effective_target_vect_perm_byte: using cached result" 2
} else {
set et_vect_perm_byte_saved($et_index) 0
- if { ([is-effective-target arm_neon_ok]
+ if { ([is-effective-target arm_neon]
&& [is-effective-target arm_little_endian])
|| ([istarget aarch64*-*-*]
&& [is-effective-target aarch64_little_endian])
@@ -5243,7 +5316,7 @@ proc check_effective_target_vect_perm_short { } {
verbose "check_effective_target_vect_perm_short: using cached result" 2
} else {
set et_vect_perm_short_saved($et_index) 0
- if { ([is-effective-target arm_neon_ok]
+ if { ([is-effective-target arm_neon]
&& [is-effective-target arm_little_endian])
|| ([istarget aarch64*-*-*]
&& [is-effective-target aarch64_little_endian])
@@ -5275,8 +5348,7 @@ proc check_effective_target_vect_widen_sum_hi_to_si_pattern { } {
set et_vect_widen_sum_hi_to_si_pattern_saved($et_index) 0
if { [istarget powerpc*-*-*]
|| [istarget aarch64*-*-*]
- || ([istarget arm*-*-*] &&
- [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| [istarget ia64-*-*] } {
set et_vect_widen_sum_hi_to_si_pattern_saved($et_index) 1
}
@@ -5330,7 +5402,7 @@ proc check_effective_target_vect_widen_sum_qi_to_hi { } {
} else {
set et_vect_widen_sum_qi_to_hi_saved($et_index) 0
if { [check_effective_target_vect_unpack]
- || [check_effective_target_arm_neon_ok]
+ || [is-effective-target arm_neon]
|| [istarget ia64-*-*] } {
set et_vect_widen_sum_qi_to_hi_saved($et_index) 1
}
@@ -5388,7 +5460,7 @@ proc check_effective_target_vect_widen_mult_qi_to_hi { } {
}
if { [istarget powerpc*-*-*]
|| [istarget aarch64*-*-*]
- || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } {
+ || [is-effective-target arm_neon] } {
set et_vect_widen_mult_qi_to_hi_saved($et_index) 1
}
}
@@ -5425,8 +5497,7 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } {
|| [istarget ia64-*-*]
|| [istarget aarch64*-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]) } {
+ || [is-effective-target arm_neon] } {
set et_vect_widen_mult_hi_to_si_saved($et_index) 1
}
}
@@ -5450,8 +5521,7 @@ proc check_effective_target_vect_widen_mult_qi_to_hi_pattern { } {
} else {
set et_vect_widen_mult_qi_to_hi_pattern_saved($et_index) 0
if { [istarget powerpc*-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]
+ || ([is-effective-target arm_neon]
&& [check_effective_target_arm_little_endian]) } {
set et_vect_widen_mult_qi_to_hi_pattern_saved($et_index) 1
}
@@ -5479,8 +5549,7 @@ proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } {
|| [istarget spu-*-*]
|| [istarget ia64-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]
+ || ([is-effective-target arm_neon]
&& [check_effective_target_arm_little_endian]) } {
set et_vect_widen_mult_hi_to_si_pattern_saved($et_index) 1
}
@@ -5527,7 +5596,7 @@ proc check_effective_target_vect_widen_shift { } {
verbose "check_effective_target_vect_widen_shift: using cached result" 2
} else {
set et_vect_widen_shift_saved($et_index) 0
- if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } {
+ if { [is-effective-target arm_neon] } {
set et_vect_widen_shift_saved($et_index) 1
}
}
@@ -6081,7 +6150,7 @@ proc check_effective_target_vect_extract_even_odd { } {
set et_vect_extract_even_odd_saved($et_index) 0
if { [istarget aarch64*-*-*]
|| [istarget powerpc*-*-*]
- || [is-effective-target arm_neon_ok]
+ || [is-effective-target arm_neon]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget ia64-*-*]
|| [istarget spu-*-*]
@@ -6109,7 +6178,7 @@ proc check_effective_target_vect_interleave { } {
set et_vect_interleave_saved($et_index) 0
if { [istarget aarch64*-*-*]
|| [istarget powerpc*-*-*]
- || [is-effective-target arm_neon_ok]
+ || [is-effective-target arm_neon]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget ia64-*-*]
|| [istarget spu-*-*]
@@ -6163,7 +6232,7 @@ proc check_effective_target_vect_multiple_sizes { } {
set et_vect_multiple_sizes_saved($et_index) 0
if { [istarget aarch64*-*-*]
- || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok])
+ || [is-effective-target arm_neon]
|| (([istarget i?86-*-*] || [istarget x86_64-*-*])
&& ([check_avx_available] && ![check_prefer_avx128])) } {
set et_vect_multiple_sizes_saved($et_index) 1
@@ -6184,8 +6253,7 @@ proc check_effective_target_vect64 { } {
verbose "check_effective_target_vect64: using cached result" 2
} else {
set et_vect64_saved($et_index) 0
- if { ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]
+ if { ([is-effective-target arm_neon]
&& [check_effective_target_arm_little_endian])
|| [istarget aarch64*-*-*]
|| [istarget sparc*-*-*] } {
@@ -6922,6 +6990,7 @@ proc is-effective-target { arg } {
"ppc_float128_sw" { set selected [check_ppc_float128_sw_available] }
"ppc_float128_hw" { set selected [check_ppc_float128_hw_available] }
"ppc_recip_hw" { set selected [check_ppc_recip_hw_available] }
+ "ppc_cpu_supports_hw" { set selected [check_ppc_cpu_supports_hw_available] }
"dfp_hw" { set selected [check_dfp_hw_available] }
"htm_hw" { set selected [check_htm_hw_available] }
"named_sections" { set selected [check_named_sections_available] }
@@ -8209,7 +8278,7 @@ proc check_effective_target_builtin_eh_return { } {
# Return 1 if the target supports max reduction for vectors.
proc check_effective_target_vect_max_reduc { } {
- if { [istarget aarch64*-*-*] || [istarget arm*-*-*] } {
+ if { [istarget aarch64*-*-*] || [is-effective-target arm_neon] } {
return 1
}
return 0
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 9ceda8a3268..e2460585d62 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -68,6 +68,7 @@ DEFTIMEVAR (TV_PCH_CPP_RESTORE , "PCH preprocessor state restore")
DEFTIMEVAR (TV_CGRAPH , "callgraph construction")
DEFTIMEVAR (TV_CGRAPHOPT , "callgraph optimization")
+DEFTIMEVAR (TV_IPA_FNSUMMARY , "ipa function summary")
DEFTIMEVAR (TV_IPA_UNREACHABLE , "ipa dead code removal")
DEFTIMEVAR (TV_IPA_INHERITANCE , "ipa inheritance graph")
DEFTIMEVAR (TV_IPA_VIRTUAL_CALL , "ipa virtual call target")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index e6c69a4ba93..b28f1847c83 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1630,8 +1630,10 @@ process_options (void)
}
/* Do not use IPA optimizations for register allocation if profiler is active
+ or patchable function entries are inserted for run-time instrumentation
or port does not emit prologue and epilogue as RTL. */
- if (profile_flag || !targetm.have_prologue () || !targetm.have_epilogue ())
+ if (profile_flag || function_entry_patch_area_size
+ || !targetm.have_prologue () || !targetm.have_epilogue ())
flag_ipa_ra = 0;
/* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
diff --git a/gcc/tracer.c b/gcc/tracer.c
index 0b7f4da0d81..dd071c1650c 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -135,10 +135,8 @@ better_p (const_edge e1, const_edge e2)
if (e1->count.initialized_p () && e2->count.initialized_p ()
&& !(e1->count == e2->count))
return e1->count > e2->count;
- if (e1->src->frequency * e1->probability !=
- e2->src->frequency * e2->probability)
- return (e1->src->frequency * e1->probability
- > e2->src->frequency * e2->probability);
+ if (EDGE_FREQUENCY (e1) != EDGE_FREQUENCY (e2))
+ return EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2);
/* This is needed to avoid changes in the decision after
CFG is modified. */
if (e1->src != e2->src)
@@ -160,7 +158,8 @@ find_best_successor (basic_block bb)
best = e;
if (!best || ignore_bb_p (best->dest))
return NULL;
- if (best->probability <= probability_cutoff)
+ if (best->probability.initialized_p ()
+ && best->probability.to_reg_br_prob_base () <= probability_cutoff)
return NULL;
return best;
}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index f66abfc8835..eb03560be26 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -2934,9 +2934,9 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
join_bb->frequency = test_bb->frequency = transaction_bb->frequency;
join_bb->count = test_bb->count = transaction_bb->count;
- ei->probability = PROB_ALWAYS;
- et->probability = PROB_LIKELY;
- ef->probability = PROB_UNLIKELY;
+ ei->probability = profile_probability::always ();
+ et->probability = profile_probability::likely ();
+ ef->probability = profile_probability::unlikely ();
et->count = test_bb->count.apply_probability (et->probability);
ef->count = test_bb->count.apply_probability (ef->probability);
@@ -2967,20 +2967,20 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU);
test_bb->frequency = transaction_bb->frequency;
test_bb->count = transaction_bb->count;
- ei->probability = PROB_ALWAYS;
+ ei->probability = profile_probability::always ();
// Not abort edge. If both are live, chose one at random as we'll
// we'll be fixing that up below.
redirect_edge_pred (fallthru_edge, test_bb);
fallthru_edge->flags = EDGE_FALSE_VALUE;
- fallthru_edge->probability = PROB_VERY_LIKELY;
+ fallthru_edge->probability = profile_probability::very_likely ();
fallthru_edge->count = test_bb->count.apply_probability
(fallthru_edge->probability);
// Abort/over edge.
redirect_edge_pred (abort_edge, test_bb);
abort_edge->flags = EDGE_TRUE_VALUE;
- abort_edge->probability = PROB_VERY_UNLIKELY;
+ abort_edge->probability = profile_probability::unlikely ();
abort_edge->count = test_bb->count.apply_probability
(abort_edge->probability);
@@ -3020,13 +3020,13 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
// use the uninst path when falling back to serial mode.
redirect_edge_pred (inst_edge, test_bb);
inst_edge->flags = EDGE_FALSE_VALUE;
- inst_edge->probability = REG_BR_PROB_BASE / 2;
+ inst_edge->probability = profile_probability::even ();
inst_edge->count
= test_bb->count.apply_probability (inst_edge->probability);
redirect_edge_pred (uninst_edge, test_bb);
uninst_edge->flags = EDGE_TRUE_VALUE;
- uninst_edge->probability = REG_BR_PROB_BASE / 2;
+ uninst_edge->probability = profile_probability::even ();
uninst_edge->count
= test_bb->count.apply_probability (uninst_edge->probability);
}
@@ -3211,7 +3211,12 @@ split_bb_make_tm_edge (gimple *stmt, basic_block dest_bb,
edge e = split_block (bb, stmt);
*pnext = gsi_start_bb (e->dest);
}
- make_edge (bb, dest_bb, EDGE_ABNORMAL);
+ edge e = make_edge (bb, dest_bb, EDGE_ABNORMAL);
+ if (e)
+ {
+ e->probability = profile_probability::guessed_never ();
+ e->count = profile_count::guessed_zero ();
+ }
// Record the need for the edge for the benefit of the rtl passes.
if (cfun->gimple_df->tm_restart == NULL)
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 69d3207696d..862d1a6421d 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -752,10 +752,6 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
return;
}
-
-/* Probability of the branch (to the call) is taken. */
-#define ERR_PROB 0.01
-
/* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
conditions in CONDS is false. */
@@ -916,14 +912,15 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
basic_block src_bb = call_edge->src;
gcc_assert (src_bb == nocall_edge->src);
- call_edge->probability = REG_BR_PROB_BASE * ERR_PROB;
+ call_edge->probability = profile_probability::very_unlikely ();
call_edge->count
= src_bb->count.apply_probability (call_edge->probability);
- nocall_edge->probability = inverse_probability (call_edge->probability);
+ nocall_edge->probability = profile_probability::always ()
+ - call_edge->probability;
nocall_edge->count = src_bb->count - call_edge->count;
- unsigned int call_frequency = apply_probability (src_bb->frequency,
- call_edge->probability);
+ unsigned int call_frequency
+ = call_edge->probability.apply (src_bb->frequency);
bi_call_bb->count += call_edge->count;
bi_call_bb->frequency += call_frequency;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 589508df044..733c92fcdd0 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -1051,6 +1051,7 @@ gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi)
struct omp_region *cur_region = NULL;
profile_count cnt = profile_count::zero ();
int freq = 0;
+ bool all = true;
int cur_omp_region_idx = 0;
int mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx);
@@ -1061,12 +1062,16 @@ gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi)
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
{
- cnt += e->count;
+ if (e->count.initialized_p ())
+ cnt += e->count;
+ else
+ all = false;
freq += EDGE_FREQUENCY (e);
}
- bb->count = cnt;
- bb->frequency = freq;
tree_guess_outgoing_edge_probabilities (bb);
+ if (all || profile_status_for_fn (cfun) == PROFILE_READ)
+ bb->count = cnt;
+ bb->frequency = freq;
FOR_EACH_EDGE (e, ei, bb->succs)
e->count = bb->count.apply_probability (e->probability);
@@ -1675,17 +1680,17 @@ cleanup_dead_labels (void)
the ones jumping to the same label.
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
-void
+bool
group_case_labels_stmt (gswitch *stmt)
{
int old_size = gimple_switch_num_labels (stmt);
- int i, j, base_index, new_size = old_size;
+ int i, next_index, new_size;
basic_block default_bb = NULL;
default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label (stmt)));
/* Look for possible opportunities to merge cases. */
- i = 1;
+ new_size = i = 1;
while (i < old_size)
{
tree base_case, base_high;
@@ -1696,26 +1701,25 @@ group_case_labels_stmt (gswitch *stmt)
gcc_assert (base_case);
base_bb = label_to_block (CASE_LABEL (base_case));
- /* Discard cases that have the same destination as the default case. */
- if (base_bb == default_bb)
+ /* Discard cases that have the same destination as the default case or
+ whose destiniation blocks have already been removed as unreachable. */
+ if (base_bb == NULL || base_bb == default_bb)
{
- gimple_switch_set_label (stmt, i, NULL_TREE);
i++;
- new_size--;
continue;
}
base_high = CASE_HIGH (base_case)
? CASE_HIGH (base_case)
: CASE_LOW (base_case);
- base_index = i++;
+ next_index = i + 1;
/* Try to merge case labels. Break out when we reach the end
of the label vector or when we cannot merge the next case
label with the current one. */
- while (i < old_size)
+ while (next_index < old_size)
{
- tree merge_case = gimple_switch_label (stmt, i);
+ tree merge_case = gimple_switch_label (stmt, next_index);
basic_block merge_bb = label_to_block (CASE_LABEL (merge_case));
wide_int bhp1 = wi::add (base_high, 1);
@@ -1727,9 +1731,7 @@ group_case_labels_stmt (gswitch *stmt)
base_high = CASE_HIGH (merge_case) ?
CASE_HIGH (merge_case) : CASE_LOW (merge_case);
CASE_HIGH (base_case) = base_high;
- gimple_switch_set_label (stmt, i, NULL_TREE);
- new_size--;
- i++;
+ next_index++;
}
else
break;
@@ -1742,40 +1744,43 @@ group_case_labels_stmt (gswitch *stmt)
edge base_edge = find_edge (gimple_bb (stmt), base_bb);
if (base_edge != NULL)
remove_edge_and_dominated_blocks (base_edge);
- gimple_switch_set_label (stmt, base_index, NULL_TREE);
- new_size--;
+ i = next_index;
+ continue;
}
- }
- /* Compress the case labels in the label vector, and adjust the
- length of the vector. */
- for (i = 0, j = 0; i < new_size; i++)
- {
- while (! gimple_switch_label (stmt, j))
- j++;
- gimple_switch_set_label (stmt, i,
- gimple_switch_label (stmt, j++));
+ if (new_size < i)
+ gimple_switch_set_label (stmt, new_size,
+ gimple_switch_label (stmt, i));
+ i = next_index;
+ new_size++;
}
gcc_assert (new_size <= old_size);
- gimple_switch_set_num_labels (stmt, new_size);
+
+ if (new_size < old_size)
+ gimple_switch_set_num_labels (stmt, new_size);
+
+ return new_size < old_size;
}
/* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH),
and scan the sorted vector of cases. Combine the ones jumping to the
same label. */
-void
+bool
group_case_labels (void)
{
basic_block bb;
+ bool changed = false;
FOR_EACH_BB_FN (bb, cfun)
{
gimple *stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- group_case_labels_stmt (as_a <gswitch *> (stmt));
+ changed |= group_case_labels_stmt (as_a <gswitch *> (stmt));
}
+
+ return changed;
}
/* Checks whether we can merge block B into block A. */
@@ -2077,7 +2082,7 @@ gimple_merge_blocks (basic_block a, basic_block b)
profiles. */
if (a->loop_father == b->loop_father)
{
- a->count = MAX (a->count, b->count);
+ a->count = a->count.merge (b->count);
a->frequency = MAX (a->frequency, b->frequency);
}
@@ -2243,15 +2248,8 @@ find_taken_edge (basic_block bb, tree val)
stmt = last_stmt (bb);
- gcc_assert (stmt);
gcc_assert (is_ctrl_stmt (stmt));
- if (val == NULL)
- return NULL;
-
- if (!is_gimple_min_invariant (val))
- return NULL;
-
if (gimple_code (stmt) == GIMPLE_COND)
return find_taken_edge_cond_expr (bb, val);
@@ -2266,7 +2264,8 @@ find_taken_edge (basic_block bb, tree val)
It may be the case that we only need to allow the LABEL_REF to
appear inside an ADDR_EXPR, but we also allow the LABEL_REF to
appear inside a LABEL_EXPR just to be safe. */
- if ((TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
+ if (val
+ && (TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
&& TREE_CODE (TREE_OPERAND (val, 0)) == LABEL_DECL)
return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0));
return NULL;
@@ -2304,9 +2303,12 @@ find_taken_edge_cond_expr (basic_block bb, tree val)
{
edge true_edge, false_edge;
+ if (val == NULL
+ || TREE_CODE (val) != INTEGER_CST)
+ return NULL;
+
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
- gcc_assert (TREE_CODE (val) == INTEGER_CST);
return (integer_zerop (val) ? false_edge : true_edge);
}
@@ -2322,7 +2324,12 @@ find_taken_edge_switch_expr (gswitch *switch_stmt, basic_block bb,
edge e;
tree taken_case;
- taken_case = find_case_label_for_value (switch_stmt, val);
+ if (gimple_switch_num_labels (switch_stmt) == 1)
+ taken_case = gimple_switch_default_label (switch_stmt);
+ else if (! val || TREE_CODE (val) != INTEGER_CST)
+ return NULL;
+ else
+ taken_case = find_case_label_for_value (switch_stmt, val);
dest_bb = label_to_block (CASE_LABEL (taken_case));
e = find_edge (bb, dest_bb);
@@ -2837,9 +2844,7 @@ gimple_split_edge (edge edge_in)
new_bb = create_empty_bb (after_bb);
new_bb->frequency = EDGE_FREQUENCY (edge_in);
new_bb->count = edge_in->count;
- new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
- new_edge->probability = REG_BR_PROB_BASE;
- new_edge->count = edge_in->count;
+ new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU);
e = redirect_edge_and_branch (edge_in, new_bb);
gcc_assert (e == edge_in);
@@ -3049,7 +3054,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
tree t1 = TREE_OPERAND (t, 1);
tree t2 = TREE_OPERAND (t, 2);
if (!tree_fits_uhwi_p (t1)
- || !tree_fits_uhwi_p (t2))
+ || !tree_fits_uhwi_p (t2)
+ || !types_compatible_p (bitsizetype, TREE_TYPE (t1))
+ || !types_compatible_p (bitsizetype, TREE_TYPE (t2)))
{
error ("invalid position or size operand to BIT_FIELD_REF");
return t;
@@ -3493,8 +3500,6 @@ verify_gimple_call (gcall *stmt)
&& !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (fntype))
/* ??? At least C++ misses conversions at assignments from
void * call results.
- ??? Java is completely off. Especially with functions
- returning java.lang.Object.
For now simply allow arbitrary pointer type conversions. */
&& !(POINTER_TYPE_P (TREE_TYPE (lhs))
&& POINTER_TYPE_P (TREE_TYPE (fntype))))
@@ -4245,6 +4250,7 @@ verify_gimple_assign_ternary (gassign *stmt)
return true;
}
if (! tree_fits_uhwi_p (rhs3)
+ || ! types_compatible_p (bitsizetype, TREE_TYPE (rhs3))
|| ! tree_fits_uhwi_p (TYPE_SIZE (rhs2_type)))
{
error ("invalid position or size in BIT_INSERT_EXPR");
@@ -6391,9 +6397,9 @@ bb_part_of_region_p (basic_block bb, basic_block* bbs, unsigned n_region)
*/
bool
-gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNUSED,
- basic_block *region ATTRIBUTE_UNUSED, unsigned n_region ATTRIBUTE_UNUSED,
- basic_block *region_copy ATTRIBUTE_UNUSED)
+gimple_duplicate_sese_tail (edge entry, edge exit,
+ basic_block *region, unsigned n_region,
+ basic_block *region_copy)
{
unsigned i;
bool free_region_copy = false;
@@ -6503,7 +6509,12 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
sorig = single_succ_edge (switch_bb);
sorig->flags = exits[1]->flags;
+ sorig->probability = exits[1]->probability;
+ sorig->count = exits[1]->count;
snew = make_edge (switch_bb, nentry_bb, exits[0]->flags);
+ snew->probability = exits[0]->probability;
+ snew->count = exits[1]->count;
+
/* Register the new edge from SWITCH_BB in loop exit lists. */
rescan_loop_exit (snew, true, false);
@@ -7244,7 +7255,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
basic_block after, bb, *entry_pred, *exit_succ, abb;
struct function *saved_cfun = cfun;
int *entry_flag, *exit_flag;
- unsigned *entry_prob, *exit_prob;
+ profile_probability *entry_prob, *exit_prob;
unsigned i, num_entry_edges, num_exit_edges, num_nodes;
edge e;
edge_iterator ei;
@@ -7282,7 +7293,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
num_entry_edges = EDGE_COUNT (entry_bb->preds);
entry_pred = XNEWVEC (basic_block, num_entry_edges);
entry_flag = XNEWVEC (int, num_entry_edges);
- entry_prob = XNEWVEC (unsigned, num_entry_edges);
+ entry_prob = XNEWVEC (profile_probability, num_entry_edges);
i = 0;
for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;)
{
@@ -7297,7 +7308,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
num_exit_edges = EDGE_COUNT (exit_bb->succs);
exit_succ = XNEWVEC (basic_block, num_exit_edges);
exit_flag = XNEWVEC (int, num_exit_edges);
- exit_prob = XNEWVEC (unsigned, num_exit_edges);
+ exit_prob = XNEWVEC (profile_probability, num_exit_edges);
i = 0;
for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
{
@@ -8212,7 +8223,9 @@ gimple_flow_call_edges_add (sbitmap blocks)
if (e)
blocks_split++;
}
- make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ e->probability = profile_probability::guessed_never ();
+ e->count = profile_count::guessed_zero ();
}
gsi_prev (&gsi);
}
@@ -8221,7 +8234,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
}
if (blocks_split)
- verify_flow_info ();
+ checking_verify_flow_info ();
return blocks_split;
}
@@ -8703,9 +8716,11 @@ make_pass_split_crit_edges (gcc::context *ctxt)
/* Insert COND expression which is GIMPLE_COND after STMT
in basic block BB with appropriate basic block split
and creation of a new conditionally executed basic block.
+ Update profile so the new bb is visited with probability PROB.
Return created basic block. */
basic_block
-insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond)
+insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond,
+ profile_probability prob)
{
edge fall = split_block (bb, stmt);
gimple_stmt_iterator iter = gsi_last_bb (bb);
@@ -8720,11 +8735,17 @@ insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond)
/* Create conditionally executed block. */
new_bb = create_empty_bb (bb);
- make_edge (bb, new_bb, EDGE_TRUE_VALUE);
+ edge e = make_edge (bb, new_bb, EDGE_TRUE_VALUE);
+ e->probability = prob;
+ e->count = bb->count.apply_probability (prob);
+ new_bb->count = e->count;
+ new_bb->frequency = prob.apply (bb->frequency);
make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU);
/* Fix edge for split bb. */
fall->flags = EDGE_FALSE_VALUE;
+ fall->count -= e->count;
+ fall->probability -= e->probability;
/* Update dominance info. */
if (dom_info_available_p (CDI_DOMINATORS))
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index a0ef479ef20..66be43657bc 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -36,8 +36,8 @@ 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 void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gswitch *);
-extern void group_case_labels (void);
+extern bool group_case_labels_stmt (gswitch *);
+extern bool group_case_labels (void);
extern void replace_uses_by (tree, tree);
extern basic_block single_noncomplex_succ (basic_block bb);
extern void notice_special_calls (gcall *);
@@ -104,7 +104,8 @@ extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code,
extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
extern unsigned int execute_fixup_cfg (void);
extern unsigned int split_critical_edges (void);
-extern basic_block insert_cond_bb (basic_block, gimple *, gimple *);
+extern basic_block insert_cond_bb (basic_block, gimple *, gimple *,
+ profile_probability);
extern bool gimple_find_sub_bbs (gimple_seq, gimple_stmt_iterator *);
extern bool extract_true_false_controlled_edges (basic_block, basic_block,
edge *, edge *);
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 8bb5e237395..c6e5c8da03c 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -155,8 +155,6 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi,
}
if (!warned)
fold_undefer_and_ignore_overflow_warnings ();
- if (taken_edge->probability > REG_BR_PROB_BASE)
- taken_edge->probability = REG_BR_PROB_BASE;
}
else
taken_edge = single_succ_edge (bb);
@@ -638,6 +636,19 @@ fixup_noreturn_call (gimple *stmt)
return changed;
}
+/* Return true if we want to merge BB1 and BB2 into a single block. */
+
+static bool
+want_merge_blocks_p (basic_block bb1, basic_block bb2)
+{
+ if (!can_merge_blocks_p (bb1, bb2))
+ return false;
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb1);
+ if (gsi_end_p (gsi) || !stmt_can_terminate_bb_p (gsi_stmt (gsi)))
+ return true;
+ return bb1->count.ok_for_merging (bb2->count);
+}
+
/* Tries to cleanup cfg in basic block BB. Returns true if anything
changes. */
@@ -654,7 +665,7 @@ cleanup_tree_cfg_bb (basic_block bb)
This happens when we visit BBs in a non-optimal order and
avoids quadratic behavior with adjusting stmts BB pointer. */
if (single_pred_p (bb)
- && can_merge_blocks_p (single_pred (bb), bb))
+ && want_merge_blocks_p (single_pred (bb), bb))
/* But make sure we _do_ visit it. When we remove unreachable paths
ending in a backedge we fail to mark the destinations predecessors
as changed. */
@@ -664,7 +675,7 @@ cleanup_tree_cfg_bb (basic_block bb)
conditional branches (due to the elimination of single-valued PHI
nodes). */
else if (single_succ_p (bb)
- && can_merge_blocks_p (bb, single_succ (bb)))
+ && want_merge_blocks_p (bb, single_succ (bb)))
{
merge_blocks (bb, single_succ (bb));
return true;
@@ -1205,7 +1216,8 @@ execute_cleanup_cfg_post_optimizing (void)
}
maybe_remove_unreachable_handlers ();
cleanup_dead_labels ();
- group_case_labels ();
+ if (group_case_labels ())
+ todo |= TODO_cleanup_cfg;
if ((flag_compare_debug_opt || flag_compare_debug)
&& flag_dump_final_insns)
{
diff --git a/gcc/tree-chkp-opt.c b/gcc/tree-chkp-opt.c
index a08f0819435..33f2a1bfcf5 100644
--- a/gcc/tree-chkp-opt.c
+++ b/gcc/tree-chkp-opt.c
@@ -1052,7 +1052,8 @@ chkp_optimize_string_function_calls (void)
/* Split block before string function call. */
gsi_prev (&i);
- check_bb = insert_cond_bb (bb, gsi_stmt (i), check);
+ check_bb = insert_cond_bb (bb, gsi_stmt (i), check,
+ profile_probability::likely ());
/* Set position for checks. */
j = gsi_last_bb (check_bb);
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index e0dd3d9922b..d61047bbf5f 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -1186,13 +1186,22 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type,
bb_join = e->dest;
bb_true = create_empty_bb (bb_cond);
bb_false = create_empty_bb (bb_true);
+ bb_true->frequency = bb_false->frequency = bb_cond->frequency / 2;
+ bb_true->count = bb_false->count
+ = bb_cond->count.apply_probability (profile_probability::even ());
/* Wire the blocks together. */
e->flags = EDGE_TRUE_VALUE;
+ e->count = bb_true->count;
+ /* TODO: With value profile we could add an historgram to determine real
+ branch outcome. */
+ e->probability = profile_probability::even ();
redirect_edge_succ (e, bb_true);
- make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE);
- make_edge (bb_true, bb_join, EDGE_FALLTHRU);
- make_edge (bb_false, bb_join, EDGE_FALLTHRU);
+ edge e2 = make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE);
+ e2->count = bb_false->count;
+ e2->probability = profile_probability::even ();
+ make_single_succ_edge (bb_true, bb_join, EDGE_FALLTHRU);
+ make_single_succ_edge (bb_false, bb_join, EDGE_FALLTHRU);
add_bb_to_loop (bb_true, bb_cond->loop_father);
add_bb_to_loop (bb_false, bb_cond->loop_father);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 34e5c17ab22..278d0c9b8f8 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -627,6 +627,10 @@ enum tree_index {
TI_BOOLEAN_TYPE,
TI_FILEPTR_TYPE,
TI_CONST_TM_PTR_TYPE,
+ TI_FENV_T_PTR_TYPE,
+ TI_CONST_FENV_T_PTR_TYPE,
+ TI_FEXCEPT_T_PTR_TYPE,
+ TI_CONST_FEXCEPT_T_PTR_TYPE,
TI_POINTER_SIZED_TYPE,
TI_POINTER_BOUNDS_TYPE,
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index ba473021534..b7f9a570abb 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "tree-affine.h"
#include "params.h"
+#include "builtins.h"
static struct datadep_stats
{
@@ -749,16 +750,30 @@ canonicalize_base_object_address (tree addr)
return build_fold_addr_expr (TREE_OPERAND (addr, 0));
}
-/* Analyzes the behavior of the memory reference DR in the innermost loop or
- basic block that contains it. Returns true if analysis succeed or false
- otherwise. */
+/* Analyze the behavior of memory reference REF. There are two modes:
+
+ - BB analysis. In this case we simply split the address into base,
+ init and offset components, without reference to any containing loop.
+ The resulting base and offset are general expressions and they can
+ vary arbitrarily from one iteration of the containing loop to the next.
+ The step is always zero.
+
+ - loop analysis. In this case we analyze the reference both wrt LOOP
+ and on the basis that the reference occurs (is "used") in LOOP;
+ see the comment above analyze_scalar_evolution_in_loop for more
+ information about this distinction. The base, init, offset and
+ step fields are all invariant in LOOP.
+
+ Perform BB analysis if LOOP is null, or if LOOP is the function's
+ dummy outermost loop. In other cases perform loop analysis.
+
+ Return true if the analysis succeeded and store the results in DRB if so.
+ BB analysis can only fail for bitfield or reversed-storage accesses. */
bool
-dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
+dr_analyze_innermost (innermost_loop_behavior *drb, tree ref,
+ struct loop *loop)
{
- gimple *stmt = DR_STMT (dr);
- struct loop *loop = loop_containing_stmt (stmt);
- tree ref = DR_REF (dr);
HOST_WIDE_INT pbitsize, pbitpos;
tree base, poffset;
machine_mode pmode;
@@ -788,11 +803,26 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
return false;
}
+ /* Calculate the alignment and misalignment for the inner reference. */
+ unsigned int HOST_WIDE_INT base_misalignment;
+ unsigned int base_alignment;
+ get_object_alignment_1 (base, &base_alignment, &base_misalignment);
+
+ /* There are no bitfield references remaining in BASE, so the values
+ we got back must be whole bytes. */
+ gcc_assert (base_alignment % BITS_PER_UNIT == 0
+ && base_misalignment % BITS_PER_UNIT == 0);
+ base_alignment /= BITS_PER_UNIT;
+ base_misalignment /= BITS_PER_UNIT;
+
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
{
+ /* Subtract MOFF from the base and add it to POFFSET instead.
+ Adjust the misalignment to reflect the amount we subtracted. */
offset_int moff = mem_ref_offset (base);
+ base_misalignment -= moff.to_short_addr ();
tree mofft = wide_int_to_tree (sizetype, moff);
if (!poffset)
poffset = mofft;
@@ -806,22 +836,11 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
if (in_loop)
{
- if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv,
- nest ? true : false))
+ if (!simple_iv (loop, loop, base, &base_iv, true))
{
- if (nest)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "failed: evolution of base is not"
- " affine.\n");
- return false;
- }
- else
- {
- base_iv.base = base;
- base_iv.step = ssize_int (0);
- base_iv.no_overflow = true;
- }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "failed: evolution of base is not affine.\n");
+ return false;
}
}
else
@@ -843,42 +862,57 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
offset_iv.base = poffset;
offset_iv.step = ssize_int (0);
}
- else if (!simple_iv (loop, loop_containing_stmt (stmt),
- poffset, &offset_iv,
- nest ? true : false))
+ else if (!simple_iv (loop, loop, poffset, &offset_iv, true))
{
- if (nest)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "failed: evolution of offset is not"
- " affine.\n");
- return false;
- }
- else
- {
- offset_iv.base = poffset;
- offset_iv.step = ssize_int (0);
- }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "failed: evolution of offset is not affine.\n");
+ return false;
}
}
init = ssize_int (pbitpos / BITS_PER_UNIT);
+
+ /* Subtract any constant component from the base and add it to INIT instead.
+ Adjust the misalignment to reflect the amount we subtracted. */
split_constant_offset (base_iv.base, &base_iv.base, &dinit);
- init = size_binop (PLUS_EXPR, init, dinit);
+ init = size_binop (PLUS_EXPR, init, dinit);
+ base_misalignment -= TREE_INT_CST_LOW (dinit);
+
split_constant_offset (offset_iv.base, &offset_iv.base, &dinit);
- init = size_binop (PLUS_EXPR, init, dinit);
+ init = size_binop (PLUS_EXPR, init, dinit);
step = size_binop (PLUS_EXPR,
fold_convert (ssizetype, base_iv.step),
fold_convert (ssizetype, offset_iv.step));
- DR_BASE_ADDRESS (dr) = canonicalize_base_object_address (base_iv.base);
+ base = canonicalize_base_object_address (base_iv.base);
+
+ /* See if get_pointer_alignment can guarantee a higher alignment than
+ the one we calculated above. */
+ unsigned int HOST_WIDE_INT alt_misalignment;
+ unsigned int alt_alignment;
+ get_pointer_alignment_1 (base, &alt_alignment, &alt_misalignment);
- DR_OFFSET (dr) = fold_convert (ssizetype, offset_iv.base);
- DR_INIT (dr) = init;
- DR_STEP (dr) = step;
+ /* As above, these values must be whole bytes. */
+ gcc_assert (alt_alignment % BITS_PER_UNIT == 0
+ && alt_misalignment % BITS_PER_UNIT == 0);
+ alt_alignment /= BITS_PER_UNIT;
+ alt_misalignment /= BITS_PER_UNIT;
+
+ if (base_alignment < alt_alignment)
+ {
+ base_alignment = alt_alignment;
+ base_misalignment = alt_misalignment;
+ }
- DR_ALIGNED_TO (dr) = size_int (highest_pow2_factor (offset_iv.base));
+ drb->base_address = base;
+ drb->offset = fold_convert (ssizetype, offset_iv.base);
+ drb->init = init;
+ drb->step = step;
+ drb->base_alignment = base_alignment;
+ drb->base_misalignment = base_misalignment & (base_alignment - 1);
+ drb->offset_alignment = highest_pow2_factor (offset_iv.base);
+ drb->step_alignment = highest_pow2_factor (step);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "success.\n");
@@ -1077,7 +1111,8 @@ create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt,
DR_REF (dr) = memref;
DR_IS_READ (dr) = is_read;
- dr_analyze_innermost (dr, nest);
+ dr_analyze_innermost (&DR_INNERMOST (dr), memref,
+ nest != NULL ? loop : NULL);
dr_analyze_indices (dr, nest, loop);
dr_analyze_alias (dr);
@@ -1092,8 +1127,12 @@ create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt,
print_generic_expr (dump_file, DR_INIT (dr), TDF_SLIM);
fprintf (dump_file, "\n\tstep: ");
print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);
- fprintf (dump_file, "\n\taligned to: ");
- print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM);
+ fprintf (dump_file, "\n\tbase alignment: %d", DR_BASE_ALIGNMENT (dr));
+ fprintf (dump_file, "\n\tbase misalignment: %d",
+ DR_BASE_MISALIGNMENT (dr));
+ fprintf (dump_file, "\n\toffset alignment: %d",
+ DR_OFFSET_ALIGNMENT (dr));
+ fprintf (dump_file, "\n\tstep alignment: %d", DR_STEP_ALIGNMENT (dr));
fprintf (dump_file, "\n\tbase_object: ");
print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
fprintf (dump_file, "\n");
@@ -4731,6 +4770,30 @@ find_data_references_in_loop (struct loop *loop,
return NULL_TREE;
}
+/* Return the alignment in bytes that DRB is guaranteed to have at all
+ times. */
+
+unsigned int
+dr_alignment (innermost_loop_behavior *drb)
+{
+ /* Get the alignment of BASE_ADDRESS + INIT. */
+ unsigned int alignment = drb->base_alignment;
+ unsigned int misalignment = (drb->base_misalignment
+ + TREE_INT_CST_LOW (drb->init));
+ if (misalignment != 0)
+ alignment = MIN (alignment, misalignment & -misalignment);
+
+ /* Cap it to the alignment of OFFSET. */
+ if (!integer_zerop (drb->offset))
+ alignment = MIN (alignment, drb->offset_alignment);
+
+ /* Cap it to the alignment of STEP. */
+ if (!integer_zerop (drb->step))
+ alignment = MIN (alignment, drb->step_alignment);
+
+ return alignment;
+}
+
/* Recursive helper function. */
static bool
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 0013049053f..1559cd90bd2 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -52,9 +52,49 @@ struct innermost_loop_behavior
tree init;
tree step;
- /* Alignment information. ALIGNED_TO is set to the largest power of two
- that divides OFFSET. */
- tree aligned_to;
+ /* BASE_ADDRESS is known to be misaligned by BASE_MISALIGNMENT bytes
+ from an alignment boundary of BASE_ALIGNMENT bytes. For example,
+ if we had:
+
+ struct S __attribute__((aligned(16))) { ... };
+
+ char *ptr;
+ ... *(struct S *) (ptr - 4) ...;
+
+ the information would be:
+
+ base_address: ptr
+ base_aligment: 16
+ base_misalignment: 4
+ init: -4
+
+ where init cancels the base misalignment. If instead we had a
+ reference to a particular field:
+
+ struct S __attribute__((aligned(16))) { ... int f; ... };
+
+ char *ptr;
+ ... ((struct S *) (ptr - 4))->f ...;
+
+ the information would be:
+
+ base_address: ptr
+ base_aligment: 16
+ base_misalignment: 4
+ init: -4 + offsetof (S, f)
+
+ where base_address + init might also be misaligned, and by a different
+ amount from base_address. */
+ unsigned int base_alignment;
+ unsigned int base_misalignment;
+
+ /* The largest power of two that divides OFFSET, capped to a suitably
+ high value if the offset is zero. This is a byte rather than a bit
+ quantity. */
+ unsigned int offset_alignment;
+
+ /* Likewise for STEP. */
+ unsigned int step_alignment;
};
/* Describes the evolutions of indices of the memory reference. The indices
@@ -143,7 +183,10 @@ struct data_reference
#define DR_INIT(DR) (DR)->innermost.init
#define DR_STEP(DR) (DR)->innermost.step
#define DR_PTR_INFO(DR) (DR)->alias.ptr_info
-#define DR_ALIGNED_TO(DR) (DR)->innermost.aligned_to
+#define DR_BASE_ALIGNMENT(DR) (DR)->innermost.base_alignment
+#define DR_BASE_MISALIGNMENT(DR) (DR)->innermost.base_misalignment
+#define DR_OFFSET_ALIGNMENT(DR) (DR)->innermost.offset_alignment
+#define DR_STEP_ALIGNMENT(DR) (DR)->innermost.step_alignment
#define DR_INNERMOST(DR) (DR)->innermost
typedef struct data_reference *data_reference_p;
@@ -322,7 +365,7 @@ typedef struct data_dependence_relation *ddr_p;
#define DDR_REVERSED_P(DDR) (DDR)->reversed_p
-bool dr_analyze_innermost (struct data_reference *, struct loop *);
+bool dr_analyze_innermost (innermost_loop_behavior *, tree, struct loop *);
extern bool compute_data_dependences_for_loop (struct loop *, bool,
vec<loop_p> *,
vec<data_reference_p> *,
@@ -362,6 +405,16 @@ extern bool compute_all_dependences (vec<data_reference_p> ,
vec<loop_p>, bool);
extern tree find_data_references_in_bb (struct loop *, basic_block,
vec<data_reference_p> *);
+extern unsigned int dr_alignment (innermost_loop_behavior *);
+
+/* Return the alignment in bytes that DR is guaranteed to have at all
+ times. */
+
+inline unsigned int
+dr_alignment (data_reference *dr)
+{
+ return dr_alignment (&DR_INNERMOST (dr));
+}
extern bool dr_may_alias_p (const struct data_reference *,
const struct data_reference *, bool);
diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c
index 347b33ab505..da36031da30 100644
--- a/gcc/tree-dump.c
+++ b/gcc/tree-dump.c
@@ -26,7 +26,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dump.h"
#include "langhooks.h"
#include "tree-iterator.h"
-#include "tree-cfg.h"
static unsigned int queue (dump_info_p, const_tree, int);
static void dump_index (dump_info_p, unsigned int);
@@ -491,7 +490,6 @@ dequeue_and_dump (dump_info_p di)
dump_string_field (di, "tag", "union");
dump_child ("flds", TYPE_FIELDS (t));
- dump_child ("fncs", TYPE_METHODS (t));
queue_and_dump_index (di, "binf", TYPE_BINFO (t),
DUMP_BINFO);
break;
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index fc016d795b7..c68d71a5e54 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "cfgloop.h"
#include "gimple-low.h"
+#include "asan.h"
/* In some instances a tree and a gimple need to be stored in a same table,
i.e. in hash tables. This is a structure to do this. */
@@ -1563,12 +1564,6 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
/* Decide whether or not we are going to duplicate the finally block.
There are several considerations.
- First, if this is Java, then the finally block contains code
- written by the user. It has line numbers associated with it,
- so duplicating the block means it's difficult to set a breakpoint.
- Since controlling code generation via -g is verboten, we simply
- never duplicate code without optimization.
-
Second, we'd like to prevent egregious code growth. One way to
do this is to estimate the size of the finally block, multiply
that by the number of copies we'd need to make, and compare against
@@ -3244,9 +3239,7 @@ lower_resx (basic_block bb, gresx *stmt,
}
gcc_assert (EDGE_COUNT (bb->succs) == 0);
- e = make_edge (bb, new_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ e = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
}
else
{
@@ -3262,7 +3255,7 @@ lower_resx (basic_block bb, gresx *stmt,
e = single_succ_edge (bb);
gcc_assert (e->flags & EDGE_EH);
e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
/* If there are no more EH users of the landing pad, delete it. */
@@ -3287,7 +3280,7 @@ lower_resx (basic_block bb, gresx *stmt,
_Unwind_Resume library function. */
/* The ARM EABI redefines _Unwind_Resume as __cxa_end_cleanup
- with no arguments for C++ and Java. Check for that. */
+ with no arguments for C++. Check for that. */
if (src_r->use_cxa_end_cleanup)
{
fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP);
@@ -3304,6 +3297,18 @@ lower_resx (basic_block bb, gresx *stmt,
gimple_call_set_lhs (x, var);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
+ /* When exception handling is delegated to a caller function, we
+ have to guarantee that shadow memory variables living on stack
+ will be cleaner before control is given to a parent function. */
+ if (sanitize_flags_p (SANITIZE_ADDRESS))
+ {
+ tree decl
+ = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
+ gimple *g = gimple_build_call (decl, 0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+
fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
x = gimple_build_call (fn, 1, var);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
@@ -4283,7 +4288,7 @@ cleanup_empty_eh_move_lp (basic_block bb, edge e_out,
/* Clean up E_OUT for the fallthru. */
e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU;
- e_out->probability = REG_BR_PROB_BASE;
+ e_out->probability = profile_probability::always ();
e_out->count = e_out->src->count;
}
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index eb637952e22..d78731f1678 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -1441,11 +1441,8 @@ if_convertible_loop_p_1 (struct loop *loop, vec<data_reference_p> *refs)
|| TREE_CODE (ref) == REALPART_EXPR)
ref = TREE_OPERAND (ref, 0);
- DR_BASE_ADDRESS (dr) = ref;
- DR_OFFSET (dr) = NULL;
- DR_INIT (dr) = NULL;
- DR_STEP (dr) = NULL;
- DR_ALIGNED_TO (dr) = NULL;
+ memset (&DR_INNERMOST (dr), 0, sizeof (DR_INNERMOST (dr)));
+ DR_BASE_ADDRESS (dr) = ref;
}
hash_memrefs_baserefs_and_store_DRs_read_written_info (dr);
}
@@ -1853,8 +1850,11 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi)
new_stmt = gimple_build_assign (res, rhs);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
gimple_stmt_iterator new_gsi = gsi_for_stmt (new_stmt);
- fold_stmt (&new_gsi, ifcvt_follow_ssa_use_edges);
- update_stmt (new_stmt);
+ if (fold_stmt (&new_gsi, ifcvt_follow_ssa_use_edges))
+ {
+ new_stmt = gsi_stmt (new_gsi);
+ update_stmt (new_stmt);
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2400,7 +2400,7 @@ combine_blocks (struct loop *loop)
if (exit_bb != loop->header)
{
/* Connect this node to loop header. */
- make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
+ make_single_succ_edge (loop->header, exit_bb, EDGE_FALLTHRU);
set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
}
@@ -2564,8 +2564,10 @@ version_loop_for_if_conversion (struct loop *loop)
/* At this point we invalidate porfile confistency until IFN_LOOP_VECTORIZED
is re-merged in the vectorizer. */
new_loop = loop_version (loop, cond, &cond_bb,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE, true);
+ profile_probability::always (),
+ profile_probability::always (),
+ profile_probability::always (),
+ profile_probability::always (), true);
free_original_copy_tables ();
for (unsigned i = 0; i < save_length; i++)
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index aea8a79da14..d4e4ef17247 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2291,10 +2291,44 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
}
}
+ bool update_probs = false;
+
if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH)
- make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
+ {
+ make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
+ update_probs = true;
+ }
else if (can_throw)
- make_eh_edges (copy_stmt);
+ {
+ make_eh_edges (copy_stmt);
+ update_probs = true;
+ }
+
+ /* EH edges may not match old edges. Copy as much as possible. */
+ if (update_probs)
+ {
+ edge e;
+ edge_iterator ei;
+ basic_block copy_stmt_bb = gimple_bb (copy_stmt);
+
+ FOR_EACH_EDGE (old_edge, ei, bb->succs)
+ if ((old_edge->flags & EDGE_EH)
+ && (e = find_edge (copy_stmt_bb,
+ (basic_block) old_edge->dest->aux))
+ && (e->flags & EDGE_EH))
+ {
+ e->probability = old_edge->probability;
+ e->count = old_edge->count;
+ }
+
+ FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
+ if ((e->flags & EDGE_EH) && !e->probability.initialized_p ())
+ {
+ e->probability = profile_probability::never ();
+ e->count = profile_count::zero ();
+ }
+ }
+
/* If the call we inline cannot make abnormal goto do not add
additional abnormal edges but only retain those already present
@@ -2317,7 +2351,8 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
&& gimple_call_arg (copy_stmt, 0) == boolean_true_node)
nonlocal_goto = false;
else
- make_edge (copy_stmt_bb, abnormal_goto_dest, EDGE_ABNORMAL);
+ make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest,
+ EDGE_ABNORMAL);
}
if ((can_throw || nonlocal_goto)
@@ -2789,7 +2824,7 @@ copy_cfg_body (copy_body_data * id, profile_count count, int frequency_scale,
if (new_entry)
{
edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = incoming_count;
}
@@ -4615,6 +4650,9 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
else
id->dst_simt_vars = NULL;
+ if (profile_status_for_fn (id->src_cfun) == PROFILE_ABSENT)
+ profile_status_for_fn (dst_cfun) = PROFILE_ABSENT;
+
/* If the src function contains an IFN_VA_ARG, then so will the dst
function after inlining. Likewise for IFN_GOMP_USE_SIMT. */
prop_mask = PROP_gimple_lva | PROP_gimple_lomp_dev;
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index a60454b5218..8d80cccf38f 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -36,10 +36,58 @@ along with GCC; see the file COPYING3. If not see
| D(I) = A(I-1)*E
|ENDDO
- This pass uses an RDG, Reduced Dependence Graph built on top of the
- data dependence relations. The RDG is then topologically sorted to
- obtain a map of information producers/consumers based on which it
- generates the new loops. */
+ Loop distribution is the dual of loop fusion. It separates statements
+ of a loop (or loop nest) into multiple loops (or loop nests) with the
+ same loop header. The major goal is to separate statements which may
+ be vectorized from those that can't. This pass implements distribution
+ in the following steps:
+
+ 1) Seed partitions with specific type statements. For now we support
+ two types seed statements: statement defining variable used outside
+ of loop; statement storing to memory.
+ 2) Build reduced dependence graph (RDG) for loop to be distributed.
+ The vertices (RDG:V) model all statements in the loop and the edges
+ (RDG:E) model flow and control dependencies between statements.
+ 3) Apart from RDG, compute data dependencies between memory references.
+ 4) Starting from seed statement, build up partition by adding depended
+ statements according to RDG's dependence information. Partition is
+ classified as parallel type if it can be executed paralleled; or as
+ sequential type if it can't. Parallel type partition is further
+ classified as different builtin kinds if it can be implemented as
+ builtin function calls.
+ 5) Build partition dependence graph (PG) based on data dependencies.
+ The vertices (PG:V) model all partitions and the edges (PG:E) model
+ all data dependencies between every partitions pair. In general,
+ data dependence is either compilation time known or unknown. In C
+ family languages, there exists quite amount compilation time unknown
+ dependencies because of possible alias relation of data references.
+ We categorize PG's edge to two types: "true" edge that represents
+ compilation time known data dependencies; "alias" edge for all other
+ data dependencies.
+ 6) Traverse subgraph of PG as if all "alias" edges don't exist. Merge
+ partitions in each strong connected component (SCC) correspondingly.
+ Build new PG for merged partitions.
+ 7) Traverse PG again and this time with both "true" and "alias" edges
+ included. We try to break SCCs by removing some edges. Because
+ SCCs by "true" edges are all fused in step 6), we can break SCCs
+ by removing some "alias" edges. It's NP-hard to choose optimal
+ edge set, fortunately simple approximation is good enough for us
+ given the small problem scale.
+ 8) Collect all data dependencies of the removed "alias" edges. Create
+ runtime alias checks for collected data dependencies.
+ 9) Version loop under the condition of runtime alias checks. Given
+ loop distribution generally introduces additional overhead, it is
+ only useful if vectorization is achieved in distributed loop. We
+ version loop with internal function call IFN_LOOP_DIST_ALIAS. If
+ no distributed loop can be vectorized, we simply remove distributed
+ loops and recover to the original one.
+
+ TODO:
+ 1) We only distribute innermost loops now. This pass should handle loop
+ nests in the future.
+ 2) We only fuse partitions in SCC now. A better fusion algorithm is
+ desired to minimize loop overhead, maximize parallelism and maximize
+ data reuse. */
#include "config.h"
#include "system.h"
@@ -63,9 +111,55 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
+#include "params.h"
#include "tree-vectorizer.h"
+#define MAX_DATAREFS_NUM \
+ ((unsigned) PARAM_VALUE (PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS))
+
+/* Hashtable helpers. */
+
+struct ddr_hasher : nofree_ptr_hash <struct data_dependence_relation>
+{
+ static inline hashval_t hash (const data_dependence_relation *);
+ static inline bool equal (const data_dependence_relation *,
+ const data_dependence_relation *);
+};
+
+/* Hash function for data dependence. */
+
+inline hashval_t
+ddr_hasher::hash (const data_dependence_relation *ddr)
+{
+ inchash::hash h;
+ h.add_ptr (DDR_A (ddr));
+ h.add_ptr (DDR_B (ddr));
+ return h.end ();
+}
+
+/* Hash table equality function for data dependence. */
+
+inline bool
+ddr_hasher::equal (const data_dependence_relation *ddr1,
+ const data_dependence_relation *ddr2)
+{
+ return (DDR_A (ddr1) == DDR_A (ddr2) && DDR_B (ddr1) == DDR_B (ddr2));
+}
+
+/* The loop (nest) to be distributed. */
+static vec<loop_p> loop_nest;
+
+/* Vector of data references in the loop to be distributed. */
+static vec<data_reference_p> datarefs_vec;
+
+/* Store index of data reference in aux field. */
+#define DR_INDEX(dr) ((uintptr_t) (dr)->aux)
+
+/* Hash table for data dependence relation in the loop to be distributed. */
+static hash_table<ddr_hasher> ddrs_table (389);
+
+
/* A Reduced Dependence Graph (RDG) vertex representing a statement. */
struct rdg_vertex
{
@@ -336,8 +430,7 @@ create_rdg_cd_edges (struct graph *rdg, control_dependences *cd, loop_p loop)
if that failed. */
static bool
-create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop,
- vec<data_reference_p> *datarefs)
+create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop)
{
int i;
gimple *stmt;
@@ -357,12 +450,12 @@ create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop,
if (gimple_code (stmt) == GIMPLE_PHI)
continue;
- unsigned drp = datarefs->length ();
- if (!find_data_references_in_stmt (loop, stmt, datarefs))
+ unsigned drp = datarefs_vec.length ();
+ if (!find_data_references_in_stmt (loop, stmt, &datarefs_vec))
return false;
- for (unsigned j = drp; j < datarefs->length (); ++j)
+ for (unsigned j = drp; j < datarefs_vec.length (); ++j)
{
- data_reference_p dr = (*datarefs)[j];
+ data_reference_p dr = datarefs_vec[j];
if (DR_IS_READ (dr))
RDGV_HAS_MEM_READS (v) = true;
else
@@ -373,16 +466,39 @@ create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop,
return true;
}
-/* Initialize STMTS with all the statements of LOOP. The order in
- which we discover statements is important as
- generate_loops_for_partition is using the same traversal for
- identifying statements in loop copies. */
+/* Array mapping basic block's index to its topological order. */
+static int *bb_top_order_index;
+/* And size of the array. */
+static int bb_top_order_index_size;
+
+/* If X has a smaller topological sort number than Y, returns -1;
+ if greater, returns 1. */
+
+static int
+bb_top_order_cmp (const void *x, const void *y)
+{
+ basic_block bb1 = *(const basic_block *) x;
+ basic_block bb2 = *(const basic_block *) y;
+
+ gcc_assert (bb1->index < bb_top_order_index_size
+ && bb2->index < bb_top_order_index_size);
+ gcc_assert (bb1 == bb2
+ || bb_top_order_index[bb1->index]
+ != bb_top_order_index[bb2->index]);
+
+ return (bb_top_order_index[bb1->index] - bb_top_order_index[bb2->index]);
+}
+
+/* Initialize STMTS with all the statements of LOOP. We use topological
+ order to discover all statements. The order is important because
+ generate_loops_for_partition is using the same traversal for identifying
+ statements in loop copies. */
static void
stmts_from_loop (struct loop *loop, vec<gimple *> *stmts)
{
unsigned int i;
- basic_block *bbs = get_loop_body_in_dom_order (loop);
+ basic_block *bbs = get_loop_body_in_custom_order (loop, bb_top_order_cmp);
for (i = 0; i < loop->num_nodes; i++)
{
@@ -423,7 +539,7 @@ free_rdg (struct graph *rdg)
if (v->data)
{
gimple_set_uid (RDGV_STMT (v), -1);
- free_data_refs (RDGV_DATAREFS (v));
+ (RDGV_DATAREFS (v)).release ();
free (v->data);
}
}
@@ -431,24 +547,22 @@ free_rdg (struct graph *rdg)
free_graph (rdg);
}
-/* Build the Reduced Dependence Graph (RDG) with one vertex per
- statement of the loop nest LOOP_NEST, and one edge per data dependence or
- scalar dependence. */
+/* Build the Reduced Dependence Graph (RDG) with one vertex per statement of
+ LOOP, and one edge per flow dependence or control dependence from control
+ dependence CD. During visiting each statement, data references are also
+ collected and recorded in global data DATAREFS_VEC. */
static struct graph *
-build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
+build_rdg (struct loop *loop, control_dependences *cd)
{
struct graph *rdg;
- vec<data_reference_p> datarefs;
/* Create the RDG vertices from the stmts of the loop nest. */
auto_vec<gimple *, 10> stmts;
- stmts_from_loop (loop_nest[0], &stmts);
+ stmts_from_loop (loop, &stmts);
rdg = new_graph (stmts.length ());
- datarefs.create (10);
- if (!create_rdg_vertices (rdg, stmts, loop_nest[0], &datarefs))
+ if (!create_rdg_vertices (rdg, stmts, loop))
{
- datarefs.release ();
free_rdg (rdg);
return NULL;
}
@@ -456,43 +570,60 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
create_rdg_flow_edges (rdg);
if (cd)
- create_rdg_cd_edges (rdg, cd, loop_nest[0]);
-
- datarefs.release ();
+ create_rdg_cd_edges (rdg, cd, loop);
return rdg;
}
-
+/* Kind of distributed loop. */
enum partition_kind {
PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY, PKIND_MEMMOVE
};
+/* Type of distributed loop. */
+enum partition_type {
+ /* The distributed loop can be executed parallelly. */
+ PTYPE_PARALLEL = 0,
+ /* The distributed loop has to be executed sequentially. */
+ PTYPE_SEQUENTIAL
+};
+
+/* Partition for loop distribution. */
struct partition
{
+ /* Statements of the partition. */
bitmap stmts;
+ /* Loops of the partition. */
bitmap loops;
+ /* True if the partition defines variable which is used outside of loop. */
bool reduction_p;
+ /* For builtin partition, true if it executes one iteration more than
+ number of loop (latch) iterations. */
bool plus_one;
enum partition_kind kind;
+ enum partition_type type;
/* data-references a kind != PKIND_NORMAL partition is about. */
data_reference_p main_dr;
data_reference_p secondary_dr;
+ /* Number of loop (latch) iterations. */
tree niter;
+ /* Data references in the partition. */
+ bitmap datarefs;
};
/* Allocate and initialize a partition from BITMAP. */
static partition *
-partition_alloc (bitmap stmts, bitmap loops)
+partition_alloc (void)
{
partition *partition = XCNEW (struct partition);
- partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL);
- partition->loops = loops ? loops : BITMAP_ALLOC (NULL);
+ partition->stmts = BITMAP_ALLOC (NULL);
+ partition->loops = BITMAP_ALLOC (NULL);
partition->reduction_p = false;
partition->kind = PKIND_NORMAL;
+ partition->datarefs = BITMAP_ALLOC (NULL);
return partition;
}
@@ -503,6 +634,7 @@ partition_free (partition *partition)
{
BITMAP_FREE (partition->stmts);
BITMAP_FREE (partition->loops);
+ BITMAP_FREE (partition->datarefs);
free (partition);
}
@@ -522,15 +654,57 @@ partition_reduction_p (partition *partition)
return partition->reduction_p;
}
-/* Merge PARTITION into the partition DEST. */
+/* Partitions are fused because of different reasons. */
+enum fuse_type
+{
+ FUSE_NON_BUILTIN = 0,
+ FUSE_REDUCTION = 1,
+ FUSE_SHARE_REF = 2,
+ FUSE_SAME_SCC = 3,
+ FUSE_FINALIZE = 4
+};
+
+/* Description on different fusing reason. */
+static const char *fuse_message[] = {
+ "they are non-builtins",
+ "they have reductions",
+ "they have shared memory refs",
+ "they are in the same dependence scc",
+ "there is no point to distribute loop"};
+
+static void
+update_type_for_merge (struct graph *, partition *, partition *);
+
+/* Merge PARTITION into the partition DEST. RDG is the reduced dependence
+ graph and we update type for result partition if it is non-NULL. */
static void
-partition_merge_into (partition *dest, partition *partition)
+partition_merge_into (struct graph *rdg, partition *dest,
+ partition *partition, enum fuse_type ft)
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Fuse partitions because %s:\n", fuse_message[ft]);
+ fprintf (dump_file, " Part 1: ");
+ dump_bitmap (dump_file, dest->stmts);
+ fprintf (dump_file, " Part 2: ");
+ dump_bitmap (dump_file, partition->stmts);
+ }
+
dest->kind = PKIND_NORMAL;
+ if (dest->type == PTYPE_PARALLEL)
+ dest->type = partition->type;
+
bitmap_ior_into (dest->stmts, partition->stmts);
if (partition_reduction_p (partition))
dest->reduction_p = true;
+
+ /* Further check if any data dependence prevents us from executing the
+ new partition parallelly. */
+ if (dest->type == PTYPE_PARALLEL && rdg != NULL)
+ update_type_for_merge (rdg, dest, partition);
+
+ bitmap_ior_into (dest->datarefs, partition->datarefs);
}
@@ -618,11 +792,18 @@ generate_loops_for_partition (struct loop *loop, partition *partition,
if (copy_p)
{
+ int orig_loop_num = loop->orig_loop_num;
loop = copy_loop_before (loop);
gcc_assert (loop != NULL);
+ loop->orig_loop_num = orig_loop_num;
create_preheader (loop, CP_SIMPLE_PREHEADERS);
create_bb_after_loop (loop);
}
+ else
+ {
+ /* Origin number is set to the new versioned loop's num. */
+ gcc_assert (loop->orig_loop_num != loop->num);
+ }
/* Remove stmts not in the PARTITION bitmap. */
bbs = get_loop_body_in_dom_order (loop);
@@ -986,6 +1167,101 @@ generate_code_for_partition (struct loop *loop,
return false;
}
+/* Return data dependence relation for data references A and B. The two
+ data references must be in lexicographic order wrto reduced dependence
+ graph RDG. We firstly try to find ddr from global ddr hash table. If
+ it doesn't exist, compute the ddr and cache it. */
+
+static data_dependence_relation *
+get_data_dependence (struct graph *rdg, data_reference_p a, data_reference_p b)
+{
+ struct data_dependence_relation ent, **slot;
+ struct data_dependence_relation *ddr;
+
+ gcc_assert (DR_IS_WRITE (a) || DR_IS_WRITE (b));
+ gcc_assert (rdg_vertex_for_stmt (rdg, DR_STMT (a))
+ <= rdg_vertex_for_stmt (rdg, DR_STMT (b)));
+ ent.a = a;
+ ent.b = b;
+ slot = ddrs_table.find_slot (&ent, INSERT);
+ if (*slot == NULL)
+ {
+ ddr = initialize_data_dependence_relation (a, b, loop_nest);
+ compute_affine_dependence (ddr, loop_nest[0]);
+ *slot = ddr;
+ }
+
+ return *slot;
+}
+
+/* In reduced dependence graph RDG for loop distribution, return true if
+ dependence between references DR1 and DR2 leads to a dependence cycle
+ and such dependence cycle can't be resolved by runtime alias check. */
+
+static bool
+data_dep_in_cycle_p (struct graph *rdg,
+ data_reference_p dr1, data_reference_p dr2)
+{
+ struct data_dependence_relation *ddr;
+
+ /* Re-shuffle data-refs to be in topological order. */
+ if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
+ > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
+ std::swap (dr1, dr2);
+
+ ddr = get_data_dependence (rdg, dr1, dr2);
+
+ /* In case of no data dependence. */
+ if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
+ return false;
+ /* For unknown data dependence or known data dependence which can't be
+ expressed in classic distance vector, we check if it can be resolved
+ by runtime alias check. If yes, we still consider data dependence
+ as won't introduce data dependence cycle. */
+ else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
+ || DDR_NUM_DIST_VECTS (ddr) == 0)
+ return !runtime_alias_check_p (ddr, NULL, true);
+ else if (DDR_NUM_DIST_VECTS (ddr) > 1)
+ return true;
+ else if (DDR_REVERSED_P (ddr)
+ || lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
+ return false;
+
+ return true;
+}
+
+/* Given reduced dependence graph RDG, PARTITION1 and PARTITION2, update
+ PARTITION1's type after merging PARTITION2 into PARTITION1. */
+
+static void
+update_type_for_merge (struct graph *rdg,
+ partition *partition1, partition *partition2)
+{
+ unsigned i, j;
+ bitmap_iterator bi, bj;
+ data_reference_p dr1, dr2;
+
+ EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
+ {
+ unsigned start = (partition1 == partition2) ? i + 1 : 0;
+
+ dr1 = datarefs_vec[i];
+ EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, start, j, bj)
+ {
+ dr2 = datarefs_vec[j];
+ if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
+ continue;
+
+ /* Partition can only be executed sequentially if there is any
+ data dependence cycle. */
+ if (data_dep_in_cycle_p (rdg, dr1, dr2))
+ {
+ partition1->type = PTYPE_SEQUENTIAL;
+ return;
+ }
+ }
+ }
+}
/* Returns a partition with all the statements needed for computing
the vertex V of the RDG, also including the loop exit conditions. */
@@ -993,10 +1269,11 @@ generate_code_for_partition (struct loop *loop,
static partition *
build_rdg_partition_for_vertex (struct graph *rdg, int v)
{
- partition *partition = partition_alloc (NULL, NULL);
+ partition *partition = partition_alloc ();
auto_vec<int, 3> nodes;
- unsigned i;
+ unsigned i, j;
int x;
+ data_reference_p dr;
graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
@@ -1005,23 +1282,45 @@ build_rdg_partition_for_vertex (struct graph *rdg, int v)
bitmap_set_bit (partition->stmts, x);
bitmap_set_bit (partition->loops,
loop_containing_stmt (RDG_STMT (rdg, x))->num);
+
+ for (j = 0; RDG_DATAREFS (rdg, x).iterate (j, &dr); ++j)
+ {
+ unsigned idx = (unsigned) DR_INDEX (dr);
+ gcc_assert (idx < datarefs_vec.length ());
+
+ /* Partition can only be executed sequentially if there is any
+ unknown data reference. */
+ if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr)
+ || !DR_INIT (dr) || !DR_STEP (dr))
+ partition->type = PTYPE_SEQUENTIAL;
+
+ bitmap_set_bit (partition->datarefs, idx);
+ }
}
+ if (partition->type == PTYPE_SEQUENTIAL)
+ return partition;
+
+ /* Further check if any data dependence prevents us from executing the
+ partition parallelly. */
+ update_type_for_merge (rdg, partition, partition);
+
return partition;
}
/* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
- For the moment we detect only the memset zero pattern. */
+ For the moment we detect memset, memcpy and memmove patterns. Bitmap
+ STMT_IN_ALL_PARTITIONS contains statements belonging to all partitions. */
static void
-classify_partition (loop_p loop, struct graph *rdg, partition *partition)
+classify_partition (loop_p loop, struct graph *rdg, partition *partition,
+ bitmap stmt_in_all_partitions)
{
bitmap_iterator bi;
unsigned i;
tree nb_iter;
data_reference_p single_load, single_store;
- bool volatiles_p = false;
- bool plus_one = false;
+ bool volatiles_p = false, plus_one = false, has_reduction = false;
partition->kind = PKIND_NORMAL;
partition->main_dr = NULL;
@@ -1036,16 +1335,31 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition)
if (gimple_has_volatile_ops (stmt))
volatiles_p = true;
- /* If the stmt has uses outside of the loop mark it as reduction. */
+ /* If the stmt is not included by all partitions and there is uses
+ outside of the loop, then mark the partition as reduction. */
if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
{
- partition->reduction_p = true;
- return;
+ /* Due to limitation in the transform phase we have to fuse all
+ reduction partitions. As a result, this could cancel valid
+ loop distribution especially for loop that induction variable
+ is used outside of loop. To workaround this issue, we skip
+ marking partition as reudction if the reduction stmt belongs
+ to all partitions. In such case, reduction will be computed
+ correctly no matter how partitions are fused/distributed. */
+ if (!bitmap_bit_p (stmt_in_all_partitions, i))
+ {
+ partition->reduction_p = true;
+ return;
+ }
+ has_reduction = true;
}
}
/* Perform general partition disqualification for builtins. */
if (volatiles_p
+ /* Simple workaround to prevent classifying the partition as builtin
+ if it contains any use outside of loop. */
+ || has_reduction
|| !flag_tree_loop_distribute_patterns)
return;
@@ -1098,8 +1412,7 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition)
return;
nb_iter = number_of_latch_executions (loop);
- if (!nb_iter || nb_iter == chrec_dont_know)
- return;
+ gcc_assert (nb_iter && nb_iter != chrec_dont_know);
if (dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
gimple_bb (DR_STMT (single_store))))
plus_one = true;
@@ -1143,44 +1456,27 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition)
return;
/* Now check that if there is a dependence this dependence is
of a suitable form for memmove. */
- vec<loop_p> loops = vNULL;
- ddr_p ddr;
- loops.safe_push (loop);
- ddr = initialize_data_dependence_relation (single_load, single_store,
- loops);
- compute_affine_dependence (ddr, loop);
+ ddr_p ddr = get_data_dependence (rdg, single_load, single_store);
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
- {
- free_dependence_relation (ddr);
- loops.release ();
- return;
- }
+ return;
+
if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
{
if (DDR_NUM_DIST_VECTS (ddr) == 0)
- {
- free_dependence_relation (ddr);
- loops.release ();
- return;
- }
+ return;
+
lambda_vector dist_v;
FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
{
int dist = dist_v[index_in_loop_nest (loop->num,
DDR_LOOP_NEST (ddr))];
if (dist > 0 && !DDR_REVERSED_P (ddr))
- {
- free_dependence_relation (ddr);
- loops.release ();
- return;
- }
+ return;
}
partition->kind = PKIND_MEMMOVE;
}
else
partition->kind = PKIND_MEMCPY;
- free_dependence_relation (ddr);
- loops.release ();
partition->main_dr = single_store;
partition->secondary_dr = single_load;
partition->niter = nb_iter;
@@ -1188,30 +1484,16 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition)
}
}
-/* For a data reference REF, return the declaration of its base
- address or NULL_TREE if the base is not determined. */
-
-static tree
-ref_base_address (data_reference_p dr)
-{
- tree base_address = DR_BASE_ADDRESS (dr);
- if (base_address
- && TREE_CODE (base_address) == ADDR_EXPR)
- return TREE_OPERAND (base_address, 0);
-
- return base_address;
-}
-
-/* Returns true when PARTITION1 and PARTITION2 have similar memory
- accesses in RDG. */
+/* Returns true when PARTITION1 and PARTITION2 access the same memory
+ object in RDG. */
static bool
-similar_memory_accesses (struct graph *rdg, partition *partition1,
- partition *partition2)
+share_memory_accesses (struct graph *rdg,
+ partition *partition1, partition *partition2)
{
- unsigned i, j, k, l;
+ unsigned i, j;
bitmap_iterator bi, bj;
- data_reference_p ref1, ref2;
+ data_reference_p dr1, dr2;
/* First check whether in the intersection of the two partitions are
any loads or stores. Common loads are the situation that happens
@@ -1221,30 +1503,37 @@ similar_memory_accesses (struct graph *rdg, partition *partition1,
|| RDG_MEM_READS_STMT (rdg, i))
return true;
- /* Then check all data-references against each other. */
- EXECUTE_IF_SET_IN_BITMAP (partition1->stmts, 0, i, bi)
- if (RDG_MEM_WRITE_STMT (rdg, i)
- || RDG_MEM_READS_STMT (rdg, i))
- EXECUTE_IF_SET_IN_BITMAP (partition2->stmts, 0, j, bj)
- if (RDG_MEM_WRITE_STMT (rdg, j)
- || RDG_MEM_READS_STMT (rdg, j))
- {
- FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, i), k, ref1)
- {
- tree base1 = ref_base_address (ref1);
- if (base1)
- FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, j), l, ref2)
- if (base1 == ref_base_address (ref2))
- return true;
- }
- }
+ /* Then check whether the two partitions access the same memory object. */
+ EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
+ {
+ dr1 = datarefs_vec[i];
+
+ if (!DR_BASE_ADDRESS (dr1)
+ || !DR_OFFSET (dr1) || !DR_INIT (dr1) || !DR_STEP (dr1))
+ continue;
+
+ EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, 0, j, bj)
+ {
+ dr2 = datarefs_vec[j];
+
+ if (!DR_BASE_ADDRESS (dr2)
+ || !DR_OFFSET (dr2) || !DR_INIT (dr2) || !DR_STEP (dr2))
+ continue;
+
+ if (operand_equal_p (DR_BASE_ADDRESS (dr1), DR_BASE_ADDRESS (dr2), 0)
+ && operand_equal_p (DR_OFFSET (dr1), DR_OFFSET (dr2), 0)
+ && operand_equal_p (DR_INIT (dr1), DR_INIT (dr2), 0)
+ && operand_equal_p (DR_STEP (dr1), DR_STEP (dr2), 0))
+ return true;
+ }
+ }
return false;
}
-/* Aggregate several components into a useful partition that is
- registered in the PARTITIONS vector. Partitions will be
- distributed in different loops. */
+/* For each seed statement in STARTING_STMTS, this function builds
+ partition for it by adding depended statements according to RDG.
+ All partitions are recorded in PARTITIONS. */
static void
rdg_build_partitions (struct graph *rdg,
@@ -1273,8 +1562,9 @@ rdg_build_partitions (struct graph *rdg,
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "ldist useful partition:\n");
- dump_bitmap (dump_file, partition->stmts);
+ fprintf (dump_file, "ldist creates useful %s partition:\n",
+ partition->type == PTYPE_PARALLEL ? "parallel" : "sequent");
+ bitmap_print (dump_file, partition->stmts, " ", "\n");
}
partitions->safe_push (partition);
@@ -1365,67 +1655,97 @@ partition_contains_all_rw (struct graph *rdg,
}
/* Compute partition dependence created by the data references in DRS1
- and DRS2 and modify and return DIR according to that. */
+ and DRS2, modify and return DIR according to that. IF ALIAS_DDR is
+ not NULL, we record dependence introduced by possible alias between
+ two data references in ALIAS_DDRS; otherwise, we simply ignore such
+ dependence as if it doesn't exist at all. */
static int
-pg_add_dependence_edges (struct graph *rdg, vec<loop_p> loops, int dir,
- vec<data_reference_p> drs1,
- vec<data_reference_p> drs2)
+pg_add_dependence_edges (struct graph *rdg, int dir,
+ bitmap drs1, bitmap drs2, vec<ddr_p> *alias_ddrs)
{
- data_reference_p dr1, dr2;
+ unsigned i, j;
+ bitmap_iterator bi, bj;
+ data_reference_p dr1, dr2, saved_dr1;
/* dependence direction - 0 is no dependence, -1 is back,
1 is forth, 2 is both (we can stop then, merging will occur). */
- for (int ii = 0; drs1.iterate (ii, &dr1); ++ii)
- for (int jj = 0; drs2.iterate (jj, &dr2); ++jj)
- {
- data_reference_p saved_dr1 = dr1;
- int this_dir = 1;
- ddr_p ddr;
- /* Re-shuffle data-refs to be in dominator order. */
- if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
- > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
- {
- std::swap (dr1, dr2);
- this_dir = -this_dir;
- }
- ddr = initialize_data_dependence_relation (dr1, dr2, loops);
- compute_affine_dependence (ddr, loops[0]);
- if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
- this_dir = 2;
- else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
- {
- if (DDR_REVERSED_P (ddr))
- {
- std::swap (dr1, dr2);
+ EXECUTE_IF_SET_IN_BITMAP (drs1, 0, i, bi)
+ {
+ dr1 = datarefs_vec[i];
+
+ EXECUTE_IF_SET_IN_BITMAP (drs2, 0, j, bj)
+ {
+ int res, this_dir = 1;
+ ddr_p ddr;
+
+ dr2 = datarefs_vec[j];
+
+ /* Skip all <read, read> data dependence. */
+ if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
+ continue;
+
+ saved_dr1 = dr1;
+ /* Re-shuffle data-refs to be in topological order. */
+ if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
+ > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
+ {
+ std::swap (dr1, dr2);
+ this_dir = -this_dir;
+ }
+ ddr = get_data_dependence (rdg, dr1, dr2);
+ if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+ {
+ this_dir = 0;
+ res = data_ref_compare_tree (DR_BASE_ADDRESS (dr1),
+ DR_BASE_ADDRESS (dr2));
+ /* Be conservative. If data references are not well analyzed,
+ or the two data references have the same base address and
+ offset, add dependence and consider it alias to each other.
+ In other words, the dependence can not be resolved by
+ runtime alias check. */
+ if (!DR_BASE_ADDRESS (dr1) || !DR_BASE_ADDRESS (dr2)
+ || !DR_OFFSET (dr1) || !DR_OFFSET (dr2)
+ || !DR_INIT (dr1) || !DR_INIT (dr2)
+ || !DR_STEP (dr1) || !tree_fits_uhwi_p (DR_STEP (dr1))
+ || !DR_STEP (dr2) || !tree_fits_uhwi_p (DR_STEP (dr2))
+ || res == 0)
+ this_dir = 2;
+ /* Data dependence could be resolved by runtime alias check,
+ record it in ALIAS_DDRS. */
+ else if (alias_ddrs != NULL)
+ alias_ddrs->safe_push (ddr);
+ /* Or simply ignore it. */
+ }
+ else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
+ {
+ if (DDR_REVERSED_P (ddr))
this_dir = -this_dir;
- }
- /* Known dependences can still be unordered througout the
- iteration space, see gcc.dg/tree-ssa/ldist-16.c. */
- if (DDR_NUM_DIST_VECTS (ddr) != 1)
- this_dir = 2;
- /* If the overlap is exact preserve stmt order. */
- else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
- ;
- else
- {
- /* Else as the distance vector is lexicographic positive
- swap the dependence direction. */
+
+ /* Known dependences can still be unordered througout the
+ iteration space, see gcc.dg/tree-ssa/ldist-16.c. */
+ if (DDR_NUM_DIST_VECTS (ddr) != 1)
+ this_dir = 2;
+ /* If the overlap is exact preserve stmt order. */
+ else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
+ ;
+ /* Else as the distance vector is lexicographic positive swap
+ the dependence direction. */
+ else
this_dir = -this_dir;
- }
- }
- else
- this_dir = 0;
- free_dependence_relation (ddr);
- if (this_dir == 2)
- return 2;
- else if (dir == 0)
- dir = this_dir;
- else if (this_dir != 0 && dir != this_dir)
- return 2;
- /* Shuffle "back" dr1. */
- dr1 = saved_dr1;
- }
+ }
+ else
+ this_dir = 0;
+ if (this_dir == 2)
+ return 2;
+ else if (dir == 0)
+ dir = this_dir;
+ else if (this_dir != 0 && dir != this_dir)
+ return 2;
+ /* Shuffle "back" dr1. */
+ dr1 = saved_dr1;
+ }
+ }
return dir;
}
@@ -1439,11 +1759,608 @@ pgcmp (const void *v1_, const void *v2_)
return v2->post - v1->post;
}
-/* Distributes the code from LOOP in such a way that producer
- statements are placed before consumer statements. Tries to separate
- only the statements from STMTS into separate loops.
- Returns the number of distributed loops. Set *DESTROY_P to whether
- LOOP needs to be destroyed. */
+/* Data attached to vertices of partition dependence graph. */
+struct pg_vdata
+{
+ /* ID of the corresponding partition. */
+ int id;
+ /* The partition. */
+ struct partition *partition;
+};
+
+/* Data attached to edges of partition dependence graph. */
+struct pg_edata
+{
+ /* If the dependence edge can be resolved by runtime alias check,
+ this vector contains data dependence relations for runtime alias
+ check. On the other hand, if the dependence edge is introduced
+ because of compilation time known data dependence, this vector
+ contains nothing. */
+ vec<ddr_p> alias_ddrs;
+};
+
+/* Callback data for traversing edges in graph. */
+struct pg_edge_callback_data
+{
+ /* Bitmap contains strong connected components should be merged. */
+ bitmap sccs_to_merge;
+ /* Array constains component information for all vertices. */
+ int *vertices_component;
+ /* Vector to record all data dependence relations which are needed
+ to break strong connected components by runtime alias checks. */
+ vec<ddr_p> *alias_ddrs;
+};
+
+/* Initialize vertice's data for partition dependence graph PG with
+ PARTITIONS. */
+
+static void
+init_partition_graph_vertices (struct graph *pg,
+ vec<struct partition *> *partitions)
+{
+ int i;
+ partition *partition;
+ struct pg_vdata *data;
+
+ for (i = 0; partitions->iterate (i, &partition); ++i)
+ {
+ data = new pg_vdata;
+ pg->vertices[i].data = data;
+ data->id = i;
+ data->partition = partition;
+ }
+}
+
+/* Add edge <I, J> to partition dependence graph PG. Attach vector of data
+ dependence relations to the EDGE if DDRS isn't NULL. */
+
+static void
+add_partition_graph_edge (struct graph *pg, int i, int j, vec<ddr_p> *ddrs)
+{
+ struct graph_edge *e = add_edge (pg, i, j);
+
+ /* If the edge is attached with data dependence relations, it means this
+ dependence edge can be resolved by runtime alias checks. */
+ if (ddrs != NULL)
+ {
+ struct pg_edata *data = new pg_edata;
+
+ gcc_assert (ddrs->length () > 0);
+ e->data = data;
+ data->alias_ddrs = vNULL;
+ data->alias_ddrs.safe_splice (*ddrs);
+ }
+}
+
+/* Callback function for graph travesal algorithm. It returns true
+ if edge E should skipped when traversing the graph. */
+
+static bool
+pg_skip_alias_edge (struct graph_edge *e)
+{
+ struct pg_edata *data = (struct pg_edata *)e->data;
+ return (data != NULL && data->alias_ddrs.length () > 0);
+}
+
+/* Callback function freeing data attached to edge E of graph. */
+
+static void
+free_partition_graph_edata_cb (struct graph *, struct graph_edge *e, void *)
+{
+ if (e->data != NULL)
+ {
+ struct pg_edata *data = (struct pg_edata *)e->data;
+ data->alias_ddrs.release ();
+ delete data;
+ }
+}
+
+/* Free data attached to vertice of partition dependence graph PG. */
+
+static void
+free_partition_graph_vdata (struct graph *pg)
+{
+ int i;
+ struct pg_vdata *data;
+
+ for (i = 0; i < pg->n_vertices; ++i)
+ {
+ data = (struct pg_vdata *)pg->vertices[i].data;
+ delete data;
+ }
+}
+
+/* Build and return partition dependence graph for PARTITIONS. RDG is
+ reduced dependence graph for the loop to be distributed. If IGNORE_ALIAS_P
+ is true, data dependence caused by possible alias between references
+ is ignored, as if it doesn't exist at all; otherwise all depdendences
+ are considered. */
+
+static struct graph *
+build_partition_graph (struct graph *rdg,
+ vec<struct partition *> *partitions,
+ bool ignore_alias_p)
+{
+ int i, j;
+ struct partition *partition1, *partition2;
+ graph *pg = new_graph (partitions->length ());
+ auto_vec<ddr_p> alias_ddrs, *alias_ddrs_p;
+
+ alias_ddrs_p = ignore_alias_p ? NULL : &alias_ddrs;
+
+ init_partition_graph_vertices (pg, partitions);
+
+ for (i = 0; partitions->iterate (i, &partition1); ++i)
+ {
+ for (j = i + 1; partitions->iterate (j, &partition2); ++j)
+ {
+ /* dependence direction - 0 is no dependence, -1 is back,
+ 1 is forth, 2 is both (we can stop then, merging will occur). */
+ int dir = 0;
+
+ /* If the first partition has reduction, add back edge; if the
+ second partition has reduction, add forth edge. This makes
+ sure that reduction partition will be sorted as the last one. */
+ if (partition_reduction_p (partition1))
+ dir = -1;
+ else if (partition_reduction_p (partition2))
+ dir = 1;
+
+ /* Cleanup the temporary vector. */
+ alias_ddrs.truncate (0);
+
+ dir = pg_add_dependence_edges (rdg, dir, partition1->datarefs,
+ partition2->datarefs, alias_ddrs_p);
+
+ /* Add edge to partition graph if there exists dependence. There
+ are two types of edges. One type edge is caused by compilation
+ time known dependence, this type can not be resolved by runtime
+ alias check. The other type can be resolved by runtime alias
+ check. */
+ if (dir == 1 || dir == 2
+ || alias_ddrs.length () > 0)
+ {
+ /* Attach data dependence relations to edge that can be resolved
+ by runtime alias check. */
+ bool alias_edge_p = (dir != 1 && dir != 2);
+ add_partition_graph_edge (pg, i, j,
+ (alias_edge_p) ? &alias_ddrs : NULL);
+ }
+ if (dir == -1 || dir == 2
+ || alias_ddrs.length () > 0)
+ {
+ /* Attach data dependence relations to edge that can be resolved
+ by runtime alias check. */
+ bool alias_edge_p = (dir != -1 && dir != 2);
+ add_partition_graph_edge (pg, j, i,
+ (alias_edge_p) ? &alias_ddrs : NULL);
+ }
+ }
+ }
+ return pg;
+}
+
+/* Sort partitions in PG by post order and store them in PARTITIONS. */
+
+static void
+sort_partitions_by_post_order (struct graph *pg,
+ vec<struct partition *> *partitions)
+{
+ int i;
+ struct pg_vdata *data;
+
+ /* Now order the remaining nodes in postorder. */
+ qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
+ partitions->truncate (0);
+ for (i = 0; i < pg->n_vertices; ++i)
+ {
+ data = (struct pg_vdata *)pg->vertices[i].data;
+ if (data->partition)
+ partitions->safe_push (data->partition);
+ }
+}
+
+/* Given reduced dependence graph RDG merge strong connected components
+ of PARTITIONS. In this function, data dependence caused by possible
+ alias between references is ignored, as if it doesn't exist at all. */
+
+static void
+merge_dep_scc_partitions (struct graph *rdg,
+ vec<struct partition *> *partitions)
+{
+ struct partition *partition1, *partition2;
+ struct pg_vdata *data;
+ graph *pg = build_partition_graph (rdg, partitions, true);
+ int i, j, num_sccs = graphds_scc (pg, NULL);
+
+ /* Strong connected compoenent means dependence cycle, we cannot distribute
+ them. So fuse them together. */
+ if ((unsigned) num_sccs < partitions->length ())
+ {
+ for (i = 0; i < num_sccs; ++i)
+ {
+ for (j = 0; partitions->iterate (j, &partition1); ++j)
+ if (pg->vertices[j].component == i)
+ break;
+ for (j = j + 1; partitions->iterate (j, &partition2); ++j)
+ if (pg->vertices[j].component == i)
+ {
+ partition_merge_into (NULL, partition1,
+ partition2, FUSE_SAME_SCC);
+ partition1->type = PTYPE_SEQUENTIAL;
+ (*partitions)[j] = NULL;
+ partition_free (partition2);
+ data = (struct pg_vdata *)pg->vertices[j].data;
+ data->partition = NULL;
+ }
+ }
+ }
+
+ sort_partitions_by_post_order (pg, partitions);
+ gcc_assert (partitions->length () == (unsigned)num_sccs);
+ free_partition_graph_vdata (pg);
+ free_graph (pg);
+}
+
+/* Callback function for traversing edge E in graph G. DATA is private
+ callback data. */
+
+static void
+pg_collect_alias_ddrs (struct graph *g, struct graph_edge *e, void *data)
+{
+ int i, j, component;
+ struct pg_edge_callback_data *cbdata;
+ struct pg_edata *edata = (struct pg_edata *) e->data;
+
+ /* If the edge doesn't have attached data dependence, it represents
+ compilation time known dependences. This type dependence cannot
+ be resolved by runtime alias check. */
+ if (edata == NULL || edata->alias_ddrs.length () == 0)
+ return;
+
+ cbdata = (struct pg_edge_callback_data *) data;
+ i = e->src;
+ j = e->dest;
+ component = cbdata->vertices_component[i];
+ /* Vertices are topologically sorted according to compilation time
+ known dependences, so we can break strong connected components
+ by removing edges of the opposite direction, i.e, edges pointing
+ from vertice with smaller post number to vertice with bigger post
+ number. */
+ if (g->vertices[i].post < g->vertices[j].post
+ /* We only need to remove edges connecting vertices in the same
+ strong connected component to break it. */
+ && component == cbdata->vertices_component[j]
+ /* Check if we want to break the strong connected component or not. */
+ && !bitmap_bit_p (cbdata->sccs_to_merge, component))
+ cbdata->alias_ddrs->safe_splice (edata->alias_ddrs);
+}
+
+/* This is the main function breaking strong conected components in
+ PARTITIONS giving reduced depdendence graph RDG. Store data dependence
+ relations for runtime alias check in ALIAS_DDRS. */
+
+static void
+break_alias_scc_partitions (struct graph *rdg,
+ vec<struct partition *> *partitions,
+ vec<ddr_p> *alias_ddrs)
+{
+ int i, j, num_sccs, num_sccs_no_alias;
+ /* Build partition dependence graph. */
+ graph *pg = build_partition_graph (rdg, partitions, false);
+
+ alias_ddrs->truncate (0);
+ /* Find strong connected components in the graph, with all dependence edges
+ considered. */
+ num_sccs = graphds_scc (pg, NULL);
+ /* All SCCs now can be broken by runtime alias checks because SCCs caused by
+ compilation time known dependences are merged before this function. */
+ if ((unsigned) num_sccs < partitions->length ())
+ {
+ struct pg_edge_callback_data cbdata;
+ auto_bitmap sccs_to_merge;
+ auto_vec<enum partition_type> scc_types;
+ struct partition *partition, *first;
+
+ /* If all paritions in a SCC has the same type, we can simply merge the
+ SCC. This loop finds out such SCCS and record them in bitmap. */
+ bitmap_set_range (sccs_to_merge, 0, (unsigned) num_sccs);
+ for (i = 0; i < num_sccs; ++i)
+ {
+ for (j = 0; partitions->iterate (j, &first); ++j)
+ if (pg->vertices[j].component == i)
+ break;
+ for (++j; partitions->iterate (j, &partition); ++j)
+ {
+ if (pg->vertices[j].component != i)
+ continue;
+
+ if (first->type != partition->type)
+ {
+ bitmap_clear_bit (sccs_to_merge, i);
+ break;
+ }
+ }
+ }
+
+ /* Initialize callback data for traversing. */
+ cbdata.sccs_to_merge = sccs_to_merge;
+ cbdata.alias_ddrs = alias_ddrs;
+ cbdata.vertices_component = XNEWVEC (int, pg->n_vertices);
+ /* Record the component information which will be corrupted by next
+ graph scc finding call. */
+ for (i = 0; i < pg->n_vertices; ++i)
+ cbdata.vertices_component[i] = pg->vertices[i].component;
+
+ /* Collect data dependences for runtime alias checks to break SCCs. */
+ if (bitmap_count_bits (sccs_to_merge) != (unsigned) num_sccs)
+ {
+ /* Run SCC finding algorithm again, with alias dependence edges
+ skipped. This is to topologically sort paritions according to
+ compilation time known dependence. Note the topological order
+ is stored in the form of pg's post order number. */
+ num_sccs_no_alias = graphds_scc (pg, NULL, pg_skip_alias_edge);
+ gcc_assert (partitions->length () == (unsigned) num_sccs_no_alias);
+ /* With topological order, we can construct two subgraphs L and R.
+ L contains edge <x, y> where x < y in terms of post order, while
+ R contains edge <x, y> where x > y. Edges for compilation time
+ known dependence all fall in R, so we break SCCs by removing all
+ (alias) edges of in subgraph L. */
+ for_each_edge (pg, pg_collect_alias_ddrs, &cbdata);
+ }
+
+ /* For SCC that doesn't need to be broken, merge it. */
+ for (i = 0; i < num_sccs; ++i)
+ {
+ if (!bitmap_bit_p (sccs_to_merge, i))
+ continue;
+
+ for (j = 0; partitions->iterate (j, &first); ++j)
+ if (cbdata.vertices_component[j] == i)
+ break;
+ for (++j; partitions->iterate (j, &partition); ++j)
+ {
+ struct pg_vdata *data;
+
+ if (cbdata.vertices_component[j] != i)
+ continue;
+
+ partition_merge_into (NULL, first, partition, FUSE_SAME_SCC);
+ (*partitions)[j] = NULL;
+ partition_free (partition);
+ data = (struct pg_vdata *)pg->vertices[j].data;
+ gcc_assert (data->id == j);
+ data->partition = NULL;
+ }
+ }
+ }
+
+ sort_partitions_by_post_order (pg, partitions);
+ free_partition_graph_vdata (pg);
+ for_each_edge (pg, free_partition_graph_edata_cb, NULL);
+ free_graph (pg);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Possible alias data dependence to break:\n");
+ dump_data_dependence_relations (dump_file, *alias_ddrs);
+ }
+}
+
+/* Compute and return an expression whose value is the segment length which
+ will be accessed by DR in NITERS iterations. */
+
+static tree
+data_ref_segment_size (struct data_reference *dr, tree niters)
+{
+ tree segment_length;
+
+ if (integer_zerop (DR_STEP (dr)))
+ segment_length = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
+ else
+ segment_length = size_binop (MULT_EXPR,
+ fold_convert (sizetype, DR_STEP (dr)),
+ fold_convert (sizetype, niters));
+
+ return segment_length;
+}
+
+/* Return true if LOOP's latch is dominated by statement for data reference
+ DR. */
+
+static inline bool
+latch_dominated_by_data_ref (struct loop *loop, data_reference *dr)
+{
+ return dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
+ gimple_bb (DR_STMT (dr)));
+}
+
+/* Compute alias check pairs and store them in COMP_ALIAS_PAIRS for LOOP's
+ data dependence relations ALIAS_DDRS. */
+
+static void
+compute_alias_check_pairs (struct loop *loop, vec<ddr_p> *alias_ddrs,
+ vec<dr_with_seg_len_pair_t> *comp_alias_pairs)
+{
+ unsigned int i;
+ unsigned HOST_WIDE_INT factor = 1;
+ tree niters_plus_one, niters = number_of_latch_executions (loop);
+
+ gcc_assert (niters != NULL_TREE && niters != chrec_dont_know);
+ niters = fold_convert (sizetype, niters);
+ niters_plus_one = size_binop (PLUS_EXPR, niters, size_one_node);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Creating alias check pairs:\n");
+
+ /* Iterate all data dependence relations and compute alias check pairs. */
+ for (i = 0; i < alias_ddrs->length (); i++)
+ {
+ ddr_p ddr = (*alias_ddrs)[i];
+ struct data_reference *dr_a = DDR_A (ddr);
+ struct data_reference *dr_b = DDR_B (ddr);
+ tree seg_length_a, seg_length_b;
+ int comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (dr_a),
+ DR_BASE_ADDRESS (dr_b));
+
+ if (comp_res == 0)
+ comp_res = data_ref_compare_tree (DR_OFFSET (dr_a), DR_OFFSET (dr_b));
+ gcc_assert (comp_res != 0);
+
+ if (latch_dominated_by_data_ref (loop, dr_a))
+ seg_length_a = data_ref_segment_size (dr_a, niters_plus_one);
+ else
+ seg_length_a = data_ref_segment_size (dr_a, niters);
+
+ if (latch_dominated_by_data_ref (loop, dr_b))
+ seg_length_b = data_ref_segment_size (dr_b, niters_plus_one);
+ else
+ seg_length_b = data_ref_segment_size (dr_b, niters);
+
+ dr_with_seg_len_pair_t dr_with_seg_len_pair
+ (dr_with_seg_len (dr_a, seg_length_a),
+ dr_with_seg_len (dr_b, seg_length_b));
+
+ /* Canonicalize pairs by sorting the two DR members. */
+ if (comp_res > 0)
+ std::swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
+
+ comp_alias_pairs->safe_push (dr_with_seg_len_pair);
+ }
+
+ if (tree_fits_uhwi_p (niters))
+ factor = tree_to_uhwi (niters);
+
+ /* Prune alias check pairs. */
+ prune_runtime_alias_test_list (comp_alias_pairs, factor);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Improved number of alias checks from %d to %d\n",
+ alias_ddrs->length (), comp_alias_pairs->length ());
+}
+
+/* Given data dependence relations in ALIAS_DDRS, generate runtime alias
+ checks and version LOOP under condition of these runtime alias checks. */
+
+static void
+version_loop_by_alias_check (struct loop *loop, vec<ddr_p> *alias_ddrs)
+{
+ profile_probability prob;
+ basic_block cond_bb;
+ struct loop *nloop;
+ tree lhs, arg0, cond_expr = NULL_TREE;
+ gimple_seq cond_stmts = NULL;
+ gimple *call_stmt = NULL;
+ auto_vec<dr_with_seg_len_pair_t> comp_alias_pairs;
+
+ /* Generate code for runtime alias checks if necessary. */
+ gcc_assert (alias_ddrs->length () > 0);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Version loop <%d> with runtime alias check\n", loop->num);
+
+ compute_alias_check_pairs (loop, alias_ddrs, &comp_alias_pairs);
+ create_runtime_alias_checks (loop, &comp_alias_pairs, &cond_expr);
+ cond_expr = force_gimple_operand_1 (cond_expr, &cond_stmts,
+ is_gimple_condexpr, NULL_TREE);
+
+ /* Depend on vectorizer to fold IFN_LOOP_DIST_ALIAS. */
+ if (flag_tree_loop_vectorize)
+ {
+ /* Generate internal function call for loop distribution alias check. */
+ call_stmt = gimple_build_call_internal (IFN_LOOP_DIST_ALIAS,
+ 2, NULL_TREE, cond_expr);
+ lhs = make_ssa_name (boolean_type_node);
+ gimple_call_set_lhs (call_stmt, lhs);
+ }
+ else
+ lhs = cond_expr;
+
+ prob = profile_probability::guessed_always ().apply_scale (9, 10);
+ initialize_original_copy_tables ();
+ nloop = loop_version (loop, lhs, &cond_bb, prob, prob.invert (),
+ prob, prob.invert (), true);
+ free_original_copy_tables ();
+ /* Record the original loop number in newly generated loops. In case of
+ distribution, the original loop will be distributed and the new loop
+ is kept. */
+ loop->orig_loop_num = nloop->num;
+ nloop->orig_loop_num = nloop->num;
+ nloop->dont_vectorize = true;
+ nloop->force_vectorize = false;
+
+ if (call_stmt)
+ {
+ /* Record new loop's num in IFN_LOOP_DIST_ALIAS because the original
+ loop could be destroyed. */
+ arg0 = build_int_cst (integer_type_node, loop->orig_loop_num);
+ gimple_call_set_arg (call_stmt, 0, arg0);
+ gimple_seq_add_stmt_without_update (&cond_stmts, call_stmt);
+ }
+
+ if (cond_stmts)
+ {
+ gimple_stmt_iterator cond_gsi = gsi_last_bb (cond_bb);
+ gsi_insert_seq_before (&cond_gsi, cond_stmts, GSI_SAME_STMT);
+ }
+ update_ssa (TODO_update_ssa);
+}
+
+/* Return true if loop versioning is needed to distrubute PARTITIONS.
+ ALIAS_DDRS are data dependence relations for runtime alias check. */
+
+static inline bool
+version_for_distribution_p (vec<struct partition *> *partitions,
+ vec<ddr_p> *alias_ddrs)
+{
+ /* No need to version loop if we have only one partition. */
+ if (partitions->length () == 1)
+ return false;
+
+ /* Need to version loop if runtime alias check is necessary. */
+ return (alias_ddrs->length () > 0);
+}
+
+/* Fuse all partitions if necessary before finalizing distribution. */
+
+static void
+finalize_partitions (vec<struct partition *> *partitions,
+ vec<ddr_p> *alias_ddrs)
+{
+ unsigned i;
+ struct partition *a, *partition;
+
+ if (partitions->length () == 1
+ || alias_ddrs->length () > 0)
+ return;
+
+ a = (*partitions)[0];
+ if (a->kind != PKIND_NORMAL)
+ return;
+
+ for (i = 1; partitions->iterate (i, &partition); ++i)
+ {
+ /* Don't fuse if partition has different type or it is a builtin. */
+ if (partition->type != a->type
+ || partition->kind != PKIND_NORMAL)
+ return;
+ }
+
+ /* Fuse all partitions. */
+ for (i = 1; partitions->iterate (i, &partition); ++i)
+ {
+ partition_merge_into (NULL, a, partition, FUSE_FINALIZE);
+ partition_free (partition);
+ }
+ partitions->truncate (1);
+}
+
+/* Distributes the code from LOOP in such a way that producer statements
+ are placed before consumer statements. Tries to separate only the
+ statements from STMTS into separate loops. Returns the number of
+ distributed loops. Set NB_CALLS to number of generated builtin calls.
+ Set *DESTROY_P to whether LOOP needs to be destroyed. */
static int
distribute_loop (struct loop *loop, vec<gimple *> stmts,
@@ -1453,16 +2370,18 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
partition *partition;
bool any_builtin;
int i, nbp;
- graph *pg = NULL;
- int num_sccs = 1;
*destroy_p = false;
*nb_calls = 0;
- auto_vec<loop_p, 3> loop_nest;
+ loop_nest.create (0);
if (!find_loop_nest (loop, &loop_nest))
- return 0;
+ {
+ loop_nest.release ();
+ return 0;
+ }
- rdg = build_rdg (loop_nest, cd);
+ datarefs_vec.create (20);
+ rdg = build_rdg (loop, cd);
if (!rdg)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1470,19 +2389,45 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
"Loop %d not distributed: failed to build the RDG.\n",
loop->num);
+ loop_nest.release ();
+ free_data_refs (datarefs_vec);
+ return 0;
+ }
+
+ if (datarefs_vec.length () > MAX_DATAREFS_NUM)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Loop %d not distributed: too many memory references.\n",
+ loop->num);
+
+ free_rdg (rdg);
+ loop_nest.release ();
+ free_data_refs (datarefs_vec);
return 0;
}
+ data_reference_p dref;
+ for (i = 0; datarefs_vec.iterate (i, &dref); ++i)
+ dref->aux = (void *) (uintptr_t) i;
+
if (dump_file && (dump_flags & TDF_DETAILS))
dump_rdg (dump_file, rdg);
auto_vec<struct partition *, 3> partitions;
rdg_build_partitions (rdg, stmts, &partitions);
+ auto_vec<ddr_p> alias_ddrs;
+
+ auto_bitmap stmt_in_all_partitions;
+ bitmap_copy (stmt_in_all_partitions, partitions[0]->stmts);
+ for (i = 1; partitions.iterate (i, &partition); ++i)
+ bitmap_and_into (stmt_in_all_partitions, partitions[i]->stmts);
+
any_builtin = false;
FOR_EACH_VEC_ELT (partitions, i, partition)
{
- classify_partition (loop, rdg, partition);
+ classify_partition (loop, rdg, partition, stmt_in_all_partitions);
any_builtin |= partition_builtin_p (partition);
}
@@ -1508,13 +2453,7 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
for (++i; partitions.iterate (i, &partition); ++i)
if (!partition_builtin_p (partition))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing non-builtin partitions\n");
- dump_bitmap (dump_file, into->stmts);
- dump_bitmap (dump_file, partition->stmts);
- }
- partition_merge_into (into, partition);
+ partition_merge_into (NULL, into, partition, FUSE_NON_BUILTIN);
partitions.unordered_remove (i);
partition_free (partition);
i--;
@@ -1530,14 +2469,7 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
for (i = i + 1; partitions.iterate (i, &partition); ++i)
if (partition_reduction_p (partition))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing partitions\n");
- dump_bitmap (dump_file, into->stmts);
- dump_bitmap (dump_file, partition->stmts);
- fprintf (dump_file, "because they have reductions\n");
- }
- partition_merge_into (into, partition);
+ partition_merge_into (rdg, into, partition, FUSE_REDUCTION);
partitions.unordered_remove (i);
partition_free (partition);
i--;
@@ -1553,17 +2485,9 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
for (int j = i + 1;
partitions.iterate (j, &partition); ++j)
{
- if (similar_memory_accesses (rdg, into, partition))
+ if (share_memory_accesses (rdg, into, partition))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing partitions\n");
- dump_bitmap (dump_file, into->stmts);
- dump_bitmap (dump_file, partition->stmts);
- fprintf (dump_file, "because they have similar "
- "memory accesses\n");
- }
- partition_merge_into (into, partition);
+ partition_merge_into (rdg, into, partition, FUSE_SHARE_REF);
partitions.unordered_remove (j);
partition_free (partition);
j--;
@@ -1581,111 +2505,14 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
/* Build the partition dependency graph. */
if (partitions.length () > 1)
{
- pg = new_graph (partitions.length ());
- struct pgdata {
- struct partition *partition;
- vec<data_reference_p> writes;
- vec<data_reference_p> reads;
- };
-#define PGDATA(i) ((pgdata *)(pg->vertices[i].data))
- for (i = 0; partitions.iterate (i, &partition); ++i)
- {
- vertex *v = &pg->vertices[i];
- pgdata *data = new pgdata;
- data_reference_p dr;
- /* FIXME - leaks. */
- v->data = data;
- bitmap_iterator bi;
- unsigned j;
- data->partition = partition;
- data->reads = vNULL;
- data->writes = vNULL;
- EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, j, bi)
- for (int k = 0; RDG_DATAREFS (rdg, j).iterate (k, &dr); ++k)
- if (DR_IS_READ (dr))
- data->reads.safe_push (dr);
- else
- data->writes.safe_push (dr);
- }
- struct partition *partition1, *partition2;
- for (i = 0; partitions.iterate (i, &partition1); ++i)
- for (int j = i + 1; partitions.iterate (j, &partition2); ++j)
- {
- /* dependence direction - 0 is no dependence, -1 is back,
- 1 is forth, 2 is both (we can stop then, merging will occur). */
- int dir = 0;
- dir = pg_add_dependence_edges (rdg, loop_nest, dir,
- PGDATA(i)->writes,
- PGDATA(j)->reads);
- if (dir != 2)
- dir = pg_add_dependence_edges (rdg, loop_nest, dir,
- PGDATA(i)->reads,
- PGDATA(j)->writes);
- if (dir != 2)
- dir = pg_add_dependence_edges (rdg, loop_nest, dir,
- PGDATA(i)->writes,
- PGDATA(j)->writes);
- if (dir == 1 || dir == 2)
- add_edge (pg, i, j);
- if (dir == -1 || dir == 2)
- add_edge (pg, j, i);
- }
-
- /* Add edges to the reduction partition (if any) to force it last. */
- unsigned j;
- for (j = 0; partitions.iterate (j, &partition); ++j)
- if (partition_reduction_p (partition))
- break;
- if (j < partitions.length ())
- {
- for (unsigned i = 0; partitions.iterate (i, &partition); ++i)
- if (i != j)
- add_edge (pg, i, j);
- }
-
- /* Compute partitions we cannot separate and fuse them. */
- num_sccs = graphds_scc (pg, NULL);
- for (i = 0; i < num_sccs; ++i)
- {
- struct partition *first;
- int j;
- for (j = 0; partitions.iterate (j, &first); ++j)
- if (pg->vertices[j].component == i)
- break;
- for (j = j + 1; partitions.iterate (j, &partition); ++j)
- if (pg->vertices[j].component == i)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing partitions\n");
- dump_bitmap (dump_file, first->stmts);
- dump_bitmap (dump_file, partition->stmts);
- fprintf (dump_file, "because they are in the same "
- "dependence SCC\n");
- }
- partition_merge_into (first, partition);
- partitions[j] = NULL;
- partition_free (partition);
- PGDATA (j)->partition = NULL;
- }
- }
-
- /* Now order the remaining nodes in postorder. */
- qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
- partitions.truncate (0);
- for (i = 0; i < pg->n_vertices; ++i)
- {
- pgdata *data = PGDATA (i);
- if (data->partition)
- partitions.safe_push (data->partition);
- data->reads.release ();
- data->writes.release ();
- delete data;
- }
- gcc_assert (partitions.length () == (unsigned)num_sccs);
- free_graph (pg);
+ merge_dep_scc_partitions (rdg, &partitions);
+ alias_ddrs.truncate (0);
+ if (partitions.length () > 1)
+ break_alias_scc_partitions (rdg, &partitions, &alias_ddrs);
}
+ finalize_partitions (&partitions, &alias_ddrs);
+
nbp = partitions.length ();
if (nbp == 0
|| (nbp == 1 && !partition_builtin_p (partitions[0]))
@@ -1695,8 +2522,15 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
goto ldist_done;
}
+ if (version_for_distribution_p (&partitions, &alias_ddrs))
+ version_loop_by_alias_check (loop, &alias_ddrs);
+
if (dump_file && (dump_flags & TDF_DETAILS))
- dump_rdg_partitions (dump_file, partitions);
+ {
+ fprintf (dump_file,
+ "distribute loop <%d> into partitions:\n", loop->num);
+ dump_rdg_partitions (dump_file, partitions);
+ }
FOR_EACH_VEC_ELT (partitions, i, partition)
{
@@ -1706,6 +2540,15 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
}
ldist_done:
+ loop_nest.release ();
+ free_data_refs (datarefs_vec);
+ for (hash_table<ddr_hasher>::iterator iter = ddrs_table.begin ();
+ iter != ddrs_table.end (); ++iter)
+ {
+ free_dependence_relation (*iter);
+ *iter = NULL;
+ }
+ ddrs_table.empty ();
FOR_EACH_VEC_ELT (partitions, i, partition)
partition_free (partition);
@@ -1758,6 +2601,26 @@ pass_loop_distribution::execute (function *fun)
control_dependences *cd = NULL;
auto_vec<loop_p> loops_to_be_destroyed;
+ if (number_of_loops (fun) <= 1)
+ return 0;
+
+ /* Compute topological order for basic blocks. Topological order is
+ needed because data dependence is computed for data references in
+ lexicographical order. */
+ if (bb_top_order_index == NULL)
+ {
+ int rpo_num;
+ int *rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
+
+ bb_top_order_index = XNEWVEC (int, last_basic_block_for_fn (cfun));
+ bb_top_order_index_size = last_basic_block_for_fn (cfun);
+ rpo_num = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, true);
+ for (int i = 0; i < rpo_num; i++)
+ bb_top_order_index[rpo[i]] = i;
+
+ free (rpo);
+ }
+
FOR_ALL_BB_FN (bb, fun)
{
gimple_stmt_iterator gsi;
@@ -1785,6 +2648,11 @@ pass_loop_distribution::execute (function *fun)
if (!optimize_loop_for_speed_p (loop))
continue;
+ /* Don't distribute loop if niters is unknown. */
+ tree niters = number_of_latch_executions (loop);
+ if (niters == NULL_TREE || niters == chrec_dont_know)
+ continue;
+
/* Initialize the worklist with stmts we seed the partitions with. */
bbs = get_loop_body_in_dom_order (loop);
for (i = 0; i < loop->num_nodes; ++i)
@@ -1865,13 +2733,20 @@ out:
if (cd)
delete cd;
+ if (bb_top_order_index != NULL)
+ {
+ free (bb_top_order_index);
+ bb_top_order_index = NULL;
+ bb_top_order_index_size = 0;
+ }
+
if (changed)
{
/* Destroy loop bodies that could not be reused. Do this late as we
otherwise can end up refering to stale data in control dependences. */
unsigned i;
FOR_EACH_VEC_ELT (loops_to_be_destroyed, i, loop)
- destroy_loop (loop);
+ destroy_loop (loop);
/* Cached scalar evolutions now may refer to wrong or non-existing
loops. */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 79d616b760a..538932e50bf 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1824,7 +1824,7 @@ try_transform_to_exit_first_loop_alt (struct loop *loop,
/* Figure out whether nit + 1 overflows. */
if (TREE_CODE (nit) == INTEGER_CST)
{
- if (!tree_int_cst_equal (nit, TYPE_MAXVAL (nit_type)))
+ if (!tree_int_cst_equal (nit, TYPE_MAX_VALUE (nit_type)))
{
alt_bound = fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR, nit_type,
nit, build_one_cst (nit_type));
@@ -1869,7 +1869,7 @@ try_transform_to_exit_first_loop_alt (struct loop *loop,
return false;
/* Check if nit + 1 overflows. */
- widest_int type_max = wi::to_widest (TYPE_MAXVAL (nit_type));
+ widest_int type_max = wi::to_widest (TYPE_MAX_VALUE (nit_type));
if (nit_max >= type_max)
return false;
@@ -2115,10 +2115,12 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
gcc_assert (exit == single_dom_exit (loop));
guard = make_edge (for_bb, ex_bb, 0);
+ /* FIXME: What is the probability? */
+ guard->probability = profile_probability::guessed_never ();
/* Split the latch edge, so LOOPS_HAVE_SIMPLE_LATCHES is still valid. */
loop->latch = split_edge (single_succ_edge (loop->latch));
single_pred_edge (loop->latch)->flags = 0;
- end = make_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
+ end = make_single_succ_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
rescan_loop_exit (end, true, false);
for (gphi_iterator gpi = gsi_start_phis (ex_bb);
@@ -2249,7 +2251,6 @@ gen_parallel_loop (struct loop *loop,
gimple_seq stmts;
edge entry, exit;
struct clsn_data clsn_data;
- unsigned prob;
location_t loc;
gimple *cond_stmt;
unsigned int m_p_thread=2;
@@ -2356,10 +2357,11 @@ gen_parallel_loop (struct loop *loop,
initialize_original_copy_tables ();
/* We assume that the loop usually iterates a lot. */
- prob = 4 * REG_BR_PROB_BASE / 5;
loop_version (loop, many_iterations_cond, NULL,
- prob, REG_BR_PROB_BASE - prob,
- prob, REG_BR_PROB_BASE - prob, true);
+ profile_probability::likely (),
+ profile_probability::unlikely (),
+ profile_probability::likely (),
+ profile_probability::unlikely (), true);
update_ssa (TODO_update_ssa);
free_original_copy_tables ();
}
@@ -2473,23 +2475,39 @@ build_new_reduction (reduction_info_table_type *reduction_list,
gcc_assert (reduc_stmt);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file,
- "Detected reduction. reduction stmt is:\n");
- print_gimple_stmt (dump_file, reduc_stmt, 0);
- fprintf (dump_file, "\n");
- }
-
if (gimple_code (reduc_stmt) == GIMPLE_PHI)
{
tree op1 = PHI_ARG_DEF (reduc_stmt, 0);
gimple *def1 = SSA_NAME_DEF_STMT (op1);
reduction_code = gimple_assign_rhs_code (def1);
}
-
else
reduction_code = gimple_assign_rhs_code (reduc_stmt);
+ /* Check for OpenMP supported reduction. */
+ switch (reduction_code)
+ {
+ case PLUS_EXPR:
+ case MULT_EXPR:
+ case MAX_EXPR:
+ case MIN_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ case TRUTH_AND_EXPR:
+ break;
+ default:
+ return;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "Detected reduction. reduction stmt is:\n");
+ print_gimple_stmt (dump_file, reduc_stmt, 0);
+ fprintf (dump_file, "\n");
+ }
new_reduction = XCNEW (struct reduction_info);
@@ -3132,6 +3150,8 @@ oacc_entry_exit_single_gang (bitmap in_loop_bbs, vec<basic_block> region_bbs,
gsi_insert_after (&gsi2, cond, GSI_NEW_STMT);
edge e3 = make_edge (bb, bb3, EDGE_FALSE_VALUE);
+ /* FIXME: What is the probability? */
+ e3->probability = profile_probability::guessed_never ();
e->flags = EDGE_TRUE_VALUE;
tree vdef = gimple_vdef (stmt);
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index c49c5c1d6e4..1c2e5c555ab 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -190,7 +190,7 @@ make_phi_node (tree var, int len)
else
gimple_phi_set_result (phi, make_ssa_name (var, phi));
- for (i = 0; i < capacity; i++)
+ for (i = 0; i < len; i++)
{
use_operand_p imm;
@@ -248,6 +248,10 @@ resize_phi_node (gphi *phi, size_t len)
new_phi = allocate_phi_node (len);
memcpy (new_phi, phi, old_size);
+ memset ((char *)new_phi + old_size, 0,
+ (sizeof (struct gphi)
+ - sizeof (struct phi_arg_d)
+ + sizeof (struct phi_arg_d) * len) - old_size);
for (i = 0; i < gimple_phi_num_args (new_phi); i++)
{
@@ -260,18 +264,6 @@ resize_phi_node (gphi *phi, size_t len)
new_phi->capacity = len;
- for (i = gimple_phi_num_args (new_phi); i < len; i++)
- {
- use_operand_p imm;
-
- gimple_phi_arg_set_location (new_phi, i, UNKNOWN_LOCATION);
- imm = gimple_phi_arg_imm_use_ptr (new_phi, i);
- imm->use = gimple_phi_arg_def_ptr (new_phi, i);
- imm->prev = NULL;
- imm->next = NULL;
- imm->loc.stmt = new_phi;
- }
-
return new_phi;
}
@@ -300,6 +292,8 @@ reserve_phi_args_for_new_edge (basic_block bb)
stmt = new_phi;
}
+ stmt->nargs++;
+
/* We represent a "missing PHI argument" by placing NULL_TREE in
the corresponding slot. If PHI arguments were added
immediately after an edge is created, this zeroing would not
@@ -307,10 +301,13 @@ reserve_phi_args_for_new_edge (basic_block bb)
example, the loop optimizer duplicates several basic blocks,
redirects edges, and then fixes up PHI arguments later in
batch. */
+ use_operand_p imm = gimple_phi_arg_imm_use_ptr (stmt, len - 1);
+ imm->use = gimple_phi_arg_def_ptr (stmt, len - 1);
+ imm->prev = NULL;
+ imm->next = NULL;
+ imm->loc.stmt = stmt;
SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE);
gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION);
-
- stmt->nargs++;
}
}
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 23e7870dd2d..a4011bf4698 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -156,29 +156,45 @@ along with GCC; see the file COPYING3. If not see
b[10] = x;
}
- TODO -- stores killing other stores can be taken into account, e.g.,
- for (i = 0; i < n; i++)
- {
- a[i] = 1;
- a[i+2] = 2;
- }
+ Apart from predictive commoning on Load-Load and Store-Load chains, we
+ also support Store-Store chains -- stores killed by other store can be
+ eliminated. Given below example:
+
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ a[i+2] = 2;
+ }
- can be replaced with
+ It can be replaced with:
- t0 = a[0];
- t1 = a[1];
- for (i = 0; i < n; i++)
- {
- a[i] = 1;
- t2 = 2;
- t0 = t1;
- t1 = t2;
- }
- a[n] = t0;
- a[n+1] = t1;
+ t0 = a[0];
+ t1 = a[1];
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ t2 = 2;
+ t0 = t1;
+ t1 = t2;
+ }
+ a[n] = t0;
+ a[n+1] = t1;
+
+ If the loop runs more than 1 iterations, it can be further simplified into:
+
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ }
+ a[n] = 2;
+ a[n+1] = 2;
- The interesting part is that this would generalize store motion; still, since
- sm is performed elsewhere, it does not seem that important.
+ The interesting part is this can be viewed either as general store motion
+ or general dead store elimination in either intra/inter-iterations way.
+
+ TODO: For now, we don't support store-store chains in multi-exit loops. We
+ force to not unroll in case of store-store chain even if other chains might
+ ask for unroll.
Predictive commoning can be generalized for arbitrary computations (not
just memory loads), and also nontrivial transfer functions (e.g., replacing
@@ -265,6 +281,9 @@ enum chain_type
/* Root of the chain is store, the rest are loads. */
CT_STORE_LOAD,
+ /* There are only stores in the chain. */
+ CT_STORE_STORE,
+
/* A combination of two chains. */
CT_COMBINATION
};
@@ -294,6 +313,15 @@ typedef struct chain
/* Initializers for the variables. */
vec<tree> inits;
+ /* Finalizers for the eliminated stores. */
+ vec<tree> finis;
+
+ /* gimple stmts intializing the initial variables of the chain. */
+ gimple_seq init_seq;
+
+ /* gimple stmts finalizing the eliminated stores of the chain. */
+ gimple_seq fini_seq;
+
/* True if there is a use of a variable with the maximal distance
that comes after the root in the loop. */
unsigned has_max_use_after : 1;
@@ -303,6 +331,10 @@ typedef struct chain
/* True if this chain was combined together with some other chain. */
unsigned combined : 1;
+
+ /* True if this is store elimination chain and eliminated stores store
+ loop invariant value into memory. */
+ unsigned inv_store_elimination : 1;
} *chain_p;
@@ -331,6 +363,10 @@ struct component
/* What we know about the step of the references in the component. */
enum ref_step_type comp_step;
+ /* True if all references in component are stores and we try to do
+ intra/inter loop iteration dead store elimination. */
+ bool eliminate_store_p;
+
/* Next component in the list. */
struct component *next;
};
@@ -401,6 +437,10 @@ dump_chain (FILE *file, chain_p chain)
chain_type = "Store-loads";
break;
+ case CT_STORE_STORE:
+ chain_type = "Store-stores";
+ break;
+
case CT_COMBINATION:
chain_type = "Combination";
break;
@@ -511,6 +551,12 @@ release_chain (chain_p chain)
chain->refs.release ();
chain->vars.release ();
chain->inits.release ();
+ if (chain->init_seq)
+ gimple_seq_discard (chain->init_seq);
+
+ chain->finis.release ();
+ if (chain->fini_seq)
+ gimple_seq_discard (chain->fini_seq);
free (chain);
}
@@ -714,6 +760,8 @@ split_data_refs_to_components (struct loop *loop,
struct data_dependence_relation *ddr;
struct component *comp_list = NULL, *comp;
dref dataref;
+ /* Don't do store elimination if loop has multiple exit edges. */
+ bool eliminate_store_p = single_exit (loop) != NULL;
basic_block last_always_executed = last_always_executed_block (loop);
FOR_EACH_VEC_ELT (datarefs, i, dr)
@@ -756,6 +804,14 @@ split_data_refs_to_components (struct loop *loop,
dra = DDR_A (ddr);
drb = DDR_B (ddr);
+
+ /* Don't do store elimination if there is any unknown dependence for
+ any store data reference. */
+ if ((DR_IS_WRITE (dra) || DR_IS_WRITE (drb))
+ && (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
+ || DDR_NUM_DIST_VECTS (ddr) == 0))
+ eliminate_store_p = false;
+
ia = component_of (comp_father, (unsigned) (size_t) dra->aux);
ib = component_of (comp_father, (unsigned) (size_t) drb->aux);
if (ia == ib)
@@ -795,10 +851,28 @@ split_data_refs_to_components (struct loop *loop,
continue;
}
}
+ else if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb)
+ && ia != bad && ib != bad
+ && !determine_offset (dra, drb, &dummy_off))
+ {
+ merge_comps (comp_father, comp_size, bad, ia);
+ merge_comps (comp_father, comp_size, bad, ib);
+ continue;
+ }
merge_comps (comp_father, comp_size, ia, ib);
}
+ if (eliminate_store_p)
+ {
+ tree niters = number_of_latch_executions (loop);
+
+ /* Don't do store elimination if niters info is unknown because stores
+ in the last iteration can't be eliminated and we need to recover it
+ after loop. */
+ eliminate_store_p = (niters != NULL_TREE && niters != chrec_dont_know);
+ }
+
comps = XCNEWVEC (struct component *, n);
bad = component_of (comp_father, n);
FOR_EACH_VEC_ELT (datarefs, i, dr)
@@ -813,6 +887,7 @@ split_data_refs_to_components (struct loop *loop,
{
comp = XCNEW (struct component);
comp->refs.create (comp_size[ca]);
+ comp->eliminate_store_p = eliminate_store_p;
comps[ca] = comp;
}
@@ -827,6 +902,8 @@ split_data_refs_to_components (struct loop *loop,
gimple_bb (dataref->stmt));
dataref->pos = comp->refs.length ();
comp->refs.quick_push (dataref);
+ if (DR_IS_READ (dr))
+ comp->eliminate_store_p = false;
}
for (i = 0; i < n; i++)
@@ -951,6 +1028,21 @@ get_chain_root (chain_p chain)
return chain->refs[0];
}
+/* Given CHAIN, returns the last ref at DISTANCE, or NULL if it doesn't
+ exist. */
+
+static inline dref
+get_chain_last_ref_at (chain_p chain, unsigned distance)
+{
+ unsigned i;
+
+ for (i = chain->refs.length (); i > 0; i--)
+ if (distance == chain->refs[i - 1]->distance)
+ break;
+
+ return (i > 0) ? chain->refs[i - 1] : NULL;
+}
+
/* Adds REF to the chain CHAIN. */
static void
@@ -1003,23 +1095,27 @@ make_invariant_chain (struct component *comp)
chain->all_always_accessed &= ref->always_accessed;
}
+ chain->inits = vNULL;
+ chain->finis = vNULL;
+
return chain;
}
-/* Make a new chain rooted at REF. */
+/* Make a new chain of type TYPE rooted at REF. */
static chain_p
-make_rooted_chain (dref ref)
+make_rooted_chain (dref ref, enum chain_type type)
{
chain_p chain = XCNEW (struct chain);
- chain->type = DR_IS_READ (ref->ref) ? CT_LOAD : CT_STORE_LOAD;
-
+ chain->type = type;
chain->refs.safe_push (ref);
chain->all_always_accessed = ref->always_accessed;
-
ref->distance = 0;
+ chain->inits = vNULL;
+ chain->finis = vNULL;
+
return chain;
}
@@ -1149,7 +1245,7 @@ find_looparound_phi (struct loop *loop, dref ref, dref root)
memset (&init_dr, 0, sizeof (struct data_reference));
DR_REF (&init_dr) = init_ref;
DR_STMT (&init_dr) = phi;
- if (!dr_analyze_innermost (&init_dr, loop))
+ if (!dr_analyze_innermost (&DR_INNERMOST (&init_dr), init_ref, loop))
return NULL;
if (!valid_initializer_p (&init_dr, ref->distance + 1, root->ref))
@@ -1194,6 +1290,9 @@ add_looparound_copies (struct loop *loop, chain_p chain)
dref ref, root = get_chain_root (chain);
gphi *phi;
+ if (chain->type == CT_STORE_STORE)
+ return;
+
FOR_EACH_VEC_ELT (chain->refs, i, ref)
{
phi = find_looparound_phi (loop, ref, root);
@@ -1218,6 +1317,7 @@ determine_roots_comp (struct loop *loop,
dref a;
chain_p chain = NULL;
widest_int last_ofs = 0;
+ enum chain_type type;
/* Invariants are handled specially. */
if (comp->comp_step == RS_INVARIANT)
@@ -1227,11 +1327,15 @@ determine_roots_comp (struct loop *loop,
return;
}
- comp->refs.qsort (order_drefs);
+ /* Trivial component. */
+ if (comp->refs.length () <= 1)
+ return;
+ comp->refs.qsort (order_drefs);
FOR_EACH_VEC_ELT (comp->refs, i, a)
{
- if (!chain || DR_IS_WRITE (a->ref)
+ if (!chain
+ || (!comp->eliminate_store_p && DR_IS_WRITE (a->ref))
|| wi::leu_p (MAX_DISTANCE, a->offset - last_ofs))
{
if (nontrivial_chain_p (chain))
@@ -1241,7 +1345,13 @@ determine_roots_comp (struct loop *loop,
}
else
release_chain (chain);
- chain = make_rooted_chain (a);
+
+ if (DR_IS_READ (a->ref))
+ type = CT_LOAD;
+ else
+ type = comp->eliminate_store_p ? CT_STORE_STORE : CT_STORE_LOAD;
+
+ chain = make_rooted_chain (a, type);
last_ofs = a->offset;
continue;
}
@@ -1362,11 +1472,12 @@ replace_ref_with (gimple *stmt, tree new_tree, bool set, bool in_lhs)
gsi_insert_after (&bsi, new_stmt, GSI_NEW_STMT);
}
-/* Returns a memory reference to DR in the ITER-th iteration of
- the loop it was analyzed in. Append init stmts to STMTS. */
+/* Returns a memory reference to DR in the (NITERS + ITER)-th iteration
+ of the loop it was analyzed in. Append init stmts to STMTS. */
static tree
-ref_at_iteration (data_reference_p dr, int iter, gimple_seq *stmts)
+ref_at_iteration (data_reference_p dr, int iter,
+ gimple_seq *stmts, tree niters = NULL_TREE)
{
tree off = DR_OFFSET (dr);
tree coff = DR_INIT (dr);
@@ -1375,14 +1486,27 @@ ref_at_iteration (data_reference_p dr, int iter, gimple_seq *stmts)
tree ref_type = NULL_TREE;
tree ref_op1 = NULL_TREE;
tree ref_op2 = NULL_TREE;
- if (iter == 0)
- ;
- else if (TREE_CODE (DR_STEP (dr)) == INTEGER_CST)
- coff = size_binop (PLUS_EXPR, coff,
- size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
- else
- off = size_binop (PLUS_EXPR, off,
- size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
+ tree new_offset;
+
+ if (iter != 0)
+ {
+ new_offset = size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter));
+ if (TREE_CODE (new_offset) == INTEGER_CST)
+ coff = size_binop (PLUS_EXPR, coff, new_offset);
+ else
+ off = size_binop (PLUS_EXPR, off, new_offset);
+ }
+
+ if (niters != NULL_TREE)
+ {
+ niters = fold_convert (ssizetype, niters);
+ new_offset = size_binop (MULT_EXPR, DR_STEP (dr), niters);
+ if (TREE_CODE (niters) == INTEGER_CST)
+ coff = size_binop (PLUS_EXPR, coff, new_offset);
+ else
+ off = size_binop (PLUS_EXPR, off, new_offset);
+ }
+
/* While data-ref analysis punts on bit offsets it still handles
bitfield accesses at byte boundaries. Cope with that. Note that
if the bitfield object also starts at a byte-boundary we can simply
@@ -1514,21 +1638,204 @@ initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars)
}
}
-/* Create the variables and initialization statement for root of chain
- CHAIN. Uids of the newly created temporary variables are marked
- in TMP_VARS. */
+/* For inter-iteration store elimination CHAIN in LOOP, returns true if
+ all stores to be eliminated store loop invariant values into memory.
+ In this case, we can use these invariant values directly after LOOP. */
+
+static bool
+is_inv_store_elimination_chain (struct loop *loop, chain_p chain)
+{
+ if (chain->length == 0 || chain->type != CT_STORE_STORE)
+ return false;
+
+ gcc_assert (!chain->has_max_use_after);
+
+ /* If loop iterates for unknown times or fewer times than chain->lenght,
+ we still need to setup root variable and propagate it with PHI node. */
+ tree niters = number_of_latch_executions (loop);
+ if (TREE_CODE (niters) != INTEGER_CST || wi::leu_p (niters, chain->length))
+ return false;
+
+ /* Check stores in chain for elimination if they only store loop invariant
+ values. */
+ for (unsigned i = 0; i < chain->length; i++)
+ {
+ dref a = get_chain_last_ref_at (chain, i);
+ if (a == NULL)
+ continue;
+
+ gimple *def_stmt, *stmt = a->stmt;
+ if (!gimple_assign_single_p (stmt))
+ return false;
+
+ tree val = gimple_assign_rhs1 (stmt);
+ if (TREE_CLOBBER_P (val))
+ return false;
+
+ if (CONSTANT_CLASS_P (val))
+ continue;
+
+ if (TREE_CODE (val) != SSA_NAME)
+ return false;
+
+ def_stmt = SSA_NAME_DEF_STMT (val);
+ if (gimple_nop_p (def_stmt))
+ continue;
+
+ if (flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
+ return false;
+ }
+ return true;
+}
+
+/* Creates root variables for store elimination CHAIN in which stores for
+ elimination only store loop invariant values. In this case, we neither
+ need to load root variables before loop nor propagate it with PHI nodes. */
static void
-initialize_root (struct loop *loop, chain_p chain, bitmap tmp_vars)
+initialize_root_vars_store_elim_1 (chain_p chain)
{
- dref root = get_chain_root (chain);
- bool in_lhs = (chain->type == CT_STORE_LOAD
- || chain->type == CT_COMBINATION);
+ tree var;
+ unsigned i, n = chain->length;
+
+ chain->vars.create (n);
+ chain->vars.safe_grow_cleared (n);
+
+ /* Initialize root value for eliminated stores at each distance. */
+ for (i = 0; i < n; i++)
+ {
+ dref a = get_chain_last_ref_at (chain, i);
+ if (a == NULL)
+ continue;
+
+ var = gimple_assign_rhs1 (a->stmt);
+ chain->vars[a->distance] = var;
+ }
+
+ /* We don't propagate values with PHI nodes, so manually propagate value
+ to bubble positions. */
+ var = chain->vars[0];
+ for (i = 1; i < n; i++)
+ {
+ if (chain->vars[i] != NULL_TREE)
+ {
+ var = chain->vars[i];
+ continue;
+ }
+ chain->vars[i] = var;
+ }
+
+ /* Revert the vector. */
+ for (i = 0; i < n / 2; i++)
+ std::swap (chain->vars[i], chain->vars[n - i - 1]);
+}
+
+/* Creates root variables for store elimination CHAIN in which stores for
+ elimination store loop variant values. In this case, we may need to
+ load root variables before LOOP and propagate it with PHI nodes. Uids
+ of the newly created root variables are marked in TMP_VARS. */
+
+static void
+initialize_root_vars_store_elim_2 (struct loop *loop,
+ chain_p chain, bitmap tmp_vars)
+{
+ unsigned i, n = chain->length;
+ tree ref, init, var, next, val, phi_result;
+ gimple *stmt;
+ gimple_seq stmts;
+
+ chain->vars.create (n);
+
+ ref = DR_REF (get_chain_root (chain)->ref);
+ for (i = 0; i < n; i++)
+ {
+ var = predcom_tmp_var (ref, i, tmp_vars);
+ chain->vars.quick_push (var);
+ }
+
+ FOR_EACH_VEC_ELT (chain->vars, i, var)
+ chain->vars[i] = make_ssa_name (var);
+
+ /* Root values are either rhs operand of stores to be eliminated, or
+ loaded from memory before loop. */
+ auto_vec<tree> vtemps;
+ vtemps.safe_grow_cleared (n);
+ for (i = 0; i < n; i++)
+ {
+ init = get_init_expr (chain, i);
+ if (init == NULL_TREE)
+ {
+ /* Root value is rhs operand of the store to be eliminated if
+ it isn't loaded from memory before loop. */
+ dref a = get_chain_last_ref_at (chain, i);
+ val = gimple_assign_rhs1 (a->stmt);
+ if (TREE_CLOBBER_P (val))
+ val = get_or_create_ssa_default_def (cfun, SSA_NAME_VAR (var));
+
+ vtemps[n - i - 1] = val;
+ }
+ else
+ {
+ edge latch = loop_latch_edge (loop);
+ edge entry = loop_preheader_edge (loop);
+
+ /* Root value is loaded from memory before loop, we also need
+ to add PHI nodes to propagate the value across iterations. */
+ init = force_gimple_operand (init, &stmts, true, NULL_TREE);
+ if (stmts)
+ gsi_insert_seq_on_edge_immediate (entry, stmts);
+
+ next = chain->vars[n - i];
+ phi_result = copy_ssa_name (next);
+ gphi *phi = create_phi_node (phi_result, loop->header);
+ add_phi_arg (phi, init, entry, UNKNOWN_LOCATION);
+ add_phi_arg (phi, next, latch, UNKNOWN_LOCATION);
+ vtemps[n - i - 1] = phi_result;
+ }
+ }
+
+ /* Find the insertion position. */
+ dref last = get_chain_root (chain);
+ for (i = 0; i < chain->refs.length (); i++)
+ {
+ if (chain->refs[i]->pos > last->pos)
+ last = chain->refs[i];
+ }
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (last->stmt);
- initialize_root_vars (loop, chain, tmp_vars);
- replace_ref_with (root->stmt,
- chain->vars[chain->length],
- true, in_lhs);
+ /* Insert statements copying root value to root variable. */
+ for (i = 0; i < n; i++)
+ {
+ var = chain->vars[i];
+ val = vtemps[i];
+ stmt = gimple_build_assign (var, val);
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ }
+}
+
+/* Generates stores for CHAIN's eliminated stores in LOOP's last
+ (CHAIN->length - 1) iterations. */
+
+static void
+finalize_eliminated_stores (struct loop *loop, chain_p chain)
+{
+ unsigned i, n = chain->length;
+
+ for (i = 0; i < n; i++)
+ {
+ tree var = chain->vars[i];
+ tree fini = chain->finis[n - i - 1];
+ gimple *stmt = gimple_build_assign (fini, var);
+
+ gimple_seq_add_stmt_without_update (&chain->fini_seq, stmt);
+ }
+
+ if (chain->fini_seq)
+ {
+ gsi_insert_seq_on_edge_immediate (single_exit (loop), chain->fini_seq);
+ chain->fini_seq = NULL;
+ }
}
/* Initializes a variable for load motion for ROOT and prepares phi nodes and
@@ -1699,10 +2006,17 @@ remove_stmt (gimple *stmt)
bsi = gsi_for_stmt (stmt);
name = gimple_assign_lhs (stmt);
- gcc_assert (TREE_CODE (name) == SSA_NAME);
-
- next = single_nonlooparound_use (name);
- reset_debug_uses (stmt);
+ if (TREE_CODE (name) == SSA_NAME)
+ {
+ next = single_nonlooparound_use (name);
+ reset_debug_uses (stmt);
+ }
+ else
+ {
+ /* This is a store to be eliminated. */
+ gcc_assert (gimple_vdef (stmt) != NULL);
+ next = NULL;
+ }
unlink_stmt_vdef (stmt);
gsi_remove (&bsi, true);
@@ -1722,11 +2036,12 @@ remove_stmt (gimple *stmt)
static void
execute_pred_commoning_chain (struct loop *loop, chain_p chain,
- bitmap tmp_vars)
+ bitmap tmp_vars)
{
- unsigned i;
+ unsigned i, n;
dref a;
tree var;
+ bool in_lhs;
if (chain->combined)
{
@@ -1734,12 +2049,47 @@ execute_pred_commoning_chain (struct loop *loop, chain_p chain,
compute the values of the expression (except for the root one).
We delay this until after all chains are processed. */
}
+ else if (chain->type == CT_STORE_STORE)
+ {
+ if (chain->length > 0)
+ {
+ if (chain->inv_store_elimination)
+ {
+ /* If dead stores in this chain only store loop invariant
+ values, we can simply record the invariant value and use
+ it directly after loop. */
+ initialize_root_vars_store_elim_1 (chain);
+ }
+ else
+ {
+ /* If dead stores in this chain store loop variant values,
+ we need to set up the variables by loading from memory
+ before loop and propagating it with PHI nodes. */
+ initialize_root_vars_store_elim_2 (loop, chain, tmp_vars);
+ }
+
+ /* For inter-iteration store elimination chain, stores at each
+ distance in loop's last (chain->length - 1) iterations can't
+ be eliminated, because there is no following killing store.
+ We need to generate these stores after loop. */
+ finalize_eliminated_stores (loop, chain);
+ }
+
+ /* Eliminate the stores killed by following store. */
+ n = chain->refs.length ();
+ for (i = 0; i < n - 1; i++)
+ remove_stmt (chain->refs[i]->stmt);
+ }
else
{
- /* For non-combined chains, set up the variables that hold its value,
- and replace the uses of the original references by these
- variables. */
- initialize_root (loop, chain, tmp_vars);
+ /* For non-combined chains, set up the variables that hold its value. */
+ initialize_root_vars (loop, chain, tmp_vars);
+ a = get_chain_root (chain);
+ in_lhs = (chain->type == CT_STORE_LOAD
+ || chain->type == CT_COMBINATION);
+ replace_ref_with (a->stmt, chain->vars[chain->length], true, in_lhs);
+
+ /* Replace the uses of the original references by these variables. */
for (i = 1; chain->refs.iterate (i, &a); i++)
{
var = chain->vars[chain->length - a->distance];
@@ -1763,6 +2113,9 @@ determine_unroll_factor (vec<chain_p> chains)
{
if (chain->type == CT_INVARIANT)
continue;
+ /* For now we can't handle unrolling when eliminating stores. */
+ else if (chain->type == CT_STORE_STORE)
+ return 1;
if (chain->combined)
{
@@ -2409,6 +2762,74 @@ try_combine_chains (vec<chain_p> *chains)
}
}
+/* Prepare initializers for store elimination CHAIN in LOOP. Returns false
+ if this is impossible because one of these initializers may trap, true
+ otherwise. */
+
+static bool
+prepare_initializers_chain_store_elim (struct loop *loop, chain_p chain)
+{
+ unsigned i, n = chain->length;
+
+ /* For now we can't eliminate stores if some of them are conditional
+ executed. */
+ if (!chain->all_always_accessed)
+ return false;
+
+ /* Nothing to intialize for intra-iteration store elimination. */
+ if (n == 0 && chain->type == CT_STORE_STORE)
+ return true;
+
+ /* For store elimination chain, there is nothing to initialize if stores
+ to be eliminated only store loop invariant values into memory. */
+ if (chain->type == CT_STORE_STORE
+ && is_inv_store_elimination_chain (loop, chain))
+ {
+ chain->inv_store_elimination = true;
+ return true;
+ }
+
+ chain->inits.create (n);
+ chain->inits.safe_grow_cleared (n);
+
+ /* For store eliminatin chain like below:
+
+ for (i = 0; i < len; i++)
+ {
+ a[i] = 1;
+ // a[i + 1] = ...
+ a[i + 2] = 3;
+ }
+
+ store to a[i + 1] is missed in loop body, it acts like bubbles. The
+ content of a[i + 1] remain the same if the loop iterates fewer times
+ than chain->length. We need to set up root variables for such stores
+ by loading from memory before loop. Note we only need to load bubble
+ elements because loop body is guaranteed to be executed at least once
+ after loop's preheader edge. */
+ auto_vec<bool> bubbles;
+ bubbles.safe_grow_cleared (n + 1);
+ for (i = 0; i < chain->refs.length (); i++)
+ bubbles[chain->refs[i]->distance] = true;
+
+ struct data_reference *dr = get_chain_root (chain)->ref;
+ for (i = 0; i < n; i++)
+ {
+ if (bubbles[i])
+ continue;
+
+ gimple_seq stmts = NULL;
+
+ tree init = ref_at_iteration (dr, (int) 0 - i, &stmts);
+ if (stmts)
+ gimple_seq_add_seq_without_update (&chain->init_seq, stmts);
+
+ chain->inits[i] = init;
+ }
+
+ return true;
+}
+
/* Prepare initializers for CHAIN in LOOP. Returns false if this is
impossible because one of these initializers may trap, true otherwise. */
@@ -2421,6 +2842,9 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
dref laref;
edge entry = loop_preheader_edge (loop);
+ if (chain->type == CT_STORE_STORE)
+ return prepare_initializers_chain_store_elim (loop, chain);
+
/* Find the initializers for the variables, and check that they cannot
trap. */
chain->inits.create (n);
@@ -2454,7 +2878,7 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
}
if (stmts)
- gsi_insert_seq_on_edge_immediate (entry, stmts);
+ gimple_seq_add_seq_without_update (&chain->init_seq, stmts);
chain->inits[i] = init;
}
@@ -2484,10 +2908,115 @@ prepare_initializers (struct loop *loop, vec<chain_p> chains)
}
}
-/* Performs predictive commoning for LOOP. Returns true if LOOP was
- unrolled. */
+/* Generates finalizer memory references for CHAIN in LOOP. Returns true
+ if finalizer code for CHAIN can be generated, otherwise false. */
+
+static bool
+prepare_finalizers_chain (struct loop *loop, chain_p chain)
+{
+ unsigned i, n = chain->length;
+ struct data_reference *dr = get_chain_root (chain)->ref;
+ tree fini, niters = number_of_latch_executions (loop);
+
+ /* For now we can't eliminate stores if some of them are conditional
+ executed. */
+ if (!chain->all_always_accessed)
+ return false;
+
+ chain->finis.create (n);
+ for (i = 0; i < n; i++)
+ chain->finis.quick_push (NULL_TREE);
+
+ /* We never use looparound phi node for store elimination chains. */
+
+ /* Find the finalizers for the variables, and check that they cannot
+ trap. */
+ for (i = 0; i < n; i++)
+ {
+ gimple_seq stmts = NULL;
+ gcc_assert (chain->finis[i] == NULL_TREE);
+
+ if (TREE_CODE (niters) != INTEGER_CST && TREE_CODE (niters) != SSA_NAME)
+ {
+ niters = copy_node (niters);
+ niters = force_gimple_operand (niters, &stmts, true, NULL);
+ if (stmts)
+ {
+ gimple_seq_add_seq_without_update (&chain->fini_seq, stmts);
+ stmts = NULL;
+ }
+ }
+ fini = ref_at_iteration (dr, (int) 0 - i, &stmts, niters);
+ if (stmts)
+ gimple_seq_add_seq_without_update (&chain->fini_seq, stmts);
+
+ chain->finis[i] = fini;
+ }
+
+ return true;
+}
+
+/* Generates finalizer memory reference for CHAINS in LOOP. Returns true
+ if finalizer code generation for CHAINS breaks loop closed ssa form. */
static bool
+prepare_finalizers (struct loop *loop, vec<chain_p> chains)
+{
+ chain_p chain;
+ unsigned i;
+ bool loop_closed_ssa = false;
+
+ for (i = 0; i < chains.length ();)
+ {
+ chain = chains[i];
+
+ /* Finalizer is only necessary for inter-iteration store elimination
+ chains. */
+ if (chain->length == 0 || chain->type != CT_STORE_STORE)
+ {
+ i++;
+ continue;
+ }
+
+ if (prepare_finalizers_chain (loop, chain))
+ {
+ i++;
+ /* We don't corrupt loop closed ssa form for store elimination
+ chain if eliminated stores only store loop invariant values
+ into memory. */
+ if (!chain->inv_store_elimination)
+ loop_closed_ssa |= (!chain->inv_store_elimination);
+ }
+ else
+ {
+ release_chain (chain);
+ chains.unordered_remove (i);
+ }
+ }
+ return loop_closed_ssa;
+}
+
+/* Insert all initializing gimple stmts into loop's entry edge. */
+
+static void
+insert_init_seqs (struct loop *loop, vec<chain_p> chains)
+{
+ unsigned i;
+ edge entry = loop_preheader_edge (loop);
+
+ for (i = 0; i < chains.length (); ++i)
+ if (chains[i]->init_seq)
+ {
+ gsi_insert_seq_on_edge_immediate (entry, chains[i]->init_seq);
+ chains[i]->init_seq = NULL;
+ }
+}
+
+/* Performs predictive commoning for LOOP. Sets bit 1<<0 of return value
+ if LOOP was unrolled; Sets bit 1<<1 of return value if loop closed ssa
+ form was corrupted. */
+
+static unsigned
tree_predictive_commoning_loop (struct loop *loop)
{
vec<data_reference_p> datarefs;
@@ -2496,7 +3025,7 @@ tree_predictive_commoning_loop (struct loop *loop)
vec<chain_p> chains = vNULL;
unsigned unroll_factor;
struct tree_niter_desc desc;
- bool unroll = false;
+ bool unroll = false, loop_closed_ssa = false;
edge exit;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2508,7 +3037,7 @@ tree_predictive_commoning_loop (struct loop *loop)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Loop iterates only 1 time, nothing to do.\n");
- return false;
+ return 0;
}
/* Find the data references and split them into components according to their
@@ -2523,7 +3052,7 @@ tree_predictive_commoning_loop (struct loop *loop)
fprintf (dump_file, "Cannot analyze data dependencies\n");
free_data_refs (datarefs);
free_dependence_relations (dependences);
- return false;
+ return 0;
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2536,7 +3065,7 @@ tree_predictive_commoning_loop (struct loop *loop)
{
free_data_refs (datarefs);
free_affine_expand_cache (&name_expansions);
- return false;
+ return 0;
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2561,10 +3090,13 @@ tree_predictive_commoning_loop (struct loop *loop)
goto end;
}
prepare_initializers (loop, chains);
+ loop_closed_ssa = prepare_finalizers (loop, chains);
/* Try to combine the chains that are always worked with together. */
try_combine_chains (&chains);
+ insert_init_seqs (loop, chains);
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Before commoning:\n\n");
@@ -2620,7 +3152,7 @@ end: ;
free_affine_expand_cache (&name_expansions);
- return unroll;
+ return (unroll ? 1 : 0) | (loop_closed_ssa ? 2 : 0);
}
/* Runs predictive commoning. */
@@ -2628,23 +3160,26 @@ end: ;
unsigned
tree_predictive_commoning (void)
{
- bool unrolled = false;
struct loop *loop;
- unsigned ret = 0;
+ unsigned ret = 0, changed = 0;
initialize_original_copy_tables ();
FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
if (optimize_loop_for_speed_p (loop))
{
- unrolled |= tree_predictive_commoning_loop (loop);
+ changed |= tree_predictive_commoning_loop (loop);
}
+ free_original_copy_tables ();
- if (unrolled)
+ if (changed > 0)
{
scev_reset ();
+
+ if (changed > 1)
+ rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+
ret = TODO_cleanup_cfg;
}
- free_original_copy_tables ();
return ret;
}
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index b70e32573ee..4d8177c4a62 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1860,22 +1860,9 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
dump_decl_name (pp, node, flags);
else if (TYPE_NAME (TREE_TYPE (node)) != node)
{
- if ((TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
- && TYPE_METHODS (TREE_TYPE (node)))
- {
- /* The type is a c++ class: all structures have at least
- 4 methods. */
- pp_string (pp, "class ");
- dump_generic_node (pp, TREE_TYPE (node), spc, flags, false);
- }
- else
- {
- pp_string (pp,
- (TREE_CODE (TREE_TYPE (node)) == UNION_TYPE
+ pp_string (pp, (TREE_CODE (TREE_TYPE (node)) == UNION_TYPE
? "union" : "struct "));
- dump_generic_node (pp, TREE_TYPE (node), spc, flags, false);
- }
+ dump_generic_node (pp, TREE_TYPE (node), spc, flags, false);
}
else
pp_string (pp, "<anon>");
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index 2ae4b69b68e..b1ee7f2b3f5 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -436,16 +436,16 @@ gimple_gen_ic_func_profiler (void)
edge true_edge = single_succ_edge (cond_bb);
true_edge->flags = EDGE_TRUE_VALUE;
- int probability;
+ profile_probability probability;
if (DECL_VIRTUAL_P (current_function_decl))
- probability = PROB_VERY_LIKELY;
+ probability = profile_probability::very_likely ();
else
- probability = PROB_UNLIKELY;
+ probability = profile_probability::unlikely ();
true_edge->probability = probability;
edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE - true_edge->probability;
+ e->probability = true_edge->probability.invert ();
/* Insert code:
@@ -497,10 +497,10 @@ gimple_gen_time_profiler (unsigned tag, unsigned base)
edge true_edge = single_succ_edge (cond_bb);
true_edge->flags = EDGE_TRUE_VALUE;
- true_edge->probability = PROB_UNLIKELY;
+ true_edge->probability = profile_probability::unlikely ();
edge e
= make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE - true_edge->probability;
+ e->probability = true_edge->probability.invert ();
gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
tree original_ref = tree_coverage_counter_ref (tag, base);
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 74ee2b0a0cc..5794d227fe5 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1991,6 +1991,7 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
case IFN_UBSAN_BOUNDS:
case IFN_UBSAN_VPTR:
case IFN_UBSAN_OBJECT_SIZE:
+ case IFN_UBSAN_PTR:
case IFN_ASAN_CHECK:
return false;
default:
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 934324990e8..e62afad1bea 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1054,7 +1054,7 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
e = e2;
}
gcc_assert (e);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
/* The edge is no longer associated with a conditional, so it does
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index 904befa9808..c564ea104bc 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -363,18 +363,14 @@ update_profile_after_ifcombine (basic_block inner_cond_bb,
inner_taken->count += outer2->count;
outer2->count = profile_count::zero ();
- inner_taken->probability = outer2->probability
- + RDIV (outer_to_inner->probability
- * inner_taken->probability,
- REG_BR_PROB_BASE);
- if (inner_taken->probability > REG_BR_PROB_BASE)
- inner_taken->probability = REG_BR_PROB_BASE;
- inner_not_taken->probability = REG_BR_PROB_BASE
+ inner_taken->probability = outer2->probability + outer_to_inner->probability
+ * inner_taken->probability;
+ inner_not_taken->probability = profile_probability::always ()
- inner_taken->probability;
- outer_to_inner->probability = REG_BR_PROB_BASE;
+ outer_to_inner->probability = profile_probability::always ();
inner_cond_bb->frequency = outer_cond_bb->frequency;
- outer2->probability = 0;
+ outer2->probability = profile_probability::never ();
}
/* If-convert on a and pattern with a common else block. The inner
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 86be34a1ac7..14cc6d8d721 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -436,7 +436,7 @@ pass_ch::process_loop_p (struct loop *loop)
bool
pass_ch_vect::process_loop_p (struct loop *loop)
{
- if (!flag_tree_vectorize && !loop->force_vectorize)
+ if (!flag_tree_loop_vectorize && !loop->force_vectorize)
return false;
if (loop->dont_vectorize)
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index e92eaa6e2d7..2fbaa62c142 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1801,7 +1801,7 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
int freq_sum = 0;
profile_count count_sum = profile_count::zero ();
int nbbs = 0, ncount = 0;
- int flag_probability = -1;
+ profile_probability flag_probability = profile_probability::uninitialized ();
/* Flag is set in FLAG_BBS. Determine probability that flag will be true
at loop exit.
@@ -1824,27 +1824,29 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
if ((*it)->count.initialized_p ())
count_sum += (*it)->count, ncount ++;
if (dominated_by_p (CDI_DOMINATORS, ex->src, *it))
- flag_probability = REG_BR_PROB_BASE;
+ flag_probability = profile_probability::always ();
nbbs++;
}
- if (flag_probability != -1)
+ profile_probability cap = profile_probability::always ().apply_scale (2, 3);
+
+ if (flag_probability.initialized_p ())
;
else if (ncount == nbbs && count_sum > 0 && preheader->count >= count_sum)
{
flag_probability = count_sum.probability_in (preheader->count);
- if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ if (flag_probability > cap)
+ flag_probability = cap;
}
else if (freq_sum > 0 && EDGE_FREQUENCY (preheader) >= freq_sum)
{
- flag_probability = GCOV_COMPUTE_SCALE (freq_sum,
- EDGE_FREQUENCY (preheader));
- if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ flag_probability = profile_probability::from_reg_br_prob_base
+ (GCOV_COMPUTE_SCALE (freq_sum, EDGE_FREQUENCY (preheader)));
+ if (flag_probability > cap)
+ flag_probability = cap;
}
else
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ flag_probability = cap;
/* ?? Insert store after previous store if applicable. See note
below. */
@@ -1876,7 +1878,7 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
old_dest = ex->dest;
new_bb = split_edge (ex);
then_bb = create_empty_bb (new_bb);
- then_bb->frequency = apply_probability (new_bb->frequency, flag_probability);
+ then_bb->frequency = flag_probability.apply (new_bb->frequency);
then_bb->count = new_bb->count.apply_probability (flag_probability);
if (irr)
then_bb->flags = BB_IRREDUCIBLE_LOOP;
@@ -1901,13 +1903,11 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
e1->flags |= EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0);
e1->flags &= ~EDGE_FALLTHRU;
- e1->probability = REG_BR_PROB_BASE - flag_probability;
+ e1->probability = flag_probability.invert ();
e1->count = new_bb->count - then_bb->count;
- then_old_edge = make_edge (then_bb, old_dest,
+ then_old_edge = make_single_succ_edge (then_bb, old_dest,
EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0));
- then_old_edge->probability = REG_BR_PROB_BASE;
- then_old_edge->count = then_bb->count;
set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb);
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index b6ac765aac6..efb199aaaa2 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -529,7 +529,7 @@ remove_exits_and_undefined_stmts (struct loop *loop, unsigned int npeeled)
}
if (!loop_exit_edge_p (loop, exit_edge))
exit_edge = EDGE_SUCC (bb, 1);
- exit_edge->probability = REG_BR_PROB_BASE;
+ exit_edge->probability = profile_probability::always ();
exit_edge->count = exit_edge->src->count;
gcc_checking_assert (loop_exit_edge_p (loop, exit_edge));
gcond *cond_stmt = as_a <gcond *> (elt->stmt);
@@ -642,7 +642,7 @@ unloop_loops (bitmap loop_closed_ssa_invalidated,
it in. */
stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags);
- latch_edge->probability = 0;
+ latch_edge->probability = profile_probability::never ();
latch_edge->count = profile_count::zero ();
latch_edge->flags |= flags;
latch_edge->goto_locus = locus;
@@ -1104,12 +1104,13 @@ try_peel_loop (struct loop *loop,
entry_freq += e->src->frequency;
gcc_assert (!flow_bb_inside_loop_p (loop, e->src));
}
- int scale = 1;
+ profile_probability p = profile_probability::very_unlikely ();
if (loop->header->count > 0)
- scale = entry_count.probability_in (loop->header->count);
+ p = entry_count.probability_in (loop->header->count);
else if (loop->header->frequency)
- scale = RDIV (entry_freq * REG_BR_PROB_BASE, loop->header->frequency);
- scale_loop_profile (loop, scale, 0);
+ p = profile_probability::probability_in_gcov_type
+ (entry_freq, loop->header->frequency);
+ scale_loop_profile (loop, p, 0);
bitmap_set_bit (peeled_loops, loop->num);
return true;
}
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index 18ed4f62686..5488044b18f 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -1212,7 +1212,8 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
gimple_stmt_iterator bsi;
use_operand_p op;
bool ok;
- unsigned i, prob, prob_entry, scale_unrolled, scale_rest;
+ unsigned i;
+ profile_probability prob, prob_entry, scale_unrolled;
profile_count freq_e, freq_h;
gcov_type new_est_niter = niter_for_unrolled_loop (loop, factor);
unsigned irr = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP;
@@ -1224,9 +1225,10 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
/* Let us assume that the unrolled loop is quite likely to be entered. */
if (integer_nonzerop (enter_main_cond))
- prob_entry = REG_BR_PROB_BASE;
+ prob_entry = profile_probability::always ();
else
- prob_entry = PROB_UNROLLED_LOOP_ENTERED * REG_BR_PROB_BASE / 100;
+ prob_entry = profile_probability::guessed_always ()
+ .apply_scale (PROB_UNROLLED_LOOP_ENTERED, 100);
/* The values for scales should keep profile consistent, and somewhat close
to correct.
@@ -1241,11 +1243,11 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
of this change (scale the frequencies of blocks before and after the exit
by appropriate factors). */
scale_unrolled = prob_entry;
- scale_rest = REG_BR_PROB_BASE;
- new_loop = loop_version (loop, enter_main_cond, NULL,
- prob_entry, REG_BR_PROB_BASE - prob_entry,
- scale_unrolled, scale_rest, true);
+ new_loop = loop_version (loop, enter_main_cond, NULL, prob_entry,
+ prob_entry.invert (), scale_unrolled,
+ profile_probability::guessed_always (),
+ true);
gcc_assert (new_loop != NULL);
update_ssa (TODO_update_ssa);
@@ -1259,9 +1261,13 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
/* Since the exit edge will be removed, the frequency of all the blocks
in the loop that are dominated by it must be scaled by
1 / (1 - exit->probability). */
- scale_dominated_blocks_in_loop (loop, exit->src,
- REG_BR_PROB_BASE,
- REG_BR_PROB_BASE - exit->probability);
+ if (exit->probability.initialized_p ())
+ scale_dominated_blocks_in_loop (loop, exit->src,
+ /* We are scaling up here so probability
+ does not fit. */
+ REG_BR_PROB_BASE,
+ REG_BR_PROB_BASE
+ - exit->probability.to_reg_br_prob_base ());
bsi = gsi_last_bb (exit_bb);
exit_if = gimple_build_cond (EQ_EXPR, integer_zero_node,
@@ -1278,11 +1284,11 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
new_exit->count = exit->count;
new_exit->probability = exit->probability;
new_nonexit = single_pred_edge (loop->latch);
- new_nonexit->probability = REG_BR_PROB_BASE - exit->probability;
+ new_nonexit->probability = exit->probability.invert ();
new_nonexit->flags = EDGE_TRUE_VALUE;
new_nonexit->count -= exit->count;
- scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
- REG_BR_PROB_BASE);
+ if (new_nonexit->probability.initialized_p ())
+ scale_bbs_frequencies (&loop->latch, 1, new_nonexit->probability);
old_entry = loop_preheader_edge (loop);
new_entry = loop_preheader_edge (new_loop);
@@ -1362,31 +1368,29 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
}
if (freq_h > 0)
{
- gcov_type scale;
/* Avoid dropping loop body profile counter to 0 because of zero count
in loop's preheader. */
if (freq_e == profile_count::zero ())
freq_e = profile_count::from_gcov_type (1);
- /* This should not overflow. */
- scale = freq_e.probability_in (freq_h);
- scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
+ scale_loop_frequencies (loop, freq_e.probability_in (freq_h));
}
exit_bb = single_pred (loop->latch);
new_exit = find_edge (exit_bb, rest);
new_exit->count = loop_preheader_edge (loop)->count;
- new_exit->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
+ new_exit->probability = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
rest->count += new_exit->count;
rest->frequency += EDGE_FREQUENCY (new_exit);
new_nonexit = single_pred_edge (loop->latch);
prob = new_nonexit->probability;
- new_nonexit->probability = REG_BR_PROB_BASE - new_exit->probability;
+ new_nonexit->probability = new_exit->probability.invert ();
new_nonexit->count = exit_bb->count - new_exit->count;
- if (prob > 0)
- scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
- prob);
+ prob = new_nonexit->probability / prob;
+ if (prob.initialized_p ())
+ scale_bbs_frequencies (&loop->latch, 1, prob);
/* Finally create the new counter for number of iterations and add the new
exit instruction. */
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 848e812cb96..e0107c28dfb 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1142,8 +1142,12 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
tree niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod;
- tree assumption = boolean_true_node, bound;
- tree type1 = (POINTER_TYPE_P (type)) ? sizetype : type;
+ mpz_t mmod;
+ tree assumption = boolean_true_node, bound, noloop;
+ bool ret = false, fv_comp_no_overflow;
+ tree type1 = type;
+ if (POINTER_TYPE_P (type))
+ type1 = sizetype;
if (TREE_CODE (mod) != INTEGER_CST)
return false;
@@ -1151,51 +1155,96 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
tmod = fold_convert (type1, mod);
+ mpz_init (mmod);
+ wi::to_mpz (mod, mmod, UNSIGNED);
+ mpz_neg (mmod, mmod);
+
/* If the induction variable does not overflow and the exit is taken,
- then the computation of the final value does not overflow. There
- are three cases:
- 1) The case if the new final value is equal to the current one.
- 2) Induction varaible has pointer type, as the code cannot rely
- on the object to that the pointer points being placed at the
- end of the address space (and more pragmatically,
- TYPE_{MIN,MAX}_VALUE is not defined for pointers).
- 3) EXIT_MUST_BE_TAKEN is true, note it implies that the induction
- variable does not overflow. */
- if (!integer_zerop (mod) && !POINTER_TYPE_P (type) && !exit_must_be_taken)
+ then the computation of the final value does not overflow. This is
+ also obviously the case if the new final value is equal to the
+ current one. Finally, we postulate this for pointer type variables,
+ as the code cannot rely on the object to that the pointer points being
+ placed at the end of the address space (and more pragmatically,
+ TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
+ if (integer_zerop (mod) || POINTER_TYPE_P (type))
+ fv_comp_no_overflow = true;
+ else if (!exit_must_be_taken)
+ fv_comp_no_overflow = false;
+ else
+ fv_comp_no_overflow =
+ (iv0->no_overflow && integer_nonzerop (iv0->step))
+ || (iv1->no_overflow && integer_nonzerop (iv1->step));
+
+ if (integer_nonzerop (iv0->step))
{
- if (integer_nonzerop (iv0->step))
+ /* The final value of the iv is iv1->base + MOD, assuming that this
+ computation does not overflow, and that
+ iv0->base <= iv1->base + MOD. */
+ if (!fv_comp_no_overflow)
{
- /* The final value of the iv is iv1->base + MOD, assuming
- that this computation does not overflow, and that
- iv0->base <= iv1->base + MOD. */
bound = fold_build2 (MINUS_EXPR, type1,
TYPE_MAX_VALUE (type1), tmod);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
+ if (integer_zerop (assumption))
+ goto end;
}
+ if (mpz_cmp (mmod, bnds->below) < 0)
+ noloop = boolean_false_node;
+ else if (POINTER_TYPE_P (type))
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ iv0->base,
+ fold_build_pointer_plus (iv1->base, tmod));
else
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ iv0->base,
+ fold_build2 (PLUS_EXPR, type1,
+ iv1->base, tmod));
+ }
+ else
+ {
+ /* The final value of the iv is iv0->base - MOD, assuming that this
+ computation does not overflow, and that
+ iv0->base - MOD <= iv1->base. */
+ if (!fv_comp_no_overflow)
{
- /* The final value of the iv is iv0->base - MOD, assuming
- that this computation does not overflow, and that
- iv0->base - MOD <= iv1->base. */
bound = fold_build2 (PLUS_EXPR, type1,
TYPE_MIN_VALUE (type1), tmod);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
+ if (integer_zerop (assumption))
+ goto end;
}
- if (integer_zerop (assumption))
- return false;
- else if (!integer_nonzerop (assumption))
- niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
- niter->assumptions, assumption);
+ if (mpz_cmp (mmod, bnds->below) < 0)
+ noloop = boolean_false_node;
+ else if (POINTER_TYPE_P (type))
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ fold_build_pointer_plus (iv0->base,
+ fold_build1 (NEGATE_EXPR,
+ type1, tmod)),
+ iv1->base);
+ else
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ fold_build2 (MINUS_EXPR, type1,
+ iv0->base, tmod),
+ iv1->base);
}
- /* Since we are transforming LT to NE and DELTA is constant, there
- is no need to compute may_be_zero because this loop must roll. */
-
+ if (!integer_nonzerop (assumption))
+ niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+ niter->assumptions,
+ assumption);
+ if (!integer_zerop (noloop))
+ niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+ niter->may_be_zero,
+ noloop);
bounds_add (bnds, wi::to_widest (mod), type);
*delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
- return true;
+
+ ret = true;
+end:
+ mpz_clear (mmod);
+ return ret;
}
/* Add assertions to NITER that ensure that the control variable of the loop
@@ -1668,18 +1717,34 @@ number_of_iterations_cond (struct loop *loop,
exit_must_be_taken = true;
}
- /* We can handle the case when neither of the sides of the comparison is
- invariant, provided that the test is NE_EXPR. This rarely occurs in
- practice, but it is simple enough to manage. */
+ /* We can handle cases which neither of the sides of the comparison is
+ invariant:
+
+ {iv0.base, iv0.step} cmp_code {iv1.base, iv1.step}
+ as if:
+ {iv0.base, iv0.step - iv1.step} cmp_code {iv1.base, 0}
+
+ provided that either below condition is satisfied:
+
+ a) the test is NE_EXPR;
+ b) iv0.step - iv1.step is positive integer.
+
+ This rarely occurs in practice, but it is simple enough to manage. */
if (!integer_zerop (iv0->step) && !integer_zerop (iv1->step))
{
tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
- if (code != NE_EXPR)
+ tree step = fold_binary_to_constant (MINUS_EXPR, step_type,
+ iv0->step, iv1->step);
+
+ /* No need to check sign of the new step since below code takes care
+ of this well. */
+ if (code != NE_EXPR && TREE_CODE (step) != INTEGER_CST)
return false;
- iv0->step = fold_binary_to_constant (MINUS_EXPR, step_type,
- iv0->step, iv1->step);
- iv0->no_overflow = false;
+ iv0->step = step;
+ if (!POINTER_TYPE_P (type))
+ iv0->no_overflow = false;
+
iv1->step = build_int_cst (step_type, 0);
iv1->no_overflow = true;
}
@@ -2362,9 +2427,9 @@ number_of_iterations_exit (struct loop *loop, edge exit,
return true;
if (warn)
- warning_at (gimple_location_safe (stmt),
- OPT_Wunsafe_loop_optimizations,
- "missed loop optimization, the loop counter may overflow");
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, gimple_location_safe (stmt),
+ "missed loop optimization: niters analysis ends up "
+ "with assumptions.\n");
return false;
}
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index e77f2bfd1b5..e454cc5dc93 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -354,10 +354,10 @@ connect_loops (struct loop *loop1, struct loop *loop2)
}
new_e->count = skip_bb->count;
- new_e->probability = PROB_LIKELY;
+ new_e->probability = profile_probability::likely ();
new_e->count = skip_e->count.apply_probability (PROB_LIKELY);
skip_e->count -= new_e->count;
- skip_e->probability = inverse_probability (PROB_LIKELY);
+ skip_e->probability = profile_probability::unlikely ();
return new_e;
}
@@ -559,9 +559,13 @@ split_loop (struct loop *loop1, struct tree_niter_desc *niter)
them, and fix up SSA form for that. */
initialize_original_copy_tables ();
basic_block cond_bb;
+
+ /* FIXME: probabilities seems wrong here. */
struct loop *loop2 = loop_version (loop1, cond, &cond_bb,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE,
+ profile_probability::always (),
+ profile_probability::always (),
+ profile_probability::always (),
+ profile_probability::always (),
true);
gcc_assert (loop2);
update_ssa (TODO_update_ssa);
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index 12bf640d3f8..57aba4f1dd0 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -480,7 +480,7 @@ static struct loop *
tree_unswitch_loop (struct loop *loop,
basic_block unswitch_on, tree cond)
{
- unsigned prob_true;
+ profile_probability prob_true;
edge edge_true, edge_false;
/* Some sanity checking. */
@@ -491,8 +491,10 @@ tree_unswitch_loop (struct loop *loop,
extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
prob_true = edge_true->probability;
return loop_version (loop, unshare_expr (cond),
- NULL, prob_true, REG_BR_PROB_BASE - prob_true, prob_true,
- REG_BR_PROB_BASE - prob_true, false);
+ NULL, prob_true,
+ prob_true.invert (),
+ prob_true, prob_true.invert (),
+ false);
}
/* Unswitch outer loops by hoisting invariant guard on
@@ -580,8 +582,9 @@ find_loop_guard (struct loop *loop)
gcond *cond;
do
{
+ basic_block next = NULL;
if (single_succ_p (header))
- header = single_succ (header);
+ next = single_succ (header);
else
{
cond = dyn_cast <gcond *> (last_stmt (header));
@@ -591,12 +594,16 @@ find_loop_guard (struct loop *loop)
/* Make sure to skip earlier hoisted guards that are left
in place as if (true). */
if (gimple_cond_true_p (cond))
- header = te->dest;
+ next = te->dest;
else if (gimple_cond_false_p (cond))
- header = fe->dest;
+ next = fe->dest;
else
break;
}
+ /* Never traverse a backedge. */
+ if (header->loop_father->header == next)
+ return NULL;
+ header = next;
}
while (1);
if (!flow_bb_inside_loop_p (loop, te->dest)
@@ -818,10 +825,13 @@ hoist_guard (struct loop *loop, edge guard)
/* Create new loop pre-header. */
e = split_block (pre_header, last_stmt (pre_header));
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Moving guard %i->%i (prob %i) to bb %i, "
- "new preheader is %i\n",
- guard->src->index, guard->dest->index, guard->probability,
- e->src->index, e->dest->index);
+ {
+ fprintf (dump_file, " Moving guard %i->%i (prob ",
+ guard->src->index, guard->dest->index);
+ guard->probability.dump (dump_file);
+ fprintf (dump_file, ") to bb %i, new preheader is %i\n",
+ e->src->index, e->dest->index);
+ }
gcc_assert (loop_preheader_edge (loop)->src == e->dest);
@@ -854,23 +864,26 @@ hoist_guard (struct loop *loop, edge guard)
}
new_edge->count = skip_count;
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Estimated probability of skipping loop is %i\n",
- new_edge->probability);
+ {
+ fprintf (dump_file, " Estimated probability of skipping loop is ");
+ new_edge->probability.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
/* Update profile after the transform:
First decrease count of path from newly hoisted loop guard
to loop header... */
e->count -= skip_count;
- e->probability = REG_BR_PROB_BASE - new_edge->probability;
+ e->probability = new_edge->probability.invert ();
e->dest->count = e->count;
e->dest->frequency = EDGE_FREQUENCY (e);
/* ... now update profile to represent that original guard will be optimized
away ... */
- guard->probability = 0;
+ guard->probability = profile_probability::never ();
guard->count = profile_count::zero ();
- not_guard->probability = REG_BR_PROB_BASE;
+ not_guard->probability = profile_probability::always ();
/* This count is wrong (frequency of not_guard does not change),
but will be scaled later. */
not_guard->count = guard->src->count;
@@ -888,7 +901,8 @@ hoist_guard (struct loop *loop, edge guard)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %i", bb->index);
- scale_bbs_frequencies_int (&bb, 1, e->probability, REG_BR_PROB_BASE);
+ if (e->probability.initialized_p ())
+ scale_bbs_frequencies (&bb, 1, e->probability);
}
}
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index d044374dbc2..7ac1659fa06 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -1946,7 +1946,9 @@ make_pass_cse_sincos (gcc::context *ctxt)
- a range which gives the difference between the highest and lowest accessed
memory location to make such a symbolic number;
- the address SRC of the source element of lowest address as a convenience
- to easily get BASE_ADDR + offset + lowest bytepos.
+ to easily get BASE_ADDR + offset + lowest bytepos;
+ - number of expressions N_OPS bitwise ored together to represent
+ approximate cost of the computation.
Note 1: the range is different from size as size reflects the size of the
type of the current expression. For instance, for an array char a[],
@@ -1968,6 +1970,7 @@ struct symbolic_number {
tree alias_set;
tree vuse;
unsigned HOST_WIDE_INT range;
+ int n_ops;
};
#define BITS_PER_MARKER 8
@@ -2083,6 +2086,7 @@ init_symbolic_number (struct symbolic_number *n, tree src)
return false;
n->range = size;
n->n = CMPNOP;
+ n->n_ops = 1;
if (size < 64 / BITS_PER_MARKER)
n->n &= ((uint64_t) 1 << (size * BITS_PER_MARKER)) - 1;
@@ -2293,6 +2297,7 @@ perform_symbolic_merge (gimple *source_stmt1, struct symbolic_number *n1,
return NULL;
}
n->n = n1->n | n2->n;
+ n->n_ops = n1->n_ops + n2->n_ops;
return source_stmt;
}
@@ -2588,7 +2593,7 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
return NULL;
/* Useless bit manipulation performed by code. */
- if (!n->base_addr && n->n == cmpnop)
+ if (!n->base_addr && n->n == cmpnop && n->n_ops == 1)
return NULL;
n->range *= BITS_PER_UNIT;
@@ -2747,6 +2752,36 @@ bswap_replace (gimple *cur_stmt, gimple *ins_stmt, tree fndecl,
}
src = val_tmp;
}
+ else if (!bswap)
+ {
+ gimple *g;
+ if (!useless_type_conversion_p (TREE_TYPE (tgt), TREE_TYPE (src)))
+ {
+ if (!is_gimple_val (src))
+ return false;
+ g = gimple_build_assign (tgt, NOP_EXPR, src);
+ }
+ else
+ g = gimple_build_assign (tgt, src);
+ if (n->range == 16)
+ nop_stats.found_16bit++;
+ else if (n->range == 32)
+ nop_stats.found_32bit++;
+ else
+ {
+ gcc_assert (n->range == 64);
+ nop_stats.found_64bit++;
+ }
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "%d bit reshuffle in target endianness found at: ",
+ (int) n->range);
+ print_gimple_stmt (dump_file, cur_stmt, 0);
+ }
+ gsi_replace (&gsi, g, true);
+ return true;
+ }
else if (TREE_CODE (src) == BIT_FIELD_REF)
src = TREE_OPERAND (src, 0);
@@ -3842,7 +3877,7 @@ static bool
divmod_candidate_p (gassign *stmt)
{
tree type = TREE_TYPE (gimple_assign_lhs (stmt));
- enum machine_mode mode = TYPE_MODE (type);
+ machine_mode mode = TYPE_MODE (type);
optab divmod_optab, div_optab;
if (TYPE_UNSIGNED (type))
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index fb843afcec0..ed80442031e 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1139,7 +1139,7 @@ DEBUG_FUNCTION bool
verify_imm_links (FILE *f, tree var)
{
use_operand_p ptr, prev, list;
- int count;
+ unsigned int count;
gcc_assert (TREE_CODE (var) == SSA_NAME);
@@ -1157,20 +1157,31 @@ verify_imm_links (FILE *f, tree var)
for (ptr = list->next; ptr != list; )
{
if (prev != ptr->prev)
- goto error;
+ {
+ fprintf (f, "prev != ptr->prev\n");
+ goto error;
+ }
if (ptr->use == NULL)
- goto error; /* 2 roots, or SAFE guard node. */
+ {
+ fprintf (f, "ptr->use == NULL\n");
+ goto error; /* 2 roots, or SAFE guard node. */
+ }
else if (*(ptr->use) != var)
- goto error;
+ {
+ fprintf (f, "*(ptr->use) != var\n");
+ goto error;
+ }
prev = ptr;
ptr = ptr->next;
- /* Avoid infinite loops. 50,000,000 uses probably indicates a
- problem. */
- if (count++ > 50000000)
- goto error;
+ count++;
+ if (count == 0)
+ {
+ fprintf (f, "number of immediate uses doesn't fit unsigned int\n");
+ goto error;
+ }
}
/* Verify list in the other direction. */
@@ -1178,15 +1189,25 @@ verify_imm_links (FILE *f, tree var)
for (ptr = list->prev; ptr != list; )
{
if (prev != ptr->next)
- goto error;
+ {
+ fprintf (f, "prev != ptr->next\n");
+ goto error;
+ }
prev = ptr;
ptr = ptr->prev;
- if (count-- < 0)
- goto error;
+ if (count == 0)
+ {
+ fprintf (f, "count-- < 0\n");
+ goto error;
+ }
+ count--;
}
if (count != 0)
- goto error;
+ {
+ fprintf (f, "count != 0\n");
+ goto error;
+ }
return false;
diff --git a/gcc/tree-ssa-phionlycprop.c b/gcc/tree-ssa-phionlycprop.c
index 9fa427ff2f7..65af44834df 100644
--- a/gcc/tree-ssa-phionlycprop.c
+++ b/gcc/tree-ssa-phionlycprop.c
@@ -313,8 +313,6 @@ propagate_rhs_into_lhs (gimple *stmt, tree lhs, tree rhs,
te->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
te->flags &= ~EDGE_ABNORMAL;
te->flags |= EDGE_FALLTHRU;
- if (te->probability > REG_BR_PROB_BASE)
- te->probability = REG_BR_PROB_BASE;
}
}
}
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index b652361b255..f5c07dc27f1 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -374,7 +374,7 @@ replace_phi_edge_with_variable (basic_block cond_block,
{
EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
@@ -384,7 +384,7 @@ replace_phi_edge_with_variable (basic_block cond_block,
EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 1)->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
@@ -1017,7 +1017,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
if (optimize_bb_for_speed_p (cond_bb)
/* The special case is useless if it has a low probability. */
&& profile_status_for_fn (cfun) != PROFILE_ABSENT
- && EDGE_PRED (middle_bb, 0)->probability < PROB_EVEN
+ && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
/* If assign is cheap, there is no point avoiding it. */
&& estimate_num_insns (assign, &eni_time_weights)
>= 3 * estimate_num_insns (cond, &eni_time_weights))
diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c
index 8f8c1336c02..7dcb9ee49a4 100644
--- a/gcc/tree-ssa-phiprop.c
+++ b/gcc/tree-ssa-phiprop.c
@@ -327,7 +327,7 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
if (!dominated_by_p (CDI_POST_DOMINATORS,
bb, gimple_bb (use_stmt)))
continue;
-
+
/* Check whether this is a load of *ptr. */
if (!(is_gimple_assign (use_stmt)
&& gimple_assign_rhs_code (use_stmt) == MEM_REF
@@ -356,6 +356,9 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
insert aggregate copies on the edges instead. */
if (!is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
{
+ if (!gimple_vdef (use_stmt))
+ goto next;
+
/* As we replicate the lhs on each incoming edge all
used SSA names have to be available there. */
if (! for_each_index (gimple_assign_lhs_ptr (use_stmt),
@@ -363,6 +366,28 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
get_immediate_dominator (CDI_DOMINATORS,
gimple_bb (phi))))
goto next;
+
+ gimple *vuse_stmt;
+ imm_use_iterator vui;
+ use_operand_p vuse_p;
+ /* In order to move the aggregate copies earlier, make sure
+ there are no statements that could read from memory
+ aliasing the lhs in between the start of bb and use_stmt.
+ As we require use_stmt to have a VDEF above, loads after
+ use_stmt will use a different virtual SSA_NAME. */
+ FOR_EACH_IMM_USE_FAST (vuse_p, vui, vuse)
+ {
+ vuse_stmt = USE_STMT (vuse_p);
+ if (vuse_stmt == use_stmt)
+ continue;
+ if (!dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (vuse_stmt), bb))
+ continue;
+ if (ref_maybe_used_by_stmt_p (vuse_stmt,
+ gimple_assign_lhs (use_stmt)))
+ goto next;
+ }
+
phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
/* Remove old stmt. The phi is taken care of by DCE. */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 2a431c96f7f..0ec3d3c7f7e 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1489,6 +1489,45 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
PRE_EXPR_NARY (expr) = nary;
new_val_id = nary->value_id;
get_or_alloc_expression_id (expr);
+ /* When we end up re-using a value number make sure that
+ doesn't have unrelated (which we can't check here)
+ range or points-to info on it. */
+ if (result
+ && INTEGRAL_TYPE_P (TREE_TYPE (result))
+ && SSA_NAME_RANGE_INFO (result)
+ && ! SSA_NAME_IS_DEFAULT_DEF (result))
+ {
+ if (! VN_INFO (result)->info.range_info)
+ {
+ VN_INFO (result)->info.range_info
+ = SSA_NAME_RANGE_INFO (result);
+ VN_INFO (result)->range_info_anti_range_p
+ = SSA_NAME_ANTI_RANGE_P (result);
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "clearing range info of ");
+ print_generic_expr (dump_file, result);
+ fprintf (dump_file, "\n");
+ }
+ SSA_NAME_RANGE_INFO (result) = NULL;
+ }
+ else if (result
+ && POINTER_TYPE_P (TREE_TYPE (result))
+ && SSA_NAME_PTR_INFO (result)
+ && ! SSA_NAME_IS_DEFAULT_DEF (result))
+ {
+ if (! VN_INFO (result)->info.ptr_info)
+ VN_INFO (result)->info.ptr_info
+ = SSA_NAME_PTR_INFO (result);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "clearing points-to info of ");
+ print_generic_expr (dump_file, result);
+ fprintf (dump_file, "\n");
+ }
+ SSA_NAME_PTR_INFO (result) = NULL;
+ }
}
else
{
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 35eb72ce310..7c3007f853a 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -2561,7 +2561,7 @@ optimize_range_tests_diff (enum tree_code opcode, tree type,
tem2 = fold_convert (type, tem2);
lowi = fold_convert (type, lowi);
mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
- tem1 = fold_binary (MINUS_EXPR, type,
+ tem1 = fold_build2 (MINUS_EXPR, type,
fold_convert (type, rangei->exp), lowi);
tem1 = fold_build2 (BIT_AND_EXPR, type, tem1, mask);
lowj = build_int_cst (type, 0);
@@ -4205,11 +4205,15 @@ insert_stmt_before_use (gimple *stmt, gimple *stmt_to_insert)
/* Recursively rewrite our linearized statements so that the operators
match those in OPS[OPINDEX], putting the computation in rank
- order. Return new lhs. */
+ order. Return new lhs.
+ CHANGED is true if we shouldn't reuse the lhs SSA_NAME both in
+ the current stmt and during recursive invocations.
+ NEXT_CHANGED is true if we shouldn't reuse the lhs SSA_NAME in
+ recursive invocations. */
static tree
rewrite_expr_tree (gimple *stmt, unsigned int opindex,
- vec<operand_entry *> ops, bool changed)
+ vec<operand_entry *> ops, bool changed, bool next_changed)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
@@ -4300,7 +4304,8 @@ rewrite_expr_tree (gimple *stmt, unsigned int opindex,
be the non-leaf side. */
tree new_rhs1
= rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops,
- changed || oe->op != rhs2);
+ changed || oe->op != rhs2 || next_changed,
+ false);
if (oe->op != rhs2 || new_rhs1 != rhs1)
{
@@ -5654,6 +5659,7 @@ reassociate_bb (basic_block bb)
gimple_set_visited (stmt, true);
linearize_expr_tree (&ops, stmt, true, true);
ops.qsort (sort_by_operand_rank);
+ int orig_len = ops.length ();
optimize_ops_list (rhs_code, &ops);
if (undistribute_ops_list (rhs_code, &ops,
loop_containing_stmt (stmt)))
@@ -5744,7 +5750,8 @@ reassociate_bb (basic_block bb)
new_lhs = rewrite_expr_tree (stmt, 0, ops,
powi_result != NULL
- || negate_result);
+ || negate_result,
+ len != orig_len);
}
/* If we combined some repeated factors into a
@@ -5843,7 +5850,7 @@ branch_fixup (void)
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
edge etrue = make_edge (cond_bb, merge_bb, EDGE_TRUE_VALUE);
- etrue->probability = REG_BR_PROB_BASE / 2;
+ etrue->probability = profile_probability::even ();
etrue->count = cond_bb->count.apply_scale (1, 2);
edge efalse = find_edge (cond_bb, then_bb);
efalse->flags = EDGE_FALSE_VALUE;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 324cd73f513..ca43f01b1f5 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -2636,6 +2636,14 @@ vn_nary_op_eq (const_vn_nary_op_t const vno1, const_vn_nary_op_t const vno2)
if (!expressions_equal_p (vno1->op[i], vno2->op[i]))
return false;
+ /* BIT_INSERT_EXPR has an implict operand as the type precision
+ of op1. Need to check to make sure they are the same. */
+ if (vno1->opcode == BIT_INSERT_EXPR
+ && TREE_CODE (vno1->op[1]) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (vno1->op[1]))
+ != TYPE_PRECISION (TREE_TYPE (vno2->op[1])))
+ return false;
+
return true;
}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index e4f18dba1e7..b0563fe7c32 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -57,11 +57,22 @@ static int max_stridx;
/* String information record. */
struct strinfo
{
- /* String length of this string. */
- tree length;
+ /* Number of leading characters that are known to be nonzero. This is
+ also the length of the string if FULL_STRING_P.
+
+ The values in a list of related string pointers must be consistent;
+ that is, if strinfo B comes X bytes after strinfo A, it must be
+ the case that A->nonzero_chars == X + B->nonzero_chars. */
+ tree nonzero_chars;
/* Any of the corresponding pointers for querying alias oracle. */
tree ptr;
- /* Statement for delayed length computation. */
+ /* This is used for two things:
+
+ - To record the statement that should be used for delayed length
+ computations. We maintain the invariant that all related strinfos
+ have delayed lengths or none do.
+
+ - To record the malloc or calloc call that produced this result. */
gimple *stmt;
/* Pointer to '\0' if known, if NULL, it can be computed as
ptr + length. */
@@ -99,6 +110,10 @@ struct strinfo
/* A flag for the next maybe_invalidate that this strinfo shouldn't
be invalidated. Always cleared by maybe_invalidate. */
bool dont_invalidate;
+ /* True if the string is known to be nul-terminated after NONZERO_CHARS
+ characters. False is useful when detecting strings that are built
+ up via successive memcpys. */
+ bool full_string_p;
};
/* Pool for allocating strinfo_struct entries. */
@@ -144,7 +159,34 @@ struct laststmt_struct
int stridx;
} laststmt;
-static int get_stridx_plus_constant (strinfo *, HOST_WIDE_INT, tree);
+static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
+
+/* Return:
+
+ - 1 if SI is known to start with more than OFF nonzero characters.
+
+ - 0 if SI is known to start with OFF nonzero characters,
+ but is not known to start with more.
+
+ - -1 if SI might not start with OFF nonzero characters. */
+
+static inline int
+compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
+{
+ if (si->nonzero_chars
+ && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
+ return compare_tree_int (si->nonzero_chars, off);
+ else
+ return -1;
+}
+
+/* Return true if SI is known to be a zero-length string. */
+
+static inline bool
+zero_length_string_p (strinfo *si)
+{
+ return si->full_string_p && integer_zerop (si->nonzero_chars);
+}
/* Return strinfo vector entry IDX. */
@@ -169,10 +211,13 @@ get_next_strinfo (strinfo *si)
return nextsi;
}
-/* Helper function for get_stridx. */
+/* Helper function for get_stridx. Return the strinfo index of the address
+ of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
+ OK to return the index for some X <= &EXP and store &EXP - X in
+ *OFFSET_OUT. */
static int
-get_addr_stridx (tree exp, tree ptr)
+get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
{
HOST_WIDE_INT off;
struct stridxlist *list, *last = NULL;
@@ -192,7 +237,11 @@ get_addr_stridx (tree exp, tree ptr)
do
{
if (list->offset == off)
- return list->idx;
+ {
+ if (offset_out)
+ *offset_out = 0;
+ return list->idx;
+ }
if (list->offset > off)
return 0;
last = list;
@@ -200,14 +249,21 @@ get_addr_stridx (tree exp, tree ptr)
}
while (list);
- if (ptr && last && last->idx > 0)
+ if ((offset_out || ptr) && last && last->idx > 0)
{
+ unsigned HOST_WIDE_INT rel_off
+ = (unsigned HOST_WIDE_INT) off - last->offset;
strinfo *si = get_strinfo (last->idx);
- if (si
- && si->length
- && TREE_CODE (si->length) == INTEGER_CST
- && compare_tree_int (si->length, off - last->offset) != -1)
- return get_stridx_plus_constant (si, off - last->offset, ptr);
+ if (si && compare_nonzero_chars (si, rel_off) >= 0)
+ {
+ if (offset_out)
+ {
+ *offset_out = rel_off;
+ return last->idx;
+ }
+ else
+ return get_stridx_plus_constant (si, rel_off, ptr);
+ }
}
return 0;
}
@@ -247,10 +303,7 @@ get_stridx (tree exp)
{
strinfo *si
= get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
- if (si
- && si->length
- && TREE_CODE (si->length) == INTEGER_CST
- && compare_tree_int (si->length, off) != -1)
+ if (si && compare_nonzero_chars (si, off) >= 0)
return get_stridx_plus_constant (si, off, exp);
}
e = rhs1;
@@ -260,7 +313,7 @@ get_stridx (tree exp)
if (TREE_CODE (exp) == ADDR_EXPR)
{
- int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp);
+ int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
if (idx != 0)
return idx;
}
@@ -413,10 +466,10 @@ new_addr_stridx (tree exp)
/* Create a new strinfo. */
static strinfo *
-new_strinfo (tree ptr, int idx, tree length)
+new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
{
strinfo *si = strinfo_pool.allocate ();
- si->length = length;
+ si->nonzero_chars = nonzero_chars;
si->ptr = ptr;
si->stmt = NULL;
si->endptr = NULL_TREE;
@@ -427,6 +480,7 @@ new_strinfo (tree ptr, int idx, tree length)
si->next = 0;
si->writable = false;
si->dont_invalidate = false;
+ si->full_string_p = full_string_p;
return si;
}
@@ -451,13 +505,53 @@ set_strinfo (int idx, strinfo *si)
(*stridx_to_strinfo)[idx] = si;
}
+/* Return the first strinfo in the related strinfo chain
+ if all strinfos in between belong to the chain, otherwise NULL. */
+
+static strinfo *
+verify_related_strinfos (strinfo *origsi)
+{
+ strinfo *si = origsi, *psi;
+
+ if (origsi->first == 0)
+ return NULL;
+ for (; si->prev; si = psi)
+ {
+ if (si->first != origsi->first)
+ return NULL;
+ psi = get_strinfo (si->prev);
+ if (psi == NULL)
+ return NULL;
+ if (psi->next != si->idx)
+ return NULL;
+ }
+ if (si->idx != si->first)
+ return NULL;
+ return si;
+}
+
+/* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
+ Use LOC for folding. */
+
+static void
+set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
+{
+ si->endptr = endptr;
+ si->stmt = NULL;
+ tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
+ tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
+ si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
+ end_as_size, start_as_size);
+ si->full_string_p = true;
+}
+
/* Return string length, or NULL if it can't be computed. */
static tree
get_string_length (strinfo *si)
{
- if (si->length)
- return si->length;
+ if (si->nonzero_chars)
+ return si->full_string_p ? si->nonzero_chars : NULL;
if (si->stmt)
{
@@ -546,23 +640,23 @@ get_string_length (strinfo *si)
case BUILT_IN_STPCPY_CHK_CHKP:
gcc_assert (lhs != NULL_TREE);
loc = gimple_location (stmt);
- si->endptr = lhs;
- si->stmt = NULL;
- lhs = fold_convert_loc (loc, size_type_node, lhs);
- si->length = fold_convert_loc (loc, size_type_node, si->ptr);
- si->length = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
- lhs, si->length);
+ set_endptr_and_length (loc, si, lhs);
+ for (strinfo *chainsi = verify_related_strinfos (si);
+ chainsi != NULL;
+ chainsi = get_next_strinfo (chainsi))
+ if (chainsi->nonzero_chars == NULL)
+ set_endptr_and_length (loc, chainsi, lhs);
break;
case BUILT_IN_MALLOC:
break;
- /* BUILT_IN_CALLOC always has si->length set. */
+ /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
default:
gcc_unreachable ();
break;
}
}
- return si->length;
+ return si->nonzero_chars;
}
/* Invalidate string length information for strings whose length
@@ -581,7 +675,7 @@ maybe_invalidate (gimple *stmt)
if (!si->dont_invalidate)
{
ao_ref r;
- /* Do not use si->length. */
+ /* Do not use si->nonzero_chars. */
ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
if (stmt_may_clobber_ref_p_1 (stmt, &r))
{
@@ -608,7 +702,7 @@ unshare_strinfo (strinfo *si)
if (si->refcount == 1 && !strinfo_shared ())
return si;
- nsi = new_strinfo (si->ptr, si->idx, si->length);
+ nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
nsi->stmt = si->stmt;
nsi->endptr = si->endptr;
nsi->first = si->first;
@@ -620,70 +714,44 @@ unshare_strinfo (strinfo *si)
return nsi;
}
-/* Return first strinfo in the related strinfo chain
- if all strinfos in between belong to the chain, otherwise
- NULL. */
-
-static strinfo *
-verify_related_strinfos (strinfo *origsi)
-{
- strinfo *si = origsi, *psi;
-
- if (origsi->first == 0)
- return NULL;
- for (; si->prev; si = psi)
- {
- if (si->first != origsi->first)
- return NULL;
- psi = get_strinfo (si->prev);
- if (psi == NULL)
- return NULL;
- if (psi->next != si->idx)
- return NULL;
- }
- if (si->idx != si->first)
- return NULL;
- return si;
-}
-
/* Attempt to create a new strinfo for BASESI + OFF, or find existing
strinfo if there is any. Return it's idx, or 0 if no strinfo has
been created. */
static int
-get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
+get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
+ tree ptr)
{
if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
return 0;
- if (basesi->length == NULL_TREE
- || TREE_CODE (basesi->length) != INTEGER_CST
- || compare_tree_int (basesi->length, off) == -1
- || !tree_fits_shwi_p (basesi->length))
+ if (compare_nonzero_chars (basesi, off) < 0
+ || !tree_fits_uhwi_p (basesi->nonzero_chars))
return 0;
- HOST_WIDE_INT len = tree_to_shwi (basesi->length) - off;
+ unsigned HOST_WIDE_INT nonzero_chars
+ = tree_to_uhwi (basesi->nonzero_chars) - off;
strinfo *si = basesi, *chainsi;
if (si->first || si->prev || si->next)
si = verify_related_strinfos (basesi);
if (si == NULL
- || si->length == NULL_TREE
- || TREE_CODE (si->length) != INTEGER_CST)
+ || si->nonzero_chars == NULL_TREE
+ || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
return 0;
if (TREE_CODE (ptr) == SSA_NAME
&& ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
- gcc_checking_assert (compare_tree_int (si->length, off) != -1);
+ gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
for (chainsi = si; chainsi->next; chainsi = si)
{
si = get_next_strinfo (chainsi);
if (si == NULL
- || si->length == NULL_TREE
- || TREE_CODE (si->length) != INTEGER_CST)
+ || si->nonzero_chars == NULL_TREE
+ || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
break;
- int r = compare_tree_int (si->length, len);
+ int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
if (r != 1)
{
if (r == 0)
@@ -705,7 +773,8 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
int idx = new_stridx (ptr);
if (idx == 0)
return 0;
- si = new_strinfo (ptr, idx, build_int_cst (size_type_node, len));
+ si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
+ basesi->full_string_p);
set_strinfo (idx, si);
if (chainsi->next)
{
@@ -717,7 +786,7 @@ get_stridx_plus_constant (strinfo *basesi, HOST_WIDE_INT off, tree ptr)
if (chainsi->first == 0)
chainsi->first = chainsi->idx;
chainsi->next = idx;
- if (chainsi->endptr == NULL_TREE && len == 0)
+ if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
chainsi->endptr = ptr;
si->endptr = chainsi->endptr;
si->prev = chainsi->idx;
@@ -749,7 +818,8 @@ zero_length_string (tree ptr, strinfo *chainsi)
{
do
{
- gcc_assert (si->length || si->stmt);
+ /* We shouldn't mix delayed and non-delayed lengths. */
+ gcc_assert (si->full_string_p);
if (si->endptr == NULL_TREE)
{
si = unshare_strinfo (si);
@@ -759,7 +829,7 @@ zero_length_string (tree ptr, strinfo *chainsi)
si = get_next_strinfo (si);
}
while (si != NULL);
- if (chainsi->length && integer_zerop (chainsi->length))
+ if (zero_length_string_p (chainsi))
{
if (chainsi->next)
{
@@ -770,18 +840,23 @@ zero_length_string (tree ptr, strinfo *chainsi)
return chainsi;
}
}
- else if (chainsi->first || chainsi->prev || chainsi->next)
+ else
{
- chainsi = unshare_strinfo (chainsi);
- chainsi->first = 0;
- chainsi->prev = 0;
- chainsi->next = 0;
+ /* We shouldn't mix delayed and non-delayed lengths. */
+ gcc_assert (chainsi->full_string_p);
+ if (chainsi->first || chainsi->prev || chainsi->next)
+ {
+ chainsi = unshare_strinfo (chainsi);
+ chainsi->first = 0;
+ chainsi->prev = 0;
+ chainsi->next = 0;
+ }
}
}
idx = new_stridx (ptr);
if (idx == 0)
return NULL;
- si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0));
+ si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
set_strinfo (idx, si);
si->endptr = ptr;
if (chainsi != NULL)
@@ -799,9 +874,11 @@ zero_length_string (tree ptr, strinfo *chainsi)
return si;
}
-/* For strinfo ORIGSI whose length has been just updated
- update also related strinfo lengths (add ADJ to each,
- but don't adjust ORIGSI). */
+/* For strinfo ORIGSI whose length has been just updated, adjust other
+ related strinfos so that they match the new ORIGSI. This involves:
+
+ - adding ADJ to the nonzero_chars fields
+ - copying full_string_p from the new ORIGSI. */
static void
adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
@@ -820,18 +897,15 @@ adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
tree tem;
si = unshare_strinfo (si);
- if (si->length)
- {
- tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
- si->length = fold_build2_loc (loc, PLUS_EXPR,
- TREE_TYPE (si->length), si->length,
- tem);
- }
- else if (si->stmt != NULL)
- /* Delayed length computation is unaffected. */
- ;
- else
- gcc_unreachable ();
+ /* We shouldn't see delayed lengths here; the caller must have
+ calculated the old length in order to calculate the
+ adjustment. */
+ gcc_assert (si->nonzero_chars);
+ tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
+ si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
+ TREE_TYPE (si->nonzero_chars),
+ si->nonzero_chars, tem);
+ si->full_string_p = origsi->full_string_p;
si->endptr = NULL_TREE;
si->dont_invalidate = true;
@@ -1000,11 +1074,8 @@ adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
}
}
- if (!is_strcat)
- {
- if (si->length == NULL_TREE || !integer_zerop (si->length))
- return;
- }
+ if (!is_strcat && !zero_length_string_p (si))
+ return;
if (is_gimple_assign (last.stmt))
{
@@ -1118,12 +1189,13 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
if (si != NULL
- && TREE_CODE (si->length) != SSA_NAME
- && TREE_CODE (si->length) != INTEGER_CST
+ && TREE_CODE (si->nonzero_chars) != SSA_NAME
+ && TREE_CODE (si->nonzero_chars) != INTEGER_CST
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
{
si = unshare_strinfo (si);
- si->length = lhs;
+ si->nonzero_chars = lhs;
+ gcc_assert (si->full_string_p);
}
return;
}
@@ -1132,11 +1204,40 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
return;
if (idx == 0)
idx = new_stridx (src);
- else if (get_strinfo (idx) != NULL)
- return;
+ else
+ {
+ strinfo *si = get_strinfo (idx);
+ if (si != NULL)
+ {
+ if (!si->full_string_p && !si->stmt)
+ {
+ /* Until now we only had a lower bound on the string length.
+ Install LHS as the actual length. */
+ si = unshare_strinfo (si);
+ tree old = si->nonzero_chars;
+ si->nonzero_chars = lhs;
+ si->full_string_p = true;
+ if (TREE_CODE (old) == INTEGER_CST)
+ {
+ location_t loc = gimple_location (stmt);
+ old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
+ tree adj = fold_build2_loc (loc, MINUS_EXPR,
+ TREE_TYPE (lhs), lhs, old);
+ adjust_related_strinfos (loc, si, adj);
+ }
+ else
+ {
+ si->first = 0;
+ si->prev = 0;
+ si->next = 0;
+ }
+ }
+ return;
+ }
+ }
if (idx)
{
- strinfo *si = new_strinfo (src, idx, lhs);
+ strinfo *si = new_strinfo (src, idx, lhs, true);
set_strinfo (idx, si);
find_equal_ptrs (src, idx);
}
@@ -1240,7 +1341,7 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
tree srcu = fold_convert_loc (loc, size_type_node, src);
tree length = fold_build2_loc (loc, MINUS_EXPR,
size_type_node, lhsu, srcu);
- strinfo *si = new_strinfo (src, idx, length);
+ strinfo *si = new_strinfo (src, idx, length, true);
si->endptr = lhs;
set_strinfo (idx, si);
find_equal_ptrs (src, idx);
@@ -1329,9 +1430,10 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
}
if (olddsi != NULL)
{
- oldlen = olddsi->length;
+ oldlen = olddsi->nonzero_chars;
dsi = unshare_strinfo (olddsi);
- dsi->length = srclen;
+ dsi->nonzero_chars = srclen;
+ dsi->full_string_p = (srclen != NULL_TREE);
/* Break the chain, so adjust_related_strinfo on later pointers in
the chain won't adjust this one anymore. */
dsi->next = 0;
@@ -1340,14 +1442,14 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
}
else
{
- dsi = new_strinfo (dst, didx, srclen);
+ dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
set_strinfo (didx, dsi);
find_equal_ptrs (dst, didx);
}
dsi->writable = true;
dsi->dont_invalidate = true;
- if (dsi->length == NULL_TREE)
+ if (dsi->nonzero_chars == NULL_TREE)
{
strinfo *chainsi;
@@ -1368,7 +1470,8 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
invalidated. */
chainsi = unshare_strinfo (chainsi);
chainsi->stmt = stmt;
- chainsi->length = NULL_TREE;
+ chainsi->nonzero_chars = NULL_TREE;
+ chainsi->full_string_p = false;
chainsi->endptr = NULL_TREE;
chainsi->dont_invalidate = true;
}
@@ -1536,31 +1639,61 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
&& !integer_zerop (len))
adjust_last_stmt (olddsi, stmt, false);
+ bool full_string_p;
if (idx > 0)
{
gimple *def_stmt;
- /* Handle memcpy (x, y, l) where l is strlen (y) + 1. */
+ /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
+ is known. */
si = get_strinfo (idx);
- if (si == NULL || si->length == NULL_TREE)
- return;
- if (TREE_CODE (len) != SSA_NAME)
- return;
- def_stmt = SSA_NAME_DEF_STMT (len);
- if (!is_gimple_assign (def_stmt)
- || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
- || gimple_assign_rhs1 (def_stmt) != si->length
- || !integer_onep (gimple_assign_rhs2 (def_stmt)))
+ if (si == NULL || si->nonzero_chars == NULL_TREE)
return;
+ if (TREE_CODE (len) == INTEGER_CST
+ && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
+ {
+ if (tree_int_cst_le (len, si->nonzero_chars))
+ {
+ /* Copying LEN nonzero characters, where LEN is constant. */
+ newlen = len;
+ full_string_p = false;
+ }
+ else
+ {
+ /* Copying the whole of the analyzed part of SI. */
+ newlen = si->nonzero_chars;
+ full_string_p = si->full_string_p;
+ }
+ }
+ else
+ {
+ if (!si->full_string_p)
+ return;
+ if (TREE_CODE (len) != SSA_NAME)
+ return;
+ def_stmt = SSA_NAME_DEF_STMT (len);
+ if (!is_gimple_assign (def_stmt)
+ || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
+ || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
+ || !integer_onep (gimple_assign_rhs2 (def_stmt)))
+ return;
+ /* Copying variable-length string SI (and no more). */
+ newlen = si->nonzero_chars;
+ full_string_p = true;
+ }
}
else
{
si = NULL;
/* Handle memcpy (x, "abcd", 5) or
memcpy (x, "abc\0uvw", 7). */
- if (!tree_fits_uhwi_p (len)
- || tree_to_uhwi (len) <= (unsigned HOST_WIDE_INT) ~idx)
+ if (!tree_fits_uhwi_p (len))
return;
+
+ unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
+ unsigned HOST_WIDE_INT nonzero_chars = ~idx;
+ newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
+ full_string_p = clen > nonzero_chars;
}
if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
@@ -1572,16 +1705,13 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (didx == 0)
return;
}
- if (si != NULL)
- newlen = si->length;
- else
- newlen = build_int_cst (size_type_node, ~idx);
oldlen = NULL_TREE;
if (olddsi != NULL)
{
dsi = unshare_strinfo (olddsi);
- oldlen = olddsi->length;
- dsi->length = newlen;
+ oldlen = olddsi->nonzero_chars;
+ dsi->nonzero_chars = newlen;
+ dsi->full_string_p = full_string_p;
/* Break the chain, so adjust_related_strinfo on later pointers in
the chain won't adjust this one anymore. */
dsi->next = 0;
@@ -1590,7 +1720,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
}
else
{
- dsi = new_strinfo (dst, didx, newlen);
+ dsi = new_strinfo (dst, didx, newlen, full_string_p);
set_strinfo (didx, dsi);
find_equal_ptrs (dst, didx);
}
@@ -1603,12 +1733,11 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (oldlen == NULL_TREE)
;
else if (integer_zerop (oldlen))
- adj = dsi->length;
+ adj = newlen;
else if (TREE_CODE (oldlen) == INTEGER_CST
- || TREE_CODE (dsi->length) == INTEGER_CST)
- adj = fold_build2_loc (loc, MINUS_EXPR,
- TREE_TYPE (dsi->length), dsi->length,
- fold_convert_loc (loc, TREE_TYPE (dsi->length),
+ || TREE_CODE (newlen) == INTEGER_CST)
+ adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
+ fold_convert_loc (loc, TREE_TYPE (newlen),
oldlen));
if (adj != NULL_TREE)
adjust_related_strinfos (loc, dsi, adj);
@@ -1620,27 +1749,30 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (si != NULL)
si->dont_invalidate = true;
- lhs = gimple_call_lhs (stmt);
- switch (bcode)
+ if (full_string_p)
{
- case BUILT_IN_MEMCPY:
- case BUILT_IN_MEMCPY_CHK:
- case BUILT_IN_MEMCPY_CHKP:
- case BUILT_IN_MEMCPY_CHK_CHKP:
- /* Allow adjust_last_stmt to decrease this memcpy's size. */
- laststmt.stmt = stmt;
- laststmt.len = dsi->length;
- laststmt.stridx = dsi->idx;
- if (lhs)
- ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
- break;
- case BUILT_IN_MEMPCPY:
- case BUILT_IN_MEMPCPY_CHK:
- case BUILT_IN_MEMPCPY_CHKP:
- case BUILT_IN_MEMPCPY_CHK_CHKP:
- break;
- default:
- gcc_unreachable ();
+ lhs = gimple_call_lhs (stmt);
+ switch (bcode)
+ {
+ case BUILT_IN_MEMCPY:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMCPY_CHKP:
+ case BUILT_IN_MEMCPY_CHK_CHKP:
+ /* Allow adjust_last_stmt to decrease this memcpy's size. */
+ laststmt.stmt = stmt;
+ laststmt.len = dsi->nonzero_chars;
+ laststmt.stridx = dsi->idx;
+ if (lhs)
+ ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
+ break;
+ case BUILT_IN_MEMPCPY:
+ case BUILT_IN_MEMPCPY_CHK:
+ case BUILT_IN_MEMPCPY_CHKP:
+ case BUILT_IN_MEMPCPY_CHK_CHKP:
+ break;
+ default:
+ gcc_unreachable ();
+ }
}
}
@@ -1689,14 +1821,15 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
}
if (dsi == NULL)
{
- dsi = new_strinfo (dst, didx, NULL_TREE);
+ dsi = new_strinfo (dst, didx, NULL_TREE, false);
set_strinfo (didx, dsi);
find_equal_ptrs (dst, didx);
}
else
{
dsi = unshare_strinfo (dsi);
- dsi->length = NULL_TREE;
+ dsi->nonzero_chars = NULL_TREE;
+ dsi->full_string_p = false;
dsi->next = 0;
dsi->endptr = NULL_TREE;
}
@@ -1720,7 +1853,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
}
loc = gimple_location (stmt);
- dstlen = dsi->length;
+ dstlen = dsi->nonzero_chars;
endptr = dsi->endptr;
dsi = unshare_strinfo (dsi);
@@ -1730,14 +1863,17 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (srclen != NULL_TREE)
{
- dsi->length = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (dsi->length),
- dsi->length, srclen);
+ dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
+ TREE_TYPE (dsi->nonzero_chars),
+ dsi->nonzero_chars, srclen);
+ gcc_assert (dsi->full_string_p);
adjust_related_strinfos (loc, dsi, srclen);
dsi->dont_invalidate = true;
}
else
{
- dsi->length = NULL;
+ dsi->nonzero_chars = NULL;
+ dsi->full_string_p = false;
if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
dsi->dont_invalidate = true;
}
@@ -1870,7 +2006,7 @@ handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
tree length = NULL_TREE;
if (bcode == BUILT_IN_CALLOC)
length = build_int_cst (size_type_node, 0);
- strinfo *si = new_strinfo (lhs, idx, length);
+ strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
if (bcode == BUILT_IN_CALLOC)
si->endptr = lhs;
set_strinfo (idx, si);
@@ -1912,7 +2048,8 @@ handle_builtin_memset (gimple_stmt_iterator *gsi)
gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
size, build_one_cst (size_type_node));
- si1->length = build_int_cst (size_type_node, 0);
+ si1->nonzero_chars = build_int_cst (size_type_node, 0);
+ si1->full_string_p = true;
si1->stmt = gsi_stmt (gsi1);
}
else
@@ -2044,18 +2181,20 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
}
si = get_strinfo (idx);
- if (si == NULL || si->length == NULL_TREE)
+ if (si == NULL || si->nonzero_chars == NULL_TREE)
return;
off = gimple_assign_rhs2 (stmt);
zsi = NULL;
- if (operand_equal_p (si->length, off, 0))
+ if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
zsi = zero_length_string (lhs, si);
else if (TREE_CODE (off) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (off);
if (gimple_assign_single_p (def_stmt)
- && operand_equal_p (si->length, gimple_assign_rhs1 (def_stmt), 0))
+ && si->full_string_p
+ && operand_equal_p (si->nonzero_chars,
+ gimple_assign_rhs1 (def_stmt), 0))
zsi = zero_length_string (lhs, si);
}
if (zsi != NULL
@@ -2081,63 +2220,63 @@ handle_char_store (gimple_stmt_iterator *gsi)
strinfo *si = NULL;
gimple *stmt = gsi_stmt (*gsi);
tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
+ tree rhs = gimple_assign_rhs1 (stmt);
+ unsigned HOST_WIDE_INT offset = 0;
if (TREE_CODE (lhs) == MEM_REF
&& TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
{
- if (integer_zerop (TREE_OPERAND (lhs, 1)))
+ tree mem_offset = TREE_OPERAND (lhs, 1);
+ if (tree_fits_uhwi_p (mem_offset))
{
- ssaname = TREE_OPERAND (lhs, 0);
- idx = get_stridx (ssaname);
+ /* Get the strinfo for the base, and use it if it starts with at
+ least OFFSET nonzero characters. This is trivially true if
+ OFFSET is zero. */
+ offset = tree_to_uhwi (mem_offset);
+ idx = get_stridx (TREE_OPERAND (lhs, 0));
+ if (idx > 0)
+ si = get_strinfo (idx);
+ if (offset == 0)
+ ssaname = TREE_OPERAND (lhs, 0);
+ else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
+ return true;
}
}
else
- idx = get_addr_stridx (lhs, NULL_TREE);
+ {
+ idx = get_addr_stridx (lhs, NULL_TREE, &offset);
+ if (idx > 0)
+ si = get_strinfo (idx);
+ }
- if (idx > 0)
+ bool storing_zero_p = initializer_zerop (rhs);
+ bool storing_nonzero_p = (!storing_zero_p
+ && TREE_CODE (rhs) == INTEGER_CST
+ && integer_nonzerop (rhs));
+
+ if (si != NULL)
{
- si = get_strinfo (idx);
- if (si != NULL && si->length != NULL_TREE && integer_zerop (si->length))
+ int cmp = compare_nonzero_chars (si, offset);
+ gcc_assert (offset == 0 || cmp >= 0);
+ if (storing_zero_p && cmp == 0 && si->full_string_p)
{
- if (initializer_zerop (gimple_assign_rhs1 (stmt)))
+ /* When overwriting a '\0' with a '\0', the store can be removed
+ if we know it has been stored in the current function. */
+ if (!stmt_could_throw_p (stmt) && si->writable)
{
- /* When storing '\0', the store can be removed
- if we know it has been stored in the current function. */
- if (!stmt_could_throw_p (stmt) && si->writable)
- {
- unlink_stmt_vdef (stmt);
- release_defs (stmt);
- gsi_remove (gsi, true);
- return false;
- }
- else
- {
- si->writable = true;
- gsi_next (gsi);
- return false;
- }
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
+ gsi_remove (gsi, true);
+ return false;
}
else
- /* Otherwise this statement overwrites the '\0' with
- something, if the previous stmt was a memcpy,
- its length may be decreased. */
- adjust_last_stmt (si, stmt, false);
- }
- else if (si != NULL && integer_zerop (gimple_assign_rhs1 (stmt)))
- {
- si = unshare_strinfo (si);
- si->length = build_int_cst (size_type_node, 0);
- si->endptr = NULL;
- si->prev = 0;
- si->next = 0;
- si->stmt = NULL;
- si->first = 0;
- si->writable = true;
- if (ssaname && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
- si->endptr = ssaname;
- si->dont_invalidate = true;
+ {
+ si->writable = true;
+ gsi_next (gsi);
+ return false;
+ }
}
- /* If si->length is non-zero constant, we aren't overwriting '\0',
+ /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
and if we aren't storing '\0', we know that the length of the
string and any other zero terminated string in memory remains
the same. In that case we move to the next gimple statement and
@@ -2157,35 +2296,74 @@ handle_char_store (gimple_stmt_iterator *gsi)
bar (len, len2, len3, len4);
}
*/
- else if (si != NULL && si->length != NULL_TREE
- && TREE_CODE (si->length) == INTEGER_CST
- && integer_nonzerop (gimple_assign_rhs1 (stmt)))
+ else if (storing_nonzero_p && cmp > 0)
{
gsi_next (gsi);
return false;
}
+ else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
+ {
+ /* When storing_nonzero_p, we know that the string now starts
+ with OFFSET + 1 nonzero characters, but don't know whether
+ there's a following nul terminator.
+
+ When storing_zero_p, we know that the string is now OFFSET
+ characters long.
+
+ Otherwise, we're storing an unknown value at offset OFFSET,
+ so need to clip the nonzero_chars to OFFSET. */
+ location_t loc = gimple_location (stmt);
+ tree oldlen = si->nonzero_chars;
+ if (cmp == 0 && si->full_string_p)
+ /* We're overwriting the nul terminator with a nonzero or
+ unknown character. If the previous stmt was a memcpy,
+ its length may be decreased. */
+ adjust_last_stmt (si, stmt, false);
+ si = unshare_strinfo (si);
+ if (storing_nonzero_p)
+ si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
+ else
+ si->nonzero_chars = build_int_cst (size_type_node, offset);
+ si->full_string_p = storing_zero_p;
+ if (storing_zero_p
+ && ssaname
+ && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
+ si->endptr = ssaname;
+ else
+ si->endptr = NULL;
+ si->next = 0;
+ si->stmt = NULL;
+ si->writable = true;
+ si->dont_invalidate = true;
+ if (oldlen)
+ {
+ tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
+ si->nonzero_chars, oldlen);
+ adjust_related_strinfos (loc, si, adj);
+ }
+ else
+ si->prev = 0;
+ }
}
- else if (idx == 0 && initializer_zerop (gimple_assign_rhs1 (stmt)))
+ else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
{
if (ssaname)
- {
- si = zero_length_string (ssaname, NULL);
- if (si != NULL)
- si->dont_invalidate = true;
- }
+ idx = new_stridx (ssaname);
else
+ idx = new_addr_stridx (lhs);
+ if (idx != 0)
{
- int idx = new_addr_stridx (lhs);
- if (idx != 0)
- {
- si = new_strinfo (build_fold_addr_expr (lhs), idx,
- build_int_cst (size_type_node, 0));
- set_strinfo (idx, si);
- si->dont_invalidate = true;
- }
+ tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
+ tree len = storing_nonzero_p ? size_one_node : size_zero_node;
+ si = new_strinfo (ptr, idx, len, storing_zero_p);
+ set_strinfo (idx, si);
+ if (storing_zero_p
+ && ssaname
+ && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
+ si->endptr = ssaname;
+ si->dont_invalidate = true;
+ si->writable = true;
}
- if (si != NULL)
- si->writable = true;
}
else if (idx == 0
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST
@@ -2200,14 +2378,14 @@ handle_char_store (gimple_stmt_iterator *gsi)
if (idx != 0)
{
si = new_strinfo (build_fold_addr_expr (lhs), idx,
- build_int_cst (size_type_node, l));
+ build_int_cst (size_type_node, l), true);
set_strinfo (idx, si);
si->dont_invalidate = true;
}
}
}
- if (si != NULL && initializer_zerop (gimple_assign_rhs1 (stmt)))
+ if (si != NULL && offset == 0 && storing_zero_p)
{
/* Allow adjust_last_stmt to remove it if the stored '\0'
is immediately overwritten. */
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index e563e9dee72..e743e35033e 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -2827,7 +2827,6 @@ alias_get_name (tree decl)
{
const char *res = NULL;
char *temp;
- int num_printed = 0;
if (!dump_file)
return "NULL";
@@ -2836,14 +2835,11 @@ alias_get_name (tree decl)
{
res = get_name (decl);
if (res)
- num_printed = asprintf (&temp, "%s_%u", res, SSA_NAME_VERSION (decl));
+ temp = xasprintf ("%s_%u", res, SSA_NAME_VERSION (decl));
else
- num_printed = asprintf (&temp, "_%u", SSA_NAME_VERSION (decl));
- if (num_printed > 0)
- {
- res = ggc_strdup (temp);
- free (temp);
- }
+ temp = xasprintf ("_%u", SSA_NAME_VERSION (decl));
+ res = ggc_strdup (temp);
+ free (temp);
}
else if (DECL_P (decl))
{
@@ -2854,12 +2850,9 @@ alias_get_name (tree decl)
res = get_name (decl);
if (!res)
{
- num_printed = asprintf (&temp, "D.%u", DECL_UID (decl));
- if (num_printed > 0)
- {
- res = ggc_strdup (temp);
- free (temp);
- }
+ temp = xasprintf ("D.%u", DECL_UID (decl));
+ res = ggc_strdup (temp);
+ free (temp);
}
}
}
@@ -7771,7 +7764,8 @@ refered_from_nonlocal_fn (struct cgraph_node *node, void *data)
bool *nonlocal_p = (bool *)data;
*nonlocal_p |= (node->used_from_other_partition
|| node->externally_visible
- || node->force_output);
+ || node->force_output
+ || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)));
return false;
}
@@ -7831,7 +7825,9 @@ ipa_pta_execute (void)
constraints for parameters. */
bool nonlocal_p = (node->used_from_other_partition
|| node->externally_visible
- || node->force_output);
+ || node->force_output
+ || lookup_attribute ("noipa",
+ DECL_ATTRIBUTES (node->decl)));
node->call_for_symbol_thunks_and_aliases (refered_from_nonlocal_fn,
&nonlocal_p, true);
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index f6c9878a0a3..a65ff31d900 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -207,6 +207,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "tree-cfgcleanup.h"
+const int ignore_edge_flags = EDGE_DFS_BACK | EDGE_EXECUTABLE;
+
/* Describes a group of bbs with the same successors. The successor bbs are
cached in succs, and the successor edge flags are cached in succ_flags.
If a bb has the EDGE_TRUE/FALSE_VALUE flags swapped compared to succ_flags,
@@ -479,6 +481,8 @@ same_succ_hash (const same_succ *e)
hstate.add_int (size);
BB_SIZE (bb) = size;
+ hstate.add_int (bb->loop_father->num);
+
for (i = 0; i < e->succ_flags.length (); ++i)
{
flags = e->succ_flags[i];
@@ -568,6 +572,9 @@ same_succ::equal (const same_succ *e1, const same_succ *e2)
if (BB_SIZE (bb1) != BB_SIZE (bb2))
return 0;
+ if (bb1->loop_father != bb2->loop_father)
+ return 0;
+
gsi1 = gsi_start_nondebug_bb (bb1);
gsi2 = gsi_start_nondebug_bb (bb2);
gsi_advance_fw_nondebug_nonlocal (&gsi1);
@@ -695,22 +702,14 @@ find_same_succ_bb (basic_block bb, same_succ **same_p)
edge_iterator ei;
edge e;
- if (bb == NULL
- /* Be conservative with loop structure. It's not evident that this test
- is sufficient. Before tail-merge, we've just called
- loop_optimizer_finalize, and LOOPS_MAY_HAVE_MULTIPLE_LATCHES is now
- set, so there's no guarantee that the loop->latch value is still valid.
- But we assume that, since we've forced LOOPS_HAVE_SIMPLE_LATCHES at the
- start of pre, we've kept that property intact throughout pre, and are
- keeping it throughout tail-merge using this test. */
- || bb->loop_father->latch == bb)
+ if (bb == NULL)
return;
bitmap_set_bit (same->bbs, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
{
int index = e->dest->index;
bitmap_set_bit (same->succs, index);
- same_succ_edge_flags[index] = e->flags;
+ same_succ_edge_flags[index] = (e->flags & ~ignore_edge_flags);
}
EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
same->succ_flags.safe_push (same_succ_edge_flags[j]);
@@ -809,6 +808,9 @@ static void
same_succ_flush_bb (basic_block bb)
{
same_succ *same = BB_SAME_SUCC (bb);
+ if (! same)
+ return;
+
BB_SAME_SUCC (bb) = NULL;
if (bitmap_single_bit_set_p (same->bbs))
same_succ_htab->remove_elt_with_hash (same, same->hashval);
@@ -1239,6 +1241,7 @@ merge_stmts_p (gimple *stmt1, gimple *stmt2)
case IFN_UBSAN_CHECK_SUB:
case IFN_UBSAN_CHECK_MUL:
case IFN_UBSAN_OBJECT_SIZE:
+ case IFN_UBSAN_PTR:
case IFN_ASAN_CHECK:
/* For these internal functions, gimple_location is an implicit
parameter, which will be used explicitly after expansion.
@@ -1592,9 +1595,10 @@ replace_block_by (basic_block bb1, basic_block bb2)
else if (bb2->frequency && !bb1->frequency)
;
else if (out_freq_sum)
- e2->probability = GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
- + EDGE_FREQUENCY (e2),
- out_freq_sum);
+ e2->probability = profile_probability::from_reg_br_prob_base
+ (GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
+ + EDGE_FREQUENCY (e2),
+ out_freq_sum));
out_sum += e2->count;
}
bb2->frequency += bb1->frequency;
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index df4c6def78a..9da74675eef 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -302,7 +302,7 @@ remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
}
else
{
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
ei_next (&ei);
}
@@ -546,11 +546,9 @@ static void
create_edge_and_update_destination_phis (struct redirection_data *rd,
basic_block bb, int idx)
{
- edge e = make_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
+ edge e = make_single_succ_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
rescan_loop_exit (e, true, false);
- e->probability = REG_BR_PROB_BASE;
- e->count = bb->count;
/* We used to copy the thread path here. That was added in 2007
and dutifully updated through the representation changes in 2013.
@@ -765,7 +763,7 @@ compute_path_counts (struct redirection_data *rd,
/* Handle incoming profile insanities. */
if (total_count < path_in_count)
path_in_count = total_count;
- int onpath_scale = path_in_count.probability_in (total_count);
+ profile_probability onpath_scale = path_in_count.probability_in (total_count);
/* Walk the entire path to do some more computation in order to estimate
how much of the path_in_count will flow out of the duplicated threading
@@ -909,7 +907,7 @@ recompute_probabilities (basic_block bb)
/* Prevent overflow computation due to insane profiles. */
if (esucc->count < bb->count)
- esucc->probability = esucc->count.probability_in (bb->count);
+ esucc->probability = esucc->count.probability_in (bb->count).guessed ();
else
/* Can happen with missing/guessed probabilities, since we
may determine that more is flowing along duplicated
@@ -919,7 +917,7 @@ recompute_probabilities (basic_block bb)
get a flow verification error.
Not much we can do to make counts/freqs sane without
redoing the profile estimation. */
- esucc->probability = REG_BR_PROB_BASE;
+ esucc->probability = profile_probability::guessed_always ();
}
}
@@ -978,7 +976,8 @@ update_joiner_offpath_counts (edge epath, basic_block dup_bb,
among the duplicated off-path edges based on their original
ratio to the full off-path count (total_orig_off_path_count).
*/
- int scale = enonpath->count.probability_in (total_orig_off_path_count);
+ profile_probability scale
+ = enonpath->count.probability_in (total_orig_off_path_count);
/* Give the duplicated offpath edge a portion of the duplicated
total. */
enonpathdup->count = total_dup_off_path_count.apply_probability (scale);
@@ -1048,9 +1047,14 @@ freqs_to_counts_path (struct redirection_data *rd)
/* Scale up the frequency by REG_BR_PROB_BASE, to avoid rounding
errors applying the probability when the frequencies are very
small. */
- ein->count = profile_count::from_gcov_type
- (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
- ein->probability));
+ if (ein->probability.initialized_p ())
+ ein->count = profile_count::from_gcov_type
+ (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
+ ein->probability
+ .to_reg_br_prob_base ())).guessed ();
+ else
+ /* FIXME: this is hack; we should track uninitialized values. */
+ ein->count = profile_count::zero ();
}
for (unsigned int i = 1; i < path->length (); i++)
@@ -2358,7 +2362,7 @@ duplicate_thread_path (edge entry, edge exit,
if (e)
{
rescan_loop_exit (e, true, false);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = region_copy[n_region - 1]->count;
}
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index b587599f8f8..67f0d840bf5 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -273,6 +273,11 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
&& gimple_has_location (stmt))
{
tree rhs = gimple_assign_rhs1 (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
+ bool has_bit_insert = false;
+ use_operand_p luse_p;
+ imm_use_iterator liter;
+
if (TREE_NO_WARNING (rhs))
continue;
@@ -300,6 +305,26 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
ref.offset) <= 0)))
continue;
+ /* Do not warn if the access is then used for a BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == SSA_NAME)
+ FOR_EACH_IMM_USE_FAST (luse_p, liter, lhs)
+ {
+ gimple *use_stmt = USE_STMT (luse_p);
+ /* BIT_INSERT_EXPR first operand should not be considered
+ a use for the purpose of uninit warnings. */
+ if (gassign *ass = dyn_cast <gassign *> (use_stmt))
+ {
+ if (gimple_assign_rhs_code (ass) == BIT_INSERT_EXPR
+ && luse_p->use == gimple_assign_rhs1_ptr (ass))
+ {
+ has_bit_insert = true;
+ break;
+ }
+ }
+ }
+ if (has_bit_insert)
+ continue;
+
/* Limit the walking to a constant number of stmts after
we overcommit quadratic behavior for small functions
and O(n) behavior. */
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index fa8f81e9a1a..a67012c043f 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1513,8 +1513,8 @@ non_rewritable_lvalue_p (tree lhs)
if (DECL_P (decl)
&& VECTOR_TYPE_P (TREE_TYPE (decl))
&& TYPE_MODE (TREE_TYPE (decl)) != BLKmode
- && types_compatible_p (TREE_TYPE (lhs),
- TREE_TYPE (TREE_TYPE (decl)))
+ && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
+ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))), 0)
&& tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
&& tree_int_cst_lt (TREE_OPERAND (lhs, 1),
TYPE_SIZE_UNIT (TREE_TYPE (decl)))
@@ -1529,8 +1529,9 @@ non_rewritable_lvalue_p (tree lhs)
&& DECL_P (TREE_OPERAND (lhs, 0))
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0)))
&& TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode
- && types_compatible_p (TREE_TYPE (lhs),
- TREE_TYPE (TREE_TYPE (TREE_OPERAND (lhs, 0))))
+ && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
+ TYPE_SIZE_UNIT
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (lhs, 0)))), 0)
&& (tree_to_uhwi (TREE_OPERAND (lhs, 2))
% tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs)))) == 0)
return false;
@@ -1812,14 +1813,26 @@ execute_update_addresses_taken (void)
DECL_UID (TREE_OPERAND (lhs, 0)))
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0)))
&& TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode
- && types_compatible_p (TREE_TYPE (lhs),
- TREE_TYPE (TREE_TYPE
- (TREE_OPERAND (lhs, 0))))
+ && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
+ TYPE_SIZE_UNIT (TREE_TYPE
+ (TREE_TYPE (TREE_OPERAND (lhs, 0)))),
+ 0)
&& (tree_to_uhwi (TREE_OPERAND (lhs, 2))
% tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs))) == 0))
{
tree var = TREE_OPERAND (lhs, 0);
tree val = gimple_assign_rhs1 (stmt);
+ if (! types_compatible_p (TREE_TYPE (TREE_TYPE (var)),
+ TREE_TYPE (val)))
+ {
+ tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (var)));
+ gimple *pun
+ = gimple_build_assign (tem,
+ build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (tem), val));
+ gsi_insert_before (&gsi, pun, GSI_SAME_STMT);
+ val = tem;
+ }
tree bitpos = TREE_OPERAND (lhs, 2);
gimple_assign_set_lhs (stmt, var);
gimple_assign_set_rhs_with_ops
@@ -1839,8 +1852,9 @@ execute_update_addresses_taken (void)
&& bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
&& VECTOR_TYPE_P (TREE_TYPE (sym))
&& TYPE_MODE (TREE_TYPE (sym)) != BLKmode
- && types_compatible_p (TREE_TYPE (lhs),
- TREE_TYPE (TREE_TYPE (sym)))
+ && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
+ TYPE_SIZE_UNIT
+ (TREE_TYPE (TREE_TYPE (sym))), 0)
&& tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
&& tree_int_cst_lt (TREE_OPERAND (lhs, 1),
TYPE_SIZE_UNIT (TREE_TYPE (sym)))
@@ -1848,6 +1862,17 @@ execute_update_addresses_taken (void)
% tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
{
tree val = gimple_assign_rhs1 (stmt);
+ if (! types_compatible_p (TREE_TYPE (val),
+ TREE_TYPE (TREE_TYPE (sym))))
+ {
+ tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (sym)));
+ gimple *pun
+ = gimple_build_assign (tem,
+ build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (tem), val));
+ gsi_insert_before (&gsi, pun, GSI_SAME_STMT);
+ val = tem;
+ }
tree bitpos
= wide_int_to_tree (bitsizetype,
mem_ref_offset (lhs) * BITS_PER_UNIT);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index e83dd469846..676c806c622 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -320,11 +320,14 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
return t;
}
-/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name NAME. */
+/* Helper function for set_range_info.
+
+ Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name
+ NAME. */
void
-set_range_info (tree name, enum value_range_type range_type,
- const wide_int_ref &min, const wide_int_ref &max)
+set_range_info_raw (tree name, enum value_range_type range_type,
+ const wide_int_ref &min, const wide_int_ref &max)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
@@ -360,6 +363,34 @@ set_range_info (tree name, enum value_range_type range_type,
}
}
+/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name
+ NAME while making sure we don't store useless range info. */
+
+void
+set_range_info (tree name, enum value_range_type range_type,
+ const wide_int_ref &min, const wide_int_ref &max)
+{
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+
+ /* A range of the entire domain is really no range at all. */
+ tree type = TREE_TYPE (name);
+ if (min == wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type))
+ && max == wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
+ {
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ if (ri == NULL)
+ return;
+ if (ri->get_nonzero_bits () == -1)
+ {
+ ggc_free (ri);
+ SSA_NAME_RANGE_INFO (name) = NULL;
+ return;
+ }
+ }
+
+ set_range_info_raw (name, range_type, min, max);
+}
+
/* Gets range information MIN, MAX and returns enum value_range_type
corresponding to tree ssa_name NAME. enum value_range_type returned
@@ -419,9 +450,13 @@ set_nonzero_bits (tree name, const wide_int_ref &mask)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
if (SSA_NAME_RANGE_INFO (name) == NULL)
- set_range_info (name, VR_RANGE,
- TYPE_MIN_VALUE (TREE_TYPE (name)),
- TYPE_MAX_VALUE (TREE_TYPE (name)));
+ {
+ if (mask == -1)
+ return;
+ set_range_info_raw (name, VR_RANGE,
+ TYPE_MIN_VALUE (TREE_TYPE (name)),
+ TYPE_MAX_VALUE (TREE_TYPE (name)));
+ }
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
ri->set_nonzero_bits (mask);
}
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 9a18394f5a8..f7e032fe11d 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -69,6 +69,9 @@ struct GTY ((variable_size)) range_info_def {
/* Sets the value range to SSA. */
extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
const wide_int_ref &);
+extern void set_range_info_raw (tree, enum value_range_type,
+ const wide_int_ref &,
+ const wide_int_ref &);
/* Gets the value range from SSA. */
extern enum value_range_type get_range_info (const_tree, wide_int *,
wide_int *);
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 7f7ea7f90ab..d7b6d224ab5 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -821,8 +821,8 @@ lto_input_ts_type_non_common_tree_pointers (struct lto_input_block *ib,
TYPE_ARG_TYPES (expr) = stream_read_tree (ib, data_in);
if (!POINTER_TYPE_P (expr))
- TYPE_MINVAL (expr) = stream_read_tree (ib, data_in);
- TYPE_MAXVAL (expr) = stream_read_tree (ib, data_in);
+ TYPE_MIN_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
+ TYPE_MAX_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_BINFO (expr) = stream_read_tree (ib, data_in);
}
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 05239fb7c25..ec47a9b8040 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -704,8 +704,8 @@ write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
if (!POINTER_TYPE_P (expr))
- stream_write_tree (ob, TYPE_MINVAL (expr), ref_p);
- stream_write_tree (ob, TYPE_MAXVAL (expr), ref_p);
+ stream_write_tree (ob, TYPE_MIN_VALUE_RAW (expr), ref_p);
+ stream_write_tree (ob, TYPE_MAX_VALUE_RAW (expr), ref_p);
if (RECORD_OR_UNION_TYPE_P (expr))
stream_write_tree (ob, TYPE_BINFO (expr), ref_p);
}
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 72e53af773f..e5b5cb9a0be 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -103,7 +103,7 @@ hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
e_false->flags &= ~EDGE_FALLTHRU;
e_false->flags |= EDGE_FALSE_VALUE;
- e_false->probability = REG_BR_PROB_BASE - e_true->probability;
+ e_false->probability = e_true->probability.invert ();
e_false->count = split_bb->count - e_true->count;
new_bb->count = e_false->count;
@@ -556,7 +556,7 @@ struct switch_conv_info
basic_block final_bb;
/* The probability of the default edge in the replaced switch. */
- int default_prob;
+ profile_probability default_prob;
/* The count of the default edge in the replaced switch. */
profile_count default_count;
@@ -1422,7 +1422,7 @@ gen_inbound_check (gswitch *swtch, struct switch_conv_info *info)
/* flags and profiles of the edge for in-range values */
if (!info->default_case_nonstandard)
e01 = make_edge (bb0, bb1, EDGE_TRUE_VALUE);
- e01->probability = REG_BR_PROB_BASE - info->default_prob;
+ e01->probability = info->default_prob.invert ();
e01->count = info->other_count;
/* flags and profiles of the edge taking care of out-of-range values */
@@ -1434,7 +1434,7 @@ gen_inbound_check (gswitch *swtch, struct switch_conv_info *info)
bbf = info->final_bb;
e1f = make_edge (bb1, bbf, EDGE_FALLTHRU);
- e1f->probability = REG_BR_PROB_BASE;
+ e1f->probability = profile_probability::always ();
e1f->count = info->other_count;
if (info->default_case_nonstandard)
@@ -1442,7 +1442,7 @@ gen_inbound_check (gswitch *swtch, struct switch_conv_info *info)
else
{
e2f = make_edge (bb2, bbf, EDGE_FALLTHRU);
- e2f->probability = REG_BR_PROB_BASE;
+ e2f->probability = profile_probability::always ();
e2f->count = info->default_count;
}
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 6aa9a56462e..e0497e596bb 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -573,6 +573,11 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
{
if (! tail_recursion)
return;
+ /* Do not deal with checking dominance, the real fix is to
+ do path isolation for the transform phase anyway, removing
+ the need to compute the accumulators with new stmts. */
+ if (abb != bb)
+ return;
for (unsigned opno = 1; opno < gimple_num_ops (stmt); ++opno)
{
tree op = gimple_op (stmt, opno);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 623acf695ed..177729006e8 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "builtins.h"
#include "params.h"
+#include "tree-cfg.h"
/* Return true if load- or store-lanes optab OPTAB is implemented for
COUNT vectors of type VECTYPE. NAME is the name of OPTAB. */
@@ -666,12 +667,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
tree ref = DR_REF (dr);
- tree vectype;
- tree base, base_addr;
- tree misalign = NULL_TREE;
- tree aligned_to;
- tree step;
- unsigned HOST_WIDE_INT alignment;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -683,11 +679,15 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
/* Initialize misalignment to unknown. */
SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_UNKNOWN);
- if (tree_fits_shwi_p (DR_STEP (dr)))
- misalign = DR_INIT (dr);
- aligned_to = DR_ALIGNED_TO (dr);
- base_addr = DR_BASE_ADDRESS (dr);
- vectype = STMT_VINFO_VECTYPE (stmt_info);
+ innermost_loop_behavior *drb = vect_dr_behavior (dr);
+ bool step_preserves_misalignment_p;
+
+ /* No step for BB vectorization. */
+ if (!loop)
+ {
+ gcc_assert (integer_zerop (drb->step));
+ step_preserves_misalignment_p = true;
+ }
/* In case the dataref is in an inner-loop of the loop that is being
vectorized (LOOP), we use the base and misalignment information
@@ -695,26 +695,20 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
stays the same throughout the execution of the inner-loop, which is why
we have to check that the stride of the dataref in the inner-loop evenly
divides by the vector size. */
- if (loop && nested_in_vect_loop_p (loop, stmt))
+ else if (nested_in_vect_loop_p (loop, stmt))
{
- tree step = DR_STEP (dr);
+ step_preserves_misalignment_p
+ = (DR_STEP_ALIGNMENT (dr)
+ % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;
- if (tree_fits_shwi_p (step)
- && tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "inner step divides the vector-size.\n");
- misalign = STMT_VINFO_DR_INIT (stmt_info);
- aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
- base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
- }
- else
+ if (dump_enabled_p ())
{
- if (dump_enabled_p ())
+ if (step_preserves_misalignment_p)
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "inner step divides the vector-size.\n");
+ else
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "inner step doesn't divide the vector-size.\n");
- misalign = NULL_TREE;
+ "inner step doesn't divide the vector-size.\n");
}
}
@@ -724,61 +718,25 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
the dataref evenly divides by the vector size. */
else
{
- tree step = DR_STEP (dr);
- unsigned vf = loop ? LOOP_VINFO_VECT_FACTOR (loop_vinfo) : 1;
-
- if (tree_fits_shwi_p (step)
- && ((tree_to_shwi (step) * vf)
- % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "step doesn't divide the vector-size.\n");
- misalign = NULL_TREE;
- }
- }
+ unsigned vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ step_preserves_misalignment_p
+ = ((DR_STEP_ALIGNMENT (dr) * vf)
+ % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;
- /* To look at alignment of the base we have to preserve an inner MEM_REF
- as that carries alignment information of the actual access. */
- base = ref;
- while (handled_component_p (base))
- base = TREE_OPERAND (base, 0);
- unsigned int base_alignment = 0;
- unsigned HOST_WIDE_INT base_bitpos;
- get_object_alignment_1 (base, &base_alignment, &base_bitpos);
- /* As data-ref analysis strips the MEM_REF down to its base operand
- to form DR_BASE_ADDRESS and adds the offset to DR_INIT we have to
- adjust things to make base_alignment valid as the alignment of
- DR_BASE_ADDRESS. */
- if (TREE_CODE (base) == MEM_REF)
- {
- /* Note all this only works if DR_BASE_ADDRESS is the same as
- MEM_REF operand zero, otherwise DR/SCEV analysis might have factored
- in other offsets. We need to rework DR to compute the alingment
- of DR_BASE_ADDRESS as long as all information is still available. */
- if (operand_equal_p (TREE_OPERAND (base, 0), base_addr, 0))
- {
- base_bitpos -= mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
- base_bitpos &= (base_alignment - 1);
- }
- else
- base_bitpos = BITS_PER_UNIT;
+ if (!step_preserves_misalignment_p && dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "step doesn't divide the vector-size.\n");
}
- if (base_bitpos != 0)
- base_alignment = base_bitpos & -base_bitpos;
- /* Also look at the alignment of the base address DR analysis
- computed. */
- unsigned int base_addr_alignment = get_pointer_alignment (base_addr);
- if (base_addr_alignment > base_alignment)
- base_alignment = base_addr_alignment;
-
- if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype)))
- DR_VECT_AUX (dr)->base_element_aligned = true;
- alignment = TYPE_ALIGN_UNIT (vectype);
+ unsigned int base_alignment = drb->base_alignment;
+ unsigned int base_misalignment = drb->base_misalignment;
+ unsigned HOST_WIDE_INT vector_alignment = TYPE_ALIGN_UNIT (vectype);
- if ((compare_tree_int (aligned_to, alignment) < 0)
- || !misalign)
+ if (drb->offset_alignment < vector_alignment
+ || !step_preserves_misalignment_p
+ /* We need to know whether the step wrt the vectorized loop is
+ negative when computing the starting misalignment below. */
+ || TREE_CODE (drb->step) != INTEGER_CST)
{
if (dump_enabled_p ())
{
@@ -790,12 +748,13 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
return true;
}
- if (base_alignment < TYPE_ALIGN (vectype))
+ if (base_alignment < vector_alignment)
{
- base = base_addr;
+ tree base = drb->base_address;
if (TREE_CODE (base) == ADDR_EXPR)
base = TREE_OPERAND (base, 0);
- if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype)))
+ if (!vect_can_force_dr_alignment_p (base,
+ vector_alignment * BITS_PER_UNIT))
{
if (dump_enabled_p ())
{
@@ -832,28 +791,20 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
DR_VECT_AUX (dr)->base_decl = base;
DR_VECT_AUX (dr)->base_misaligned = true;
- DR_VECT_AUX (dr)->base_element_aligned = true;
+ base_misalignment = 0;
}
+ unsigned int misalignment = (base_misalignment
+ + TREE_INT_CST_LOW (drb->init));
- if (loop && nested_in_vect_loop_p (loop, stmt))
- step = STMT_VINFO_DR_STEP (stmt_info);
- else
- step = DR_STEP (dr);
/* If this is a backward running DR then first access in the larger
vectype actually is N-1 elements before the address in the DR.
Adjust misalign accordingly. */
- if (tree_int_cst_sgn (step) < 0)
- {
- tree offset = ssize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
- /* DR_STEP(dr) is the same as -TYPE_SIZE of the scalar type,
- otherwise we wouldn't be here. */
- offset = fold_build2 (MULT_EXPR, ssizetype, offset, step);
- /* PLUS because STEP was negative. */
- misalign = size_binop (PLUS_EXPR, misalign, offset);
- }
+ if (tree_int_cst_sgn (drb->step) < 0)
+ /* PLUS because STEP is negative. */
+ misalignment += ((TYPE_VECTOR_SUBPARTS (vectype) - 1)
+ * TREE_INT_CST_LOW (drb->step));
- SET_DR_MISALIGNMENT (dr,
- wi::mod_floor (misalign, alignment, SIGNED).to_uhwi ());
+ SET_DR_MISALIGNMENT (dr, misalignment & (vector_alignment - 1));
if (dump_enabled_p ())
{
@@ -906,8 +857,10 @@ vect_update_misalignment_for_peel (struct data_reference *dr,
{
if (current_dr != dr)
continue;
- gcc_assert (DR_MISALIGNMENT (dr) / dr_size ==
- DR_MISALIGNMENT (dr_peel) / dr_peel_size);
+ 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);
return;
}
@@ -1125,7 +1078,6 @@ typedef struct _vect_peel_extended_info
struct _vect_peel_info peel_info;
unsigned int inside_cost;
unsigned int outside_cost;
- stmt_vector_for_cost body_cost_vec;
} *vect_peel_extended_info;
@@ -1207,25 +1159,21 @@ vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
misalignment will be zero after peeling. */
static void
-vect_get_peeling_costs_all_drs (struct data_reference *dr0,
+vect_get_peeling_costs_all_drs (vec<data_reference_p> datarefs,
+ struct data_reference *dr0,
unsigned int *inside_cost,
unsigned int *outside_cost,
stmt_vector_for_cost *body_cost_vec,
unsigned int npeel,
bool unknown_misalignment)
{
- gimple *stmt = DR_STMT (dr0);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
-
unsigned i;
data_reference *dr;
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- stmt = DR_STMT (dr);
- stmt_info = vinfo_for_stmt (stmt);
+ gimple *stmt = DR_STMT (dr);
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
/* For interleaving, only the alignment of the first access
matters. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
@@ -1240,7 +1188,9 @@ vect_get_peeling_costs_all_drs (struct data_reference *dr0,
int save_misalignment;
save_misalignment = DR_MISALIGNMENT (dr);
- if (unknown_misalignment && dr == dr0)
+ if (npeel == 0)
+ ;
+ else if (unknown_misalignment && dr == dr0)
SET_DR_MISALIGNMENT (dr, 0);
else
vect_update_misalignment_for_peel (dr, dr0, npeel);
@@ -1270,9 +1220,12 @@ 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 (elem->dr, &inside_cost, &outside_cost,
+ vect_get_peeling_costs_all_drs (LOOP_VINFO_DATAREFS (loop_vinfo),
+ elem->dr, &inside_cost, &outside_cost,
&body_cost_vec, elem->npeel, false);
+ body_cost_vec.release ();
+
outside_cost += vect_get_known_peeling_cost
(loop_vinfo, elem->npeel, &dummy,
&LOOP_VINFO_SCALAR_ITERATION_COST (loop_vinfo),
@@ -1291,14 +1244,10 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
{
min->inside_cost = inside_cost;
min->outside_cost = outside_cost;
- min->body_cost_vec.release ();
- min->body_cost_vec = body_cost_vec;
min->peel_info.dr = elem->dr;
min->peel_info.npeel = elem->npeel;
min->peel_info.count = elem->count;
}
- else
- body_cost_vec.release ();
return 1;
}
@@ -1310,14 +1259,11 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
static struct _vect_peel_extended_info
vect_peeling_hash_choose_best_peeling (hash_table<peel_info_hasher> *peeling_htab,
- loop_vec_info loop_vinfo,
- unsigned int *npeel,
- stmt_vector_for_cost *body_cost_vec)
+ loop_vec_info loop_vinfo)
{
struct _vect_peel_extended_info res;
res.peel_info.dr = NULL;
- res.body_cost_vec = stmt_vector_for_cost ();
if (!unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo)))
{
@@ -1335,8 +1281,6 @@ vect_peeling_hash_choose_best_peeling (hash_table<peel_info_hasher> *peeling_hta
res.outside_cost = 0;
}
- *npeel = res.peel_info.npeel;
- *body_cost_vec = res.body_cost_vec;
return res;
}
@@ -1501,7 +1445,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unsigned possible_npeel_number = 1;
tree vectype;
unsigned int nelements, mis, same_align_drs_max = 0;
- stmt_vector_for_cost body_cost_vec = stmt_vector_for_cost ();
hash_table<peel_info_hasher> peeling_htab (1);
if (dump_enabled_p ())
@@ -1707,7 +1650,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 (dr0,
+ vect_get_peeling_costs_all_drs (datarefs, dr0,
&load_inside_cost,
&load_outside_cost,
&dummy, vf / 2, true);
@@ -1716,7 +1659,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (first_store)
{
dummy.create (2);
- vect_get_peeling_costs_all_drs (first_store,
+ vect_get_peeling_costs_all_drs (datarefs, first_store,
&store_inside_cost,
&store_outside_cost,
&dummy, vf / 2, true);
@@ -1776,7 +1719,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unless aligned. So we try to choose the best possible peeling from
the hash table. */
peel_for_known_alignment = vect_peeling_hash_choose_best_peeling
- (&peeling_htab, loop_vinfo, &npeel, &body_cost_vec);
+ (&peeling_htab, loop_vinfo);
}
/* Compare costs of peeling for known and unknown alignment. */
@@ -1800,17 +1743,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
dr0 = unsupportable_dr;
else if (do_peeling)
{
- /* Calculate the penalty for no peeling, i.e. leaving everything
- unaligned.
- TODO: Adapt vect_get_peeling_costs_all_drs and use here. */
+ /* Calculate the penalty for no peeling, i.e. leaving everything as-is.
+ TODO: Use nopeel_outside_cost or get rid of it? */
unsigned nopeel_inside_cost = 0;
unsigned nopeel_outside_cost = 0;
stmt_vector_for_cost dummy;
dummy.create (2);
- FOR_EACH_VEC_ELT (datarefs, i, dr)
- vect_get_data_access_cost (dr, &nopeel_inside_cost,
- &nopeel_outside_cost, &dummy);
+ vect_get_peeling_costs_all_drs (datarefs, NULL, &nopeel_inside_cost,
+ &nopeel_outside_cost, &dummy, 0, false);
dummy.release ();
/* Add epilogue costs. As we do not peel for alignment here, no prologue
@@ -1884,10 +1825,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (!stat)
do_peeling = false;
else
- {
- body_cost_vec.release ();
- return stat;
- }
+ return stat;
}
/* Cost model #1 - honor --param vect-max-peeling-for-alignment. */
@@ -1963,19 +1901,16 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
dump_printf_loc (MSG_NOTE, vect_location,
"Peeling for alignment will be applied.\n");
}
+
/* The inside-loop cost will be accounted for in vectorizable_load
and vectorizable_store correctly with adjusted alignments.
Drop the body_cst_vec on the floor here. */
- body_cost_vec.release ();
-
stat = vect_verify_datarefs_alignment (loop_vinfo);
gcc_assert (stat);
return stat;
}
}
- body_cost_vec.release ();
-
/* (2) Versioning to force alignment. */
/* Try versioning if:
@@ -3418,8 +3353,10 @@ again:
{
DR_OFFSET (newdr) = ssize_int (0);
DR_STEP (newdr) = step;
- DR_ALIGNED_TO (newdr)
- = size_int (BIGGEST_ALIGNMENT);
+ DR_OFFSET_ALIGNMENT (newdr)
+ = BIGGEST_ALIGNMENT;
+ DR_STEP_ALIGNMENT (newdr)
+ = highest_pow2_factor (step);
dr = newdr;
simd_lane_access = true;
}
@@ -3558,100 +3495,27 @@ again:
the outer-loop. */
if (loop && nested_in_vect_loop_p (loop, stmt))
{
- tree outer_step, outer_base, outer_init;
- HOST_WIDE_INT pbitsize, pbitpos;
- tree poffset;
- machine_mode pmode;
- int punsignedp, preversep, pvolatilep;
- affine_iv base_iv, offset_iv;
- tree dinit;
-
/* Build a reference to the first location accessed by the
- inner-loop: *(BASE+INIT). (The first location is actually
- BASE+INIT+OFFSET, but we add OFFSET separately later). */
- tree inner_base = build_fold_indirect_ref
- (fold_build_pointer_plus (base, init));
+ inner loop: *(BASE + INIT + OFFSET). By construction,
+ this address must be invariant in the inner loop, so we
+ can consider it as being used in the outer loop. */
+ tree init_offset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset),
+ init, offset);
+ tree init_addr = fold_build_pointer_plus (base, init_offset);
+ 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, inner_base);
+ "analyze in outer loop: ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, init_ref);
dump_printf (MSG_NOTE, "\n");
}
- outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos,
- &poffset, &pmode, &punsignedp,
- &preversep, &pvolatilep);
- gcc_assert (outer_base != NULL_TREE);
-
- if (pbitpos % BITS_PER_UNIT != 0)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "failed: bit offset alignment.\n");
- return false;
- }
-
- if (preversep)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "failed: reverse storage order.\n");
- return false;
- }
-
- outer_base = build_fold_addr_expr (outer_base);
- if (!simple_iv (loop, loop_containing_stmt (stmt), outer_base,
- &base_iv, false))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "failed: evolution of base is not affine.\n");
- return false;
- }
-
- if (offset)
- {
- if (poffset)
- poffset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset), offset,
- poffset);
- else
- poffset = offset;
- }
-
- if (!poffset)
- {
- offset_iv.base = ssize_int (0);
- offset_iv.step = ssize_int (0);
- }
- else if (!simple_iv (loop, loop_containing_stmt (stmt), poffset,
- &offset_iv, false))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "evolution of offset is not affine.\n");
- return false;
- }
-
- outer_init = ssize_int (pbitpos / BITS_PER_UNIT);
- split_constant_offset (base_iv.base, &base_iv.base, &dinit);
- outer_init = size_binop (PLUS_EXPR, outer_init, dinit);
- split_constant_offset (offset_iv.base, &offset_iv.base, &dinit);
- outer_init = size_binop (PLUS_EXPR, outer_init, dinit);
-
- outer_step = size_binop (PLUS_EXPR,
- fold_convert (ssizetype, base_iv.step),
- fold_convert (ssizetype, offset_iv.step));
-
- STMT_VINFO_DR_STEP (stmt_info) = outer_step;
- /* FIXME: Use canonicalize_base_object_address (base_iv.base); */
- STMT_VINFO_DR_BASE_ADDRESS (stmt_info) = base_iv.base;
- STMT_VINFO_DR_INIT (stmt_info) = outer_init;
- STMT_VINFO_DR_OFFSET (stmt_info) =
- fold_convert (ssizetype, offset_iv.base);
- STMT_VINFO_DR_ALIGNED_TO (stmt_info) =
- size_int (highest_pow2_factor (offset_iv.base));
+ if (!dr_analyze_innermost (&STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info),
+ init_ref, loop))
+ /* dr_analyze_innermost already explained the failure. */
+ return false;
if (dump_enabled_p ())
{
@@ -3669,10 +3533,14 @@ again:
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 aligned to: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_DR_ALIGNED_TO (stmt_info));
- dump_printf (MSG_NOTE, "\n");
+ 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));
}
}
@@ -3971,38 +3839,22 @@ tree
vect_create_addr_base_for_vector_ref (gimple *stmt,
gimple_seq *new_stmt_list,
tree offset,
- struct loop *loop,
tree byte_offset)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- tree data_ref_base;
const char *base_name;
tree addr_base;
tree dest;
gimple_seq seq = NULL;
- tree base_offset;
- tree init;
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);
- if (loop_vinfo && loop && loop != (gimple_bb (stmt))->loop_father)
- {
- struct loop *outer_loop = LOOP_VINFO_LOOP (loop_vinfo);
-
- gcc_assert (nested_in_vect_loop_p (outer_loop, stmt));
-
- data_ref_base = unshare_expr (STMT_VINFO_DR_BASE_ADDRESS (stmt_info));
- base_offset = unshare_expr (STMT_VINFO_DR_OFFSET (stmt_info));
- init = unshare_expr (STMT_VINFO_DR_INIT (stmt_info));
- }
- else
- {
- data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
- base_offset = unshare_expr (DR_OFFSET (dr));
- init = unshare_expr (DR_INIT (dr));
- }
+ tree data_ref_base = unshare_expr (drb->base_address);
+ tree base_offset = unshare_expr (drb->offset);
+ tree init = unshare_expr (drb->init);
if (loop_vinfo)
base_name = get_name (data_ref_base);
@@ -4167,11 +4019,7 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
/* Check the step (evolution) of the load in LOOP, and record
whether it's invariant. */
- if (nested_in_vect_loop)
- step = STMT_VINFO_DR_STEP (stmt_info);
- else
- step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
-
+ step = vect_dr_behavior (dr)->step;
if (integer_zerop (step))
*inv_p = true;
else
@@ -4269,7 +4117,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,
- offset, loop, byte_offset);
+ offset, byte_offset);
if (new_stmt_list)
{
if (pe)
@@ -4983,7 +4831,7 @@ vect_setup_realignment (gimple *stmt, gimple_stmt_iterator *gsi,
{
/* Generate the INIT_ADDR computation outside LOOP. */
init_addr = vect_create_addr_base_for_vector_ref (stmt, &stmts,
- NULL_TREE, loop);
+ NULL_TREE);
if (loop)
{
pe = loop_preheader_edge (loop);
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index d60b84e60ef..97080a61ff7 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -540,7 +540,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop,
static edge
slpeel_add_loop_guard (basic_block guard_bb, tree cond,
basic_block guard_to, basic_block dom_bb,
- int probability, bool irreducible_p)
+ profile_probability probability, bool irreducible_p)
{
gimple_stmt_iterator gsi;
edge new_e, enter_e;
@@ -571,7 +571,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond,
new_e->flags |= EDGE_IRREDUCIBLE_LOOP;
enter_e->count -= new_e->count;
- enter_e->probability = inverse_probability (probability);
+ enter_e->probability = probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, guard_to, dom_bb);
/* Split enter_e to preserve LOOPS_HAVE_PREHEADERS. */
@@ -949,7 +949,6 @@ 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);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree var;
tree niters_type = TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo));
gimple_seq stmts = NULL, new_stmts = NULL;
@@ -977,7 +976,7 @@ vect_gen_prolog_loop_niters (loop_vec_info loop_vinfo,
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,
- &stmts, offset, loop);
+ &stmts, offset);
tree type = unsigned_type_for (TREE_TYPE (start_addr));
tree vectype_align_minus_1 = build_int_cst (type, vectype_align - 1);
HOST_WIDE_INT elem_size =
@@ -1660,7 +1659,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
edge e, guard_e;
tree type = TREE_TYPE (niters), guard_cond;
basic_block guard_bb, guard_to;
- int prob_prolog, prob_vector, prob_epilog;
+ profile_probability prob_prolog, prob_vector, prob_epilog;
int bound_prolog = 0, bound_scalar = 0, bound = 0;
int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
int prolog_peeling = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
@@ -1670,10 +1669,11 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
if (!prolog_peeling && !epilog_peeling)
return NULL;
- prob_vector = 9 * REG_BR_PROB_BASE / 10;
+ prob_vector = profile_probability::guessed_always ().apply_scale (9, 10);
if ((vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo)) == 2)
vf = 3;
- prob_prolog = prob_epilog = (vf - 1) * REG_BR_PROB_BASE / vf;
+ prob_prolog = prob_epilog = profile_probability::guessed_always ()
+ .apply_scale (vf - 1, vf);
vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
struct loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -1718,8 +1718,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
separately. Note in this case, the probability of epilog loop
needs to be scaled back later. */
basic_block bb_before_loop = loop_preheader_edge (loop)->src;
- scale_bbs_frequencies_int (&bb_before_loop, 1, prob_vector,
- REG_BR_PROB_BASE);
+ if (prob_vector.initialized_p ())
+ scale_bbs_frequencies (&bb_before_loop, 1, prob_vector);
scale_loop_profile (loop, prob_vector, bound);
}
@@ -1762,14 +1762,13 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
guard_to = split_edge (loop_preheader_edge (loop));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
guard_to, guard_bb,
- inverse_probability (prob_prolog),
+ prob_prolog.invert (),
irred_flag);
e = EDGE_PRED (guard_to, 0);
e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
slpeel_update_phi_nodes_for_guard1 (prolog, loop, guard_e, e);
- scale_bbs_frequencies_int (&bb_after_prolog, 1, prob_prolog,
- REG_BR_PROB_BASE);
+ scale_bbs_frequencies (&bb_after_prolog, 1, prob_prolog);
scale_loop_profile (prolog, prob_prolog, bound_prolog);
}
/* Update init address of DRs. */
@@ -1834,7 +1833,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
guard_to = split_edge (loop_preheader_edge (epilog));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
guard_to, guard_bb,
- inverse_probability (prob_vector),
+ prob_vector.invert (),
irred_flag);
e = EDGE_PRED (guard_to, 0);
e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
@@ -1845,9 +1844,15 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
guard_to->frequency = guard_bb->frequency;
guard_to->count = guard_bb->count;
single_succ_edge (guard_to)->count = guard_to->count;
- /* Scale probability of epilog loop back. */
- int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE / prob_vector;
- scale_loop_frequencies (epilog, scale_up, REG_BR_PROB_BASE);
+ /* Scale probability of epilog loop back.
+ FIXME: We should avoid scaling down and back up. Profile may
+ get lost if we scale down to 0. */
+ int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE
+ / prob_vector.to_reg_br_prob_base ();
+ basic_block *bbs = get_loop_body (epilog);
+ scale_bbs_frequencies_int (bbs, epilog->num_nodes, scale_up,
+ REG_BR_PROB_BASE);
+ free (bbs);
}
basic_block bb_before_epilog = loop_preheader_edge (epilog)->src;
@@ -1875,7 +1880,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
guard_to = split_edge (single_exit (epilog));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond, guard_to,
skip_vector ? anchor : guard_bb,
- inverse_probability (prob_epilog),
+ prob_epilog.invert (),
irred_flag);
slpeel_update_phi_nodes_for_guard2 (loop, epilog, guard_e,
single_exit (epilog));
@@ -1883,11 +1888,9 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
the guard_bb, which is the case when skip_vector is true. */
if (guard_bb != bb_before_epilog)
{
- prob_epilog = (combine_probabilities (prob_vector, prob_epilog)
- + inverse_probability (prob_vector));
+ prob_epilog = prob_vector * prob_epilog + prob_vector.invert ();
- scale_bbs_frequencies_int (&bb_before_epilog, 1, prob_epilog,
- REG_BR_PROB_BASE);
+ scale_bbs_frequencies (&bb_before_epilog, 1, prob_epilog);
}
scale_loop_profile (epilog, prob_epilog, bound);
}
@@ -1971,7 +1974,6 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
tree *cond_expr,
gimple_seq *cond_expr_stmt_list)
{
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
vec<gimple *> may_misalign_stmts
= LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
gimple *ref_stmt;
@@ -2012,7 +2014,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
/* create: addr_tmp = (int)(address_of_first_vector) */
addr_base =
vect_create_addr_base_for_vector_ref (ref_stmt, &new_stmt_list,
- offset, loop);
+ offset);
if (new_stmt_list != NULL)
gimple_seq_add_seq (cond_expr_stmt_list, new_stmt_list);
@@ -2132,17 +2134,17 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
tree cond_expr = NULL_TREE;
gimple_seq cond_expr_stmt_list = NULL;
tree arg;
- unsigned prob = 4 * REG_BR_PROB_BASE / 5;
+ profile_probability prob = profile_probability::likely ();
gimple_seq gimplify_stmt_list = NULL;
- tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
+ tree scalar_loop_iters = LOOP_VINFO_NITERSM1 (loop_vinfo);
bool version_align = LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo);
bool version_alias = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
bool version_niter = LOOP_REQUIRES_VERSIONING_FOR_NITERS (loop_vinfo);
if (check_profitability)
- cond_expr = fold_build2 (GT_EXPR, boolean_type_node, scalar_loop_iters,
+ cond_expr = fold_build2 (GE_EXPR, boolean_type_node, scalar_loop_iters,
build_int_cst (TREE_TYPE (scalar_loop_iters),
- th));
+ th - 1));
if (version_niter)
vect_create_cond_for_niters_checks (loop_vinfo, &cond_expr);
@@ -2171,9 +2173,8 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
/* We don't want to scale SCALAR_LOOP's frequencies, we need to
scale LOOP's frequencies instead. */
nloop = loop_version (scalar_loop, cond_expr, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE - prob, true);
- scale_loop_frequencies (loop, prob, REG_BR_PROB_BASE);
+ prob, prob.invert (), prob, prob.invert (), true);
+ scale_loop_frequencies (loop, prob);
/* CONDITION_BB was created above SCALAR_LOOP's preheader,
while we need to move it above LOOP's preheader. */
e = loop_preheader_edge (loop);
@@ -2200,8 +2201,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
}
else
nloop = loop_version (loop, cond_expr, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
- prob, REG_BR_PROB_BASE - prob, true);
+ prob, prob.invert (), prob, prob.invert (), true);
if (version_niter)
{
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index a7c3d3d7e29..8740a7573ac 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -890,8 +890,10 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
vect_reduction_def;
/* Store the reduction cycles for possible vectorization in
- loop-aware SLP. */
- LOOP_VINFO_REDUCTIONS (loop_vinfo).safe_push (reduc_stmt);
+ loop-aware SLP if it was not detected as reduction
+ chain. */
+ if (! GROUP_FIRST_ELEMENT (vinfo_for_stmt (reduc_stmt)))
+ LOOP_VINFO_REDUCTIONS (loop_vinfo).safe_push (reduc_stmt);
}
}
}
@@ -1776,6 +1778,10 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def
&& ! PURE_SLP_STMT (stmt_info))
ok = vectorizable_induction (phi, NULL, NULL, NULL);
+ 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);
}
if (ok && STMT_VINFO_LIVE_P (stmt_info))
@@ -1799,7 +1805,7 @@ 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))
+ && !vect_analyze_stmt (stmt, &need_to_vectorize, NULL, NULL))
return false;
}
} /* bbs */
@@ -2129,21 +2135,17 @@ start_over:
goto again;
}
- min_scalar_loop_bound = ((PARAM_VALUE (PARAM_MIN_VECT_LOOP_BOUND)
- * vectorization_factor) - 1);
+ min_scalar_loop_bound = (PARAM_VALUE (PARAM_MIN_VECT_LOOP_BOUND)
+ * vectorization_factor);
/* Use the cost model only if it is more conservative than user specified
threshold. */
- th = (unsigned) min_scalar_loop_bound;
- if (min_profitable_iters
- && (!min_scalar_loop_bound
- || min_profitable_iters > min_scalar_loop_bound))
- th = (unsigned) min_profitable_iters;
+ th = (unsigned) MAX (min_scalar_loop_bound, min_profitable_iters);
LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo) = th;
if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && LOOP_VINFO_INT_NITERS (loop_vinfo) <= th)
+ && LOOP_VINFO_INT_NITERS (loop_vinfo) < th)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2162,7 +2164,7 @@ start_over:
estimated_niter = max_niter;
if (estimated_niter != -1
&& ((unsigned HOST_WIDE_INT) estimated_niter
- <= MAX (th, (unsigned)min_profitable_estimate)))
+ < MAX (th, (unsigned) min_profitable_estimate)))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2179,9 +2181,9 @@ start_over:
/* Decide whether we need to create an epilogue loop to handle
remaining scalar iterations. */
- th = ((LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo) + 1)
- / LOOP_VINFO_VECT_FACTOR (loop_vinfo))
- * LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ th = ((LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo)
+ / LOOP_VINFO_VECT_FACTOR (loop_vinfo))
+ * LOOP_VINFO_VECT_FACTOR (loop_vinfo));
if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
&& LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
@@ -2244,7 +2246,7 @@ start_over:
/* Niters for at least one iteration of vectorized loop. */
niters_th += LOOP_VINFO_VECT_FACTOR (loop_vinfo);
/* One additional iteration because of peeling for gap. */
- if (!LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+ if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
niters_th++;
if (LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo) < niters_th)
LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo) = niters_th;
@@ -2811,27 +2813,29 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
return NULL;
}
+ if (! flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
+ return NULL;
+
nloop_uses = 0;
auto_vec<gphi *, 3> lcphis;
- if (flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
- {
- gimple *use_stmt = USE_STMT (use_p);
- if (is_gimple_debug (use_stmt))
- continue;
- if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
- nloop_uses++;
- else
- /* We can have more than one loop-closed PHI. */
- lcphis.safe_push (as_a <gphi *> (use_stmt));
- if (nloop_uses > 1)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "reduction used in loop.\n");
- return NULL;
- }
- }
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
+ nloop_uses++;
+ else
+ /* We can have more than one loop-closed PHI. */
+ lcphis.safe_push (as_a <gphi *> (use_stmt));
+ if (nloop_uses > 1)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "reduction used in loop.\n");
+ return NULL;
+ }
+ }
/* If DEF_STMT is a phi node itself, we expect it to have a single argument
defined in the inner loop. */
@@ -2896,9 +2900,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
gimple instruction for the first simple tests and only do this
if we're allowed to change code at all. */
if (code == MINUS_EXPR
- && (op1 = gimple_assign_rhs1 (def_stmt))
- && TREE_CODE (op1) == SSA_NAME
- && SSA_NAME_DEF_STMT (op1) == phi)
+ && ! ((op1 = gimple_assign_rhs2 (def_stmt))
+ && TREE_CODE (op1) == SSA_NAME
+ && SSA_NAME_DEF_STMT (op1) == phi))
code = PLUS_EXPR;
if (code == COND_EXPR)
@@ -3149,6 +3153,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
/* Try to find SLP reduction chain. */
if (! nested_in_vect_loop
&& code != COND_EXPR
+ && orig_code != MINUS_EXPR
&& vect_is_slp_reduction (loop_info, phi, def_stmt))
{
if (dump_enabled_p ())
@@ -3158,10 +3163,125 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
return def_stmt;
}
+ /* Dissolve group eventually half-built by vect_is_slp_reduction. */
+ gimple *first = GROUP_FIRST_ELEMENT (vinfo_for_stmt (def_stmt));
+ while (first)
+ {
+ gimple *next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (first));
+ GROUP_FIRST_ELEMENT (vinfo_for_stmt (first)) = NULL;
+ GROUP_NEXT_ELEMENT (vinfo_for_stmt (first)) = NULL;
+ first = next;
+ }
+
+ /* Look for the expression computing loop_arg from loop PHI result. */
+ auto_vec<std::pair<ssa_op_iter, use_operand_p> > path;
+ auto_bitmap visited;
+ tree lookfor = PHI_RESULT (phi);
+ ssa_op_iter curri;
+ use_operand_p curr = op_iter_init_phiuse (&curri, as_a <gphi *>(phi),
+ SSA_OP_USE);
+ while (USE_FROM_PTR (curr) != loop_arg)
+ curr = op_iter_next_use (&curri);
+ curri.i = curri.numops;
+ do
+ {
+ path.safe_push (std::make_pair (curri, curr));
+ tree use = USE_FROM_PTR (curr);
+ if (use == lookfor)
+ break;
+ gimple *def = SSA_NAME_DEF_STMT (use);
+ if (gimple_nop_p (def)
+ || ! flow_bb_inside_loop_p (loop, gimple_bb (def)))
+ {
+pop:
+ do
+ {
+ std::pair<ssa_op_iter, use_operand_p> x = path.pop ();
+ curri = x.first;
+ curr = x.second;
+ do
+ curr = op_iter_next_use (&curri);
+ /* Skip already visited or non-SSA operands (from iterating
+ over PHI args). */
+ while (curr != NULL_USE_OPERAND_P
+ && (TREE_CODE (USE_FROM_PTR (curr)) != SSA_NAME
+ || ! bitmap_set_bit (visited,
+ SSA_NAME_VERSION
+ (USE_FROM_PTR (curr)))));
+ }
+ while (curr == NULL_USE_OPERAND_P && ! path.is_empty ());
+ if (curr == NULL_USE_OPERAND_P)
+ break;
+ }
+ else
+ {
+ if (gimple_code (def) == GIMPLE_PHI)
+ curr = op_iter_init_phiuse (&curri, as_a <gphi *>(def), SSA_OP_USE);
+ else
+ curr = op_iter_init_use (&curri, def, SSA_OP_USE);
+ while (curr != NULL_USE_OPERAND_P
+ && (TREE_CODE (USE_FROM_PTR (curr)) != SSA_NAME
+ || ! bitmap_set_bit (visited,
+ SSA_NAME_VERSION
+ (USE_FROM_PTR (curr)))))
+ curr = op_iter_next_use (&curri);
+ if (curr == NULL_USE_OPERAND_P)
+ goto pop;
+ }
+ }
+ while (1);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "reduction path: ");
+ 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, "\n");
+ }
+
+ /* Check whether the reduction path detected is valid. */
+ bool fail = path.length () == 0;
+ bool neg = false;
+ for (unsigned i = 1; i < path.length (); ++i)
+ {
+ gimple *use_stmt = USE_STMT (path[i].second);
+ tree op = USE_FROM_PTR (path[i].second);
+ if (! has_single_use (op)
+ || ! is_gimple_assign (use_stmt))
+ {
+ fail = true;
+ break;
+ }
+ if (gimple_assign_rhs_code (use_stmt) != code)
+ {
+ if (code == PLUS_EXPR
+ && gimple_assign_rhs_code (use_stmt) == MINUS_EXPR)
+ {
+ /* Track whether we negate the reduction value each iteration. */
+ if (gimple_assign_rhs2 (use_stmt) == op)
+ neg = ! neg;
+ }
+ else
+ {
+ fail = true;
+ break;
+ }
+ }
+ }
+ if (! fail && ! neg)
+ return def_stmt;
+
if (dump_enabled_p ())
- report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
- "reduction: unknown pattern: ");
-
+ {
+ report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
+ "reduction: unknown pattern: ");
+ }
+
return NULL;
}
@@ -3183,6 +3303,8 @@ vect_force_simple_reduction (loop_vec_info loop_info, gimple *phi,
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_DEF (reduc_def_info) = phi;
}
return def;
}
@@ -3542,7 +3664,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
if ((scalar_single_iter_cost * vf) > (int) vec_inside_cost)
{
if (vec_outside_cost <= 0)
- min_profitable_iters = 1;
+ min_profitable_iters = 0;
else
{
min_profitable_iters = ((vec_outside_cost - scalar_outside_cost) * vf
@@ -3580,13 +3702,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
" Calculated minimum iters for profitability: %d\n",
min_profitable_iters);
- min_profitable_iters =
- min_profitable_iters < vf ? vf : min_profitable_iters;
-
- /* Because the condition we create is:
- if (niters <= min_profitable_iters)
- then skip the vectorized loop. */
- min_profitable_iters--;
+ /* We want the vectorized loop to execute at least once. */
+ if (min_profitable_iters < (vf + peel_iters_prologue + peel_iters_epilogue))
+ min_profitable_iters = vf + peel_iters_prologue + peel_iters_epilogue;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -3603,7 +3721,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
SIC * niters > VIC * ((niters-PL_ITERS-EP_ITERS)/VF) + VOC + SOC */
if (vec_outside_cost <= 0)
- min_profitable_estimate = 1;
+ min_profitable_estimate = 0;
else
{
min_profitable_estimate = ((vec_outside_cost + scalar_outside_cost) * vf
@@ -3612,7 +3730,6 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
/ ((scalar_single_iter_cost * vf)
- vec_inside_cost);
}
- min_profitable_estimate --;
min_profitable_estimate = MAX (min_profitable_estimate, min_profitable_iters);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -3625,7 +3742,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
/* Writes into SEL a mask for a vec_perm, equivalent to a vec_shr by OFFSET
vector elements (not bits) for a vector of mode MODE. */
static void
-calc_vec_perm_mask_for_shift (enum machine_mode mode, unsigned int offset,
+calc_vec_perm_mask_for_shift (machine_mode mode, unsigned int offset,
unsigned char *sel)
{
unsigned int i, nelt = GET_MODE_NUNITS (mode);
@@ -3638,7 +3755,7 @@ calc_vec_perm_mask_for_shift (enum machine_mode mode, unsigned int offset,
MODE. This is the case if _either_ the platform handles vec_shr_optab, _or_
it supports vec_perm_const with masks for all necessary shift amounts. */
static bool
-have_whole_vector_shift (enum machine_mode mode)
+have_whole_vector_shift (machine_mode mode)
{
if (optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
return true;
@@ -3658,29 +3775,6 @@ have_whole_vector_shift (enum machine_mode mode)
return true;
}
-/* Return the reduction operand (with index REDUC_INDEX) of STMT. */
-
-static tree
-get_reduction_op (gimple *stmt, int reduc_index)
-{
- switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
- {
- case GIMPLE_SINGLE_RHS:
- gcc_assert (TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt))
- == ternary_op);
- return TREE_OPERAND (gimple_assign_rhs1 (stmt), reduc_index);
- case GIMPLE_UNARY_RHS:
- return gimple_assign_rhs1 (stmt);
- case GIMPLE_BINARY_RHS:
- return (reduc_index
- ? gimple_assign_rhs2 (stmt) : gimple_assign_rhs1 (stmt));
- case GIMPLE_TERNARY_RHS:
- return gimple_op (stmt, reduc_index + 1);
- default:
- gcc_unreachable ();
- }
-}
-
/* TODO: Close dependency between vect_model_*_cost and vectorizable_*
functions. Design better to avoid maintenance issues. */
@@ -4045,6 +4139,192 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
return init_def;
}
+/* Get at the initial defs for the reduction PHIs in SLP_NODE.
+ NUMBER_OF_VECTORS is the number of vector defs to create. */
+
+static void
+get_initial_defs_for_reduction (slp_tree slp_node,
+ vec<tree> *vec_oprnds,
+ unsigned int number_of_vectors,
+ enum 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);
+ unsigned nunits;
+ tree vec_cst;
+ tree *elts;
+ unsigned j, number_of_places_left_in_vector;
+ tree vector_type, scalar_type;
+ tree vop;
+ int group_size = stmts.length ();
+ unsigned int vec_num, i;
+ unsigned number_of_copies = 1;
+ vec<tree> voprnds;
+ voprnds.create (number_of_vectors);
+ bool constant_p;
+ tree neutral_op = NULL;
+ struct loop *loop;
+ gimple_seq ctor_seq = NULL;
+
+ vector_type = STMT_VINFO_VECTYPE (stmt_vinfo);
+ scalar_type = TREE_TYPE (vector_type);
+ nunits = TYPE_VECTOR_SUBPARTS (vector_type);
+
+ gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def);
+
+ loop = (gimple_bb (stmt))->loop_father;
+ gcc_assert (loop);
+
+ /* op is the reduction operand of the first stmt already. */
+ /* For additional copies (see the explanation of NUMBER_OF_COPIES below)
+ we need either neutral operands or the original operands. See
+ get_initial_def_for_reduction() for details. */
+ switch (code)
+ {
+ case WIDEN_SUM_EXPR:
+ case DOT_PROD_EXPR:
+ case SAD_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ neutral_op = build_zero_cst (scalar_type);
+ break;
+
+ case MULT_EXPR:
+ neutral_op = build_one_cst (scalar_type);
+ break;
+
+ case BIT_AND_EXPR:
+ neutral_op = build_all_ones_cst (scalar_type);
+ break;
+
+ /* For MIN/MAX we don't have an easy neutral operand but
+ the initial values can be used fine here. Only for
+ a reduction chain we have to force a neutral element. */
+ case MAX_EXPR:
+ case MIN_EXPR:
+ if (! reduc_chain)
+ neutral_op = NULL;
+ else
+ neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt,
+ loop_preheader_edge (loop));
+ break;
+
+ default:
+ gcc_assert (! reduc_chain);
+ neutral_op = NULL;
+ }
+
+ /* NUMBER_OF_COPIES is the number of times we need to use the same values in
+ created vectors. It is greater than 1 if unrolling is performed.
+
+ For example, we have two scalar operands, s1 and s2 (e.g., group of
+ strided accesses of size two), while NUNITS is four (i.e., four scalars
+ of this type can be packed in a vector). The output vector will contain
+ two copies of each scalar operand: {s1, s2, s1, s2}. (NUMBER_OF_COPIES
+ will be 2).
+
+ If GROUP_SIZE > NUNITS, the scalars will be split into several vectors
+ containing the operands.
+
+ For example, NUNITS is four as before, and the group size is 8
+ (s1, s2, ..., s8). We will create two vectors {s1, s2, s3, s4} and
+ {s5, s6, s7, s8}. */
+
+ number_of_copies = nunits * number_of_vectors / group_size;
+
+ number_of_places_left_in_vector = nunits;
+ constant_p = true;
+ elts = XALLOCAVEC (tree, nunits);
+ for (j = 0; j < number_of_copies; j++)
+ {
+ for (i = group_size - 1; stmts.iterate (i, &stmt); i--)
+ {
+ tree op;
+ /* Get the def before the loop. In reduction chain we have only
+ one initial value. */
+ if ((j != (number_of_copies - 1)
+ || (reduc_chain && i != 0))
+ && neutral_op)
+ op = neutral_op;
+ else
+ op = PHI_ARG_DEF_FROM_EDGE (stmt,
+ loop_preheader_edge (loop));
+
+ /* Create 'vect_ = {op0,op1,...,opn}'. */
+ number_of_places_left_in_vector--;
+ elts[number_of_places_left_in_vector] = op;
+ if (!CONSTANT_CLASS_P (op))
+ constant_p = false;
+
+ if (number_of_places_left_in_vector == 0)
+ {
+ if (constant_p)
+ vec_cst = build_vector (vector_type, elts);
+ else
+ {
+ vec<constructor_elt, va_gc> *v;
+ unsigned k;
+ vec_alloc (v, nunits);
+ for (k = 0; k < nunits; ++k)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]);
+ vec_cst = build_constructor (vector_type, v);
+ }
+ tree init;
+ gimple_stmt_iterator gsi;
+ init = vect_init_vector (stmt, vec_cst, vector_type, NULL);
+ if (ctor_seq != NULL)
+ {
+ gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init));
+ gsi_insert_seq_before_without_update (&gsi, ctor_seq,
+ GSI_SAME_STMT);
+ ctor_seq = NULL;
+ }
+ voprnds.quick_push (init);
+
+ number_of_places_left_in_vector = nunits;
+ constant_p = true;
+ }
+ }
+ }
+
+ /* Since the vectors are created in the reverse order, we should invert
+ them. */
+ vec_num = voprnds.length ();
+ for (j = vec_num; j != 0; j--)
+ {
+ vop = voprnds[j - 1];
+ vec_oprnds->quick_push (vop);
+ }
+
+ voprnds.release ();
+
+ /* In case that VF is greater than the unrolling factor needed for the SLP
+ group of stmts, NUMBER_OF_VECTORS to be created is greater than
+ NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have
+ to replicate the vectors. */
+ while (number_of_vectors > vec_oprnds->length ())
+ {
+ tree neutral_vec = NULL;
+
+ if (neutral_op)
+ {
+ if (!neutral_vec)
+ neutral_vec = build_vector_from_val (vector_type, neutral_op);
+
+ vec_oprnds->quick_push (neutral_vec);
+ }
+ else
+ {
+ for (i = 0; vec_oprnds->iterate (i, &vop) && i < vec_num; i++)
+ vec_oprnds->quick_push (vop);
+ }
+ }
+}
+
+
/* Function vect_create_epilog_for_reduction
Create code at the loop-epilog to finalize the result of a reduction
@@ -4066,8 +4346,6 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
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.
- INDUCTION_INDEX is the index of the loop for condition reductions.
- Otherwise it is undefined.
This function:
1. Creates the reduction def-use cycles: sets the arguments for
@@ -4110,10 +4388,12 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
static void
vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
+ gimple *reduc_def_stmt,
int ncopies, enum tree_code reduc_code,
vec<gimple *> reduction_phis,
- int reduc_index, bool double_reduc,
- slp_tree slp_node, tree induction_index)
+ bool double_reduc,
+ slp_tree slp_node,
+ slp_instance slp_node_instance)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
stmt_vec_info prev_phi_info;
@@ -4134,7 +4414,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree bitsize;
tree adjustment_def = NULL;
tree vec_initial_def = NULL;
- tree reduction_op, expr, def, initial_def = NULL;
+ tree expr, def, initial_def = NULL;
tree orig_name, scalar_result;
imm_use_iterator imm_iter, phi_imm_iter;
use_operand_p use_p, phi_use_p;
@@ -4151,6 +4431,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
bool slp_reduc = false;
tree new_phi_result;
gimple *inner_phi = NULL;
+ tree induction_index = NULL_TREE;
if (slp_node)
group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
@@ -4163,9 +4444,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
gcc_assert (!slp_node);
}
- reduction_op = get_reduction_op (stmt, reduc_index);
-
- vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
gcc_assert (vectype);
mode = TYPE_MODE (vectype);
@@ -4189,14 +4468,19 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
/* Get the loop-entry arguments. */
enum vect_def_type initial_def_dt = vect_unknown_def_type;
if (slp_node)
- vect_get_vec_defs (reduction_op, NULL_TREE, stmt, &vec_initial_defs,
- NULL, slp_node, reduc_index);
+ {
+ unsigned vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
+ vec_initial_defs.reserve (vec_num);
+ get_initial_defs_for_reduction (slp_node_instance->reduc_phis,
+ &vec_initial_defs, vec_num, code,
+ GROUP_FIRST_ELEMENT (stmt_info));
+ }
else
{
/* Get at the scalar def before the loop, that defines the initial value
of the reduction variable. */
- gimple *def_stmt = SSA_NAME_DEF_STMT (reduction_op);
- initial_def = PHI_ARG_DEF_FROM_EDGE (def_stmt,
+ gimple *def_stmt;
+ initial_def = PHI_ARG_DEF_FROM_EDGE (reduc_def_stmt,
loop_preheader_edge (loop));
vect_is_simple_use (initial_def, loop_vinfo, &def_stmt, &initial_def_dt);
vec_initial_def = get_initial_def_for_reduction (stmt, initial_def,
@@ -4264,6 +4548,95 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
}
}
+ /* For cond reductions we want to create a new vector (INDEX_COND_EXPR)
+ which is updated with the current index of the loop for every match of
+ the original loop's cond_expr (VEC_STMT). This results in a vector
+ containing the last time the condition passed for that vector lane.
+ The first match will be a 1 to allow 0 to be used for non-matching
+ indexes. If there are no matches at all then the vector will be all
+ zeroes. */
+ if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) == COND_REDUCTION)
+ {
+ tree indx_before_incr, indx_after_incr;
+ int nunits_out = TYPE_VECTOR_SUBPARTS (vectype);
+ int k;
+
+ gimple *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
+ gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR);
+
+ int scalar_precision
+ = GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (vectype)));
+ tree cr_index_scalar_type = make_unsigned_type (scalar_precision);
+ tree cr_index_vector_type = build_vector_type
+ (cr_index_scalar_type, TYPE_VECTOR_SUBPARTS (vectype));
+
+ /* First we create a simple vector induction variable which starts
+ with the values {1,2,3,...} (SERIES_VECT) and increments by the
+ vector size (STEP). */
+
+ /* Create a {1,2,3,...} vector. */
+ tree *vtemp = XALLOCAVEC (tree, nunits_out);
+ for (k = 0; k < nunits_out; ++k)
+ vtemp[k] = build_int_cst (cr_index_scalar_type, k + 1);
+ tree series_vect = build_vector (cr_index_vector_type, vtemp);
+
+ /* Create a vector of the step value. */
+ tree step = build_int_cst (cr_index_scalar_type, nunits_out);
+ tree vec_step = build_vector_from_val (cr_index_vector_type, step);
+
+ /* Create an induction variable. */
+ gimple_stmt_iterator incr_gsi;
+ bool insert_after;
+ standard_iv_increment_position (loop, &incr_gsi, &insert_after);
+ create_iv (series_vect, vec_step, NULL_TREE, loop, &incr_gsi,
+ insert_after, &indx_before_incr, &indx_after_incr);
+
+ /* Next create a new phi node vector (NEW_PHI_TREE) which starts
+ filled with zeros (VEC_ZERO). */
+
+ /* Create a vector of 0s. */
+ tree zero = build_zero_cst (cr_index_scalar_type);
+ tree vec_zero = build_vector_from_val (cr_index_vector_type, zero);
+
+ /* 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));
+ add_phi_arg (as_a <gphi *> (new_phi), vec_zero,
+ loop_preheader_edge (loop), UNKNOWN_LOCATION);
+
+ /* Now take the condition from the loops original cond_expr
+ (VEC_STMT) and produce a new cond_expr (INDEX_COND_EXPR) which for
+ every match uses values from the induction variable
+ (INDEX_BEFORE_INCR) otherwise uses values from the phi node
+ (NEW_PHI_TREE).
+ Finally, we update the phi (NEW_PHI_TREE) to take the value of
+ the new cond_expr (INDEX_COND_EXPR). */
+
+ /* Duplicate the condition from vec_stmt. */
+ tree ccompare = unshare_expr (gimple_assign_rhs1 (vec_stmt));
+
+ /* Create a conditional, where the condition is taken from vec_stmt
+ (CCOMPARE), then is the induction index (INDEX_BEFORE_INCR) and
+ else is the phi (NEW_PHI_TREE). */
+ tree index_cond_expr = build3 (VEC_COND_EXPR, cr_index_vector_type,
+ ccompare, indx_before_incr,
+ new_phi_tree);
+ induction_index = make_ssa_name (cr_index_vector_type);
+ 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_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,
+ loop_latch_edge (loop), UNKNOWN_LOCATION);
+ }
+
/* 2. Create epilog code.
The reduction epilog code operates across the elements of the vector
of partial results computed by the vectorized loop.
@@ -4414,20 +4787,17 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
{
tree first_vect = PHI_RESULT (new_phis[0]);
- tree tmp;
gassign *new_vec_stmt = NULL;
-
vec_dest = vect_create_destination_var (scalar_dest, vectype);
for (k = 1; k < new_phis.length (); k++)
{
gimple *next_phi = new_phis[k];
tree second_vect = PHI_RESULT (next_phi);
-
- tmp = build2 (code, vectype, first_vect, second_vect);
- new_vec_stmt = gimple_build_assign (vec_dest, tmp);
- first_vect = make_ssa_name (vec_dest, new_vec_stmt);
- gimple_assign_set_lhs (new_vec_stmt, first_vect);
+ tree tem = make_ssa_name (vec_dest, new_vec_stmt);
+ new_vec_stmt = gimple_build_assign (tem, code,
+ first_vect, second_vect);
gsi_insert_before (&exit_gsi, new_vec_stmt, GSI_SAME_STMT);
+ first_vect = tem;
}
new_phi_result = first_vect;
@@ -4437,6 +4807,28 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
new_phis.safe_push (new_vec_stmt);
}
}
+ /* Likewise if we couldn't use a single defuse cycle. */
+ else if (ncopies > 1)
+ {
+ gcc_assert (new_phis.length () == 1);
+ 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];
+ 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);
+ tree tem = make_ssa_name (vec_dest, new_vec_stmt);
+ new_vec_stmt = gimple_build_assign (tem, code,
+ first_vect, second_vect);
+ gsi_insert_before (&exit_gsi, new_vec_stmt, GSI_SAME_STMT);
+ first_vect = tem;
+ }
+ new_phi_result = first_vect;
+ new_phis.truncate (0);
+ new_phis.safe_push (new_vec_stmt);
+ }
else
new_phi_result = PHI_RESULT (new_phis[0]);
@@ -4545,12 +4937,10 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
/* Convert the reduced value back to the result type and set as the
result. */
- tree data_reduc_cast = build1 (VIEW_CONVERT_EXPR, scalar_type,
- data_reduc);
- epilog_stmt = gimple_build_assign (new_scalar_dest, data_reduc_cast);
- new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
- gimple_assign_set_lhs (epilog_stmt, new_temp);
- gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
+ gimple_seq stmts = NULL;
+ new_temp = gimple_build (&stmts, VIEW_CONVERT_EXPR, scalar_type,
+ data_reduc);
+ gsi_insert_seq_before (&exit_gsi, stmts, GSI_SAME_STMT);
scalar_results.safe_push (new_temp);
}
else if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) == COND_REDUCTION
@@ -4615,6 +5005,11 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
val = new_val;
}
}
+ /* Convert the reduced value back to the result type and set as the
+ result. */
+ gimple_seq stmts = NULL;
+ val = gimple_convert (&stmts, scalar_type, val);
+ gsi_insert_seq_before (&exit_gsi, stmts, GSI_SAME_STMT);
scalar_results.safe_push (val);
}
@@ -5262,11 +5657,11 @@ is_nonwrapping_integer_induction (gimple *stmt, struct loop *loop)
bool
vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node)
+ gimple **vec_stmt, slp_tree slp_node,
+ slp_instance slp_node_instance)
{
tree vec_dest;
tree scalar_dest;
- tree loop_vec_def0 = NULL_TREE, loop_vec_def1 = NULL_TREE;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
tree vectype_in = NULL_TREE;
@@ -5279,23 +5674,20 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
tree new_temp = NULL_TREE;
gimple *def_stmt;
enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type;
- gphi *new_phi = NULL;
tree scalar_type;
bool is_simple_use;
gimple *orig_stmt;
- stmt_vec_info orig_stmt_info;
- tree expr = NULL_TREE;
+ 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;
- tree reduc_def = NULL_TREE;
gimple *new_stmt = NULL;
int j;
tree ops[3];
+ enum vect_def_type dts[3];
bool nested_cycle = false, found_nested_cycle_def = false;
- gimple *reduc_def_stmt = NULL;
bool double_reduc = false;
basic_block def_bb;
struct loop * def_stmt_loop, *outer_loop = NULL;
@@ -5303,14 +5695,27 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
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;
int vec_num;
- tree def0, def1, tem, op1 = NULL_TREE;
+ 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)
+ return false;
+
+ if (nested_in_vect_loop_p (loop, stmt))
+ {
+ 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. */
@@ -5321,11 +5726,97 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
first_p = false;
}
- if (nested_in_vect_loop_p (loop, stmt))
+ if (gimple_code (stmt) == GIMPLE_PHI)
{
- outer_loop = loop;
- loop = loop->inner;
- nested_cycle = true;
+ /* Analysis is fully done on the reduction stmt invocation. */
+ if (! vec_stmt)
+ {
+ if (slp_node)
+ slp_node_instance->reduc_phis = slp_node;
+
+ STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ 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));
+
+ gcc_assert (is_gimple_assign (reduc_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))
+ continue;
+ if (k == 1
+ && gimple_assign_rhs_code (reduc_stmt) == COND_EXPR)
+ continue;
+ tem = get_vectype_for_scalar_type (TREE_TYPE (op));
+ if (! vectype_in
+ || TYPE_VECTOR_SUBPARTS (tem) < TYPE_VECTOR_SUBPARTS (vectype_in))
+ vectype_in = tem;
+ break;
+ }
+ gcc_assert (vectype_in);
+
+ if (slp_node)
+ ncopies = 1;
+ else
+ ncopies = (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+ / TYPE_VECTOR_SUBPARTS (vectype_in));
+
+ use_operand_p use_p;
+ gimple *use_stmt;
+ 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)))
+ single_defuse_cycle = true;
+
+ /* Create the destination vector */
+ scalar_dest = gimple_assign_lhs (reduc_stmt);
+ vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
+
+ if (slp_node)
+ /* The size vect_schedule_slp_instance computes is off for us. */
+ vec_num = ((LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+ * SLP_TREE_SCALAR_STMTS (slp_node).length ())
+ / TYPE_VECTOR_SUBPARTS (vectype_in));
+ else
+ vec_num = 1;
+
+ /* Generate the reduction PHIs upfront. */
+ prev_phi_info = NULL;
+ for (j = 0; j < ncopies; j++)
+ {
+ if (j == 0 || !single_defuse_cycle)
+ {
+ for (i = 0; i < vec_num; i++)
+ {
+ /* 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));
+
+ if (slp_node)
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi);
+ else
+ {
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_phi;
+ else
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi;
+ prev_phi_info = vinfo_for_stmt (new_phi);
+ }
+ }
+ }
+ }
+
+ return true;
}
/* 1. Is vectorizable reduction? */
@@ -5341,11 +5832,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
&& !STMT_VINFO_LIVE_P (stmt_info))
return false;
- /* 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)
- return false;
-
/* 2. Has this been recognized as a reduction pattern?
Check if STMT represents a pattern that has been recognized
@@ -5393,10 +5879,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
default:
gcc_unreachable ();
}
- /* The default is that the reduction variable is the last in statement. */
- int reduc_index = op_type - 1;
- if (code == MINUS_EXPR)
- reduc_index = 0;
if (code == COND_EXPR && slp_node)
return false;
@@ -5416,20 +5898,29 @@ 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;
+ int reduc_index = -1;
for (i = 0; i < op_type; i++)
{
- if (i == reduc_index)
- continue;
-
/* The condition of COND_EXPR is checked in vectorizable_condition(). */
if (i == 0 && code == COND_EXPR)
continue;
is_simple_use = vect_is_simple_use (ops[i], loop_vinfo,
- &def_stmt, &dt, &tem);
- if (!vectype_in)
- vectype_in = tem;
+ &def_stmt, &dts[i], &tem);
+ dt = dts[i];
gcc_assert (is_simple_use);
+ if (dt == vect_reduction_def)
+ {
+ reduc_def_stmt = def_stmt;
+ reduc_index = i;
+ continue;
+ }
+ else
+ {
+ if (!vectype_in)
+ vectype_in = tem;
+ }
if (dt != vect_internal_def
&& dt != vect_external_def
@@ -5459,21 +5950,29 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
}
}
- is_simple_use = vect_is_simple_use (ops[reduc_index], loop_vinfo,
- &def_stmt, &dt, &tem);
if (!vectype_in)
- vectype_in = tem;
- gcc_assert (is_simple_use);
- if (!found_nested_cycle_def)
- reduc_def_stmt = def_stmt;
+ vectype_in = vectype_out;
- if (reduc_def_stmt && gimple_code (reduc_def_stmt) != GIMPLE_PHI)
+ /* When vectorizing a reduction chain w/o SLP the reduction PHI is not
+ directy used in stmt. */
+ if (reduc_index == -1)
+ {
+ if (orig_stmt)
+ reduc_def_stmt = STMT_VINFO_REDUC_DEF (orig_stmt_info);
+ else
+ reduc_def_stmt = STMT_VINFO_REDUC_DEF (stmt_info);
+ }
+
+ if (! reduc_def_stmt || gimple_code (reduc_def_stmt) != GIMPLE_PHI)
return false;
- if (!(dt == vect_reduction_def
- || dt == vect_nested_cycle
- || ((dt == vect_internal_def || dt == vect_external_def
- || dt == vect_constant_def || dt == vect_induction_def)
+ if (!(reduc_index == -1
+ || dts[reduc_index] == vect_reduction_def
+ || dts[reduc_index] == vect_nested_cycle
+ || ((dts[reduc_index] == vect_internal_def
+ || dts[reduc_index] == vect_external_def
+ || dts[reduc_index] == vect_constant_def
+ || dts[reduc_index] == vect_induction_def)
&& nested_cycle && found_nested_cycle_def)))
{
/* For pattern recognized stmts, orig_stmt might be a reduction,
@@ -5528,7 +6027,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
&& types_compatible_p (TREE_TYPE (cond_initial_val),
TREE_TYPE (cond_reduc_val)))
{
- tree e = fold_build2 (LE_EXPR, boolean_type_node,
+ tree e = fold_binary (LE_EXPR, boolean_type_node,
cond_initial_val, cond_reduc_val);
if (e && (integer_onep (e) || integer_zerop (e)))
{
@@ -5826,26 +6325,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
}
}
- if (!vec_stmt) /* transformation not required. */
- {
- if (first_p)
- vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies);
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
- return true;
- }
-
- /* Transform. */
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "transform reduction.\n");
-
- /* FORNOW: Multiple types are not supported for condition. */
- if (code == COND_EXPR)
- gcc_assert (ncopies == 1);
-
- /* Create the destination vector */
- vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
-
/* In case the vectorization factor (VF) is bigger than the number
of elements that we can fit in a vectype (nunits), we have to generate
more than one vector stmt - i.e - we need to "unroll" the
@@ -5871,9 +6350,17 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
(i.e. we generate VF/2 results in a single register).
In this case for each copy we get the vector def for the reduction variable
from the vectorized reduction operation generated in the previous iteration.
- */
- if (STMT_VINFO_RELEVANT (stmt_info) <= vect_used_only_live)
+ 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;
+ 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))
{
single_defuse_cycle = true;
epilog_copies = 1;
@@ -5881,6 +6368,41 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
else
epilog_copies = ncopies;
+ /* If the reduction stmt is one of the patterns that have lane
+ reduction embedded we cannot handle the case of ! single_defuse_cycle. */
+ if ((ncopies > 1
+ && ! single_defuse_cycle)
+ && (code == DOT_PROD_EXPR
+ || code == WIDEN_SUM_EXPR
+ || code == SAD_EXPR))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "multi def-use cycle not possible for lane-reducing "
+ "reduction operation\n");
+ return false;
+ }
+
+ if (!vec_stmt) /* transformation not required. */
+ {
+ if (first_p)
+ vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies);
+ STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ return true;
+ }
+
+ /* Transform. */
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "transform reduction.\n");
+
+ /* FORNOW: Multiple types are not supported for condition. */
+ if (code == COND_EXPR)
+ gcc_assert (ncopies == 1);
+
+ /* Create the destination vector */
+ vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
+
prev_stmt_info = NULL;
prev_phi_info = NULL;
if (slp_node)
@@ -5889,8 +6411,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
{
vec_num = 1;
vec_oprnds0.create (1);
+ vec_oprnds1.create (1);
if (op_type == ternary_op)
- vec_oprnds1.create (1);
+ vec_oprnds2.create (1);
}
phis.create (vec_num);
@@ -5898,22 +6421,13 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (!slp_node)
vect_defs.quick_push (NULL_TREE);
+ 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)));
+
for (j = 0; j < ncopies; j++)
{
- if (j == 0 || !single_defuse_cycle)
- {
- for (i = 0; i < vec_num; i++)
- {
- /* Create the reduction-phi that defines the reduction
- operand. */
- new_phi = create_phi_node (vec_dest, loop->header);
- set_vinfo_for_stmt (new_phi,
- new_stmt_vec_info (new_phi, loop_vinfo));
- if (j == 0 || slp_node)
- phis.quick_push (new_phi);
- }
- }
-
if (code == COND_EXPR)
{
gcc_assert (!slp_node);
@@ -5934,96 +6448,70 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
auto_vec<tree, 3> slp_ops;
auto_vec<vec<tree>, 3> vec_defs;
- slp_ops.quick_push (reduc_index == 0 ? NULL : ops[0]);
- slp_ops.quick_push (reduc_index == 1 ? NULL : ops[1]);
+ slp_ops.quick_push (ops[0]);
+ slp_ops.quick_push (ops[1]);
if (op_type == ternary_op)
- slp_ops.quick_push (reduc_index == 2 ? NULL : ops[2]);
+ slp_ops.quick_push (ops[2]);
- vect_get_slp_defs (slp_ops, slp_node, &vec_defs, -1);
+ vect_get_slp_defs (slp_ops, slp_node, &vec_defs);
- vec_oprnds0.safe_splice (vec_defs[reduc_index == 0 ? 1 : 0]);
- vec_defs[reduc_index == 0 ? 1 : 0].release ();
+ vec_oprnds0.safe_splice (vec_defs[0]);
+ vec_defs[0].release ();
+ vec_oprnds1.safe_splice (vec_defs[1]);
+ vec_defs[1].release ();
if (op_type == ternary_op)
{
- vec_oprnds1.safe_splice (vec_defs[reduc_index == 2 ? 1 : 2]);
- vec_defs[reduc_index == 2 ? 1 : 2].release ();
+ vec_oprnds2.safe_splice (vec_defs[2]);
+ vec_defs[2].release ();
}
}
else
{
- loop_vec_def0 = vect_get_vec_def_for_operand (ops[!reduc_index],
- stmt);
- vec_oprnds0.quick_push (loop_vec_def0);
+ vec_oprnds0.quick_push
+ (vect_get_vec_def_for_operand (ops[0], stmt));
+ vec_oprnds1.quick_push
+ (vect_get_vec_def_for_operand (ops[1], stmt));
if (op_type == ternary_op)
- {
- op1 = reduc_index == 0 ? ops[2] : ops[1];
- loop_vec_def1 = vect_get_vec_def_for_operand (op1, stmt);
- vec_oprnds1.quick_push (loop_vec_def1);
- }
+ vec_oprnds2.quick_push
+ (vect_get_vec_def_for_operand (ops[2], stmt));
}
}
else
{
if (!slp_node)
{
- enum vect_def_type dt;
- gimple *dummy_stmt;
-
- vect_is_simple_use (ops[!reduc_index], loop_vinfo,
- &dummy_stmt, &dt);
- loop_vec_def0 = vect_get_vec_def_for_stmt_copy (dt,
- loop_vec_def0);
- vec_oprnds0[0] = loop_vec_def0;
- if (op_type == ternary_op)
- {
- vect_is_simple_use (op1, loop_vinfo, &dummy_stmt, &dt);
- loop_vec_def1 = vect_get_vec_def_for_stmt_copy (dt,
- loop_vec_def1);
- vec_oprnds1[0] = loop_vec_def1;
- }
- }
-
- if (single_defuse_cycle)
- reduc_def = gimple_assign_lhs (new_stmt);
+ gcc_assert (reduc_index != -1 || ! single_defuse_cycle);
- STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi;
+ if (single_defuse_cycle && reduc_index == 0)
+ vec_oprnds0[0] = gimple_assign_lhs (new_stmt);
+ else
+ vec_oprnds0[0]
+ = vect_get_vec_def_for_stmt_copy (dts[0], vec_oprnds0[0]);
+ if (single_defuse_cycle && reduc_index == 1)
+ vec_oprnds1[0] = gimple_assign_lhs (new_stmt);
+ else
+ vec_oprnds1[0]
+ = vect_get_vec_def_for_stmt_copy (dts[1], vec_oprnds1[0]);
+ if (op_type == ternary_op)
+ {
+ if (single_defuse_cycle && reduc_index == 2)
+ vec_oprnds2[0] = gimple_assign_lhs (new_stmt);
+ else
+ vec_oprnds2[0]
+ = vect_get_vec_def_for_stmt_copy (dts[2], vec_oprnds2[0]);
+ }
+ }
}
FOR_EACH_VEC_ELT (vec_oprnds0, i, def0)
{
- if (slp_node)
- reduc_def = PHI_RESULT (phis[i]);
- else
- {
- if (!single_defuse_cycle || j == 0)
- reduc_def = PHI_RESULT (new_phi);
- }
-
- def1 = ((op_type == ternary_op)
- ? vec_oprnds1[i] : NULL);
- if (op_type == binary_op)
- {
- if (reduc_index == 0)
- expr = build2 (code, vectype_out, reduc_def, def0);
- else
- expr = build2 (code, vectype_out, def0, reduc_def);
- }
- else
- {
- if (reduc_index == 0)
- expr = build3 (code, vectype_out, reduc_def, def0, def1);
- else
- {
- if (reduc_index == 1)
- expr = build3 (code, vectype_out, def0, reduc_def, def1);
- else
- expr = build3 (code, vectype_out, def0, def1, reduc_def);
- }
- }
+ tree vop[3] = { def0, vec_oprnds1[i], NULL_TREE };
+ if (op_type == ternary_op)
+ vop[2] = vec_oprnds2[i];
- new_stmt = gimple_build_assign (vec_dest, expr);
new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_assign_set_lhs (new_stmt, new_temp);
+ new_stmt = gimple_build_assign (new_temp, code,
+ vop[0], vop[1], vop[2]);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (slp_node)
@@ -6044,103 +6532,17 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt);
- prev_phi_info = vinfo_for_stmt (new_phi);
}
- tree indx_before_incr, indx_after_incr, cond_name = NULL;
-
/* Finalize the reduction-phi (set its arguments) and create the
epilog reduction code. */
if ((!single_defuse_cycle || code == COND_EXPR) && !slp_node)
- {
- new_temp = gimple_assign_lhs (*vec_stmt);
- vect_defs[0] = new_temp;
-
- /* For cond reductions we want to create a new vector (INDEX_COND_EXPR)
- which is updated with the current index of the loop for every match of
- the original loop's cond_expr (VEC_STMT). This results in a vector
- containing the last time the condition passed for that vector lane.
- The first match will be a 1 to allow 0 to be used for non-matching
- indexes. If there are no matches at all then the vector will be all
- zeroes. */
- if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) == COND_REDUCTION)
- {
- int nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
- int k;
-
- gcc_assert (gimple_assign_rhs_code (*vec_stmt) == VEC_COND_EXPR);
-
- /* First we create a simple vector induction variable which starts
- with the values {1,2,3,...} (SERIES_VECT) and increments by the
- vector size (STEP). */
-
- /* Create a {1,2,3,...} vector. */
- tree *vtemp = XALLOCAVEC (tree, nunits_out);
- for (k = 0; k < nunits_out; ++k)
- vtemp[k] = build_int_cst (cr_index_scalar_type, k + 1);
- tree series_vect = build_vector (cr_index_vector_type, vtemp);
-
- /* Create a vector of the step value. */
- tree step = build_int_cst (cr_index_scalar_type, nunits_out);
- tree vec_step = build_vector_from_val (cr_index_vector_type, step);
-
- /* Create an induction variable. */
- gimple_stmt_iterator incr_gsi;
- bool insert_after;
- standard_iv_increment_position (loop, &incr_gsi, &insert_after);
- create_iv (series_vect, vec_step, NULL_TREE, loop, &incr_gsi,
- insert_after, &indx_before_incr, &indx_after_incr);
-
- /* Next create a new phi node vector (NEW_PHI_TREE) which starts
- filled with zeros (VEC_ZERO). */
-
- /* Create a vector of 0s. */
- tree zero = build_zero_cst (cr_index_scalar_type);
- tree vec_zero = build_vector_from_val (cr_index_vector_type, zero);
-
- /* 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));
- add_phi_arg (new_phi, vec_zero, loop_preheader_edge (loop),
- UNKNOWN_LOCATION);
-
- /* Now take the condition from the loops original cond_expr
- (VEC_STMT) and produce a new cond_expr (INDEX_COND_EXPR) which for
- every match uses values from the induction variable
- (INDEX_BEFORE_INCR) otherwise uses values from the phi node
- (NEW_PHI_TREE).
- Finally, we update the phi (NEW_PHI_TREE) to take the value of
- the new cond_expr (INDEX_COND_EXPR). */
-
- /* Duplicate the condition from vec_stmt. */
- tree ccompare = unshare_expr (gimple_assign_rhs1 (*vec_stmt));
-
- /* Create a conditional, where the condition is taken from vec_stmt
- (CCOMPARE), then is the induction index (INDEX_BEFORE_INCR) and
- else is the phi (NEW_PHI_TREE). */
- tree index_cond_expr = build3 (VEC_COND_EXPR, cr_index_vector_type,
- ccompare, indx_before_incr,
- new_phi_tree);
- cond_name = make_ssa_name (cr_index_vector_type);
- gimple *index_condition = gimple_build_assign (cond_name,
- 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_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 (new_phi, cond_name, loop_latch_edge (loop),
- UNKNOWN_LOCATION);
- }
- }
+ vect_defs[0] = gimple_assign_lhs (*vec_stmt);
- vect_create_epilog_for_reduction (vect_defs, stmt, epilog_copies,
- epilog_reduc_code, phis, reduc_index,
- double_reduc, slp_node, cond_name);
+ vect_create_epilog_for_reduction (vect_defs, stmt, reduc_def_stmt,
+ epilog_copies,
+ epilog_reduc_code, phis,
+ double_reduc, slp_node, slp_node_instance);
return true;
}
@@ -6912,28 +7314,28 @@ scale_profile_for_vect_loop (struct loop *loop, unsigned vf)
}
if (freq_h > 0)
{
- gcov_type scale;
+ profile_probability p;
/* Avoid dropping loop body profile counter to 0 because of zero count
in loop's preheader. */
if (!(freq_e > profile_count::from_gcov_type (1)))
freq_e = profile_count::from_gcov_type (1);
- /* This should not overflow. */
- scale = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h);
- scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
+ p = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h);
+ scale_loop_frequencies (loop, p);
}
basic_block exit_bb = single_pred (loop->latch);
edge exit_e = single_exit (loop);
exit_e->count = loop_preheader_edge (loop)->count;
- exit_e->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
+ exit_e->probability = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
edge exit_l = single_pred_edge (loop->latch);
- int prob = exit_l->probability;
- exit_l->probability = REG_BR_PROB_BASE - exit_e->probability;
+ profile_probability prob = exit_l->probability;
+ exit_l->probability = exit_e->probability.invert ();
exit_l->count = exit_bb->count - exit_e->count;
- if (prob > 0)
- scale_bbs_frequencies_int (&loop->latch, 1, exit_l->probability, prob);
+ if (prob.initialized_p () && exit_l->probability.initialized_p ())
+ scale_bbs_frequencies (&loop->latch, 1, exit_l->probability / prob);
}
/* Function vect_transform_loop.
@@ -6971,7 +7373,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
run at least the vectorization factor number of times checking
is pointless, too. */
th = LOOP_VINFO_COST_MODEL_THRESHOLD (loop_vinfo);
- if (th >= LOOP_VINFO_VECT_FACTOR (loop_vinfo) - 1
+ if (th >= LOOP_VINFO_VECT_FACTOR (loop_vinfo)
&& !LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
{
if (dump_enabled_p ())
@@ -7077,7 +7479,9 @@ vect_transform_loop (loop_vec_info loop_vinfo)
&& dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "multiple-types.\n");
- if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def
+ if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def
+ || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
+ || STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle)
&& ! PURE_SLP_STMT (stmt_info))
{
if (dump_enabled_p ())
@@ -7456,9 +7860,9 @@ optimize_mask_stores (struct loop *loop)
e->flags = EDGE_TRUE_VALUE;
efalse = make_edge (bb, store_bb, EDGE_FALSE_VALUE);
/* Put STORE_BB to likely part. */
- efalse->probability = PROB_UNLIKELY;
+ efalse->probability = profile_probability::unlikely ();
store_bb->frequency = PROB_ALWAYS - EDGE_FREQUENCY (efalse);
- make_edge (store_bb, join_bb, EDGE_FALLTHRU);
+ make_single_succ_edge (store_bb, join_bb, EDGE_FALLTHRU);
if (dom_info_available_p (CDI_DOMINATORS))
set_immediate_dominator (CDI_DOMINATORS, store_bb, bb);
if (dump_enabled_p ())
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 39f01337608..17d10835038 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -3789,14 +3789,8 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
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_BASE_ADDRESS (pattern_stmt_info)
- = STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo);
- STMT_VINFO_DR_INIT (pattern_stmt_info) = STMT_VINFO_DR_INIT (stmt_vinfo);
- STMT_VINFO_DR_OFFSET (pattern_stmt_info)
- = STMT_VINFO_DR_OFFSET (stmt_vinfo);
- STMT_VINFO_DR_STEP (pattern_stmt_info) = STMT_VINFO_DR_STEP (stmt_vinfo);
- STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info)
- = STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo);
+ STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
+ = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo)) = pattern_stmt;
*type_out = vectype;
*type_in = vectype;
@@ -3930,14 +3924,8 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
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_BASE_ADDRESS (pattern_stmt_info)
- = STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo);
- STMT_VINFO_DR_INIT (pattern_stmt_info) = STMT_VINFO_DR_INIT (stmt_vinfo);
- STMT_VINFO_DR_OFFSET (pattern_stmt_info)
- = STMT_VINFO_DR_OFFSET (stmt_vinfo);
- STMT_VINFO_DR_STEP (pattern_stmt_info) = STMT_VINFO_DR_STEP (stmt_vinfo);
- STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info)
- = STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo);
+ STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
+ = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo)) = pattern_stmt;
*type_out = vectype1;
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 0800a3f6b23..15d589d3452 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -403,9 +403,9 @@ again:
{
case vect_constant_def:
case vect_external_def:
- case vect_reduction_def:
break;
+ case vect_reduction_def:
case vect_induction_def:
case vect_internal_def:
oprnd_info->def_stmts.quick_push (def_stmt);
@@ -943,13 +943,31 @@ vect_build_slp_tree (vec_info *vinfo,
else
return NULL;
- /* If the SLP node is a PHI (induction), terminate the recursion. */
+ /* If the SLP node is a PHI (induction or reduction), terminate
+ the recursion. */
if (gimple_code (stmt) == GIMPLE_PHI)
{
- FOR_EACH_VEC_ELT (stmts, i, stmt)
- if (stmt != stmts[0])
- /* Induction from different IVs is not supported. */
- return NULL;
+ vect_def_type def_type = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt));
+ /* Induction from different IVs is not supported. */
+ if (def_type == vect_induction_def)
+ {
+ FOR_EACH_VEC_ELT (stmts, i, stmt)
+ if (stmt != stmts[0])
+ return NULL;
+ }
+ else
+ {
+ /* Else def types have to match. */
+ FOR_EACH_VEC_ELT (stmts, i, stmt)
+ {
+ /* But for reduction chains only check on the first stmt. */
+ if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
+ && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt)
+ continue;
+ if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != def_type)
+ return NULL;
+ }
+ }
node = vect_create_new_slp_node (stmts);
return node;
}
@@ -1005,6 +1023,7 @@ vect_build_slp_tree (vec_info *vinfo,
unsigned int j;
if (oprnd_info->first_dt != vect_internal_def
+ && oprnd_info->first_dt != vect_reduction_def
&& oprnd_info->first_dt != vect_induction_def)
continue;
@@ -2102,15 +2121,13 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
unsigned int i;
gimple *first_element;
- bool ok = false;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "=== vect_analyze_slp ===\n");
/* Find SLP sequences starting from groups of grouped stores. */
FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
- if (vect_analyze_slp_instance (vinfo, first_element, max_tree_size))
- ok = true;
+ vect_analyze_slp_instance (vinfo, first_element, max_tree_size);
if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
{
@@ -2118,22 +2135,28 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
/* Find SLP sequences starting from reduction chains. */
FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element)
- if (vect_analyze_slp_instance (vinfo, first_element,
+ if (! vect_analyze_slp_instance (vinfo, first_element,
max_tree_size))
- ok = true;
- else
- return false;
-
- /* Don't try to vectorize SLP reductions if reduction chain was
- detected. */
- return ok;
+ {
+ /* Dissolve reduction chain group. */
+ gimple *next, *stmt = first_element;
+ while (stmt)
+ {
+ stmt_vec_info vinfo = vinfo_for_stmt (stmt);
+ next = GROUP_NEXT_ELEMENT (vinfo);
+ GROUP_FIRST_ELEMENT (vinfo) = NULL;
+ GROUP_NEXT_ELEMENT (vinfo) = NULL;
+ stmt = next;
+ }
+ STMT_VINFO_DEF_TYPE (vinfo_for_stmt (first_element))
+ = vect_internal_def;
+ }
}
/* Find SLP sequences starting from groups of reductions. */
- if (loop_vinfo->reductions.length () > 1
- && vect_analyze_slp_instance (vinfo, loop_vinfo->reductions[0],
- max_tree_size))
- ok = true;
+ if (loop_vinfo->reductions.length () > 1)
+ vect_analyze_slp_instance (vinfo, loop_vinfo->reductions[0],
+ max_tree_size);
}
return true;
@@ -2432,7 +2455,7 @@ destroy_bb_vec_info (bb_vec_info bb_vinfo)
the subtree. Return TRUE if the operations are supported. */
static bool
-vect_slp_analyze_node_operations (slp_tree node)
+vect_slp_analyze_node_operations (slp_tree node, slp_instance node_instance)
{
bool dummy;
int i, j;
@@ -2443,32 +2466,73 @@ vect_slp_analyze_node_operations (slp_tree node)
return true;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- if (!vect_slp_analyze_node_operations (child))
+ if (!vect_slp_analyze_node_operations (child, node_instance))
return false;
- bool res = true;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ gcc_assert (stmt_info);
+ gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
+
+ /* For BB vectorization vector types are assigned here.
+ Memory accesses already got their vector type assigned
+ in vect_analyze_data_refs. */
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ if (bb_vinfo
+ && ! STMT_VINFO_DATA_REF (stmt_info))
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- gcc_assert (stmt_info);
- gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
-
- /* 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)[i]))
- = SLP_TREE_DEF_TYPE (child);
- res = vect_analyze_stmt (stmt, &dummy, node);
- /* 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)[i]))
- = vect_internal_def;
- if (! res)
- break;
+ gcc_assert (PURE_SLP_STMT (stmt_info));
+
+ tree scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
+ 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");
+ }
+
+ tree vectype = get_vectype_for_scalar_type (scalar_type);
+ if (!vectype)
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not SLPed: unsupported data-type ");
+ dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
+ scalar_type);
+ dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ }
+ return false;
+ }
+
+ 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");
+ }
+
+ gimple *sstmt;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt)
+ STMT_VINFO_VECTYPE (vinfo_for_stmt (sstmt)) = vectype;
}
- return res;
+ /* 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]))
+ = SLP_TREE_DEF_TYPE (child);
+ bool res = vect_analyze_stmt (stmt, &dummy, node, node_instance);
+ /* 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]))
+ = vect_internal_def;
+ if (! res)
+ return false;
+
+ return true;
}
@@ -2487,7 +2551,8 @@ vect_slp_analyze_operations (vec<slp_instance> slp_instances, void *data)
for (i = 0; slp_instances.iterate (i, &instance); )
{
- if (!vect_slp_analyze_node_operations (SLP_INSTANCE_TREE (instance)))
+ if (!vect_slp_analyze_node_operations (SLP_INSTANCE_TREE (instance),
+ instance))
{
dump_printf_loc (MSG_NOTE, vect_location,
"removing SLP instance operations starting from: ");
@@ -2976,8 +3041,7 @@ vect_mask_constant_operand_p (gimple *stmt, int opnum)
static void
vect_get_constant_vectors (tree op, slp_tree slp_node,
vec<tree> *vec_oprnds,
- unsigned int op_num, unsigned int number_of_vectors,
- int reduc_index)
+ unsigned int op_num, unsigned int number_of_vectors)
{
vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
gimple *stmt = stmts[0];
@@ -2996,8 +3060,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
bool constant_p, is_store;
tree neutral_op = NULL;
enum tree_code code = gimple_expr_code (stmt);
- gimple *def_stmt;
- struct loop *loop;
gimple_seq ctor_seq = NULL;
/* Check if vector type is a boolean vector. */
@@ -3009,64 +3071,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
nunits = TYPE_VECTOR_SUBPARTS (vector_type);
- if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
- && reduc_index != -1)
- {
- op_num = reduc_index;
- op = gimple_op (stmt, op_num + 1);
- /* For additional copies (see the explanation of NUMBER_OF_COPIES below)
- we need either neutral operands or the original operands. See
- get_initial_def_for_reduction() for details. */
- switch (code)
- {
- case WIDEN_SUM_EXPR:
- case DOT_PROD_EXPR:
- case SAD_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
- neutral_op = build_real (TREE_TYPE (op), dconst0);
- else
- neutral_op = build_int_cst (TREE_TYPE (op), 0);
-
- break;
-
- case MULT_EXPR:
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
- neutral_op = build_real (TREE_TYPE (op), dconst1);
- else
- neutral_op = build_int_cst (TREE_TYPE (op), 1);
-
- break;
-
- case BIT_AND_EXPR:
- neutral_op = build_int_cst (TREE_TYPE (op), -1);
- break;
-
- /* For MIN/MAX we don't have an easy neutral operand but
- the initial values can be used fine here. Only for
- a reduction chain we have to force a neutral element. */
- case MAX_EXPR:
- case MIN_EXPR:
- if (!GROUP_FIRST_ELEMENT (stmt_vinfo))
- neutral_op = NULL;
- else
- {
- def_stmt = SSA_NAME_DEF_STMT (op);
- loop = (gimple_bb (stmt))->loop_father;
- neutral_op = PHI_ARG_DEF_FROM_EDGE (def_stmt,
- loop_preheader_edge (loop));
- }
- break;
-
- default:
- gcc_assert (!GROUP_FIRST_ELEMENT (stmt_vinfo));
- neutral_op = NULL;
- }
- }
-
if (STMT_VINFO_DATA_REF (stmt_vinfo))
{
is_store = true;
@@ -3077,11 +3081,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
gcc_assert (op);
- if (CONSTANT_CLASS_P (op))
- constant_p = true;
- else
- constant_p = false;
-
/* NUMBER_OF_COPIES is the number of times we need to use the same values in
created vectors. It is greater than 1 if unrolling is performed.
@@ -3101,6 +3100,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
number_of_copies = nunits * number_of_vectors / group_size;
number_of_places_left_in_vector = nunits;
+ constant_p = true;
elts = XALLOCAVEC (tree, nunits);
bool place_after_defs = false;
for (j = 0; j < number_of_copies; j++)
@@ -3154,25 +3154,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
}
}
- if (reduc_index != -1)
- {
- loop = (gimple_bb (stmt))->loop_father;
- def_stmt = SSA_NAME_DEF_STMT (op);
-
- gcc_assert (loop);
-
- /* Get the def before the loop. In reduction chain we have only
- one initial value. */
- if ((j != (number_of_copies - 1)
- || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
- && i != 0))
- && neutral_op)
- op = neutral_op;
- else
- op = PHI_ARG_DEF_FROM_EDGE (def_stmt,
- loop_preheader_edge (loop));
- }
-
/* Create 'vect_ = {op0,op1,...,opn}'. */
number_of_places_left_in_vector--;
tree orig_op = op;
@@ -3236,8 +3217,6 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
if (number_of_places_left_in_vector == 0)
{
- number_of_places_left_in_vector = nunits;
-
if (constant_p)
vec_cst = build_vector (vector_type, elts);
else
@@ -3268,6 +3247,8 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
}
voprnds.quick_push (init);
place_after_defs = false;
+ number_of_places_left_in_vector = nunits;
+ constant_p = true;
}
}
}
@@ -3340,7 +3321,7 @@ vect_get_slp_vect_defs (slp_tree slp_node, vec<tree> *vec_oprnds)
void
vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
- vec<vec<tree> > *vec_oprnds, int reduc_index)
+ vec<vec<tree> > *vec_oprnds)
{
gimple *first_stmt;
int number_of_vects = 0, i;
@@ -3421,20 +3402,16 @@ vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
/* For reduction defs we call vect_get_constant_vectors (), since we are
looking for initial loop invariant values. */
- if (vectorized_defs && reduc_index == -1)
+ if (vectorized_defs)
/* The defs are already vectorized. */
vect_get_slp_vect_defs (child, &vec_defs);
else
/* Build vectors from scalar defs. */
vect_get_constant_vectors (oprnd, slp_node, &vec_defs, i,
- number_of_vects, reduc_index);
+ number_of_vects);
vec_oprnds->quick_push (vec_defs);
- /* For reductions, we only need initial values. */
- if (reduc_index != -1)
- return;
-
first_iteration = false;
}
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index d1d97cb662e..18dd1a4df32 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -581,9 +581,11 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
}
/* We are also not interested in uses on loop PHI backedges that are
inductions. Otherwise we'll needlessly vectorize the IV increment
- and cause hybrid SLP for SLP inductions. */
+ and cause hybrid SLP for SLP inductions. Unless the PHI is live
+ of course. */
else if (gimple_code (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))
== use))
{
@@ -1367,14 +1369,10 @@ vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
return vec_oprnd;
}
- /* operand is defined by a loop header phi - reduction */
+ /* operand is defined by a loop header phi. */
case vect_reduction_def:
case vect_double_reduction_def:
case vect_nested_cycle:
- /* Code should use get_initial_def_for_reduction. */
- gcc_unreachable ();
-
- /* operand is defined by loop-header phi - induction. */
case vect_induction_def:
{
gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
@@ -1535,7 +1533,7 @@ vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
/* Get vectorized definitions for the operands to create a copy of an original
stmt. See vect_get_vec_def_for_stmt_copy () for details. */
-static void
+void
vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt,
vec<tree> *vec_oprnds0,
vec<tree> *vec_oprnds1)
@@ -1554,15 +1552,13 @@ vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt,
}
-/* Get vectorized definitions for OP0 and OP1.
- REDUC_INDEX is the index of reduction operand in case of reduction,
- and -1 otherwise. */
+/* Get vectorized definitions for OP0 and OP1. */
void
vect_get_vec_defs (tree op0, tree op1, gimple *stmt,
vec<tree> *vec_oprnds0,
vec<tree> *vec_oprnds1,
- slp_tree slp_node, int reduc_index)
+ slp_tree slp_node)
{
if (slp_node)
{
@@ -1574,7 +1570,7 @@ vect_get_vec_defs (tree op0, tree op1, gimple *stmt,
if (op1)
ops.quick_push (op1);
- vect_get_slp_defs (ops, slp_node, &vec_defs, reduc_index);
+ vect_get_slp_defs (ops, slp_node, &vec_defs);
*vec_oprnds0 = vec_defs[0];
if (op1)
@@ -1698,13 +1694,9 @@ static int
compare_step_with_zero (gimple *stmt)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- tree step;
- if (loop_vinfo && nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt))
- step = STMT_VINFO_DR_STEP (stmt_info);
- else
- step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
- return tree_int_cst_compare (step, size_zero_node);
+ data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ return tree_int_cst_compare (vect_dr_behavior (dr)->step,
+ size_zero_node);
}
/* If the target supports a permute mask that reverses the elements in
@@ -2525,7 +2517,7 @@ vectorizable_bswap (gimple *stmt, gimple_stmt_iterator *gsi,
{
/* Handle uses. */
if (j == 0)
- vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node, -1);
+ vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
else
vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
@@ -2860,7 +2852,7 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
for (i = 0; i < nargs; i++)
vargs.quick_push (gimple_call_arg (stmt, i));
- vect_get_slp_defs (vargs, slp_node, &vec_defs, -1);
+ vect_get_slp_defs (vargs, slp_node, &vec_defs);
vec_oprnds0 = vec_defs[0];
/* Arguments are ready. Create the new vector stmt. */
@@ -2990,7 +2982,7 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
for (i = 0; i < nargs; i++)
vargs.quick_push (gimple_call_arg (stmt, i));
- vect_get_slp_defs (vargs, slp_node, &vec_defs, -1);
+ vect_get_slp_defs (vargs, slp_node, &vec_defs);
vec_oprnds0 = vec_defs[0];
/* Arguments are ready. Create the new vector stmt. */
@@ -3539,7 +3531,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
arginfo[i].op = vec_oprnd0;
vec_oprnd0
= build3 (BIT_FIELD_REF, atype, vec_oprnd0,
- size_int (prec),
+ bitsize_int (prec),
bitsize_int ((m & (k - 1)) * prec));
new_stmt
= gimple_build_assign (make_ssa_name (atype),
@@ -3700,7 +3692,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
}
else
t = build3 (BIT_FIELD_REF, vectype, new_temp,
- size_int (prec), bitsize_int (l * prec));
+ bitsize_int (prec), bitsize_int (l * prec));
new_stmt
= gimple_build_assign (make_ssa_name (vectype), t);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -4401,8 +4393,7 @@ 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,
- -1);
+ vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node);
else
vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
@@ -4462,11 +4453,11 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
vec_oprnds1.quick_push (vec_oprnd1);
vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
- slp_node, -1);
+ slp_node);
}
else
vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0,
- &vec_oprnds1, slp_node, -1);
+ &vec_oprnds1, slp_node);
}
else
{
@@ -4565,7 +4556,7 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
/* Handle uses. */
if (slp_node)
vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
- slp_node, -1);
+ slp_node);
else
{
vec_oprnds0.truncate (0);
@@ -4748,7 +4739,7 @@ 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, -1);
+ vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
else
vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
@@ -5155,10 +5146,10 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
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, -1);
+ slp_node);
else
vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
- slp_node, -1);
+ slp_node);
}
else
vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
@@ -5505,13 +5496,13 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
{
if (op_type == binary_op || op_type == ternary_op)
vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
- slp_node, -1);
+ slp_node);
else
vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
- slp_node, -1);
+ slp_node);
if (op_type == ternary_op)
vect_get_vec_defs (op2, NULL_TREE, stmt, &vec_oprnds2, NULL,
- slp_node, -1);
+ slp_node);
}
else
{
@@ -6076,7 +6067,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (slp)
{
vect_get_vec_defs (op, NULL_TREE, stmt, &vec_oprnds, NULL,
- slp_node, -1);
+ slp_node);
vec_oprnd = vec_oprnds[0];
}
else
@@ -6223,7 +6214,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
{
/* Get vectorized arguments for SLP_NODE. */
vect_get_vec_defs (op, NULL_TREE, stmt, &vec_oprnds,
- NULL, slp_node, -1);
+ NULL, slp_node);
vec_oprnd = vec_oprnds[0];
}
@@ -6364,11 +6355,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
misalign = 0;
else if (DR_MISALIGNMENT (first_dr) == -1)
{
- if (DR_VECT_AUX (first_dr)->base_element_aligned)
- align = TYPE_ALIGN_UNIT (elem_type);
- else
- align = get_object_alignment (DR_REF (first_dr))
- / BITS_PER_UNIT;
+ align = dr_alignment (vect_dr_behavior (first_dr));
misalign = 0;
TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref),
@@ -7022,9 +7009,9 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
to a larger load. */
unsigned lsize
= group_size * TYPE_PRECISION (TREE_TYPE (vectype));
- enum machine_mode elmode = mode_for_size (lsize, MODE_INT, 0);
- enum machine_mode vmode = mode_for_vector (elmode,
- nunits / group_size);
+ machine_mode elmode = mode_for_size (lsize, MODE_INT, 0);
+ machine_mode vmode = mode_for_vector (elmode,
+ nunits / group_size);
/* If we can't construct such a vector fall back to
element loads of the original vector type. */
if (VECTOR_MODE_P (vmode)
@@ -7133,6 +7120,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
{
first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ int group_gap = GROUP_GAP (vinfo_for_stmt (first_stmt));
/* For SLP vectorization we directly vectorize a subchain
without permutation. */
if (slp && ! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
@@ -7168,10 +7156,15 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
not only the number of vector stmts the permutation result
fits in. */
if (slp_perm)
- vec_num = (group_size * vf + nunits - 1) / nunits;
+ {
+ vec_num = (group_size * vf + nunits - 1) / nunits;
+ group_gap_adj = vf * group_size - nunits * vec_num;
+ }
else
- vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
- group_gap_adj = vf * group_size - nunits * vec_num;
+ {
+ vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
+ group_gap_adj = group_gap;
+ }
}
else
vec_num = group_size;
@@ -7299,8 +7292,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
- && (TREE_INT_CST_LOW (DR_STEP (dr))
- % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
+ && (DR_STEP_ALIGNMENT (dr) % GET_MODE_SIZE (TYPE_MODE (vectype))) != 0)
{
gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
compute_in_loop = true;
@@ -7332,6 +7324,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
aggr_type = vectype;
prev_stmt_info = NULL;
+ int group_elt = 0;
for (j = 0; j < ncopies; j++)
{
/* 1. Create the vector or array pointer update chain. */
@@ -7441,11 +7434,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
else if (DR_MISALIGNMENT (first_dr) == -1)
{
- if (DR_VECT_AUX (first_dr)->base_element_aligned)
- align = TYPE_ALIGN_UNIT (elem_type);
- else
- align = (get_object_alignment (DR_REF (first_dr))
- / BITS_PER_UNIT);
+ align = dr_alignment (vect_dr_behavior (first_dr));
misalign = 0;
TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref),
@@ -7623,10 +7612,27 @@ 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);
+
+ /* With SLP permutation we load the gaps as well, without
+ we need to skip the gaps after we manage to fully load
+ all elements. group_gap_adj is GROUP_SIZE here. */
+ group_elt += nunits;
+ if (group_gap_adj != 0 && ! slp_perm
+ && group_elt == group_size - group_gap_adj)
+ {
+ bool ovf;
+ tree bump
+ = wide_int_to_tree (sizetype,
+ wi::smul (TYPE_SIZE_UNIT (elem_type),
+ group_gap_adj, &ovf));
+ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
+ stmt, bump);
+ group_elt = 0;
+ }
}
/* Bump the vector pointer to account for a gap or for excess
elements loaded for a permuted SLP load. */
- if (group_gap_adj != 0)
+ if (group_gap_adj != 0 && slp_perm)
{
bool ovf;
tree bump
@@ -7976,7 +7982,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
}
ops.safe_push (then_clause);
ops.safe_push (else_clause);
- vect_get_slp_defs (ops, slp_node, &vec_defs, -1);
+ vect_get_slp_defs (ops, slp_node, &vec_defs);
vec_oprnds3 = vec_defs.pop ();
vec_oprnds2 = vec_defs.pop ();
if (!masked)
@@ -8314,7 +8320,7 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
ops.safe_push (rhs1);
ops.safe_push (rhs2);
- vect_get_slp_defs (ops, slp_node, &vec_defs, -1);
+ vect_get_slp_defs (ops, slp_node, &vec_defs);
vec_oprnds1 = vec_defs.pop ();
vec_oprnds0 = vec_defs.pop ();
}
@@ -8393,13 +8399,13 @@ vectorizable_comparison (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)
+vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
+ slp_instance node_instance)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
bool ok;
- tree scalar_type, vectype;
gimple *pattern_stmt;
gimple_seq pattern_def_seq;
@@ -8473,7 +8479,8 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
}
- if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node))
+ if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node,
+ node_instance))
return false;
}
@@ -8498,7 +8505,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
}
if (!vect_analyze_stmt (pattern_def_stmt,
- need_to_vectorize, node))
+ need_to_vectorize, node, node_instance))
return false;
}
}
@@ -8530,48 +8537,6 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
gcc_unreachable ();
}
- if (bb_vinfo)
- {
- gcc_assert (PURE_SLP_STMT (stmt_info));
-
- /* Memory accesses already got their vector type assigned
- in vect_analyze_data_refs. */
- if (! STMT_VINFO_DATA_REF (stmt_info))
- {
- scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
- 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");
- }
-
- vectype = get_vectype_for_scalar_type (scalar_type);
- if (!vectype)
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not SLPed: unsupported data-type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- scalar_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
- return false;
- }
-
- 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");
- }
-
- STMT_VINFO_VECTYPE (stmt_info) = vectype;
- }
- }
-
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))));
@@ -8600,7 +8565,7 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
|| vectorizable_load (stmt, NULL, NULL, node, NULL)
|| vectorizable_call (stmt, NULL, NULL, node)
|| vectorizable_store (stmt, NULL, NULL, node)
- || vectorizable_reduction (stmt, NULL, NULL, node)
+ || vectorizable_reduction (stmt, NULL, NULL, node, node_instance)
|| vectorizable_induction (stmt, NULL, NULL, node)
|| vectorizable_condition (stmt, NULL, NULL, NULL, 0, node)
|| vectorizable_comparison (stmt, NULL, NULL, NULL, node));
@@ -8750,7 +8715,8 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
break;
case reduc_vec_info_type:
- done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node);
+ done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node,
+ slp_node_instance);
gcc_assert (done);
break;
@@ -8816,20 +8782,20 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
{
gimple *slp_stmt;
int i;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt)
- {
- stmt_vec_info slp_stmt_info = vinfo_for_stmt (slp_stmt);
- if (STMT_VINFO_LIVE_P (slp_stmt_info)
- && STMT_VINFO_TYPE (slp_stmt_info) != reduc_vec_info_type)
- {
- done = vectorizable_live_operation (slp_stmt, gsi, slp_node, i,
- &vec_stmt);
- gcc_assert (done);
- }
- }
+ if (STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt)
+ {
+ stmt_vec_info slp_stmt_info = vinfo_for_stmt (slp_stmt);
+ if (STMT_VINFO_LIVE_P (slp_stmt_info))
+ {
+ done = vectorizable_live_operation (slp_stmt, gsi, slp_node, i,
+ &vec_stmt);
+ gcc_assert (done);
+ }
+ }
}
else if (STMT_VINFO_LIVE_P (stmt_info)
- && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
+ && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
{
done = vectorizable_live_operation (stmt, gsi, slp_node, -1, &vec_stmt);
gcc_assert (done);
@@ -8895,12 +8861,6 @@ new_stmt_vec_info (gimple *stmt, vec_info *vinfo)
STMT_VINFO_VEC_REDUCTION_TYPE (res) = TREE_CODE_REDUCTION;
STMT_VINFO_VEC_CONST_COND_REDUC_CODE (res) = ERROR_MARK;
- STMT_VINFO_DR_BASE_ADDRESS (res) = NULL;
- STMT_VINFO_DR_OFFSET (res) = NULL;
- STMT_VINFO_DR_INIT (res) = NULL;
- STMT_VINFO_DR_STEP (res) = NULL;
- STMT_VINFO_DR_ALIGNED_TO (res) = NULL;
-
if (gimple_code (stmt) == GIMPLE_PHI
&& is_loop_header_bb_p (gimple_bb (stmt)))
STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 0d62c829ef5..33a1f580474 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -448,11 +448,11 @@ vect_loop_vectorized_call (struct loop *loop)
return NULL;
}
-/* Fold LOOP_VECTORIZED internal call G to VALUE and
- update any immediate uses of it's LHS. */
+/* Fold loop internal call G like IFN_LOOP_VECTORIZED/IFN_LOOP_DIST_ALIAS
+ to VALUE and update any immediate uses of it's LHS. */
static void
-fold_loop_vectorized_call (gimple *g, tree value)
+fold_loop_internal_call (gimple *g, tree value)
{
tree lhs = gimple_call_lhs (g);
use_operand_p use_p;
@@ -469,6 +469,60 @@ fold_loop_vectorized_call (gimple *g, tree value)
}
}
+/* If LOOP has been versioned during loop distribution, return the gurading
+ internal call. */
+
+static gimple *
+vect_loop_dist_alias_call (struct loop *loop)
+{
+ basic_block bb;
+ basic_block entry;
+ struct loop *outer, *orig;
+ gimple_stmt_iterator gsi;
+ gimple *g;
+
+ if (loop->orig_loop_num == 0)
+ return NULL;
+
+ orig = get_loop (cfun, loop->orig_loop_num);
+ if (orig == NULL)
+ {
+ /* The original loop is somehow destroyed. Clear the information. */
+ loop->orig_loop_num = 0;
+ return NULL;
+ }
+
+ if (loop != orig)
+ bb = nearest_common_dominator (CDI_DOMINATORS, loop->header, orig->header);
+ else
+ bb = loop_preheader_edge (loop)->src;
+
+ outer = bb->loop_father;
+ entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
+ /* Look upward in dominance tree. */
+ for (; bb != entry && flow_bb_inside_loop_p (outer, bb);
+ bb = get_immediate_dominator (CDI_DOMINATORS, bb))
+ {
+ g = last_stmt (bb);
+ if (g == NULL || gimple_code (g) != GIMPLE_COND)
+ continue;
+
+ gsi = gsi_for_stmt (g);
+ gsi_prev (&gsi);
+ if (gsi_end_p (gsi))
+ continue;
+
+ g = gsi_stmt (gsi);
+ /* The guarding internal function call must have the same distribution
+ alias id. */
+ if (gimple_call_internal_p (g, IFN_LOOP_DIST_ALIAS)
+ && (tree_to_shwi (gimple_call_arg (g, 0)) == loop->orig_loop_num))
+ return g;
+ }
+ return NULL;
+}
+
/* Set the uids of all the statements in basic blocks inside loop
represented by LOOP_VINFO. LOOP_VECTORIZED_CALL is the internal
call guarding the loop which has been if converted. */
@@ -494,7 +548,7 @@ set_uid_loop_bbs (loop_vec_info loop_vinfo, gimple *loop_vectorized_call)
{
arg = gimple_call_arg (g, 0);
get_loop (cfun, tree_to_shwi (arg))->dont_vectorize = true;
- fold_loop_vectorized_call (g, boolean_false_node);
+ fold_loop_internal_call (g, boolean_false_node);
}
}
bbs = get_loop_body (scalar_loop);
@@ -595,7 +649,7 @@ vectorize_loops (void)
else
{
loop_vec_info loop_vinfo, orig_loop_vinfo;
- gimple *loop_vectorized_call;
+ gimple *loop_vectorized_call, *loop_dist_alias_call;
try_vectorize:
if (!((flag_tree_loop_vectorize
&& optimize_loop_nest_for_speed_p (loop))
@@ -603,6 +657,7 @@ vectorize_loops (void)
continue;
orig_loop_vinfo = NULL;
loop_vectorized_call = vect_loop_vectorized_call (loop);
+ loop_dist_alias_call = vect_loop_dist_alias_call (loop);
vectorize_epilogue:
vect_location = find_loop_location (loop);
if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOCATION
@@ -652,8 +707,8 @@ vectorize_loops (void)
{
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
"basic block vectorized\n");
- fold_loop_vectorized_call (loop_vectorized_call,
- boolean_true_node);
+ fold_loop_internal_call (loop_vectorized_call,
+ boolean_true_node);
loop_vectorized_call = NULL;
ret |= TODO_cleanup_cfg;
}
@@ -706,10 +761,17 @@ vectorize_loops (void)
if (loop_vectorized_call)
{
- fold_loop_vectorized_call (loop_vectorized_call, boolean_true_node);
+ fold_loop_internal_call (loop_vectorized_call, boolean_true_node);
loop_vectorized_call = NULL;
ret |= TODO_cleanup_cfg;
}
+ if (loop_dist_alias_call)
+ {
+ tree value = gimple_call_arg (loop_dist_alias_call, 1);
+ fold_loop_internal_call (loop_dist_alias_call, value);
+ loop_dist_alias_call = NULL;
+ ret |= TODO_cleanup_cfg;
+ }
if (new_loop)
{
@@ -741,7 +803,16 @@ vectorize_loops (void)
gimple *g = vect_loop_vectorized_call (loop);
if (g)
{
- fold_loop_vectorized_call (g, boolean_false_node);
+ fold_loop_internal_call (g, boolean_false_node);
+ ret |= TODO_cleanup_cfg;
+ g = NULL;
+ }
+ else
+ g = vect_loop_dist_alias_call (loop);
+
+ if (g)
+ {
+ fold_loop_internal_call (g, boolean_false_node);
ret |= TODO_cleanup_cfg;
}
}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 2e46467ee37..accac72324f 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -127,6 +127,9 @@ typedef struct _slp_instance {
/* The group of nodes that contain loads of this SLP instance. */
vec<slp_tree> loads;
+
+ /* The SLP node containing the reduction PHIs. */
+ slp_tree reduc_phis;
} *slp_instance;
@@ -554,11 +557,7 @@ typedef struct _stmt_vec_info {
/* Information about the data-ref relative to this loop
nest (the loop that is being considered for vectorization). */
- tree dr_base_address;
- tree dr_init;
- tree dr_offset;
- tree dr_step;
- tree dr_aligned_to;
+ innermost_loop_behavior dr_wrt_vec_loop;
/* For loop PHI nodes, the base and evolution part of it. This makes sure
this information is still available in vect_update_ivs_after_vectorizer
@@ -647,7 +646,9 @@ typedef struct _stmt_vec_info {
vect_force_simple_reduction. */
enum vect_reduction_type reduc_type;
- /* On a reduction PHI the def returned by vect_force_simple_reduction. */
+ /* 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;
/* The number of scalar stmt references from active SLP instances. */
@@ -706,11 +707,18 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_VEC_REDUCTION_TYPE(S) (S)->v_reduc_type
#define STMT_VINFO_VEC_CONST_COND_REDUC_CODE(S) (S)->const_cond_reduc_code
-#define STMT_VINFO_DR_BASE_ADDRESS(S) (S)->dr_base_address
-#define STMT_VINFO_DR_INIT(S) (S)->dr_init
-#define STMT_VINFO_DR_OFFSET(S) (S)->dr_offset
-#define STMT_VINFO_DR_STEP(S) (S)->dr_step
-#define STMT_VINFO_DR_ALIGNED_TO(S) (S)->dr_aligned_to
+#define STMT_VINFO_DR_WRT_VEC_LOOP(S) (S)->dr_wrt_vec_loop
+#define STMT_VINFO_DR_BASE_ADDRESS(S) (S)->dr_wrt_vec_loop.base_address
+#define STMT_VINFO_DR_INIT(S) (S)->dr_wrt_vec_loop.init
+#define STMT_VINFO_DR_OFFSET(S) (S)->dr_wrt_vec_loop.offset
+#define STMT_VINFO_DR_STEP(S) (S)->dr_wrt_vec_loop.step
+#define STMT_VINFO_DR_BASE_ALIGNMENT(S) (S)->dr_wrt_vec_loop.base_alignment
+#define STMT_VINFO_DR_BASE_MISALIGNMENT(S) \
+ (S)->dr_wrt_vec_loop.base_misalignment
+#define STMT_VINFO_DR_OFFSET_ALIGNMENT(S) \
+ (S)->dr_wrt_vec_loop.offset_alignment
+#define STMT_VINFO_DR_STEP_ALIGNMENT(S) \
+ (S)->dr_wrt_vec_loop.step_alignment
#define STMT_VINFO_IN_PATTERN_P(S) (S)->in_pattern_p
#define STMT_VINFO_RELATED_STMT(S) (S)->related_stmt
@@ -749,8 +757,6 @@ struct dataref_aux {
int misalignment;
/* If true the alignment of base_decl needs to be increased. */
bool base_misaligned;
- /* If true we know the base is at least vector element alignment aligned. */
- bool base_element_aligned;
tree base_decl;
};
@@ -1012,6 +1018,22 @@ known_alignment_for_access_p (struct data_reference *data_ref_info)
return (DR_MISALIGNMENT (data_ref_info) != DR_MISALIGNMENT_UNKNOWN);
}
+/* Return the behavior of DR with respect to the vectorization context
+ (which for outer loop vectorization might not be the behavior recorded
+ in DR itself). */
+
+static inline innermost_loop_behavior *
+vect_dr_behavior (data_reference *dr)
+{
+ gimple *stmt = DR_STMT (dr);
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ if (loop_vinfo == NULL
+ || !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt))
+ return &DR_INNERMOST (dr);
+ else
+ return &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info);
+}
/* Return true if the vect cost model is unlimited. */
static inline bool
@@ -1078,13 +1100,17 @@ extern void vect_finish_stmt_generation (gimple *, gimple *,
extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
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> *,
+ vec<tree> *, slp_tree);
+extern void vect_get_vec_defs_for_stmt_copy (enum vect_def_type *,
+ vec<tree> *, vec<tree> *);
extern tree vect_init_vector (gimple *, 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);
+extern bool vect_analyze_stmt (gimple *, bool *, slp_tree, slp_instance);
extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *,
gimple **, tree, int, slp_tree);
extern void vect_get_load_cost (struct data_reference *, int, bool,
@@ -1094,8 +1120,6 @@ extern void vect_get_load_cost (struct data_reference *, int, bool,
extern void vect_get_store_cost (struct data_reference *, int,
unsigned int *, stmt_vector_for_cost *);
extern bool vect_supportable_shift (enum tree_code, tree);
-extern void vect_get_vec_defs (tree, tree, gimple *, vec<tree> *,
- vec<tree> *, slp_tree, int);
extern tree vect_gen_perm_mask_any (tree, const unsigned char *);
extern tree vect_gen_perm_mask_checked (tree, const unsigned char *);
extern void optimize_mask_stores (struct loop*);
@@ -1140,8 +1164,7 @@ 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 *,
- tree, struct loop *,
- tree = NULL_TREE);
+ tree, tree = NULL_TREE);
/* In tree-vect-loop.c. */
/* FORNOW: Used in tree-parloops.c. */
@@ -1158,7 +1181,7 @@ extern loop_vec_info vect_analyze_loop_form (struct loop *);
extern bool vectorizable_live_operation (gimple *, gimple_stmt_iterator *,
slp_tree, int, gimple **);
extern bool vectorizable_reduction (gimple *, gimple_stmt_iterator *,
- gimple **, slp_tree);
+ gimple **, slp_tree, slp_instance);
extern bool vectorizable_induction (gimple *, gimple_stmt_iterator *,
gimple **, slp_tree);
extern tree get_initial_def_for_reduction (gimple *, tree, tree *);
@@ -1179,8 +1202,7 @@ extern bool 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> > *, int);
+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);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 9ca3924ea89..1f0b6880c45 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6393,20 +6393,37 @@ process_assert_insertions_for (tree name, assert_locus *loc)
gcc_unreachable ();
}
-/* Qsort helper for sorting assert locations. */
+/* Qsort helper for sorting assert locations. If stable is true, don't
+ use iterative_hash_expr because it can be unstable for -fcompare-debug,
+ on the other side some pointers might be NULL. */
+template <bool stable>
static int
compare_assert_loc (const void *pa, const void *pb)
{
assert_locus * const a = *(assert_locus * const *)pa;
assert_locus * const b = *(assert_locus * const *)pb;
- if (! a->e && b->e)
+
+ /* If stable, some asserts might be optimized away already, sort
+ them last. */
+ if (stable)
+ {
+ if (a == NULL)
+ return b != NULL;
+ else if (b == NULL)
+ return -1;
+ }
+
+ if (a->e == NULL && b->e != NULL)
return 1;
- else if (a->e && ! b->e)
+ else if (a->e != NULL && b->e == NULL)
return -1;
+ /* After the above checks, we know that (a->e == NULL) == (b->e == NULL),
+ no need to test both a->e and b->e. */
+
/* Sort after destination index. */
- if (! a->e && ! b->e)
+ if (a->e == NULL)
;
else if (a->e->dest->index > b->e->dest->index)
return 1;
@@ -6419,14 +6436,30 @@ compare_assert_loc (const void *pa, const void *pb)
else if (a->comp_code < b->comp_code)
return -1;
+ hashval_t ha, hb;
+
+ /* E.g. if a->val is ADDR_EXPR of a VAR_DECL, iterative_hash_expr
+ uses DECL_UID of the VAR_DECL, so sorting might differ between
+ -g and -g0. When doing the removal of redundant assert exprs
+ and commonization to successors, this does not matter, but for
+ the final sort needs to be stable. */
+ if (stable)
+ {
+ ha = 0;
+ hb = 0;
+ }
+ else
+ {
+ ha = iterative_hash_expr (a->expr, iterative_hash_expr (a->val, 0));
+ hb = iterative_hash_expr (b->expr, iterative_hash_expr (b->val, 0));
+ }
+
/* Break the tie using hashing and source/bb index. */
- hashval_t ha = iterative_hash_expr (a->expr, iterative_hash_expr (a->val, 0));
- hashval_t hb = iterative_hash_expr (b->expr, iterative_hash_expr (b->val, 0));
if (ha == hb)
- return (a->e && b->e
+ return (a->e != NULL
? a->e->src->index - b->e->src->index
: a->bb->index - b->bb->index);
- return ha - hb;
+ return ha > hb ? 1 : -1;
}
/* Process all the insertions registered for every name N_i registered
@@ -6452,7 +6485,7 @@ process_assert_insertions (void)
auto_vec<assert_locus *, 16> asserts;
for (; loc; loc = loc->next)
asserts.safe_push (loc);
- asserts.qsort (compare_assert_loc);
+ asserts.qsort (compare_assert_loc<false>);
/* Push down common asserts to successors and remove redundant ones. */
unsigned ecnt = 0;
@@ -6506,11 +6539,14 @@ process_assert_insertions (void)
}
}
+ /* The asserts vector sorting above might be unstable for
+ -fcompare-debug, sort again to ensure a stable sort. */
+ asserts.qsort (compare_assert_loc<true>);
for (unsigned j = 0; j < asserts.length (); ++j)
{
loc = asserts[j];
if (! loc)
- continue;
+ break;
update_edges_p |= process_assert_insertions_for (ssa_name (i), loc);
num_asserts++;
free (loc);
diff --git a/gcc/tree.c b/gcc/tree.c
index 13c6c90ba98..0c5acd6c8a6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -997,7 +997,7 @@ allocate_decl_uid (void)
Achoo! I got a code in the node. */
tree
-make_node_stat (enum tree_code code MEM_STAT_DECL)
+make_node (enum tree_code code MEM_STAT_DECL)
{
tree t;
enum tree_code_class type = TREE_CODE_CLASS (code);
@@ -1128,7 +1128,7 @@ free_node (tree node)
TREE_CHAIN, if it has one, is zero and it has a fresh uid. */
tree
-copy_node_stat (tree node MEM_STAT_DECL)
+copy_node (tree node MEM_STAT_DECL)
{
tree t;
enum tree_code code = TREE_CODE (node);
@@ -1681,7 +1681,7 @@ cst_and_fits_in_hwi (const_tree x)
/* Build a newly constructed VECTOR_CST node of length LEN. */
tree
-make_vector_stat (unsigned len MEM_STAT_DECL)
+make_vector (unsigned len MEM_STAT_DECL)
{
tree t;
unsigned length = (len - 1) * sizeof (tree) + sizeof (struct tree_vector);
@@ -1700,7 +1700,7 @@ make_vector_stat (unsigned len MEM_STAT_DECL)
are in a list pointed to by VALS. */
tree
-build_vector_stat (tree type, tree *vals MEM_STAT_DECL)
+build_vector (tree type, tree *vals MEM_STAT_DECL)
{
int over = 0;
unsigned cnt = 0;
@@ -2193,7 +2193,7 @@ build_zero_cst (tree type)
/* Build a BINFO with LEN language slots. */
tree
-make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
+make_tree_binfo (unsigned base_binfos MEM_STAT_DECL)
{
tree t;
size_t length = (offsetof (struct tree_binfo, base_binfos)
@@ -2235,7 +2235,7 @@ build_case_label (tree low_value, tree high_value, tree label_decl)
The latter determines the length of the HOST_WIDE_INT vector. */
tree
-make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
+make_int_cst (int len, int ext_len MEM_STAT_DECL)
{
tree t;
int length = ((ext_len - 1) * sizeof (HOST_WIDE_INT)
@@ -2265,7 +2265,7 @@ make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
/* Build a newly constructed TREE_VEC node of length LEN. */
tree
-make_tree_vec_stat (int len MEM_STAT_DECL)
+make_tree_vec (int len MEM_STAT_DECL)
{
tree t;
size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
@@ -2283,7 +2283,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
/* Grow a TREE_VEC node to new length LEN. */
tree
-grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
+grow_tree_vec (tree v, int len MEM_STAT_DECL)
{
gcc_assert (TREE_CODE (v) == TREE_VEC);
@@ -2868,9 +2868,9 @@ nreverse (tree t)
purpose and value fields are PARM and VALUE. */
tree
-build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
+build_tree_list (tree parm, tree value MEM_STAT_DECL)
{
- tree t = make_node_stat (TREE_LIST PASS_MEM_STAT);
+ tree t = make_node (TREE_LIST PASS_MEM_STAT);
TREE_PURPOSE (t) = parm;
TREE_VALUE (t) = value;
return t;
@@ -2879,7 +2879,7 @@ build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
/* Build a chain of TREE_LIST nodes from a vector. */
tree
-build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
+build_tree_list_vec (const vec<tree, va_gc> *vec MEM_STAT_DECL)
{
tree ret = NULL_TREE;
tree *pp = &ret;
@@ -2887,7 +2887,7 @@ build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
tree t;
FOR_EACH_VEC_SAFE_ELT (vec, i, t)
{
- *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
+ *pp = build_tree_list (NULL, t PASS_MEM_STAT);
pp = &TREE_CHAIN (*pp);
}
return ret;
@@ -2898,7 +2898,7 @@ build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL)
and whose TREE_CHAIN is CHAIN. */
tree
-tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
+tree_cons (tree purpose, tree value, tree chain MEM_STAT_DECL)
{
tree node;
@@ -4365,20 +4365,20 @@ do { tree _node = (NODE); \
enough for all extant tree codes. */
tree
-build0_stat (enum tree_code code, tree tt MEM_STAT_DECL)
+build0 (enum tree_code code, tree tt MEM_STAT_DECL)
{
tree t;
gcc_assert (TREE_CODE_LENGTH (code) == 0);
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
return t;
}
tree
-build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
+build1 (enum tree_code code, tree type, tree node MEM_STAT_DECL)
{
int length = sizeof (struct tree_exp);
tree t;
@@ -4454,9 +4454,9 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
} while (0)
tree
-build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
+build2 (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
{
- bool constant, read_only, side_effects;
+ bool constant, read_only, side_effects, div_by_zero;
tree t;
gcc_assert (TREE_CODE_LENGTH (code) == 2);
@@ -4474,7 +4474,7 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
&& ptrofftype_p (TREE_TYPE (arg1)));
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
/* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
@@ -4489,6 +4489,23 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
read_only = 1;
side_effects = TREE_SIDE_EFFECTS (t);
+ switch (code)
+ {
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case TRUNC_MOD_EXPR:
+ div_by_zero = integer_zerop (arg1);
+ break;
+ default:
+ div_by_zero = false;
+ }
+
PROCESS_ARG (0);
PROCESS_ARG (1);
@@ -4505,7 +4522,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
else
{
TREE_READONLY (t) = read_only;
- TREE_CONSTANT (t) = constant;
+ /* Don't mark X / 0 as constant. */
+ TREE_CONSTANT (t) = constant && !div_by_zero;
TREE_THIS_VOLATILE (t)
= (TREE_CODE_CLASS (code) == tcc_reference
&& arg0 && TREE_THIS_VOLATILE (arg0));
@@ -4516,8 +4534,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
tree
-build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
- tree arg2 MEM_STAT_DECL)
+build3 (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2 MEM_STAT_DECL)
{
bool constant, read_only, side_effects;
tree t;
@@ -4525,7 +4543,7 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
gcc_assert (TREE_CODE_LENGTH (code) == 3);
gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
read_only = 1;
@@ -4557,15 +4575,15 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
}
tree
-build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
- tree arg2, tree arg3 MEM_STAT_DECL)
+build4 (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3 MEM_STAT_DECL)
{
bool constant, read_only, side_effects;
tree t;
gcc_assert (TREE_CODE_LENGTH (code) == 4);
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
side_effects = TREE_SIDE_EFFECTS (t);
@@ -4584,15 +4602,15 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
}
tree
-build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
- tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
+build5 (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
{
bool constant, read_only, side_effects;
tree t;
gcc_assert (TREE_CODE_LENGTH (code) == 5);
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
side_effects = TREE_SIDE_EFFECTS (t);
@@ -4722,12 +4740,12 @@ build_nt_call_vec (tree fn, vec<tree, va_gc> *args)
Other slots are initialized to 0 or null pointers. */
tree
-build_decl_stat (location_t loc, enum tree_code code, tree name,
+build_decl (location_t loc, enum tree_code code, tree name,
tree type MEM_STAT_DECL)
{
tree t;
- t = make_node_stat (code PASS_MEM_STAT);
+ t = make_node (code PASS_MEM_STAT);
DECL_SOURCE_LOCATION (t) = loc;
/* if (type == error_mark_node)
@@ -5162,8 +5180,6 @@ free_lang_data_in_type (tree type)
/* C++ FE uses TREE_PURPOSE to store initial values. */
TREE_PURPOSE (p) = NULL;
}
- /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
- TYPE_MINVAL (type) = NULL;
}
if (TREE_CODE (type) == METHOD_TYPE)
{
@@ -5174,8 +5190,6 @@ free_lang_data_in_type (tree type)
/* C++ FE uses TREE_PURPOSE to store initial values. */
TREE_PURPOSE (p) = NULL;
}
- /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
- TYPE_MINVAL (type) = NULL;
}
/* Remove members that are not actually FIELD_DECLs from the field
@@ -5221,13 +5235,15 @@ free_lang_data_in_type (tree type)
if (TYPE_VFIELD (type) && TREE_CODE (TYPE_VFIELD (type)) != FIELD_DECL)
TYPE_VFIELD (type) = NULL_TREE;
- /* Remove TYPE_METHODS list. While it would be nice to keep it
- to enable ODR warnings about different method lists, doing so
- seems to impractically increase size of LTO data streamed.
- Keep the information if TYPE_METHODS was non-NULL. This is used
- by function.c and pretty printers. */
- if (TYPE_METHODS (type))
- TYPE_METHODS (type) = error_mark_node;
+ /* Splice out FUNCTION_DECLS and TEMPLATE_DECLS from
+ TYPE_FIELDS. So LTO doesn't grow. */
+ for (tree probe, *prev= &TYPE_FIELDS (type); (probe = *prev); )
+ if (TREE_CODE (probe) == FUNCTION_DECL
+ || TREE_CODE (probe) == TEMPLATE_DECL)
+ *prev = probe;
+ else
+ prev = &DECL_CHAIN (probe);
+
if (TYPE_BINFO (type))
{
free_lang_data_in_binfo (TYPE_BINFO (type));
@@ -5422,9 +5438,10 @@ free_lang_data_in_decl (tree decl)
At this point, it is not needed anymore. */
DECL_SAVED_TREE (decl) = NULL_TREE;
- /* Clear the abstract origin if it refers to a method. Otherwise
- dwarf2out.c will ICE as we clear TYPE_METHODS and thus the
- origin will not be output correctly. */
+ /* Clear the abstract origin if it refers to a method.
+ Otherwise dwarf2out.c will ICE as we splice functions out of
+ TYPE_FIELDS and thus the origin will not be output
+ correctly. */
if (DECL_ABSTRACT_ORIGIN (decl)
&& DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
&& RECORD_OR_UNION_TYPE_P
@@ -5637,9 +5654,9 @@ find_decls_types_r (tree *tp, int *ws, void *data)
them and thus do not and want not to reach unused pointer types
this way. */
if (!POINTER_TYPE_P (t))
- fld_worklist_push (TYPE_MINVAL (t), fld);
+ fld_worklist_push (TYPE_MIN_VALUE_RAW (t), fld);
if (!RECORD_OR_UNION_TYPE_P (t))
- fld_worklist_push (TYPE_MAXVAL (t), fld);
+ fld_worklist_push (TYPE_MAX_VALUE_RAW (t), fld);
fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
/* Do not walk TYPE_NEXT_VARIANT. We do not stream it and thus
do not and want not to reach unused variants this way. */
@@ -5661,16 +5678,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
tree tem;
FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (TYPE_BINFO (t)), i, tem)
fld_worklist_push (TREE_TYPE (tem), fld);
- tem = BINFO_VIRTUALS (TYPE_BINFO (t));
- if (tem
- /* The Java FE overloads BINFO_VIRTUALS for its own purpose. */
- && TREE_CODE (tem) == TREE_LIST)
- do
- {
- fld_worklist_push (TREE_VALUE (tem), fld);
- tem = TREE_CHAIN (tem);
- }
- while (tem);
+ fld_worklist_push (BINFO_VIRTUALS (TYPE_BINFO (t)), fld);
}
if (RECORD_OR_UNION_TYPE_P (t))
{
@@ -6676,7 +6684,7 @@ build_aligned_type (tree type, unsigned int align)
tree
build_distinct_type_copy (tree type MEM_STAT_DECL)
{
- tree t = copy_node_stat (type PASS_MEM_STAT);
+ tree t = copy_node (type PASS_MEM_STAT);
TYPE_POINTER_TO (t) = 0;
TYPE_REFERENCE_TO (t) = 0;
@@ -6692,12 +6700,6 @@ build_distinct_type_copy (tree type MEM_STAT_DECL)
TYPE_MAIN_VARIANT (t) = t;
TYPE_NEXT_VARIANT (t) = 0;
- /* We do not record methods in type copies nor variants
- so we do not need to keep them up to date when new method
- is inserted. */
- if (RECORD_OR_UNION_TYPE_P (t))
- TYPE_METHODS (t) = NULL_TREE;
-
/* Note that it is now possible for TYPE_MIN_VALUE to be a value
whose TREE_TYPE is not t. This can also happen in the Ada
frontend when using subtypes. */
@@ -10799,7 +10801,7 @@ build_common_builtin_nodes (void)
ECF_PURE | ECF_NOTHROW | ECF_LEAF);
/* If there's a possibility that we might use the ARM EABI, build the
- alternate __cxa_end_cleanup node used to resume from C++ and Java. */
+ alternate __cxa_end_cleanup node used to resume from C++. */
if (targetm.arm_eabi_unwinder)
{
ftype = build_function_type_list (void_type_node, NULL_TREE);
@@ -11246,7 +11248,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code)
object is initialized to zeros. */
tree
-build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL)
+build_vl_exp (enum tree_code code, int len MEM_STAT_DECL)
{
tree t;
int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp);
@@ -13423,8 +13425,6 @@ verify_type_variant (const_tree t, tree tv)
- aggregates may have new TYPE_FIELDS list that list variants of
the main variant TYPE_FIELDS.
- vector types may differ by TYPE_VECTOR_OPAQUE
- - TYPE_METHODS is always NULL for variant types and maintained for
- main variant only.
*/
/* Convenience macro for matching individual fields. */
@@ -13525,12 +13525,6 @@ verify_type_variant (const_tree t, tree tv)
}
if (TREE_CODE (t) == METHOD_TYPE)
verify_variant_match (TYPE_METHOD_BASETYPE);
- if (RECORD_OR_UNION_TYPE_P (t) && TYPE_METHODS (t))
- {
- error ("type variant has TYPE_METHODS");
- debug_tree (tv);
- return false;
- }
if (TREE_CODE (t) == OFFSET_TYPE)
verify_variant_match (TYPE_OFFSET_BASETYPE);
if (TREE_CODE (t) == ARRAY_TYPE)
@@ -13987,7 +13981,7 @@ verify_type (const_tree t)
}
- /* Check various uses of TYPE_MINVAL. */
+ /* Check various uses of TYPE_MIN_VALUE_RAW. */
if (RECORD_OR_UNION_TYPE_P (t))
{
/* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
@@ -14029,27 +14023,10 @@ verify_type (const_tree t)
TREE_TYPE (TYPE_MIN_VALUE (t))
but does not for C sizetypes in LTO. */
}
- /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
- else if (TYPE_MINVAL (t)
- && ((TREE_CODE (t) != METHOD_TYPE && TREE_CODE (t) != FUNCTION_TYPE)
- || in_lto_p))
- {
- error ("TYPE_MINVAL non-NULL");
- debug_tree (TYPE_MINVAL (t));
- error_found = true;
- }
/* Check various uses of TYPE_MAXVAL. */
if (RECORD_OR_UNION_TYPE_P (t))
{
- if (TYPE_METHODS (t) && TREE_CODE (TYPE_METHODS (t)) != FUNCTION_DECL
- && TREE_CODE (TYPE_METHODS (t)) != TEMPLATE_DECL
- && TYPE_METHODS (t) != error_mark_node)
- {
- error ("TYPE_METHODS is not FUNCTION_DECL, TEMPLATE_DECL nor error_mark_node");
- debug_tree (TYPE_METHODS (t));
- error_found = true;
- }
}
else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
{
@@ -14091,10 +14068,10 @@ verify_type (const_tree t)
error_found = true;
}
}
- else if (TYPE_MAXVAL (t))
+ else if (TYPE_MAX_VALUE_RAW (t))
{
- error ("TYPE_MAXVAL non-NULL");
- debug_tree (TYPE_MAXVAL (t));
+ error ("TYPE_MAX_VALUE_RAW non-NULL");
+ debug_tree (TYPE_MAX_VALUE_RAW (t));
error_found = true;
}
@@ -14109,14 +14086,6 @@ verify_type (const_tree t)
debug_tree (TYPE_BINFO (t));
error_found = true;
}
- /* FIXME: Java builds invalid empty binfos that do not have
- TREE_TYPE set. */
- else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t) && 0)
- {
- error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
- debug_tree (TREE_TYPE (TYPE_BINFO (t)));
- error_found = true;
- }
}
else if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
{
@@ -14188,6 +14157,8 @@ verify_type (const_tree t)
;
else if (TREE_CODE (fld) == USING_DECL)
;
+ else if (TREE_CODE (fld) == FUNCTION_DECL)
+ ;
else
{
error ("Wrong tree in TYPE_FIELDS list");
@@ -14271,20 +14242,6 @@ verify_type (const_tree t)
error ("TYPE_STRING_FLAG is set on wrong type code");
error_found = true;
}
- else if (TYPE_STRING_FLAG (t))
- {
- const_tree b = t;
- if (TREE_CODE (b) == ARRAY_TYPE)
- b = TREE_TYPE (t);
- /* Java builds arrays with TYPE_STRING_FLAG of promoted_char_type
- that is 32bits. */
- if (TREE_CODE (b) != INTEGER_TYPE)
- {
- error ("TYPE_STRING_FLAG is set on type that does not look like "
- "char nor array of chars");
- error_found = true;
- }
- }
/* ipa-devirt makes an assumption that TYPE_METHOD_BASETYPE is always
TYPE_MAIN_VARIANT and it would be odd to add methods only to variatns
@@ -14552,10 +14509,14 @@ get_nonnull_args (const_tree fntype)
real declaration.
Keep the size up to date in tree.h ! */
-const builtin_structptr_type builtin_structptr_types[2] =
+const builtin_structptr_type builtin_structptr_types[6] =
{
{ fileptr_type_node, ptr_type_node, "FILE" },
- { const_tm_ptr_type_node, const_ptr_type_node, "tm" }
+ { const_tm_ptr_type_node, const_ptr_type_node, "tm" },
+ { fenv_t_ptr_type_node, ptr_type_node, "fenv_t" },
+ { const_fenv_t_ptr_type_node, const_ptr_type_node, "fenv_t" },
+ { fexcept_t_ptr_type_node, ptr_type_node, "fexcept_t" },
+ { const_fexcept_t_ptr_type_node, const_ptr_type_node, "fexcept_t" }
};
#if CHECKING_P
diff --git a/gcc/tree.def b/gcc/tree.def
index 0ec805903a9..9f80c4d41f5 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -112,10 +112,7 @@ DEFTREECODE (BLOCK, "block", tcc_exceptional, 0)
itself or have named members doesn't really have a "scope" per se.
The TYPE_STUB_DECL field is used as a forward-references to names for
ENUMERAL_TYPE, RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE nodes;
- see below.
- The TYPE_METHODS points to list of all methods associated with the type.
- It is non-NULL only at main variant of the type and after free_lang_data
- it may be set to error_mark_node instead of actual list to save memory. */
+ see below. */
/* The ordering of the following codes is optimized for the checking
macros in tree.h. Changing the order will degrade the speed of the
@@ -213,8 +210,9 @@ DEFTREECODE (ARRAY_TYPE, "array_type", tcc_type, 0)
/* Struct in C, or record in Pascal. */
/* Special fields:
TYPE_FIELDS chain of FIELD_DECLs for the fields of the struct,
- and VAR_DECLs, TYPE_DECLs and CONST_DECLs for record-scope variables,
- types and enumerators.
+ VAR_DECLs, TYPE_DECLs and CONST_DECLs for record-scope variables,
+ types and enumerators and FUNCTION_DECLs for methods associated
+ with the type.
A few may need to be added for Pascal. */
/* See the comment above, before ENUMERAL_TYPE, for how
forward references to struct tags are handled in C. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 7a4f5d64f19..e9e7931b1ae 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2103,37 +2103,35 @@ extern machine_mode element_mode (const_tree t);
#define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type_non_common.values)
#define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type_non_common.values)
-#define TYPE_FIELDS(NODE) \
+#define TYPE_FIELDS(NODE) \
(RECORD_OR_UNION_CHECK (NODE)->type_non_common.values)
#define TYPE_CACHED_VALUES(NODE) (TYPE_CHECK (NODE)->type_non_common.values)
-#define TYPE_ARG_TYPES(NODE) \
+#define TYPE_ARG_TYPES(NODE) \
(FUNC_OR_METHOD_CHECK (NODE)->type_non_common.values)
#define TYPE_VALUES_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.values)
-#define TYPE_METHODS(NODE) \
- (RECORD_OR_UNION_CHECK (NODE)->type_non_common.maxval)
-#define TYPE_VFIELD(NODE) \
- (RECORD_OR_UNION_CHECK (NODE)->type_non_common.minval)
-#define TYPE_METHOD_BASETYPE(NODE) \
- (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.maxval)
-#define TYPE_OFFSET_BASETYPE(NODE) \
- (OFFSET_TYPE_CHECK (NODE)->type_non_common.maxval)
-#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type_non_common.maxval)
-#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type_non_common.minval)
-#define TYPE_NEXT_PTR_TO(NODE) \
+#define TYPE_MIN_VALUE(NODE) \
+ (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_NEXT_PTR_TO(NODE) \
(POINTER_TYPE_CHECK (NODE)->type_non_common.minval)
-#define TYPE_NEXT_REF_TO(NODE) \
+#define TYPE_NEXT_REF_TO(NODE) \
(REFERENCE_TYPE_CHECK (NODE)->type_non_common.minval)
-#define TYPE_MIN_VALUE(NODE) \
- (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_VFIELD(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_non_common.minval)
+#define TYPE_MIN_VALUE_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.minval)
+
#define TYPE_MAX_VALUE(NODE) \
(NUMERICAL_TYPE_CHECK (NODE)->type_non_common.maxval)
-
+#define TYPE_METHOD_BASETYPE(NODE) \
+ (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_OFFSET_BASETYPE(NODE) \
+ (OFFSET_TYPE_CHECK (NODE)->type_non_common.maxval)
/* If non-NULL, this is an upper bound of the size (in bytes) of an
object of the given ARRAY_TYPE_NON_COMMON. This allows temporaries to be
allocated. */
#define TYPE_ARRAY_MAX_SIZE(ARRAY_TYPE) \
(ARRAY_TYPE_CHECK (ARRAY_TYPE)->type_non_common.maxval)
+#define TYPE_MAX_VALUE_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.maxval)
/* For record and union types, information about this type, as a base type
for itself. */
@@ -3725,6 +3723,12 @@ id_equal (const char *str, const_tree id)
#define fileptr_type_node global_trees[TI_FILEPTR_TYPE]
/* The C type `const struct tm *'. */
#define const_tm_ptr_type_node global_trees[TI_CONST_TM_PTR_TYPE]
+/* The C type `fenv_t *'. */
+#define fenv_t_ptr_type_node global_trees[TI_FENV_T_PTR_TYPE]
+#define const_fenv_t_ptr_type_node global_trees[TI_CONST_FENV_T_PTR_TYPE]
+/* The C type `fexcept_t *'. */
+#define fexcept_t_ptr_type_node global_trees[TI_FEXCEPT_T_PTR_TYPE]
+#define const_fexcept_t_ptr_type_node global_trees[TI_CONST_FEXCEPT_T_PTR_TYPE]
#define pointer_sized_int_node global_trees[TI_POINTER_SIZED_TYPE]
#define boolean_type_node global_trees[TI_BOOLEAN_TYPE]
@@ -3885,8 +3889,7 @@ extern int allocate_decl_uid (void);
The TREE_CODE is the only argument. Contents are initialized
to zero except for a few of the common fields. */
-extern tree make_node_stat (enum tree_code MEM_STAT_DECL);
-#define make_node(t) make_node_stat (t MEM_STAT_INFO)
+extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
/* Free tree node. */
@@ -3894,8 +3897,7 @@ extern void free_node (tree);
/* Make a copy of a node, with all the same contents. */
-extern tree copy_node_stat (tree MEM_STAT_DECL);
-#define copy_node(t) copy_node_stat (t MEM_STAT_INFO)
+extern tree copy_node (tree CXX_MEM_STAT_INFO);
/* Make a copy of a chain of TREE_LIST nodes. */
@@ -3906,109 +3908,86 @@ extern tree copy_list (tree);
extern tree build_case_label (tree, tree, tree);
/* Make a BINFO. */
-extern tree make_tree_binfo_stat (unsigned MEM_STAT_DECL);
-#define make_tree_binfo(t) make_tree_binfo_stat (t MEM_STAT_INFO)
+extern tree make_tree_binfo (unsigned CXX_MEM_STAT_INFO);
/* Make an INTEGER_CST. */
-extern tree make_int_cst_stat (int, int MEM_STAT_DECL);
-#define make_int_cst(LEN, EXT_LEN) \
- make_int_cst_stat (LEN, EXT_LEN MEM_STAT_INFO)
+extern tree make_int_cst (int, int CXX_MEM_STAT_INFO);
/* Make a TREE_VEC. */
-extern tree make_tree_vec_stat (int MEM_STAT_DECL);
-#define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO)
+extern tree make_tree_vec (int CXX_MEM_STAT_INFO);
/* Grow a TREE_VEC. */
-extern tree grow_tree_vec_stat (tree v, int MEM_STAT_DECL);
-#define grow_tree_vec(v, t) grow_tree_vec_stat (v, t MEM_STAT_INFO)
+extern tree grow_tree_vec (tree v, int CXX_MEM_STAT_INFO);
/* Construct various types of nodes. */
extern tree build_nt (enum tree_code, ...);
extern tree build_nt_call_vec (tree, vec<tree, va_gc> *);
-extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL);
-#define build0(c,t) build0_stat (c,t MEM_STAT_INFO)
-extern tree build1_stat (enum tree_code, tree, tree MEM_STAT_DECL);
-#define build1(c,t1,t2) build1_stat (c,t1,t2 MEM_STAT_INFO)
-extern tree build2_stat (enum tree_code, tree, tree, tree MEM_STAT_DECL);
-#define build2(c,t1,t2,t3) build2_stat (c,t1,t2,t3 MEM_STAT_INFO)
-extern tree build3_stat (enum tree_code, tree, tree, tree, tree MEM_STAT_DECL);
-#define build3(c,t1,t2,t3,t4) build3_stat (c,t1,t2,t3,t4 MEM_STAT_INFO)
-extern tree build4_stat (enum tree_code, tree, tree, tree, tree,
- tree MEM_STAT_DECL);
-#define build4(c,t1,t2,t3,t4,t5) build4_stat (c,t1,t2,t3,t4,t5 MEM_STAT_INFO)
-extern tree build5_stat (enum tree_code, tree, tree, tree, tree, tree,
- tree MEM_STAT_DECL);
-#define build5(c,t1,t2,t3,t4,t5,t6) build5_stat (c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
+extern tree build0 (enum tree_code, tree CXX_MEM_STAT_INFO);
+extern tree build1 (enum tree_code, tree, tree CXX_MEM_STAT_INFO);
+extern tree build2 (enum tree_code, tree, tree, tree CXX_MEM_STAT_INFO);
+extern tree build3 (enum tree_code, tree, tree, tree, tree CXX_MEM_STAT_INFO);
+extern tree build4 (enum tree_code, tree, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
+extern tree build5 (enum tree_code, tree, tree, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
/* _loc versions of build[1-5]. */
static inline tree
-build1_stat_loc (location_t loc, enum tree_code code, tree type,
- tree arg1 MEM_STAT_DECL)
+build1_loc (location_t loc, enum tree_code code, tree type,
+ tree arg1 CXX_MEM_STAT_INFO)
{
- tree t = build1_stat (code, type, arg1 PASS_MEM_STAT);
+ tree t = build1 (code, type, arg1 PASS_MEM_STAT);
if (CAN_HAVE_LOCATION_P (t))
SET_EXPR_LOCATION (t, loc);
return t;
}
-#define build1_loc(l,c,t1,t2) build1_stat_loc (l,c,t1,t2 MEM_STAT_INFO)
static inline tree
-build2_stat_loc (location_t loc, enum tree_code code, tree type, tree arg0,
- tree arg1 MEM_STAT_DECL)
+build2_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1 CXX_MEM_STAT_INFO)
{
- tree t = build2_stat (code, type, arg0, arg1 PASS_MEM_STAT);
+ tree t = build2 (code, type, arg0, arg1 PASS_MEM_STAT);
if (CAN_HAVE_LOCATION_P (t))
SET_EXPR_LOCATION (t, loc);
return t;
}
-#define build2_loc(l,c,t1,t2,t3) build2_stat_loc (l,c,t1,t2,t3 MEM_STAT_INFO)
static inline tree
-build3_stat_loc (location_t loc, enum tree_code code, tree type, tree arg0,
- tree arg1, tree arg2 MEM_STAT_DECL)
+build3_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2 CXX_MEM_STAT_INFO)
{
- tree t = build3_stat (code, type, arg0, arg1, arg2 PASS_MEM_STAT);
+ tree t = build3 (code, type, arg0, arg1, arg2 PASS_MEM_STAT);
if (CAN_HAVE_LOCATION_P (t))
SET_EXPR_LOCATION (t, loc);
return t;
}
-#define build3_loc(l,c,t1,t2,t3,t4) \
- build3_stat_loc (l,c,t1,t2,t3,t4 MEM_STAT_INFO)
static inline tree
-build4_stat_loc (location_t loc, enum tree_code code, tree type, tree arg0,
- tree arg1, tree arg2, tree arg3 MEM_STAT_DECL)
+build4_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2, tree arg3 CXX_MEM_STAT_INFO)
{
- tree t = build4_stat (code, type, arg0, arg1, arg2, arg3 PASS_MEM_STAT);
+ tree t = build4 (code, type, arg0, arg1, arg2, arg3 PASS_MEM_STAT);
if (CAN_HAVE_LOCATION_P (t))
SET_EXPR_LOCATION (t, loc);
return t;
}
-#define build4_loc(l,c,t1,t2,t3,t4,t5) \
- build4_stat_loc (l,c,t1,t2,t3,t4,t5 MEM_STAT_INFO)
static inline tree
-build5_stat_loc (location_t loc, enum tree_code code, tree type, tree arg0,
- tree arg1, tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
+build5_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2, tree arg3, tree arg4 CXX_MEM_STAT_INFO)
{
- tree t = build5_stat (code, type, arg0, arg1, arg2, arg3,
+ tree t = build5 (code, type, arg0, arg1, arg2, arg3,
arg4 PASS_MEM_STAT);
if (CAN_HAVE_LOCATION_P (t))
SET_EXPR_LOCATION (t, loc);
return t;
}
-#define build5_loc(l,c,t1,t2,t3,t4,t5,t6) \
- build5_stat_loc (l,c,t1,t2,t3,t4,t5,t6 MEM_STAT_INFO)
-
-extern tree build_var_debug_value_stat (tree, tree MEM_STAT_DECL);
-#define build_var_debug_value(t1,t2) \
- build_var_debug_value_stat (t1,t2 MEM_STAT_INFO)
/* Constructs double_int from tree CST. */
@@ -4023,10 +4002,8 @@ extern tree force_fit_type (tree, const wide_int_ref &, int, bool);
extern tree build_int_cst (tree, HOST_WIDE_INT);
extern tree build_int_cstu (tree type, unsigned HOST_WIDE_INT cst);
extern tree build_int_cst_type (tree, HOST_WIDE_INT);
-extern tree make_vector_stat (unsigned MEM_STAT_DECL);
-#define make_vector(n) make_vector_stat (n MEM_STAT_INFO)
-extern tree build_vector_stat (tree, tree * MEM_STAT_DECL);
-#define build_vector(t,v) build_vector_stat (t, v MEM_STAT_INFO)
+extern tree make_vector (unsigned CXX_MEM_STAT_INFO);
+extern tree build_vector (tree, tree * CXX_MEM_STAT_INFO);
extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
extern tree build_vector_from_val (tree, tree);
extern void recompute_constructor_flags (tree);
@@ -4044,21 +4021,17 @@ extern tree build_minus_one_cst (tree);
extern tree build_all_ones_cst (tree);
extern tree build_zero_cst (tree);
extern tree build_string (int, const char *);
-extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
-#define build_tree_list(t, q) build_tree_list_stat (t, q MEM_STAT_INFO)
-extern tree build_tree_list_vec_stat (const vec<tree, va_gc> *MEM_STAT_DECL);
-#define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
-extern tree build_decl_stat (location_t, enum tree_code,
- tree, tree MEM_STAT_DECL);
+extern tree build_tree_list (tree, tree CXX_MEM_STAT_INFO);
+extern tree build_tree_list_vec (const vec<tree, va_gc> * CXX_MEM_STAT_INFO);
+extern tree build_decl (location_t, enum tree_code,
+ tree, tree CXX_MEM_STAT_INFO);
extern tree build_fn_decl (const char *, tree);
-#define build_decl(l,c,t,q) build_decl_stat (l, c, t, q MEM_STAT_INFO)
extern tree build_translation_unit_decl (tree);
extern tree build_block (tree, tree, tree, tree);
extern tree build_empty_stmt (location_t);
extern tree build_omp_clause (location_t, enum omp_clause_code);
-extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
-#define build_vl_exp(c, n) build_vl_exp_stat (c, n MEM_STAT_INFO)
+extern tree build_vl_exp (enum tree_code, int CXX_MEM_STAT_INFO);
extern tree build_call_nary (tree, tree, int, ...);
extern tree build_call_valist (tree, tree, int, va_list);
@@ -4358,8 +4331,7 @@ extern tree chainon (tree, tree);
/* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */
-extern tree tree_cons_stat (tree, tree, tree MEM_STAT_DECL);
-#define tree_cons(t,q,w) tree_cons_stat (t,q,w MEM_STAT_INFO)
+extern tree tree_cons (tree, tree, tree CXX_MEM_STAT_INFO);
/* Return the last tree node in a chain. */
@@ -5531,5 +5503,5 @@ struct builtin_structptr_type
tree& base;
const char *str;
};
-extern const builtin_structptr_type builtin_structptr_types[2];
+extern const builtin_structptr_type builtin_structptr_types[6];
#endif /* GCC_TREE_H */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 44effdd2216..2580a58b6eb 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-object-size.h"
#include "tree-cfg.h"
+#include "gimple-fold.h"
+#include "varasm.h"
/* Map from a tree to a VAR_DECL tree. */
@@ -153,6 +155,7 @@ ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
{
var = create_tmp_var_raw (type);
TREE_ADDRESSABLE (var) = 1;
+ DECL_CONTEXT (var) = current_function_decl;
}
if (phase == UBSAN_ENCODE_VALUE_RTL)
{
@@ -399,6 +402,7 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
/* We weren't able to determine the type name. */
tname = "<unknown>";
+ tree eltype = type;
if (pstyle == UBSAN_PRINT_POINTER)
{
pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
@@ -449,12 +453,12 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
pp_quote (&pretty_name);
/* Save the tree with stripped types. */
- type = t;
+ eltype = t;
}
else
pp_printf (&pretty_name, "'%s'", tname);
- switch (TREE_CODE (type))
+ switch (TREE_CODE (eltype))
{
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
@@ -464,9 +468,9 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
case REAL_TYPE:
/* FIXME: libubsan right now only supports float, double and
long double type formats. */
- if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
- || TYPE_MODE (type) == TYPE_MODE (double_type_node)
- || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
+ if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
+ || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
+ || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
tkind = 0x0001;
else
tkind = 0xffff;
@@ -475,7 +479,7 @@ ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
tkind = 0xffff;
break;
}
- tinfo = get_ubsan_type_info_for_type (type);
+ tinfo = get_ubsan_type_info_for_type (eltype);
/* Create a new VAR_DECL of type descriptor. */
const char *tmp = pp_formatted_text (&pretty_name);
@@ -798,7 +802,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
/* Make an edge coming from the 'cond block' into the 'then block';
this edge is unlikely taken, so set up the probability accordingly. */
e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
/* Connect 'then block' with the 'else block'. This is needed
as the ubsan routines we call in the 'then block' are not noreturn.
@@ -809,7 +813,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
e = find_edge (cond_bb, fallthru_bb);
e->flags = EDGE_FALSE_VALUE;
e->count = cond_bb->count;
- e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_likely ();
/* Update dominance info for the newly created then_bb; note that
fallthru_bb's dominance info has already been updated by
@@ -872,13 +876,13 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
this edge is unlikely taken, so set up the probability
accordingly. */
e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
/* Set up the fallthrough basic block. */
e = find_edge (cond1_bb, cond2_bb);
e->flags = EDGE_FALSE_VALUE;
e->count = cond1_bb->count;
- e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_likely ();
/* Update dominance info. */
if (dom_info_available_p (CDI_DOMINATORS))
@@ -1028,6 +1032,170 @@ ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
return true;
}
+/* Expand UBSAN_PTR internal call. */
+
+bool
+ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
+{
+ gimple_stmt_iterator gsi = *gsip;
+ gimple *stmt = gsi_stmt (gsi);
+ location_t loc = gimple_location (stmt);
+ gcc_assert (gimple_call_num_args (stmt) == 2);
+ tree ptr = gimple_call_arg (stmt, 0);
+ tree off = gimple_call_arg (stmt, 1);
+
+ if (integer_zerop (off))
+ {
+ gsi_remove (gsip, true);
+ unlink_stmt_vdef (stmt);
+ return true;
+ }
+
+ basic_block cur_bb = gsi_bb (gsi);
+ tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
+ tree ptri = make_ssa_name (pointer_sized_int_node);
+ int pos_neg = get_range_pos_neg (off);
+
+ /* Split the original block holding the pointer dereference. */
+ edge e = split_block (cur_bb, stmt);
+
+ /* Get a hold on the 'condition block', the 'then block' and the
+ 'else block'. */
+ basic_block cond_bb = e->src;
+ basic_block fallthru_bb = e->dest;
+ basic_block then_bb = create_empty_bb (cond_bb);
+ basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
+ add_bb_to_loop (then_bb, cond_bb->loop_father);
+ loops_state_set (LOOPS_NEED_FIXUP);
+
+ /* Set up the fallthrough basic block. */
+ e->flags = EDGE_FALSE_VALUE;
+ if (pos_neg != 3)
+ {
+ e->count = cond_bb->count;
+ e->probability = profile_probability::very_likely ();
+
+ /* Connect 'then block' with the 'else block'. This is needed
+ as the ubsan routines we call in the 'then block' are not noreturn.
+ The 'then block' only has one outcoming edge. */
+ make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
+
+ /* Make an edge coming from the 'cond block' into the 'then block';
+ this edge is unlikely taken, so set up the probability
+ accordingly. */
+ e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
+ e->probability = profile_probability::very_unlikely ();
+ }
+ else
+ {
+ profile_count count = cond_bb->count.apply_probability (PROB_EVEN);
+ e->count = count;
+ e->probability = profile_probability::even ();
+
+ e = split_block (fallthru_bb, (gimple *) NULL);
+ cond_neg_bb = e->src;
+ fallthru_bb = e->dest;
+ e->count = count;
+ e->probability = profile_probability::very_likely ();
+ e->flags = EDGE_FALSE_VALUE;
+
+ e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
+ e->probability = profile_probability::very_unlikely ();
+
+ cond_pos_bb = create_empty_bb (cond_bb);
+ add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
+
+ e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
+ e->count = count;
+ e->probability = profile_probability::even ();
+
+ e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
+ e->probability = profile_probability::very_unlikely ();
+
+ e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
+ e->count = count;
+ e->probability = profile_probability::very_likely ();
+
+ make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
+ }
+
+ gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ /* Update dominance info for the newly created then_bb; note that
+ fallthru_bb's dominance info has already been updated by
+ split_block. */
+ if (dom_info_available_p (CDI_DOMINATORS))
+ {
+ set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
+ if (pos_neg == 3)
+ {
+ set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
+ set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
+ }
+ }
+
+ /* Put the ubsan builtin call into the newly created BB. */
+ if (flag_sanitize_undefined_trap_on_error)
+ g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
+ else
+ {
+ enum built_in_function bcode
+ = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
+ ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
+ : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
+ tree fn = builtin_decl_implicit (bcode);
+ tree data
+ = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
+ NULL_TREE, NULL_TREE);
+ data = build_fold_addr_expr_loc (loc, data);
+ g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
+ }
+ gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
+ gimple_set_location (g, loc);
+ gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
+
+ /* Unlink the UBSAN_PTRs vops before replacing it. */
+ unlink_stmt_vdef (stmt);
+
+ if (TREE_CODE (off) == INTEGER_CST)
+ g = gimple_build_cond (wi::neg_p (off) ? LT_EXPR : GE_EXPR, ptri,
+ fold_build1 (NEGATE_EXPR, sizetype, off),
+ NULL_TREE, NULL_TREE);
+ else if (pos_neg != 3)
+ g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
+ ptrplusoff, ptri, NULL_TREE, NULL_TREE);
+ else
+ {
+ gsi2 = gsi_start_bb (cond_pos_bb);
+ g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
+ gimple_set_location (g, loc);
+ gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
+
+ gsi2 = gsi_start_bb (cond_neg_bb);
+ g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
+ gimple_set_location (g, loc);
+ gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
+
+ gimple_seq seq = NULL;
+ tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetype, off);
+ t = gimple_build (&seq, loc, GE_EXPR, boolean_type_node,
+ t, ssize_int (0));
+ gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
+ g = gimple_build_cond (NE_EXPR, t, boolean_false_node,
+ NULL_TREE, NULL_TREE);
+ }
+ gimple_set_location (g, loc);
+ /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
+ gsi_replace (&gsi, g, false);
+ return false;
+}
+
+
/* Cached __ubsan_vptr_type_cache decl. */
static GTY(()) tree ubsan_vptr_type_cache_decl;
@@ -1227,11 +1395,117 @@ instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
if (TREE_CODE (t) == ADDR_EXPR)
t = TREE_OPERAND (t, 0);
tree base = get_base_address (t);
- if (TREE_CODE (base) == MEM_REF
+ if (base != NULL_TREE
+ && TREE_CODE (base) == MEM_REF
&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
instrument_mem_ref (t, base, &gsi, is_lhs);
}
+/* Instrument pointer arithmetics PTR p+ OFF. */
+
+static void
+instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
+{
+ if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
+ return;
+ gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
+ gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
+ gsi_insert_before (gsi, g, GSI_SAME_STMT);
+}
+
+/* Instrument pointer arithmetics if any. */
+
+static void
+maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
+{
+ if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
+ return;
+
+ /* Handle also e.g. &s->i. */
+ if (TREE_CODE (t) == ADDR_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
+ return;
+
+ HOST_WIDE_INT bitsize, bitpos, bytepos;
+ tree offset;
+ machine_mode mode;
+ int volatilep = 0, reversep, unsignedp = 0;
+ tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep);
+ tree moff = NULL_TREE;
+
+ bool decl_p = DECL_P (inner);
+ tree base;
+ if (decl_p)
+ {
+ if (DECL_REGISTER (inner))
+ return;
+ base = inner;
+ /* If BASE is a fixed size automatic variable or
+ global variable defined in the current TU and bitpos
+ fits, don't instrument anything. */
+ if (offset == NULL_TREE
+ && bitpos > 0
+ && (VAR_P (base)
+ || TREE_CODE (base) == PARM_DECL
+ || TREE_CODE (base) == RESULT_DECL)
+ && DECL_SIZE (base)
+ && TREE_CODE (DECL_SIZE (base)) == INTEGER_CST
+ && compare_tree_int (DECL_SIZE (base), bitpos) >= 0
+ && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
+ return;
+ }
+ else if (TREE_CODE (inner) == MEM_REF)
+ {
+ base = TREE_OPERAND (inner, 0);
+ if (TREE_CODE (base) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (base, 0))
+ && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
+ && !is_global_var (TREE_OPERAND (base, 0)))
+ return;
+ moff = TREE_OPERAND (inner, 1);
+ if (integer_zerop (moff))
+ moff = NULL_TREE;
+ }
+ else
+ return;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
+ return;
+ bytepos = bitpos / BITS_PER_UNIT;
+ if (offset == NULL_TREE && bytepos == 0 && moff == NULL_TREE)
+ return;
+
+ tree base_addr = base;
+ if (decl_p)
+ base_addr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (base)), base);
+ t = offset;
+ if (bytepos)
+ {
+ if (t)
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
+ build_int_cst (TREE_TYPE (t), bytepos));
+ else
+ t = size_int (bytepos);
+ }
+ if (moff)
+ {
+ if (t)
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
+ fold_convert (TREE_TYPE (t), moff));
+ else
+ t = fold_convert (sizetype, moff);
+ }
+ t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
+ GSI_SAME_STMT);
+ base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
+ GSI_SAME_STMT);
+ instrument_pointer_overflow (gsi, base_addr, t);
+}
+
/* Build an ubsan builtin call for the signed-integer-overflow
sanitization. CODE says what kind of builtin are we building,
LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
@@ -1847,7 +2121,7 @@ instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
{
tree rhs1 = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (rhs1) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
break;
else
base = rhs1;
@@ -1971,7 +2245,8 @@ public:
| SANITIZE_ALIGNMENT
| SANITIZE_NONNULL_ATTRIBUTE
| SANITIZE_RETURNS_NONNULL_ATTRIBUTE
- | SANITIZE_OBJECT_SIZE));
+ | SANITIZE_OBJECT_SIZE
+ | SANITIZE_POINTER_OVERFLOW));
}
virtual unsigned int execute (function *);
@@ -2063,6 +2338,32 @@ pass_ubsan::execute (function *fun)
}
}
+ if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
+ {
+ if (is_gimple_assign (stmt)
+ && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+ instrument_pointer_overflow (&gsi,
+ gimple_assign_rhs1 (stmt),
+ gimple_assign_rhs2 (stmt));
+ if (gimple_store_p (stmt))
+ maybe_instrument_pointer_overflow (&gsi,
+ gimple_get_lhs (stmt));
+ if (gimple_assign_single_p (stmt))
+ maybe_instrument_pointer_overflow (&gsi,
+ gimple_assign_rhs1 (stmt));
+ if (is_gimple_call (stmt))
+ {
+ unsigned args_num = gimple_call_num_args (stmt);
+ for (unsigned i = 0; i < args_num; ++i)
+ {
+ tree arg = gimple_call_arg (stmt, i);
+ if (is_gimple_reg (arg))
+ continue;
+ maybe_instrument_pointer_overflow (&gsi, arg);
+ }
+ }
+ }
+
gsi_next (&gsi);
}
if (gimple_purge_dead_eh_edges (bb))
diff --git a/gcc/ubsan.h b/gcc/ubsan.h
index 8d990b6a4b3..20a33473689 100644
--- a/gcc/ubsan.h
+++ b/gcc/ubsan.h
@@ -52,6 +52,7 @@ enum ubsan_encode_value_phase {
extern bool ubsan_expand_bounds_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_null_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_objsize_ifn (gimple_stmt_iterator *);
+extern bool ubsan_expand_ptr_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_vptr_ifn (gimple_stmt_iterator *);
extern bool ubsan_instrument_unreachable (gimple_stmt_iterator *);
extern tree ubsan_create_data (const char *, int, const location_t *, ...);
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 56ec9fe570b..23b8dc26471 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -104,11 +104,6 @@ along with GCC; see the file COPYING3. If not see
and gimple_value_profile_transformations table-driven, perhaps...
*/
-static tree gimple_divmod_fixed_value (gassign *, tree, int, gcov_type,
- gcov_type);
-static tree gimple_mod_pow2 (gassign *, int, gcov_type, gcov_type);
-static tree gimple_mod_subtract (gassign *, int, int, int, gcov_type,
- gcov_type, gcov_type);
static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
@@ -564,8 +559,6 @@ free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
{
histogram_value hist = *(histogram_value *) slot;
free (hist->hvalue.counters);
- if (flag_checking)
- memset (hist, 0xab, sizeof (*hist));
free (hist);
return 1;
}
@@ -695,7 +688,7 @@ gimple_value_profile_transformations (void)
alter the original STMT. */
static tree
-gimple_divmod_fixed_value (gassign *stmt, tree value, int prob,
+gimple_divmod_fixed_value (gassign *stmt, tree value, profile_probability prob,
gcov_type count, gcov_type all)
{
gassign *stmt1, *stmt2;
@@ -755,16 +748,16 @@ gimple_divmod_fixed_value (gassign *stmt, tree value, int prob,
e12->count = profile_count::from_gcov_type (count);
e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
- e13->probability = REG_BR_PROB_BASE - prob;
+ e13->probability = prob.invert ();
e13->count = profile_count::from_gcov_type (all - count);
remove_edge (e23);
e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
- e24->probability = REG_BR_PROB_BASE;
+ e24->probability = profile_probability::always ();
e24->count = profile_count::from_gcov_type (count);
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count);
return tmp2;
@@ -779,7 +772,7 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
enum tree_code code;
gcov_type val, count, all;
tree result, value, tree_val;
- gcov_type prob;
+ profile_probability prob;
gassign *stmt;
stmt = dyn_cast <gassign *> (gsi_stmt (*si));
@@ -818,9 +811,9 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
/* Compute probability of taking the optimal path. */
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT))
tree_val = build_int_cst (get_gcov_type (), val);
@@ -857,7 +850,7 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
the temp; it does not replace or alter the original STMT. */
static tree
-gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all)
+gimple_mod_pow2 (gassign *stmt, profile_probability prob, gcov_type count, gcov_type all)
{
gassign *stmt1, *stmt2, *stmt3;
gcond *stmt4;
@@ -920,16 +913,16 @@ gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all)
e12->count = profile_count::from_gcov_type (count);
e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
- e13->probability = REG_BR_PROB_BASE - prob;
+ e13->probability = prob.invert ();
e13->count = profile_count::from_gcov_type (all - count);
remove_edge (e23);
e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
- e24->probability = REG_BR_PROB_BASE;
+ e24->probability = profile_probability::always ();
e24->count = profile_count::from_gcov_type (count);
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count);
return result;
@@ -944,7 +937,7 @@ gimple_mod_pow2_value_transform (gimple_stmt_iterator *si)
enum tree_code code;
gcov_type count, wrong_values, all;
tree lhs_type, result, value;
- gcov_type prob;
+ profile_probability prob;
gassign *stmt;
stmt = dyn_cast <gassign *> (gsi_stmt (*si));
@@ -989,9 +982,9 @@ gimple_mod_pow2_value_transform (gimple_stmt_iterator *si)
return false;
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
result = gimple_mod_pow2 (stmt, prob, count, all);
@@ -1011,7 +1004,8 @@ gimple_mod_pow2_value_transform (gimple_stmt_iterator *si)
/* FIXME: Generalize the interface to handle NCOUNTS > 1. */
static tree
-gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts,
+gimple_mod_subtract (gassign *stmt, profile_probability prob1,
+ profile_probability prob2, int ncounts,
gcov_type count1, gcov_type count2, gcov_type all)
{
gassign *stmt1;
@@ -1081,7 +1075,7 @@ gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts,
e12->flags &= ~EDGE_FALLTHRU;
e12->flags |= EDGE_FALSE_VALUE;
- e12->probability = REG_BR_PROB_BASE - prob1;
+ e12->probability = prob1.invert ();
e12->count = profile_count::from_gcov_type (all - count1);
e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
@@ -1093,14 +1087,14 @@ gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts,
e23->flags &= ~EDGE_FALLTHRU;
e23->flags |= EDGE_FALSE_VALUE;
e23->count = profile_count::from_gcov_type (all - count1 - count2);
- e23->probability = REG_BR_PROB_BASE - prob2;
+ e23->probability = prob2.invert ();
e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
e24->probability = prob2;
e24->count = profile_count::from_gcov_type (count2);
}
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count1 - count2);
return result;
@@ -1115,7 +1109,7 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si)
enum tree_code code;
gcov_type count, wrong_values, all;
tree lhs_type, result;
- gcov_type prob1, prob2;
+ profile_probability prob1, prob2;
unsigned int i, steps;
gcov_type count1, count2;
gassign *stmt;
@@ -1183,12 +1177,12 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si)
/* Compute probability of taking the optimal path(s). */
if (all > 0)
{
- prob1 = GCOV_COMPUTE_SCALE (count1, all);
- prob2 = GCOV_COMPUTE_SCALE (count2, all);
+ prob1 = profile_probability::probability_in_gcov_type (count1, all);
+ prob2 = profile_probability::probability_in_gcov_type (count2, all);
}
else
{
- prob1 = prob2 = 0;
+ prob1 = prob2 = profile_probability::never ();
}
/* In practice, "steps" is always 2. This interface reflects this,
@@ -1318,7 +1312,7 @@ check_ic_target (gcall *call_stmt, struct cgraph_node *target)
gcall *
gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
- int prob, profile_count count, profile_count all)
+ profile_probability prob, profile_count count, profile_count all)
{
gcall *dcall_stmt;
gassign *load_stmt;
@@ -1388,7 +1382,7 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
/* The indirect call might be noreturn. */
if (e_ij != NULL)
{
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
e_ij->count = all - count;
e_ij = single_pred_edge (split_edge (e_ij));
}
@@ -1404,7 +1398,7 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
e_cd->count = count;
e_ci = make_edge (cond_bb, icall_bb, EDGE_FALSE_VALUE);
- e_ci->probability = REG_BR_PROB_BASE - prob;
+ e_ci->probability = prob.invert ();
e_ci->count = all - count;
remove_edge (e_di);
@@ -1416,12 +1410,12 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
else
{
e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
- e_dj->probability = REG_BR_PROB_BASE;
+ e_dj->probability = profile_probability::always ();
e_dj->count = count;
e_ij->count = all - count;
}
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
}
/* Insert PHI node for the call result if necessary. */
@@ -1499,6 +1493,8 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
if (e_eh->flags & (EDGE_EH | EDGE_ABNORMAL))
{
e = make_edge (dcall_bb, e_eh->dest, e_eh->flags);
+ e->probability = e_eh->probability;
+ e->count = e_eh->count;
for (gphi_iterator psi = gsi_start_phis (e_eh->dest);
!gsi_end_p (psi); gsi_next (&psi))
{
@@ -1647,7 +1643,7 @@ interesting_stringop_to_profile_p (gcall *call, int *size_arg)
assuming we'll propagate a true constant into ICALL_SIZE later. */
static void
-gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob,
+gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probability prob,
gcov_type count, gcov_type all)
{
gassign *tmp_stmt;
@@ -1711,16 +1707,16 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob,
e_ci->count = profile_count::from_gcov_type (count);
e_cv = make_edge (cond_bb, vcall_bb, EDGE_FALSE_VALUE);
- e_cv->probability = REG_BR_PROB_BASE - prob;
+ e_cv->probability = prob.invert ();
e_cv->count = profile_count::from_gcov_type (all - count);
remove_edge (e_iv);
e_ij = make_edge (icall_bb, join_bb, EDGE_FALLTHRU);
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
e_ij->count = profile_count::from_gcov_type (count);
- e_vj->probability = REG_BR_PROB_BASE;
+ e_vj->probability = profile_probability::always ();
e_vj->count = profile_count::from_gcov_type (all - count);
/* Insert PHI node for the call result if necessary. */
@@ -1755,7 +1751,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
gcov_type count, all, val;
tree dest, src;
unsigned int dest_align, src_align;
- gcov_type prob;
+ profile_probability prob;
tree tree_val;
int size_arg;
@@ -1790,9 +1786,9 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count))
return false;
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
dest = gimple_call_arg (stmt, 0);
dest_align = get_pointer_alignment (dest);
diff --git a/gcc/value-prof.h b/gcc/value-prof.h
index 92649ecd322..f72bb2d2241 100644
--- a/gcc/value-prof.h
+++ b/gcc/value-prof.h
@@ -90,8 +90,8 @@ void gimple_move_stmt_histograms (struct function *, gimple *, gimple *);
void verify_histograms (void);
void free_histograms (function *);
void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
-gcall *gimple_ic (gcall *, struct cgraph_node *, int, profile_count,
- profile_count);
+gcall *gimple_ic (gcall *, struct cgraph_node *, profile_probability,
+ profile_count, profile_count);
bool check_ic_target (gcall *, struct cgraph_node *);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index fbaebc1b5c0..6eccbe4b3f7 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1825,6 +1825,46 @@ assemble_start_function (tree decl, const char *fnname)
if (DECL_PRESERVE_P (decl))
targetm.asm_out.mark_decl_preserved (fnname);
+ unsigned HOST_WIDE_INT patch_area_size = function_entry_patch_area_size;
+ unsigned HOST_WIDE_INT patch_area_entry = function_entry_patch_area_start;
+
+ tree patchable_function_entry_attr
+ = lookup_attribute ("patchable_function_entry", DECL_ATTRIBUTES (decl));
+ if (patchable_function_entry_attr)
+ {
+ tree pp_val = TREE_VALUE (patchable_function_entry_attr);
+ tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
+
+ if (tree_fits_uhwi_p (patchable_function_entry_value1))
+ patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
+ else
+ gcc_unreachable ();
+
+ patch_area_entry = 0;
+ if (list_length (pp_val) > 1)
+ {
+ tree patchable_function_entry_value2 =
+ TREE_VALUE (TREE_CHAIN (pp_val));
+
+ if (tree_fits_uhwi_p (patchable_function_entry_value2))
+ patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
+ else
+ gcc_unreachable ();
+ }
+ }
+
+ if (patch_area_entry > patch_area_size)
+ {
+ if (patch_area_size > 0)
+ warning (OPT_Wattributes, "Patchable function entry > size");
+ patch_area_entry = 0;
+ }
+
+ /* Emit the patching area before the entry label, if any. */
+ if (patch_area_entry > 0)
+ targetm.asm_out.print_patchable_function_entry (asm_out_file,
+ patch_area_entry, true);
+
/* Do any machine/system dependent processing of the function name. */
#ifdef ASM_DECLARE_FUNCTION_NAME
ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
@@ -1833,6 +1873,12 @@ assemble_start_function (tree decl, const char *fnname)
ASM_OUTPUT_FUNCTION_LABEL (asm_out_file, fnname, current_function_decl);
#endif /* ASM_DECLARE_FUNCTION_NAME */
+ /* And the area after the label. Record it if we haven't done so yet. */
+ if (patch_area_size > patch_area_entry)
+ targetm.asm_out.print_patchable_function_entry (asm_out_file,
+ patch_area_size-patch_area_entry,
+ patch_area_entry == 0);
+
if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl)))
saw_no_split_stack = true;
}
@@ -2403,7 +2449,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
gcc_assert (asm_out_file);
/* In a perfect world, the following condition would be true.
- Sadly, the Java and Go front ends emit assembly *from the front end*,
+ Sadly, the Go front end emit assembly *from the front end*,
bypassing the call graph. See PR52739. Fix before GCC 4.8. */
#if 0
/* This function should only be called if we are expanding, or have
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 41928a400a9..42300e2d538 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -197,7 +197,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
vmsdbgout_early_global_decl,
vmsdbgout_late_global_decl,
vmsdbgout_type_decl, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool, /* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
vmsdbgout_abstract_function,
debug_nothing_rtx_code_label, /* label */
diff --git a/gcc/wide-int-print.cc b/gcc/wide-int-print.cc
index c67b1a08bbf..36d8ad863f5 100644
--- a/gcc/wide-int-print.cc
+++ b/gcc/wide-int-print.cc
@@ -21,7 +21,6 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "wide-int-print.h"
/*
* public printing routines.
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index dab4c194f23..71e24ec22af 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "selftest.h"
-#include "wide-int-print.h"
#define HOST_BITS_PER_HALF_WIDE_INT 32
diff --git a/gcc/xcoffout.c b/gcc/xcoffout.c
index c6eab21a55d..17b201aced6 100644
--- a/gcc/xcoffout.c
+++ b/gcc/xcoffout.c
@@ -143,7 +143,7 @@ static const struct xcoff_type_number xcoff_type_numbers[] = {
{ "float", -12 },
{ "double", -13 },
{ "long double", -14 },
- /* Pascal and Fortran types run from -15 to -29. */
+ /* Fortran types run from -15 to -29. */
{ "wchar", -30 }, /* XXX Should be "wchar_t" ? */
{ "long long int", -31 },
{ "long long unsigned int", -32 },
diff --git a/gotools/ChangeLog b/gotools/ChangeLog
index 9fbc221bb90..18cbf119933 100644
--- a/gotools/ChangeLog
+++ b/gotools/ChangeLog
@@ -1,3 +1,36 @@
+2017-07-26 Ian Lance Taylor <iant@golang.org>
+
+ PR go/81548
+ * Makefile.am (MOSTLYCLEANFILES): Add *.sent.
+ * Makefile.in: Rebuild.
+
+2017-07-15 Ian Lance Taylor <iant@golang.org>
+
+ * Makefile.am (CHECK_ENV): Set GOROOT.
+ (ECHO_ENV): Report setting GOROOT.
+ * Makefile.in: Rebuild.
+
+2017-06-29 Ian Lance Taylor <iant@golang.org>
+
+ * Makefile.am (MOSTLYCLEANFILES): Remove testing files and logs.
+ (mostlyclean-local): Remove check-runtime-dir, cgo-test-dir,
+ carchive-test-dir.
+ (ECHO_ENV): Define.
+ (check-go-tool): Depend on cgo. Write command to testlog.
+ (check-runtime): New target.
+ (check-cgo-test): New target.
+ (check-carchive-test): New target.
+ (check): Depend on check-runtime, check-cgo-test,
+ check-carchive-test. Add @ to prettify output.
+ (.PHONY): Add check-runtime, check-cgo-test, check-carchive-test.
+ * Makefile.in: Rebuild.
+
+2017-06-26 Ian Lance Taylor <iant@golang.org>
+
+ * Makefile.am (s-zdefaultcc): Don't record $(bindir) for defaultCC
+ or defaultCXX.
+ * Makefile.in: Rebuild.
+
2017-06-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* Makefile.am (check-go-tool): Don't use >& for I/O redirection.
diff --git a/gotools/Makefile.am b/gotools/Makefile.am
index 010c5bb554b..b9dced4a5d7 100644
--- a/gotools/Makefile.am
+++ b/gotools/Makefile.am
@@ -44,6 +44,7 @@ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
libgosrcdir = $(srcdir)/../libgo/go
cmdsrcdir = $(libgosrcdir)/cmd
+libgomiscdir = $(srcdir)/../libgo/misc
go_cmd_go_files = \
$(cmdsrcdir)/go/alldocs.go \
@@ -100,13 +101,18 @@ zdefaultcc.go: s-zdefaultcc; @true
s-zdefaultcc: Makefile
echo 'package main' > zdefaultcc.go.tmp
echo 'const defaultGCCGO = "$(bindir)/$(GCCGO_INSTALL_NAME)"' >> zdefaultcc.go.tmp
- echo 'const defaultCC = "$(bindir)/$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
- echo 'const defaultCXX = "$(bindir)/$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const defaultCC = "$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const defaultCXX = "$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
echo 'const defaultPkgConfig = "pkg-config"' >> zdefaultcc.go.tmp
$(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go
$(STAMP) $@
-MOSTLYCLEANFILES = zdefaultcc.go s-zdefaultcc
+MOSTLYCLEANFILES = \
+ zdefaultcc.go s-zdefaultcc \
+ check-gccgo gotools.head *-testlog gotools.sum gotools.log *.sent
+
+mostlyclean-local:
+ rm -rf check-go-dir check-runtime-dir cgo-test-dir carchive-test-dir
if NATIVE
@@ -156,6 +162,7 @@ check-gccgo: Makefile
chmod +x $@
# CHECK_ENV sets up the environment to run the newly built go tool.
+# If you change this, change ECHO_ENV, below.
CHECK_ENV = \
PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
export PATH; \
@@ -167,27 +174,85 @@ CHECK_ENV = \
export GO_TESTING_GOTOOLS; \
abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
- export LD_LIBRARY_PATH;
+ export LD_LIBRARY_PATH; \
+ GOROOT=$${abs_libgodir}; \
+ export GOROOT;
+
+# ECHO_ENV is a variant of CHECK_ENV to put into a testlog file.
+# It assumes that abs_libgodir is set.
+ECHO_ENV = PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'` GCCGO='$(abs_builddir)/check-gccgo' GCCGOTOOLDIR='$(abs_builddir)' GO_TESTING_GOTOOLS=yes LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'` GOROOT=`echo $${abs_libgodir}`
# check-go-tools runs `go test cmd/go` in our environment.
-check-go-tool: go$(EXEEXT) check-head check-gccgo
- rm -rf check-go-dir
+check-go-tool: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+ rm -rf check-go-dir cmd_go-testlog
$(MKDIR_P) check-go-dir/src/cmd/go
cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/
cp zdefaultcc.go check-go-dir/src/cmd/go/
cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
+ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+ abs_checkdir=`cd check-go-dir && $(PWD_COMMAND)`; \
+ echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_go-testlog
$(CHECK_ENV) \
GOPATH=`cd check-go-dir && $(PWD_COMMAND)`; \
export GOPATH; \
(cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) > cmd_go-testlog 2>&1 || true
grep '^--- ' cmd_go-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+# check-runtime runs `go test runtime` in our environment.
+# The runtime package is also tested as part of libgo,
+# but the runtime tests use the go tool heavily, so testing
+# here too will catch more problems.
+check-runtime: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+ rm -rf check-runtime-dir runtime-testlog
+ $(MKDIR_P) check-runtime-dir
+ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+ LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+ GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
+ GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
+ files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
+ echo "$(ECHO_ENV) GC='$(abs_builddir)/check-gccgo -fgo-compiling-runtime' GOARCH=$${GOARCH} GOOS=$${GOOS} $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles='$${files}' -test.v" > runtime-testlog
+ $(CHECK_ENV) \
+ GC="$${GCCGO} -fgo-compiling-runtime"; \
+ export GC; \
+ GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
+ GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
+ files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
+ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || true
+ grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
+# check-cgo-test runs `go test misc/cgo/test` in our environment.
+check-cgo-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+ rm -rf cgo-test-dir cgo-testlog
+ $(MKDIR_P) cgo-test-dir/misc/cgo
+ cp -r $(libgomiscdir)/cgo/test cgo-test-dir/misc/cgo/
+ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+ echo "cd cgo-test-dir/misc/cgo/test && $(ECHO_ENV) GOTRACEBACK=2 $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cgo-testlog
+ $(CHECK_ENV) \
+ GOTRACEBACK=2; \
+ export GOTRACEBACK; \
+ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || true
+ grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
+# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
+# in our environment.
+check-carchive-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+ rm -rf carchive-test-dir carchive-testlog
+ $(MKDIR_P) carchive-test-dir/misc/cgo
+ cp -r $(libgomiscdir)/cgo/testcarchive carchive-test-dir/misc/cgo/
+ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+ echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go" > carchive-testlog
+ $(CHECK_ENV) \
+ LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+ export LIBRARY_PATH; \
+ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go) >> carchive-testlog 2>&1 || true
+ grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
# The check targets runs the tests and assembles the output files.
-check: check-head check-go-tool
- mv gotools.head gotools.sum
- cp gotools.sum gotools.log
- for file in cmd_go-testlog; do \
+check: check-head check-go-tool check-runtime check-cgo-test check-carchive-test
+ @mv gotools.head gotools.sum
+ @cp gotools.sum gotools.log
+ @for file in cmd_go-testlog runtime-testlog cgo-testlog carchive-testlog; do \
testname=`echo $${file} | sed -e 's/-testlog//' -e 's|_|/|'`; \
echo "Running $${testname}" >> gotools.sum; \
echo "Running $${testname}" >> gotools.log; \
@@ -196,24 +261,24 @@ check: check-head check-go-tool
done
@echo >> gotools.sum
@echo " === gotools Summary ===" >> gotools.sum
- pass=`grep -c '^PASS' gotools.sum`; \
+ @pass=`grep -c '^PASS' gotools.sum`; \
if test "$${pass}" -ne "0"; then \
echo "# of expected passes $${pass}" >> gotools.sum; \
fi
- fail=`grep -c '^FAIL' gotools.sum`; \
+ @fail=`grep -c '^FAIL' gotools.sum`; \
if test "$${fail}" -ne "0"; then \
echo "# of unexpected failures $${fail}" >> gotools.sum; \
fi
- untested=`grep -c '^UNTESTED' gotools.sum`; \
+ @untested=`grep -c '^UNTESTED' gotools.sum`; \
if test "$${untested}" -ne "0"; then \
echo "# of untested testcases $${untested}" >> gotools.sum; \
fi
- echo `echo $(GOC_FOR_TARGET) | sed -e 's/ .*//'` `$(GOC_FOR_TARGET) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> gotools.sum
- echo >> gotools.log
- echo "runtest completed at `date`" >> gotools.log
- if grep '^FAIL' gotools.sum >/dev/null 2>&1; then exit 1; fi
+ @echo `echo $(GOC_FOR_TARGET) | sed -e 's/ .*//'` `$(GOC_FOR_TARGET) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> gotools.sum
+ @echo >> gotools.log
+ @echo "runtest completed at `date`" >> gotools.log
+ @if grep '^FAIL' gotools.sum >/dev/null 2>&1; then exit 1; fi
-.PHONY: check check-head check-go-tool
+.PHONY: check check-head check-go-tool check-runtime check-cgo-test check-carchive-test
else
@@ -224,6 +289,3 @@ else
# the go/build package. Figure this out later.
endif
-
-mostlyclean-local:
- rm -rf check-go-dir
diff --git a/gotools/Makefile.in b/gotools/Makefile.in
index b57d89a9230..9c0084e2e18 100644
--- a/gotools/Makefile.in
+++ b/gotools/Makefile.in
@@ -263,6 +263,7 @@ AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
libgosrcdir = $(srcdir)/../libgo/go
cmdsrcdir = $(libgosrcdir)/cmd
+libgomiscdir = $(srcdir)/../libgo/misc
go_cmd_go_files = \
$(cmdsrcdir)/go/alldocs.go \
$(cmdsrcdir)/go/bug.go \
@@ -313,7 +314,10 @@ go_cmd_cgo_files = \
GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)')
GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)')
GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)')
-MOSTLYCLEANFILES = zdefaultcc.go s-zdefaultcc
+MOSTLYCLEANFILES = \
+ zdefaultcc.go s-zdefaultcc \
+ check-gccgo gotools.head *-testlog gotools.sum gotools.log *.sent
+
# For a native build we build the programs using the newly built libgo
# and install them as regular programs.
@@ -322,6 +326,7 @@ MOSTLYCLEANFILES = zdefaultcc.go s-zdefaultcc
@NATIVE_TRUE@man_MANS = go.1 gofmt.1
# CHECK_ENV sets up the environment to run the newly built go tool.
+# If you change this, change ECHO_ENV, below.
@NATIVE_TRUE@CHECK_ENV = \
@NATIVE_TRUE@ PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
@NATIVE_TRUE@ export PATH; \
@@ -333,8 +338,14 @@ MOSTLYCLEANFILES = zdefaultcc.go s-zdefaultcc
@NATIVE_TRUE@ export GO_TESTING_GOTOOLS; \
@NATIVE_TRUE@ abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
@NATIVE_TRUE@ LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
-@NATIVE_TRUE@ export LD_LIBRARY_PATH;
+@NATIVE_TRUE@ export LD_LIBRARY_PATH; \
+@NATIVE_TRUE@ GOROOT=$${abs_libgodir}; \
+@NATIVE_TRUE@ export GOROOT;
+
+# ECHO_ENV is a variant of CHECK_ENV to put into a testlog file.
+# It assumes that abs_libgodir is set.
+@NATIVE_TRUE@ECHO_ENV = PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'` GCCGO='$(abs_builddir)/check-gccgo' GCCGOTOOLDIR='$(abs_builddir)' GO_TESTING_GOTOOLS=yes LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'` GOROOT=`echo $${abs_libgodir}`
all: all-am
.SUFFIXES:
@@ -682,12 +693,15 @@ zdefaultcc.go: s-zdefaultcc; @true
s-zdefaultcc: Makefile
echo 'package main' > zdefaultcc.go.tmp
echo 'const defaultGCCGO = "$(bindir)/$(GCCGO_INSTALL_NAME)"' >> zdefaultcc.go.tmp
- echo 'const defaultCC = "$(bindir)/$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
- echo 'const defaultCXX = "$(bindir)/$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const defaultCC = "$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const defaultCXX = "$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
echo 'const defaultPkgConfig = "pkg-config"' >> zdefaultcc.go.tmp
$(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go
$(STAMP) $@
+mostlyclean-local:
+ rm -rf check-go-dir check-runtime-dir cgo-test-dir carchive-test-dir
+
@NATIVE_TRUE@go$(EXEEXT): $(go_cmd_go_files) zdefaultcc.go $(LIBGODEP)
@NATIVE_TRUE@ $(GOLINK) $(go_cmd_go_files) zdefaultcc.go $(LIBS) $(NET_LIBS)
@NATIVE_TRUE@gofmt$(EXEEXT): $(go_cmd_gofmt_files) $(LIBGODEP)
@@ -727,24 +741,76 @@ s-zdefaultcc: Makefile
@NATIVE_TRUE@ chmod +x $@
# check-go-tools runs `go test cmd/go` in our environment.
-@NATIVE_TRUE@check-go-tool: go$(EXEEXT) check-head check-gccgo
-@NATIVE_TRUE@ rm -rf check-go-dir
+@NATIVE_TRUE@check-go-tool: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+@NATIVE_TRUE@ rm -rf check-go-dir cmd_go-testlog
@NATIVE_TRUE@ $(MKDIR_P) check-go-dir/src/cmd/go
@NATIVE_TRUE@ cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
@NATIVE_TRUE@ cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/
@NATIVE_TRUE@ cp zdefaultcc.go check-go-dir/src/cmd/go/
@NATIVE_TRUE@ cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
+@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+@NATIVE_TRUE@ abs_checkdir=`cd check-go-dir && $(PWD_COMMAND)`; \
+@NATIVE_TRUE@ echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_go-testlog
@NATIVE_TRUE@ $(CHECK_ENV) \
@NATIVE_TRUE@ GOPATH=`cd check-go-dir && $(PWD_COMMAND)`; \
@NATIVE_TRUE@ export GOPATH; \
@NATIVE_TRUE@ (cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) > cmd_go-testlog 2>&1 || true
@NATIVE_TRUE@ grep '^--- ' cmd_go-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+# check-runtime runs `go test runtime` in our environment.
+# The runtime package is also tested as part of libgo,
+# but the runtime tests use the go tool heavily, so testing
+# here too will catch more problems.
+@NATIVE_TRUE@check-runtime: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+@NATIVE_TRUE@ rm -rf check-runtime-dir runtime-testlog
+@NATIVE_TRUE@ $(MKDIR_P) check-runtime-dir
+@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+@NATIVE_TRUE@ LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+@NATIVE_TRUE@ GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
+@NATIVE_TRUE@ GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
+@NATIVE_TRUE@ files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
+@NATIVE_TRUE@ echo "$(ECHO_ENV) GC='$(abs_builddir)/check-gccgo -fgo-compiling-runtime' GOARCH=$${GOARCH} GOOS=$${GOOS} $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles='$${files}' -test.v" > runtime-testlog
+@NATIVE_TRUE@ $(CHECK_ENV) \
+@NATIVE_TRUE@ GC="$${GCCGO} -fgo-compiling-runtime"; \
+@NATIVE_TRUE@ export GC; \
+@NATIVE_TRUE@ GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
+@NATIVE_TRUE@ GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
+@NATIVE_TRUE@ files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
+@NATIVE_TRUE@ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || true
+@NATIVE_TRUE@ grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
+# check-cgo-test runs `go test misc/cgo/test` in our environment.
+@NATIVE_TRUE@check-cgo-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+@NATIVE_TRUE@ rm -rf cgo-test-dir cgo-testlog
+@NATIVE_TRUE@ $(MKDIR_P) cgo-test-dir/misc/cgo
+@NATIVE_TRUE@ cp -r $(libgomiscdir)/cgo/test cgo-test-dir/misc/cgo/
+@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+@NATIVE_TRUE@ echo "cd cgo-test-dir/misc/cgo/test && $(ECHO_ENV) GOTRACEBACK=2 $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cgo-testlog
+@NATIVE_TRUE@ $(CHECK_ENV) \
+@NATIVE_TRUE@ GOTRACEBACK=2; \
+@NATIVE_TRUE@ export GOTRACEBACK; \
+@NATIVE_TRUE@ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || true
+@NATIVE_TRUE@ grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
+# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
+# in our environment.
+@NATIVE_TRUE@check-carchive-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo
+@NATIVE_TRUE@ rm -rf carchive-test-dir carchive-testlog
+@NATIVE_TRUE@ $(MKDIR_P) carchive-test-dir/misc/cgo
+@NATIVE_TRUE@ cp -r $(libgomiscdir)/cgo/testcarchive carchive-test-dir/misc/cgo/
+@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
+@NATIVE_TRUE@ echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go" > carchive-testlog
+@NATIVE_TRUE@ $(CHECK_ENV) \
+@NATIVE_TRUE@ LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
+@NATIVE_TRUE@ export LIBRARY_PATH; \
+@NATIVE_TRUE@ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go) >> carchive-testlog 2>&1 || true
+@NATIVE_TRUE@ grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
+
# The check targets runs the tests and assembles the output files.
-@NATIVE_TRUE@check: check-head check-go-tool
-@NATIVE_TRUE@ mv gotools.head gotools.sum
-@NATIVE_TRUE@ cp gotools.sum gotools.log
-@NATIVE_TRUE@ for file in cmd_go-testlog; do \
+@NATIVE_TRUE@check: check-head check-go-tool check-runtime check-cgo-test check-carchive-test
+@NATIVE_TRUE@ @mv gotools.head gotools.sum
+@NATIVE_TRUE@ @cp gotools.sum gotools.log
+@NATIVE_TRUE@ @for file in cmd_go-testlog runtime-testlog cgo-testlog carchive-testlog; do \
@NATIVE_TRUE@ testname=`echo $${file} | sed -e 's/-testlog//' -e 's|_|/|'`; \
@NATIVE_TRUE@ echo "Running $${testname}" >> gotools.sum; \
@NATIVE_TRUE@ echo "Running $${testname}" >> gotools.log; \
@@ -753,24 +819,24 @@ s-zdefaultcc: Makefile
@NATIVE_TRUE@ done
@NATIVE_TRUE@ @echo >> gotools.sum
@NATIVE_TRUE@ @echo " === gotools Summary ===" >> gotools.sum
-@NATIVE_TRUE@ pass=`grep -c '^PASS' gotools.sum`; \
+@NATIVE_TRUE@ @pass=`grep -c '^PASS' gotools.sum`; \
@NATIVE_TRUE@ if test "$${pass}" -ne "0"; then \
@NATIVE_TRUE@ echo "# of expected passes $${pass}" >> gotools.sum; \
@NATIVE_TRUE@ fi
-@NATIVE_TRUE@ fail=`grep -c '^FAIL' gotools.sum`; \
+@NATIVE_TRUE@ @fail=`grep -c '^FAIL' gotools.sum`; \
@NATIVE_TRUE@ if test "$${fail}" -ne "0"; then \
@NATIVE_TRUE@ echo "# of unexpected failures $${fail}" >> gotools.sum; \
@NATIVE_TRUE@ fi
-@NATIVE_TRUE@ untested=`grep -c '^UNTESTED' gotools.sum`; \
+@NATIVE_TRUE@ @untested=`grep -c '^UNTESTED' gotools.sum`; \
@NATIVE_TRUE@ if test "$${untested}" -ne "0"; then \
@NATIVE_TRUE@ echo "# of untested testcases $${untested}" >> gotools.sum; \
@NATIVE_TRUE@ fi
-@NATIVE_TRUE@ echo `echo $(GOC_FOR_TARGET) | sed -e 's/ .*//'` `$(GOC_FOR_TARGET) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> gotools.sum
-@NATIVE_TRUE@ echo >> gotools.log
-@NATIVE_TRUE@ echo "runtest completed at `date`" >> gotools.log
-@NATIVE_TRUE@ if grep '^FAIL' gotools.sum >/dev/null 2>&1; then exit 1; fi
+@NATIVE_TRUE@ @echo `echo $(GOC_FOR_TARGET) | sed -e 's/ .*//'` `$(GOC_FOR_TARGET) -v 2>&1 | grep " version" | sed -n -e 's/.* \(version.*$$\)/\1/p'` >> gotools.sum
+@NATIVE_TRUE@ @echo >> gotools.log
+@NATIVE_TRUE@ @echo "runtest completed at `date`" >> gotools.log
+@NATIVE_TRUE@ @if grep '^FAIL' gotools.sum >/dev/null 2>&1; then exit 1; fi
-@NATIVE_TRUE@.PHONY: check check-head check-go-tool
+@NATIVE_TRUE@.PHONY: check check-head check-go-tool check-runtime check-cgo-test check-carchive-test
# For a non-native build we have to build the programs using a
# previously built host (or build -> host) Go compiler. We should
@@ -778,9 +844,6 @@ s-zdefaultcc: Makefile
# the right values for GOARCH and GOOS in the default build context in
# the go/build package. Figure this out later.
-mostlyclean-local:
- rm -rf check-go-dir
-
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/include/ChangeLog b/include/ChangeLog
index 47318dac9f0..bbcc87d418b 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,16 @@
+2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * dwarf2.def (DW_IDX_compile_unit, DW_IDX_type_unit, DW_IDX_die_offset)
+ (DW_IDX_parent, DW_IDX_type_hash, DW_IDX_lo_user, DW_IDX_hi_user)
+ (DW_IDX_GNU_internal, DW_IDX_GNU_external): New.
+ * dwarf2.h (DW_IDX, DW_IDX_DUP, DW_FIRST_IDX, DW_END_IDX): New.
+ (enum dwarf_name_index_attribute): Remove.
+ (get_DW_IDX_name): New declaration.
+
+2017-05-27 Maya Rashish <coypu@sdf.org>
+
+ * longlong.h: Remove ns32k support.
+
2017-05-24 Nathan Sidwell <nathan@acm.org>
* libiberty.h (ASTRDUP): Adjust cast to avoid warning.
diff --git a/include/dwarf2.def b/include/dwarf2.def
index ea6194ef33e..a91e9439cd8 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -782,3 +782,15 @@ DW_CFA (DW_CFA_GNU_args_size, 0x2e)
DW_CFA (DW_CFA_GNU_negative_offset_extended, 0x2f)
DW_END_CFA
+
+/* Index attributes in the Abbreviations Table. */
+DW_FIRST_IDX (DW_IDX_compile_unit, 1)
+DW_IDX (DW_IDX_type_unit, 2)
+DW_IDX (DW_IDX_die_offset, 3)
+DW_IDX (DW_IDX_parent, 4)
+DW_IDX (DW_IDX_type_hash, 5)
+DW_IDX_DUP (DW_IDX_lo_user, 0x2000)
+DW_IDX (DW_IDX_hi_user, 0x3fff)
+DW_IDX (DW_IDX_GNU_internal, 0x2000)
+DW_IDX (DW_IDX_GNU_external, 0x2001)
+DW_END_IDX
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 9c788803e49..14b6f22e39e 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -52,6 +52,8 @@
#define DW_ATE(name, value) , name = value
#define DW_ATE_DUP(name, value) , name = value
#define DW_CFA(name, value) , name = value
+#define DW_IDX(name, value) , name = value
+#define DW_IDX_DUP(name, value) , name = value
#define DW_FIRST_TAG(name, value) enum dwarf_tag { \
name = value
@@ -71,6 +73,9 @@
#define DW_FIRST_CFA(name, value) enum dwarf_call_frame_info { \
name = value
#define DW_END_CFA };
+#define DW_FIRST_IDX(name, value) enum dwarf_name_index_attribute { \
+ name = value
+#define DW_END_IDX };
#include "dwarf2.def"
@@ -86,6 +91,8 @@
#undef DW_END_ATE
#undef DW_FIRST_CFA
#undef DW_END_CFA
+#undef DW_FIRST_IDX
+#undef DW_END_IDX
#undef DW_TAG
#undef DW_TAG_DUP
@@ -97,6 +104,8 @@
#undef DW_ATE
#undef DW_ATE_DUP
#undef DW_CFA
+#undef DW_IDX
+#undef DW_IDX_DUP
/* Flag that tells whether entry has a child or not. */
#define DW_children_no 0
@@ -420,18 +429,6 @@ enum dwarf_macro_record_type
DW_MACRO_GNU_hi_user = 0xff
};
-/* Index attributes in the Abbreviations Table. */
-enum dwarf_name_index_attribute
- {
- DW_IDX_compile_unit = 1,
- DW_IDX_type_unit = 2,
- DW_IDX_die_offset = 3,
- DW_IDX_parent = 4,
- DW_IDX_type_hash = 5,
- DW_IDX_lo_user = 0x2000,
- DW_IDX_hi_user = 0x3fff
- };
-
/* Range list entry kinds in .debug_rnglists* section. */
enum dwarf_range_list_entry
{
@@ -524,6 +521,10 @@ extern const char *get_DW_ATE_name (unsigned int enc);
recognized. */
extern const char *get_DW_CFA_name (unsigned int opc);
+/* Return the name of a DW_IDX_ constant, or NULL if the value is not
+ recognized. */
+extern const char *get_DW_IDX_name (unsigned int idx);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/include/longlong.h b/include/longlong.h
index 9d3ab21be2d..c24568acea0 100644
--- a/include/longlong.h
+++ b/include/longlong.h
@@ -858,42 +858,6 @@ extern UDItype __umulsidi3 (USItype, USItype);
#endif
#endif /* __mips__ */
-#if defined (__ns32000__) && W_TYPE_SIZE == 32
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("meid %2,%0" \
- : "=g" (__xx.__ll) \
- : "%0" ((USItype) (u)), \
- "g" ((USItype) (v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define __umulsidi3(u, v) \
- ({UDItype __w; \
- __asm__ ("meid %2,%0" \
- : "=g" (__w) \
- : "%0" ((USItype) (u)), \
- "g" ((USItype) (v))); \
- __w; })
-#define udiv_qrnnd(q, r, n1, n0, d) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
- __asm__ ("deid %2,%0" \
- : "=g" (__xx.__ll) \
- : "0" (__xx.__ll), \
- "g" ((USItype) (d))); \
- (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
-#define count_trailing_zeros(count,x) \
- do { \
- __asm__ ("ffsd %2,%0" \
- : "=r" ((USItype) (count)) \
- : "0" ((USItype) 0), \
- "r" ((USItype) (x))); \
- } while (0)
-#endif /* __ns32000__ */
-
/* FIXME: We should test _IBMR2 here when we add assembly support for the
system vendor compilers.
FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good
diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index eb9bb6ab889..313a4c61855 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,28 @@
+2017-07-28 Tony Reix <tony.reix@atos.net>
+
+ * xcoff.c: Don't leak a file descriptor if an archive is malformed.
+
+2017-07-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * fileline.c (fileline_initialize): Print pid_t as long.
+
+2017-07-26 Tony Reix <tony.reix@atos.net>
+
+ * configure.ac: Check for XCOFF32/XCOFF64. Check for loadquery.
+ * filetype.awk: Separate AIX XCOFF32 and XCOFF64.
+ * xcoff.c: Add support for AIX XCOFF32 and XCOFF64 formats.
+ * configure, config.h.in: Regenerate.
+
+2017-07-21 Tony Reix <tony.reix@atos.net>
+
+ * filetype.awk: Add AIX XCOFF type detection.
+ * configure.ac: Recognize xcoff format.
+ * Makefile.am (FORMAT_FILES): Add xcoff.c.
+ * fileline.c: Include <unistd.h>.
+ (fileline_initialize): Add case for AIX procfs.
+ * xcoff.c: New file.
+ * configure, Makefile.in: Rebuild.
+
2017-06-21 Richard Biener <rguenther@suse.de>
* configure.ac: Add AC_SYS_LARGEFILE.
diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 640eeec5e22..b91d6bca2d6 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -57,7 +57,8 @@ BACKTRACE_FILES = \
FORMAT_FILES = \
elf.c \
pecoff.c \
- unknown.c
+ unknown.c \
+ xcoff.c
VIEW_FILES = \
read.c \
@@ -155,3 +156,5 @@ sort.lo: config.h backtrace.h internal.h
stest.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h
+xcoff.lo: config.h backtrace.h internal.h
+
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index a57dc235b33..5b2159d77ba 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -319,7 +319,8 @@ BACKTRACE_FILES = \
FORMAT_FILES = \
elf.c \
pecoff.c \
- unknown.c
+ unknown.c \
+ xcoff.c
VIEW_FILES = \
read.c \
@@ -817,6 +818,7 @@ sort.lo: config.h backtrace.h internal.h
stest.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h
+xcoff.lo: config.h backtrace.h internal.h
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in
index 06f91f2e29f..9fc771564ba 100644
--- a/libbacktrace/config.h.in
+++ b/libbacktrace/config.h.in
@@ -3,6 +3,9 @@
/* ELF size: 32 or 64 */
#undef BACKTRACE_ELF_SIZE
+/* XCOFF size: 32 or 64 */
+#undef BACKTRACE_XCOFF_SIZE
+
/* Define to 1 if you have the __atomic functions */
#undef HAVE_ATOMIC_FUNCTIONS
@@ -31,6 +34,9 @@
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
+/* Define if AIX loadquery is available. */
+#undef HAVE_LOADQUERY
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@@ -49,6 +55,9 @@
/* Define to 1 if you have the __sync functions */
#undef HAVE_SYNC_FUNCTIONS
+/* Define to 1 if you have the <sys/ldr.h> header file. */
+#undef HAVE_SYS_LDR_H
+
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
diff --git a/libbacktrace/configure b/libbacktrace/configure
index e6420ea94da..35767344f25 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -12048,6 +12048,9 @@ elf*) FORMAT_FILE="elf.lo" ;;
pecoff) FORMAT_FILE="pecoff.lo"
backtrace_supports_data=no
;;
+xcoff*) FORMAT_FILE="xcoff.lo"
+ backtrace_supports_data=no
+ ;;
*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type" >&5
$as_echo "$as_me: WARNING: could not determine output file type" >&2;}
FORMAT_FILE="unknown.lo"
@@ -12069,6 +12072,19 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# XCOFF defines.
+xcoffsize=
+case "$libbacktrace_cv_sys_filetype" in
+xcoff32) xcoffsize=32 ;;
+xcoff64) xcoffsize=64 ;;
+*) xcoffsize=unused
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define BACKTRACE_XCOFF_SIZE $xcoffsize
+_ACEOF
+
+
BACKTRACE_SUPPORTED=0
if test "$backtrace_supported" = "yes"; then
BACKTRACE_SUPPORTED=1
@@ -12607,6 +12623,53 @@ $as_echo "#define HAVE_DL_ITERATE_PHDR 1" >>confdefs.h
fi
+# Check for loadquery.
+for ac_header in sys/ldr.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/ldr.h" "ac_cv_header_sys_ldr_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ldr_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_LDR_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_sys_ldr_h" = "no"; then
+ have_loadquery=no
+else
+ if test -n "${with_target_subdir}"; then
+ # When built as a GCC target library, we can't do a link test.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/ldr.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "loadquery" >/dev/null 2>&1; then :
+ have_loadquery=yes
+else
+ have_loadquery=no
+fi
+rm -f conftest*
+
+ else
+ ac_fn_c_check_func "$LINENO" "loadquery" "ac_cv_func_loadquery"
+if test "x$ac_cv_func_loadquery" = x""yes; then :
+ have_loadquery=yes
+else
+ have_loadquery=no
+fi
+
+ fi
+fi
+if test "$have_loadquery" = "yes"; then
+
+$as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h
+
+fi
+
# Check for the fcntl function.
if test -n "${with_target_subdir}"; then
case "${host}" in
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 47ebdc18af2..e644c7da796 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -233,6 +233,9 @@ elf*) FORMAT_FILE="elf.lo" ;;
pecoff) FORMAT_FILE="pecoff.lo"
backtrace_supports_data=no
;;
+xcoff*) FORMAT_FILE="xcoff.lo"
+ backtrace_supports_data=no
+ ;;
*) AC_MSG_WARN([could not determine output file type])
FORMAT_FILE="unknown.lo"
backtrace_supported=no
@@ -249,6 +252,15 @@ elf64) elfsize=64 ;;
esac
AC_DEFINE_UNQUOTED([BACKTRACE_ELF_SIZE], [$elfsize], [ELF size: 32 or 64])
+# XCOFF defines.
+xcoffsize=
+case "$libbacktrace_cv_sys_filetype" in
+xcoff32) xcoffsize=32 ;;
+xcoff64) xcoffsize=64 ;;
+*) xcoffsize=unused
+esac
+AC_DEFINE_UNQUOTED([BACKTRACE_XCOFF_SIZE], [$xcoffsize], [XCOFF size: 32 or 64])
+
BACKTRACE_SUPPORTED=0
if test "$backtrace_supported" = "yes"; then
BACKTRACE_SUPPORTED=1
@@ -327,6 +339,24 @@ if test "$have_dl_iterate_phdr" = "yes"; then
AC_DEFINE(HAVE_DL_ITERATE_PHDR, 1, [Define if dl_iterate_phdr is available.])
fi
+# Check for loadquery.
+AC_CHECK_HEADERS(sys/ldr.h)
+if test "$ac_cv_header_sys_ldr_h" = "no"; then
+ have_loadquery=no
+else
+ if test -n "${with_target_subdir}"; then
+ # When built as a GCC target library, we can't do a link test.
+ AC_EGREP_HEADER([loadquery], [sys/ldr.h], [have_loadquery=yes],
+ [have_loadquery=no])
+ else
+ AC_CHECK_FUNC([loadquery], [have_loadquery=yes],
+ [have_loadquery=no])
+ fi
+fi
+if test "$have_loadquery" = "yes"; then
+ AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.])
+fi
+
# Check for the fcntl function.
if test -n "${with_target_subdir}"; then
case "${host}" in
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 8e169715d32..1471007d4ea 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -70,7 +70,7 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
ELF. We could make this code test and support either possibility,
but there is no point. This code only works for the currently
running executable, which means that we know the ELF mode at
- configure mode. */
+ configure time. */
#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64
#error "Unknown BACKTRACE_ELF_SIZE"
diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c
index 0fd350a30c9..68120583d7b 100644
--- a/libbacktrace/fileline.c
+++ b/libbacktrace/fileline.c
@@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. */
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
+#include <unistd.h>
#include "backtrace.h"
#include "internal.h"
@@ -57,6 +58,7 @@ fileline_initialize (struct backtrace_state *state,
int pass;
int called_error_callback;
int descriptor;
+ char buf[64];
if (!state->threaded)
failed = state->fileline_initialization_failed;
@@ -80,7 +82,7 @@ fileline_initialize (struct backtrace_state *state,
descriptor = -1;
called_error_callback = 0;
- for (pass = 0; pass < 4; ++pass)
+ for (pass = 0; pass < 5; ++pass)
{
const char *filename;
int does_not_exist;
@@ -99,6 +101,11 @@ fileline_initialize (struct backtrace_state *state,
case 3:
filename = "/proc/curproc/file";
break;
+ case 4:
+ snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
+ (long) getpid ());
+ filename = buf;
+ break;
default:
abort ();
}
diff --git a/libbacktrace/filetype.awk b/libbacktrace/filetype.awk
index 57bab797a9a..cf6e1b695d2 100644
--- a/libbacktrace/filetype.awk
+++ b/libbacktrace/filetype.awk
@@ -3,3 +3,6 @@
/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }
/\114\001/ { if (NR == 1) { print "pecoff"; exit } }
/\144\206/ { if (NR == 1) { print "pecoff"; exit } }
+/\001\337/ { if (NR == 1) { print "xcoff32"; exit } }
+/\001\367/ { if (NR == 1) { print "xcoff64"; exit } }
+
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
new file mode 100644
index 00000000000..2faa9fdfa05
--- /dev/null
+++ b/libbacktrace/xcoff.c
@@ -0,0 +1,1485 @@
+/* xcoff.c -- Get debug data from an XCOFF file for backtraces.
+ Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Adapted from elf.c.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) 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.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_LOADQUERY
+#include <sys/ldr.h>
+#endif
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The configure script must tell us whether we are 32-bit or 64-bit
+ XCOFF. We could make this code test and support either possibility,
+ but there is no point. This code only works for the currently
+ running executable, which means that we know the XCOFF mode at
+ configure time. */
+
+#if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
+#error "Unknown BACKTRACE_XCOFF_SIZE"
+#endif
+
+/* XCOFF file header. */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+ uint16_t f_magic;
+ uint16_t f_nscns;
+ uint32_t f_timdat;
+ uint32_t f_symptr;
+ uint32_t f_nsyms;
+ uint16_t f_opthdr;
+ uint16_t f_flags;
+} b_xcoff_filhdr;
+
+#define XCOFF_MAGIC 0737
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+ uint16_t f_magic;
+ uint16_t f_nscns;
+ uint32_t f_timdat;
+ uint64_t f_symptr;
+ uint16_t f_opthdr;
+ uint16_t f_flags;
+ uint32_t f_nsyms;
+} b_xcoff_filhdr;
+
+#define XCOFF_MAGIC 0767
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define F_SHROBJ 0x2000 /* File is a shared object. */
+
+/* XCOFF section header. */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+ char s_name[8];
+ uint32_t s_paddr;
+ uint32_t s_vaddr;
+ uint32_t s_size;
+ uint32_t s_scnptr;
+ uint32_t s_relptr;
+ uint32_t s_lnnoptr;
+ uint16_t s_nreloc;
+ uint16_t s_nlnno;
+ uint32_t s_flags;
+} b_xcoff_scnhdr;
+
+#define _OVERFLOW_MARKER 65535
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+ char name[8];
+ uint64_t s_paddr;
+ uint64_t s_vaddr;
+ uint64_t s_size;
+ uint64_t s_scnptr;
+ uint64_t s_relptr;
+ uint64_t s_lnnoptr;
+ uint32_t s_nreloc;
+ uint32_t s_nlnno;
+ uint32_t s_flags;
+} b_xcoff_scnhdr;
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define STYP_TEXT 0x20 /* Executable text (code) section. */
+#define STYP_OVRFLO 0x8000 /* Line-number field overflow section. */
+
+/* XCOFF symbol. */
+
+#define SYMNMLEN 8
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+ union {
+ char _name[SYMNMLEN];
+ struct {
+ uint32_t _zeroes;
+ uint32_t _offset;
+ } _s;
+ } _u;
+#define n_name _u._name
+#define n_zeroes _u._s._zeroes
+#define n_offset_ _u._s._offset
+
+ uint32_t n_value;
+ int16_t n_scnum;
+ uint16_t n_type;
+ uint8_t n_sclass;
+ uint8_t n_numaux;
+} __attribute__ ((packed)) b_xcoff_syment;
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+ uint64_t n_value;
+ uint32_t n_offset_;
+ int16_t n_scnum;
+ uint16_t n_type;
+ uint8_t n_sclass;
+ uint8_t n_numaux;
+} __attribute__ ((packed)) b_xcoff_syment;
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define SYMESZ 18
+
+#define C_EXT 2 /* External symbol. */
+#define C_FCN 101 /* Beginning or end of function. */
+#define C_FILE 103 /* Source file name. */
+#define C_HIDEXT 107 /* Unnamed external symbol. */
+#define C_BINCL 108 /* Beginning of include file. */
+#define C_EINCL 109 /* End of include file. */
+#define C_WEAKEXT 111 /* Weak external symbol. */
+
+#define ISFCN(x) ((x) & 0x0020)
+
+/* XCOFF AUX entry. */
+
+#define AUXESZ 18
+#define FILNMLEN 14
+
+typedef union {
+#if BACKTRACE_XCOFF_SIZE == 32
+ struct {
+ uint16_t pad;
+ uint16_t x_lnnohi;
+ uint16_t x_lnno;
+ } x_block;
+#else
+ struct {
+ uint32_t x_lnno;
+ } x_block;
+#endif
+ union {
+ char x_fname[FILNMLEN];
+ struct {
+ uint32_t x_zeroes;
+ uint32_t x_offset;
+ char pad[FILNMLEN-8];
+ uint8_t x_ftype;
+ } _x;
+ } x_file;
+#if BACKTRACE_XCOFF_SIZE == 32
+ struct {
+ uint32_t x_exptr;
+ uint32_t x_fsize;
+ uint32_t x_lnnoptr;
+ uint32_t x_endndx;
+ } x_fcn;
+#else
+ struct {
+ uint64_t x_lnnoptr;
+ uint32_t x_fsize;
+ uint32_t x_endndx;
+ } x_fcn;
+#endif
+ struct {
+ uint8_t pad[AUXESZ-1];
+ uint8_t x_auxtype;
+ } x_auxtype;
+} __attribute__ ((packed)) b_xcoff_auxent;
+
+/* XCOFF line number entry. */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+ union {
+ uint32_t l_symndx;
+ uint32_t l_paddr;
+ } l_addr;
+ uint16_t l_lnno;
+} b_xcoff_lineno;
+
+#define LINESZ 6
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+ union {
+ uint32_t l_symndx;
+ uint64_t l_paddr;
+ } l_addr;
+ uint32_t l_lnno;
+} b_xcoff_lineno;
+
+#define LINESZ 12
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+#define XCOFF_AIX_TEXTBASE 0x10000000u
+#else
+#define XCOFF_AIX_TEXTBASE 0x100000000ul
+#endif
+
+/* AIX big archive fixed-length header. */
+
+#define AIAMAGBIG "<bigaf>\n"
+
+typedef struct {
+ char fl_magic[8]; /* Archive magic string. */
+ char fl_memoff[20]; /* Offset to member table. */
+ char fl_gstoff[20]; /* Offset to global symbol table. */
+ char fl_gst64off[20]; /* Offset to global symbol table for 64-bit objects. */
+ char fl_fstmoff[20]; /* Offset to first archive member. */
+ char fl_freeoff[20]; /* Offset to first member on free list. */
+} b_ar_fl_hdr;
+
+/* AIX big archive file member header. */
+
+typedef struct {
+ char ar_size[20]; /* File member size - decimal. */
+ char ar_nxtmem[20]; /* Next member offset - decimal. */
+ char ar_prvmem[20]; /* Previous member offset - decimal. */
+ char ar_date[12]; /* File member date - decimal. */
+ char ar_uid[12]; /* File member userid - decimal. */
+ char ar_gid[12]; /* File member group id - decimal. */
+ char ar_mode[12]; /* File member mode - octal. */
+ char ar_namlen[4]; /* File member name length - decimal. */
+ char ar_name[2]; /* Start of member name. */
+} b_ar_hdr;
+
+
+/* Information we keep for an XCOFF symbol. */
+
+struct xcoff_symbol
+{
+ /* The name of the symbol. */
+ const char *name;
+ /* The address of the symbol. */
+ uintptr_t address;
+ /* The size of the symbol. */
+ size_t size;
+};
+
+/* Information to pass to xcoff_syminfo. */
+
+struct xcoff_syminfo_data
+{
+ /* Symbols for the next module. */
+ struct xcoff_syminfo_data *next;
+ /* The XCOFF symbols, sorted by address. */
+ struct xcoff_symbol *symbols;
+ /* The number of symbols. */
+ size_t count;
+};
+
+/* Information about an include file. */
+
+struct xcoff_incl
+{
+ /* File name. */
+ const char *filename;
+ /* Offset to first line number from the include file. */
+ uintptr_t begin;
+ /* Offset to last line number from the include file. */
+ uintptr_t end;
+};
+
+/* A growable vector of include files information. */
+
+struct xcoff_incl_vector
+{
+ /* Memory. This is an array of struct xcoff_incl. */
+ struct backtrace_vector vec;
+ /* Number of include files. */
+ size_t count;
+};
+
+/* Map a single PC value to a file/function/line. */
+
+struct xcoff_line
+{
+ /* PC. */
+ uintptr_t pc;
+ /* File name. Many entries in the array are expected to point to
+ the same file name. */
+ const char *filename;
+ /* Function name. */
+ const char *function;
+ /* Line number. */
+ int lineno;
+};
+
+/* A growable vector of line number information. This is used while
+ reading the line numbers. */
+
+struct xcoff_line_vector
+{
+ /* Memory. This is an array of struct xcoff_line. */
+ struct backtrace_vector vec;
+ /* Number of valid mappings. */
+ size_t count;
+};
+
+/* The information we need to map a PC to a file and line. */
+
+struct xcoff_fileline_data
+{
+ /* The data for the next file we know about. */
+ struct xcoff_fileline_data *next;
+ /* Line number information. */
+ struct xcoff_line_vector vec;
+};
+
+
+/* A dummy callback function used when we can't find any debug info. */
+
+static int
+xcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t pc ATTRIBUTE_UNUSED,
+ backtrace_full_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no debug info in XCOFF executable", -1);
+ return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+ table. */
+
+static void
+xcoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t addr ATTRIBUTE_UNUSED,
+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no symbol table in XCOFF executable", -1);
+}
+
+/* Compare struct xcoff_symbol for qsort. */
+
+static int
+xcoff_symbol_compare (const void *v1, const void *v2)
+{
+ const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;
+ const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;
+
+ if (e1->address < e2->address)
+ return -1;
+ else if (e1->address > e2->address)
+ return 1;
+ else
+ return 0;
+}
+
+/* Compare an ADDR against an xcoff_symbol for bsearch. */
+
+static int
+xcoff_symbol_search (const void *vkey, const void *ventry)
+{
+ const uintptr_t *key = (const uintptr_t *) vkey;
+ const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;
+ uintptr_t addr;
+
+ addr = *key;
+ if (addr < entry->address)
+ return -1;
+ else if ((entry->size == 0 && addr > entry->address)
+ || (entry->size > 0 && addr >= entry->address + entry->size))
+ return 1;
+ else
+ return 0;
+}
+
+/* Add XDATA to the list in STATE. */
+
+static void
+xcoff_add_syminfo_data (struct backtrace_state *state,
+ struct xcoff_syminfo_data *xdata)
+{
+ if (!state->threaded)
+ {
+ struct xcoff_syminfo_data **pp;
+
+ for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = xdata;
+ }
+ else
+ {
+ while (1)
+ {
+ struct xcoff_syminfo_data **pp;
+
+ pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+
+ while (1)
+ {
+ struct xcoff_syminfo_data *p;
+
+ p = backtrace_atomic_load_pointer (pp);
+
+ if (p == NULL)
+ break;
+
+ pp = &p->next;
+ }
+
+ if (__sync_bool_compare_and_swap (pp, NULL, xdata))
+ break;
+ }
+ }
+}
+
+/* Return the symbol name and value for an ADDR. */
+
+static void
+xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr,
+ backtrace_syminfo_callback callback,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data)
+{
+ struct xcoff_syminfo_data *edata;
+ struct xcoff_symbol *sym = NULL;
+
+ if (!state->threaded)
+ {
+ for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;
+ edata != NULL;
+ edata = edata->next)
+ {
+ sym = ((struct xcoff_symbol *)
+ bsearch (&addr, edata->symbols, edata->count,
+ sizeof (struct xcoff_symbol), xcoff_symbol_search));
+ if (sym != NULL)
+ break;
+ }
+ }
+ else
+ {
+ struct xcoff_syminfo_data **pp;
+
+ pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+ while (1)
+ {
+ edata = backtrace_atomic_load_pointer (pp);
+ if (edata == NULL)
+ break;
+
+ sym = ((struct xcoff_symbol *)
+ bsearch (&addr, edata->symbols, edata->count,
+ sizeof (struct xcoff_symbol), xcoff_symbol_search));
+ if (sym != NULL)
+ break;
+
+ pp = &edata->next;
+ }
+ }
+
+ if (sym == NULL)
+ callback (data, addr, NULL, 0, 0);
+ else
+ callback (data, addr, sym->name, sym->address, sym->size);
+}
+
+/* Return the name of an XCOFF symbol. */
+
+static const char *
+xcoff_symname (const b_xcoff_syment *asym,
+ const unsigned char *strtab, size_t strtab_size)
+{
+#if BACKTRACE_XCOFF_SIZE == 32
+ if (asym->n_zeroes != 0)
+ {
+ /* Make a copy as we will release the symtab view. */
+ char name[SYMNMLEN+1];
+ strncpy (name, asym->n_name, SYMNMLEN);
+ name[SYMNMLEN] = '\0';
+ return strdup (name);
+ }
+#endif
+ if (asym->n_sclass & 0x80)
+ return NULL; /* .debug */
+ if (asym->n_offset_ >= strtab_size)
+ return NULL;
+ return (const char *) strtab + asym->n_offset_;
+}
+
+/* Initialize the symbol table info for xcoff_syminfo. */
+
+static int
+xcoff_initialize_syminfo (struct backtrace_state *state,
+ uintptr_t base_address,
+ const b_xcoff_scnhdr *sects,
+ const b_xcoff_syment *syms, size_t nsyms,
+ const unsigned char *strtab, size_t strtab_size,
+ backtrace_error_callback error_callback, void *data,
+ struct xcoff_syminfo_data *sdata)
+{
+ size_t xcoff_symbol_count;
+ size_t xcoff_symbol_size;
+ struct xcoff_symbol *xcoff_symbols;
+ size_t i;
+ unsigned int j;
+
+ /* We only care about function symbols. Count them. */
+ xcoff_symbol_count = 0;
+ for (i = 0; i < nsyms; ++i)
+ {
+ const b_xcoff_syment *asym = &syms[i];
+ if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
+ || asym->n_sclass == C_WEAKEXT)
+ && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
+ ++xcoff_symbol_count;
+
+ i += asym->n_numaux;
+ }
+
+ xcoff_symbol_size = xcoff_symbol_count * sizeof (struct xcoff_symbol);
+ xcoff_symbols = ((struct xcoff_symbol *)
+ backtrace_alloc (state, xcoff_symbol_size, error_callback,
+ data));
+ if (xcoff_symbols == NULL)
+ return 0;
+
+ j = 0;
+ for (i = 0; i < nsyms; ++i)
+ {
+ const b_xcoff_syment *asym = &syms[i];
+ if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
+ || asym->n_sclass == C_WEAKEXT)
+ && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
+ {
+ const b_xcoff_auxent *aux = (const b_xcoff_auxent *) (asym + 1);
+ xcoff_symbols[j].name = xcoff_symname (asym, strtab, strtab_size);
+ xcoff_symbols[j].address = base_address + asym->n_value
+ - sects[asym->n_scnum - 1].s_paddr;
+ /* x_fsize will be 0 if there is no debug information. */
+ xcoff_symbols[j].size = aux->x_fcn.x_fsize;
+ ++j;
+ }
+
+ i += asym->n_numaux;
+ }
+
+ backtrace_qsort (xcoff_symbols, xcoff_symbol_count,
+ sizeof (struct xcoff_symbol), xcoff_symbol_compare);
+
+ sdata->next = NULL;
+ sdata->symbols = xcoff_symbols;
+ sdata->count = xcoff_symbol_count;
+
+ return 1;
+}
+
+/* Compare struct xcoff_line for qsort. */
+
+static int
+xcoff_line_compare (const void *v1, const void *v2)
+{
+ const struct xcoff_line *ln1 = (const struct xcoff_line *) v1;
+ const struct xcoff_line *ln2 = (const struct xcoff_line *) v2;
+
+ if (ln1->pc < ln2->pc)
+ return -1;
+ else if (ln1->pc > ln2->pc)
+ return 1;
+ else
+ return 0;
+}
+
+/* Find a PC in a line vector. We always allocate an extra entry at
+ the end of the lines vector, so that this routine can safely look
+ at the next entry. */
+
+static int
+xcoff_line_search (const void *vkey, const void *ventry)
+{
+ const uintptr_t *key = (const uintptr_t *) vkey;
+ const struct xcoff_line *entry = (const struct xcoff_line *) ventry;
+ uintptr_t pc;
+
+ pc = *key;
+ if (pc < entry->pc)
+ return -1;
+ else if ((entry + 1)->pc == (uintptr_t) -1 || pc >= (entry + 1)->pc)
+ return 1;
+ else
+ return 0;
+}
+
+/* Look for a PC in the line vector for one module. On success,
+ call CALLBACK and return whatever it returns. On error, call
+ ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found,
+ 0 if not. */
+
+static int
+xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ struct xcoff_fileline_data *fdata, uintptr_t pc,
+ backtrace_full_callback callback,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data, int *found)
+{
+ const struct xcoff_line *ln;
+ const char *function;
+
+ *found = 1;
+
+ ln = (struct xcoff_line *) bsearch (&pc, fdata->vec.vec.base,
+ fdata->vec.count,
+ sizeof (struct xcoff_line),
+ xcoff_line_search);
+ if (ln == NULL)
+ {
+ *found = 0;
+ return 0;
+ }
+
+ function = ln->function;
+ /* AIX prepends a '.' to function entry points, remove it. */
+ if (*function == '.')
+ ++function;
+ return callback (data, pc, ln->filename, ln->lineno, function);
+}
+
+/* Return the file/line information for a PC using the XCOFF lineno
+ mapping we built earlier. */
+
+static int
+xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
+ backtrace_full_callback callback,
+ backtrace_error_callback error_callback, void *data)
+
+{
+ struct xcoff_fileline_data *fdata;
+ int found;
+ int ret;
+
+ if (!state->threaded)
+ {
+ for (fdata = (struct xcoff_fileline_data *) state->fileline_data;
+ fdata != NULL;
+ fdata = fdata->next)
+ {
+ ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
+ data, &found);
+ if (ret != 0 || found)
+ return ret;
+ }
+ }
+ else
+ {
+ struct xcoff_fileline_data **pp;
+
+ pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+ while (1)
+ {
+ fdata = backtrace_atomic_load_pointer (pp);
+ if (fdata == NULL)
+ break;
+
+ ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
+ data, &found);
+ if (ret != 0 || found)
+ return ret;
+
+ pp = &fdata->next;
+ }
+ }
+
+ /* FIXME: See if any libraries have been dlopen'ed. */
+
+ return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Add a new mapping to the vector of line mappings that we are
+ building. Returns 1 on success, 0 on failure. */
+
+static int
+xcoff_add_line (struct backtrace_state *state, uintptr_t pc,
+ const char *filename, const char *function, uint32_t lnno,
+ backtrace_error_callback error_callback, void *data,
+ struct xcoff_line_vector *vec)
+{
+ struct xcoff_line *ln;
+
+ ln = ((struct xcoff_line *)
+ backtrace_vector_grow (state, sizeof (struct xcoff_line),
+ error_callback, data, &vec->vec));
+ if (ln == NULL)
+ return 0;
+
+ ln->pc = pc;
+ ln->filename = filename;
+ ln->function = function;
+ ln->lineno = lnno;
+
+ ++vec->count;
+
+ return 1;
+}
+
+/* Add the line number entries for a function to the line vector. */
+
+static int
+xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address,
+ const b_xcoff_syment *fsym, const char *filename,
+ const b_xcoff_scnhdr *sects,
+ const unsigned char *strtab, size_t strtab_size,
+ uint32_t fcn_lnno, struct xcoff_incl_vector *vec,
+ struct xcoff_line_vector *lvec,
+ const unsigned char *linenos, size_t linenos_size,
+ uintptr_t lnnoptr0,
+ backtrace_error_callback error_callback, void *data)
+{
+ const b_xcoff_auxent *aux;
+ const b_xcoff_lineno *lineno;
+ const unsigned char *lineptr;
+ const char *function;
+ struct xcoff_incl *incl;
+ uintptr_t lnnoptr;
+ uintptr_t pc;
+ uint32_t lnno;
+ int begincl;
+ size_t i;
+
+ aux = (const b_xcoff_auxent *) (fsym + 1);
+ lnnoptr = aux->x_fcn.x_lnnoptr;
+
+ if (lnnoptr < lnnoptr0 || lnnoptr + LINESZ > lnnoptr0 + linenos_size)
+ return 0;
+
+ function = xcoff_symname (fsym, strtab, strtab_size);
+ if (function == NULL)
+ return 0;
+
+ /* Skip first entry that points to symtab. */
+
+ lnnoptr += LINESZ;
+
+ lineptr = linenos + (lnnoptr - lnnoptr0);
+
+ begincl = -1;
+ while (lineptr + LINESZ <= linenos + linenos_size)
+ {
+ lineno = (const b_xcoff_lineno *) lineptr;
+
+ lnno = lineno->l_lnno;
+ if (lnno == 0)
+ break;
+
+ /* If part of a function other than the beginning comes from an
+ include file, the line numbers are absolute, rather than
+ relative to the beginning of the function. */
+ for (i = 0; i < vec->count; ++i)
+ {
+ incl = (struct xcoff_incl *) vec->vec.base + i;
+ if (incl->begin <= lnnoptr && lnnoptr <= incl->end)
+ break;
+ }
+ if (begincl == -1)
+ begincl = (i < vec->count);
+ if (i < vec->count)
+ {
+ filename = incl->filename;
+ if (begincl == 1)
+ lnno += fcn_lnno - 1;
+ }
+ else
+ lnno += fcn_lnno - 1;
+
+ pc = base_address + lineno->l_addr.l_paddr
+ - sects[fsym->n_scnum - 1].s_paddr;
+ xcoff_add_line (state, pc, filename, function, lnno, error_callback,
+ data, lvec);
+
+ lnnoptr += LINESZ;
+ lineptr += LINESZ;
+ }
+
+ return 1;
+}
+
+/* Initialize the line vector info for xcoff_fileline. */
+
+static int
+xcoff_initialize_fileline (struct backtrace_state *state,
+ uintptr_t base_address,
+ const b_xcoff_scnhdr *sects,
+ const b_xcoff_syment *syms, size_t nsyms,
+ const unsigned char *strtab, size_t strtab_size,
+ const unsigned char *linenos, size_t linenos_size,
+ uint64_t lnnoptr0,
+ backtrace_error_callback error_callback, void *data)
+{
+ struct xcoff_fileline_data *fdata;
+ struct xcoff_incl_vector vec;
+ struct xcoff_line *ln;
+ const b_xcoff_syment *fsym;
+ const b_xcoff_auxent *aux;
+ const char *filename;
+ const char *name;
+ struct xcoff_incl *incl;
+ uintptr_t begin, end;
+ uintptr_t lnno;
+ size_t i;
+
+ fdata = ((struct xcoff_fileline_data *)
+ backtrace_alloc (state, sizeof (struct xcoff_fileline_data),
+ error_callback, data));
+ if (fdata == NULL)
+ return 0;
+
+ memset (fdata, 0, sizeof *fdata);
+ memset (&vec, 0, sizeof vec);
+
+ /* Process include files first. */
+
+ begin = 0;
+ for (i = 0; i < nsyms; ++i)
+ {
+ const b_xcoff_syment *asym = &syms[i];
+
+ switch (asym->n_sclass)
+ {
+ case C_BINCL:
+ begin = asym->n_value;
+ break;
+
+ case C_EINCL:
+ if (begin == 0)
+ break;
+ end = asym->n_value;
+ incl = ((struct xcoff_incl *)
+ backtrace_vector_grow (state, sizeof (struct xcoff_incl),
+ error_callback, data, &vec.vec));
+ if (incl != NULL)
+ {
+ incl->filename = xcoff_symname (asym, strtab, strtab_size);
+ incl->begin = begin;
+ incl->end = end;
+ ++vec.count;
+ }
+ begin = 0;
+ break;
+ }
+
+ i += asym->n_numaux;
+ }
+
+ filename = NULL;
+ fsym = NULL;
+ for (i = 0; i < nsyms; ++i)
+ {
+ const b_xcoff_syment *asym = &syms[i];
+
+ switch (asym->n_sclass)
+ {
+ case C_FILE:
+ filename = xcoff_symname (asym, strtab, strtab_size);
+ if (filename == NULL)
+ break;
+
+ /* If the file auxiliary entry is not used, the symbol name is
+ the name of the source file. If the file auxiliary entry is
+ used, then the symbol name should be .file, and the first
+ file auxiliary entry (by convention) contains the source
+ file name. */
+
+ if (asym->n_numaux > 0 && !strcmp (filename, ".file"))
+ {
+ aux = (const b_xcoff_auxent *) (asym + 1);
+ if (aux->x_file._x.x_zeroes != 0)
+ {
+ /* Make a copy as we will release the symtab view. */
+ char name[FILNMLEN+1];
+ strncpy (name, aux->x_file.x_fname, FILNMLEN);
+ name[FILNMLEN] = '\0';
+ filename = strdup (name);
+ }
+ else if (aux->x_file._x.x_offset < strtab_size)
+ filename = (const char *) strtab + aux->x_file._x.x_offset;
+ else
+ filename = NULL;
+ }
+ break;
+
+ case C_EXT:
+ case C_HIDEXT:
+ case C_WEAKEXT:
+ fsym = NULL;
+ if (!ISFCN (asym->n_type) || asym->n_numaux == 0)
+ break;
+ if (filename == NULL)
+ break;
+ fsym = asym;
+ break;
+
+ case C_FCN:
+ if (asym->n_numaux == 0)
+ break;
+ if (fsym == NULL)
+ break;
+ name = xcoff_symname (asym, strtab, strtab_size);
+ if (name == NULL)
+ break;
+ aux = (const b_xcoff_auxent *) (asym + 1);
+#if BACKTRACE_XCOFF_SIZE == 32
+ lnno = (uint32_t) aux->x_block.x_lnnohi << 16
+ | aux->x_block.x_lnno;
+#else
+ lnno = aux->x_block.x_lnno;
+#endif
+ if (!strcmp (name, ".bf"))
+ {
+ xcoff_process_linenos (state, base_address, fsym, filename,
+ sects, strtab, strtab_size, lnno, &vec,
+ &fdata->vec, linenos, linenos_size,
+ lnnoptr0, error_callback, data);
+ }
+ else if (!strcmp (name, ".ef"))
+ {
+ fsym = NULL;
+ }
+ break;
+ }
+
+ i += asym->n_numaux;
+ }
+
+ /* Allocate one extra entry at the end. */
+ ln = ((struct xcoff_line *)
+ backtrace_vector_grow (state, sizeof (struct xcoff_line),
+ error_callback, data, &fdata->vec.vec));
+ if (ln == NULL)
+ goto fail;
+ ln->pc = (uintptr_t) -1;
+ ln->filename = NULL;
+ ln->function = NULL;
+ ln->lineno = 0;
+
+ if (!backtrace_vector_release (state, &fdata->vec.vec, error_callback, data))
+ goto fail;
+
+ backtrace_qsort (fdata->vec.vec.base, fdata->vec.count,
+ sizeof (struct xcoff_line), xcoff_line_compare);
+
+ if (!state->threaded)
+ {
+ struct xcoff_fileline_data **pp;
+
+ for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = fdata;
+ }
+ else
+ {
+ while (1)
+ {
+ struct xcoff_fileline_data **pp;
+
+ pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+
+ while (1)
+ {
+ struct xcoff_fileline_data *p;
+
+ p = backtrace_atomic_load_pointer (pp);
+
+ if (p == NULL)
+ break;
+
+ pp = &p->next;
+ }
+
+ if (__sync_bool_compare_and_swap (pp, NULL, fdata))
+ break;
+ }
+ }
+
+ return 1;
+
+fail:
+ return 0;
+}
+
+/* Add the backtrace data for one XCOFF file. Returns 1 on success,
+ 0 on failure (in both cases descriptor is closed). */
+
+static int
+xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
+ uintptr_t base_address, backtrace_error_callback error_callback,
+ void *data, fileline *fileline_fn, int *found_sym, int exe)
+{
+ struct backtrace_view fhdr_view;
+ struct backtrace_view sects_view;
+ struct backtrace_view linenos_view;
+ struct backtrace_view syms_view;
+ struct backtrace_view str_view;
+ b_xcoff_filhdr fhdr;
+ const b_xcoff_scnhdr *sects;
+ const b_xcoff_scnhdr *stext;
+ uint64_t lnnoptr;
+ uint32_t nlnno;
+ off_t str_off;
+ size_t sects_size;
+ size_t syms_size;
+ int32_t str_size;
+ int sects_view_valid;
+ int linenos_view_valid;
+ int syms_view_valid;
+ int str_view_valid;
+ int magic_ok;
+ int i;
+
+ *found_sym = 0;
+
+ sects_view_valid = 0;
+ linenos_view_valid = 0;
+ syms_view_valid = 0;
+ str_view_valid = 0;
+
+ /* Map the XCOFF file header. */
+ if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),
+ error_callback, data, &fhdr_view))
+ goto fail;
+
+ memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
+ magic_ok = (fhdr.f_magic == XCOFF_MAGIC);
+
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+ if (!magic_ok)
+ {
+ if (exe)
+ error_callback (data, "executable file is not XCOFF", 0);
+ goto fail;
+ }
+
+ /* Verify object is of expected type. */
+ if ((exe && (fhdr.f_flags & F_SHROBJ))
+ || (!exe && !(fhdr.f_flags & F_SHROBJ)))
+ goto fail;
+
+ /* Read the section headers. */
+
+ sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);
+
+ if (!backtrace_get_view (state, descriptor,
+ offset + sizeof (fhdr) + fhdr.f_opthdr,
+ sects_size, error_callback, data, &sects_view))
+ goto fail;
+ sects_view_valid = 1;
+ sects = (const b_xcoff_scnhdr *) sects_view.data;
+
+ /* FIXME: assumes only one .text section. */
+ for (i = 0; i < fhdr.f_nscns; ++i)
+ if ((sects[i].s_flags & 0xffff) == STYP_TEXT)
+ break;
+ if (i == fhdr.f_nscns)
+ goto fail;
+
+ stext = &sects[i];
+
+ /* AIX ldinfo_textorg includes the XCOFF headers. */
+ base_address = (exe ? XCOFF_AIX_TEXTBASE : base_address) + stext->s_scnptr;
+
+ lnnoptr = stext->s_lnnoptr;
+ nlnno = stext->s_nlnno;
+
+#if BACKTRACE_XCOFF_SIZE == 32
+ if (nlnno == _OVERFLOW_MARKER)
+ {
+ int sntext = i + 1;
+ /* Find the matching .ovrflo section. */
+ for (i = 0; i < fhdr.f_nscns; ++i)
+ {
+ if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)
+ && sects[i].s_nlnno == sntext)
+ {
+ nlnno = sects[i].s_vaddr;
+ break;
+ }
+ }
+ }
+#endif
+
+ /* Read the symbol table and the string table. */
+
+ if (fhdr.f_symptr != 0)
+ {
+ struct xcoff_syminfo_data *sdata;
+
+ /* Symbol table is followed by the string table. The string table
+ starts with its length (on 4 bytes).
+ Map the symbol table and the length of the string table. */
+ syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);
+
+ if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,
+ syms_size + 4, error_callback, data,
+ &syms_view))
+ goto fail;
+ syms_view_valid = 1;
+
+ memcpy (&str_size, syms_view.data + syms_size, 4);
+
+ str_off = fhdr.f_symptr + syms_size;
+
+ if (str_size > 4)
+ {
+ /* Map string table (including the length word). */
+
+ if (!backtrace_get_view (state, descriptor, offset + str_off,
+ str_size, error_callback, data, &str_view))
+ goto fail;
+ str_view_valid = 1;
+ }
+
+ sdata = ((struct xcoff_syminfo_data *)
+ backtrace_alloc (state, sizeof *sdata, error_callback, data));
+ if (sdata == NULL)
+ goto fail;
+
+ if (!xcoff_initialize_syminfo (state, base_address, sects,
+ syms_view.data, fhdr.f_nsyms,
+ str_view.data, str_size,
+ error_callback, data, sdata))
+ {
+ backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+ goto fail;
+ }
+
+ *found_sym = 1;
+
+ xcoff_add_syminfo_data (state, sdata);
+ }
+
+ /* Read the line number entries. */
+
+ if (fhdr.f_symptr != 0 && lnnoptr != 0)
+ {
+ size_t linenos_size = (size_t) nlnno * LINESZ;
+
+ if (!backtrace_get_view (state, descriptor, offset + lnnoptr,
+ linenos_size,
+ error_callback, data, &linenos_view))
+ goto fail;
+ linenos_view_valid = 1;
+
+ if (xcoff_initialize_fileline (state, base_address, sects,
+ syms_view.data, fhdr.f_nsyms,
+ str_view.data, str_size,
+ linenos_view.data, linenos_size,
+ lnnoptr, error_callback, data))
+ *fileline_fn = xcoff_fileline;
+
+ backtrace_release_view (state, &linenos_view, error_callback, data);
+ linenos_view_valid = 0;
+ }
+
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ sects_view_valid = 0;
+ if (syms_view_valid)
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ syms_view_valid = 0;
+
+ /* We've read all we need from the executable. */
+ if (!backtrace_close (descriptor, error_callback, data))
+ goto fail;
+ descriptor = -1;
+
+ return 1;
+
+ fail:
+ if (sects_view_valid)
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ if (str_view_valid)
+ backtrace_release_view (state, &str_view, error_callback, data);
+ if (syms_view_valid)
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ if (linenos_view_valid)
+ backtrace_release_view (state, &linenos_view, error_callback, data);
+ if (descriptor != -1 && offset == 0)
+ backtrace_close (descriptor, error_callback, data);
+ return 0;
+}
+
+#ifdef HAVE_LOADQUERY
+
+/* Read an integer value in human-readable format from an AIX
+ big archive fixed-length or member header. */
+
+static int
+xcoff_parse_decimal (const char *buf, size_t size, off_t *off)
+{
+ char str[32];
+ char *end;
+
+ if (size >= sizeof str)
+ return 0;
+ memcpy (str, buf, size);
+ str[size] = '\0';
+ *off = strtol (str, &end, 10);
+ if (*end != '\0' && *end != ' ')
+ return 0;
+
+ return 1;
+}
+
+/* Add the backtrace data for a member of an AIX big archive.
+ Returns 1 on success, 0 on failure. */
+
+static int
+xcoff_armem_add (struct backtrace_state *state, int descriptor,
+ uintptr_t base_address, const char *member,
+ backtrace_error_callback error_callback, void *data,
+ fileline *fileline_fn, int *found_sym)
+{
+ struct backtrace_view view;
+ b_ar_fl_hdr fl_hdr;
+ const b_ar_hdr *ar_hdr;
+ off_t off;
+ off_t len;
+ int memlen;
+
+ *found_sym = 0;
+
+ /* Map archive fixed-length header. */
+
+ if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),
+ error_callback, data, &view))
+ goto fail;
+
+ memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));
+
+ backtrace_release_view (state, &view, error_callback, data);
+
+ if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)
+ goto fail;
+
+ memlen = strlen (member);
+
+ /* Read offset of first archive member. */
+ if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))
+ goto fail;
+ while (off != 0)
+ {
+ /* Map archive member header and member name. */
+
+ if (!backtrace_get_view (state, descriptor, off,
+ sizeof (b_ar_hdr) + memlen,
+ error_callback, data, &view))
+ break;
+
+ ar_hdr = (const b_ar_hdr *) view.data;
+
+ /* Read archive member name length. */
+ if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,
+ &len))
+ {
+ backtrace_release_view (state, &view, error_callback, data);
+ break;
+ }
+ if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))
+ {
+ off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;
+
+ /* The archive can contain several members with the same name
+ (e.g. 32-bit and 64-bit), so continue if not ok. */
+
+ if (xcoff_add (state, descriptor, off, base_address, error_callback,
+ data, fileline_fn, found_sym, 0))
+ {
+ backtrace_release_view (state, &view, error_callback, data);
+ return 1;
+ }
+ }
+
+ /* Read offset of next archive member. */
+ if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,
+ &off))
+ {
+ backtrace_release_view (state, &view, error_callback, data);
+ break;
+ }
+ backtrace_release_view (state, &view, error_callback, data);
+ }
+
+ fail:
+ /* No matching member found. */
+ backtrace_close (descriptor, error_callback, data);
+ return 0;
+}
+
+/* Add the backtrace data for dynamically loaded libraries. */
+
+static void
+xcoff_add_shared_libs (struct backtrace_state *state,
+ backtrace_error_callback error_callback,
+ void *data, fileline *fileline_fn, int *found_sym)
+{
+ const struct ld_info *ldinfo;
+ void *buf;
+ unsigned int buflen;
+ const char *member;
+ int descriptor;
+ int does_not_exist;
+ int lib_found_sym;
+ int ret;
+
+ /* Retrieve the list of loaded libraries. */
+
+ buf = NULL;
+ buflen = 512;
+ do
+ {
+ buf = realloc (buf, buflen);
+ if (buf == NULL)
+ {
+ ret = -1;
+ break;
+ }
+ ret = loadquery (L_GETINFO, buf, buflen);
+ if (ret == 0)
+ break;
+ buflen *= 2;
+ }
+ while (ret == -1 && errno == ENOMEM);
+ if (ret != 0)
+ {
+ free (buf);
+ return;
+ }
+
+ ldinfo = (const struct ld_info *) buf;
+ while ((const char *) ldinfo < (const char *) buf + buflen)
+ {
+ if (*ldinfo->ldinfo_filename != '/')
+ goto next;
+
+ descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,
+ data, &does_not_exist);
+ if (descriptor < 0)
+ goto next;
+
+ /* Check if it is an archive (member name not empty). */
+
+ member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;
+ if (*member)
+ {
+ xcoff_armem_add (state, descriptor,
+ (uintptr_t) ldinfo->ldinfo_textorg, member,
+ error_callback, data, fileline_fn, &lib_found_sym);
+ }
+ else
+ {
+ xcoff_add (state, descriptor, 0, (uintptr_t) ldinfo->ldinfo_textorg,
+ error_callback, data, fileline_fn, &lib_found_sym, 0);
+ }
+ if (lib_found_sym)
+ *found_sym = 1;
+
+ next:
+ if (ldinfo->ldinfo_next == 0)
+ break;
+ ldinfo = (const struct ld_info *) ((const char *) ldinfo
+ + ldinfo->ldinfo_next);
+ }
+
+ free (buf);
+}
+#endif /* HAVE_LOADQUERY */
+
+/* Initialize the backtrace data we need from an XCOFF executable.
+ Returns 1 on success, 0 on failure. */
+
+int
+backtrace_initialize (struct backtrace_state *state, int descriptor,
+ backtrace_error_callback error_callback,
+ void *data, fileline *fileline_fn)
+{
+ int ret;
+ int found_sym;
+ fileline xcoff_fileline_fn = xcoff_nodebug;
+
+ ret = xcoff_add (state, descriptor, 0, 0, error_callback, data,
+ &xcoff_fileline_fn, &found_sym, 1);
+ if (!ret)
+ return 0;
+
+#ifdef HAVE_LOADQUERY
+ xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,
+ &found_sym);
+#endif
+
+ if (!state->threaded)
+ {
+ if (found_sym)
+ state->syminfo_fn = xcoff_syminfo;
+ else if (state->syminfo_fn == NULL)
+ state->syminfo_fn = xcoff_nosyms;
+ }
+ else
+ {
+ if (found_sym)
+ backtrace_atomic_store_pointer (&state->syminfo_fn, xcoff_syminfo);
+ else
+ __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, xcoff_nosyms);
+ }
+
+ if (!state->threaded)
+ {
+ if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)
+ *fileline_fn = xcoff_fileline_fn;
+ }
+ else
+ {
+ fileline current_fn;
+
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+ if (current_fn == NULL || current_fn == xcoff_nodebug)
+ *fileline_fn = xcoff_fileline_fn;
+ }
+
+ return 1;
+}
diff --git a/libcc1/ChangeLog b/libcc1/ChangeLog
index 1d3921b4e08..4d8f40c8312 100644
--- a/libcc1/ChangeLog
+++ b/libcc1/ChangeLog
@@ -1,3 +1,27 @@
+2017-07-20 Nathan Sidwell <nathan@acm.org>
+
+ Remove TYPE_METHODS.
+ * libcp1plugin.cc (plugin_build_decl): Member fns are on TYPE_FIELDS.
+
+2017-07-12 Nathan Sidwell <nathan@acm.org>
+
+ * libcp1plugin.cc (plugin_build_decl): Use
+ DECL_CXX_{CON,DE}STRUCTOR directly.
+
+2017-07-05 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * libcp1plugin.cc (plugin_build_field): Use SET_DECL_MODE.
+
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * libcp1plugin.cc (plugin_build_decl): Use make_conv_op_name.
+ (plugin_build_dependent_expr): Likewise.
+
+2017-06-26 Nathan Sidwell <nathan@acm.org>
+
+ * libcp1plugin.cc (plugin_build_decl): Don't set
+ DECL_ASSIGNMENT_OPERATOR_P.
+
2017-06-16 Nathan Sidwell <nathan@acm.org>
* libcp1plugin.cc (plugin_build_decl): Adjust parm building.
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index 9d9221c8e50..d7bf5a29d6d 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -1321,7 +1321,7 @@ plugin_build_decl (cc1_plugin::connection *self,
opcode = ARRAY_REF;
break;
case CHARS2 ('c', 'v'): // operator <T> (conversion operator)
- identifier = mangle_conv_op_name_for_type (TREE_TYPE (sym_type));
+ identifier = make_conv_op_name (TREE_TYPE (sym_type));
break;
// C++11-only:
case CHARS2 ('l', 'i'): // operator "" <id>
@@ -1419,17 +1419,15 @@ plugin_build_decl (cc1_plugin::connection *self,
if (ctor || dtor)
{
if (ctor)
- DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_CXX_CONSTRUCTOR_P (decl) = 1;
if (dtor)
- DECL_DESTRUCTOR_P (decl) = 1;
+ DECL_CXX_DESTRUCTOR_P (decl) = 1;
}
else
{
if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION)
&& opcode != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE (decl, opcode);
- if (assop)
- DECL_ASSIGNMENT_OPERATOR_P (decl) = true;
}
}
else if (RECORD_OR_UNION_CODE_P (code))
@@ -1558,7 +1556,7 @@ plugin_build_decl (cc1_plugin::connection *self,
if ((ctor || dtor)
/* Don't crash after a duplicate declaration of a cdtor. */
- && TYPE_METHODS (current_class_type) == decl)
+ && TYPE_FIELDS (current_class_type) == decl)
{
/* ctors and dtors clones are chained after DECL.
However, we create the clones before TYPE_METHODS is
@@ -1570,9 +1568,9 @@ plugin_build_decl (cc1_plugin::connection *self,
tree save = DECL_CHAIN (decl);
DECL_CHAIN (decl) = NULL_TREE;
clone_function_decl (decl, /*update_methods=*/true);
- gcc_assert (TYPE_METHODS (current_class_type) == decl);
- TYPE_METHODS (current_class_type)
- = nreverse (TYPE_METHODS (current_class_type));
+ gcc_assert (TYPE_FIELDS (current_class_type) == decl);
+ TYPE_FIELDS (current_class_type)
+ = nreverse (TYPE_FIELDS (current_class_type));
DECL_CHAIN (decl) = save;
}
@@ -1889,7 +1887,7 @@ plugin_build_field (cc1_plugin::connection *,
= c_build_bitfield_integer_type (bitsize, TYPE_UNSIGNED (field_type));
}
- DECL_MODE (decl) = TYPE_MODE (TREE_TYPE (decl));
+ SET_DECL_MODE (decl, TYPE_MODE (TREE_TYPE (decl)));
// There's no way to recover this from DWARF.
SET_DECL_OFFSET_ALIGN (decl, TYPE_PRECISION (pointer_sized_int_node));
@@ -2624,7 +2622,7 @@ plugin_build_dependent_expr (cc1_plugin::connection *self,
break;
case CHARS2 ('c', 'v'): // operator <T> (conversion operator)
convop = true;
- identifier = mangle_conv_op_name_for_type (conv_type);
+ identifier = make_conv_op_name (conv_type);
break;
// C++11-only:
case CHARS2 ('l', 'i'): // operator "" <id>
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 526b8023b38..cf6f924ac95 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,21 @@
+2017-07-07 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/79300
+ * line-map.c (linemap_macro_loc_to_def_point): Preserve range
+ information for macro expansions by delaying resolving ad-hoc
+ locations until within the loop.
+
+2017-07-06 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/79300
+ * include/line-map.h (enum location_aspect): New enum.
+ (linemap_client_expand_location_to_spelling_point): Add
+ enum location_aspect param.
+ * line-map.c (rich_location::get_expanded_location): Update for
+ new param of linemap_client_expand_location_to_spelling_point.
+ (rich_location::maybe_add_fixit): Likewise.
+ (fixit_hint::affects_line_p): Likewise.
+
2017-06-21 Jakub Jelinek <jakub@redhat.com>
* line-map.c (location_adhoc_data_update): Perform addition in
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index f5c19e31a94..e6960410c00 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1905,6 +1905,15 @@ void linemap_dump (FILE *, struct line_maps *, unsigned, bool);
specifies how many macro maps to dump. */
void line_table_dump (FILE *, struct line_maps *, unsigned int, unsigned int);
+/* An enum for distinguishing the various parts within a source_location. */
+
+enum location_aspect
+{
+ LOCATION_ASPECT_CARET,
+ LOCATION_ASPECT_START,
+ LOCATION_ASPECT_FINISH
+};
+
/* The rich_location class requires a way to expand source_location instances.
We would directly use expand_location_to_spelling_point, which is
implemented in gcc/input.c, but we also need to use it for rich_location
@@ -1912,6 +1921,7 @@ void line_table_dump (FILE *, struct line_maps *, unsigned int, unsigned int);
Hence we require client code of libcpp to implement the following
symbol. */
extern expanded_location
-linemap_client_expand_location_to_spelling_point (source_location );
+linemap_client_expand_location_to_spelling_point (source_location,
+ enum location_aspect);
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 476a465efa0..0e5804b65bc 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1440,21 +1440,23 @@ linemap_macro_loc_to_def_point (struct line_maps *set,
{
struct line_map *map;
- if (IS_ADHOC_LOC (location))
- location = set->location_adhoc_data_map.data[location
- & MAX_SOURCE_LOCATION].locus;
-
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
while (true)
{
- map = const_cast <line_map *> (linemap_lookup (set, location));
+ source_location caret_loc;
+ if (IS_ADHOC_LOC (location))
+ caret_loc = get_location_from_adhoc_loc (set, location);
+ else
+ caret_loc = location;
+
+ map = const_cast <line_map *> (linemap_lookup (set, caret_loc));
if (!linemap_macro_expansion_map_p (map))
break;
location =
linemap_macro_map_loc_to_def_point (linemap_check_macro (map),
- location);
+ caret_loc);
}
if (original_map)
@@ -2066,7 +2068,8 @@ rich_location::get_expanded_location (unsigned int idx)
if (!m_have_expanded_location)
{
m_expanded_location
- = linemap_client_expand_location_to_spelling_point (get_loc (0));
+ = linemap_client_expand_location_to_spelling_point
+ (get_loc (0), LOCATION_ASPECT_CARET);
if (m_column_override)
m_expanded_location.column = m_column_override;
m_have_expanded_location = true;
@@ -2075,7 +2078,8 @@ rich_location::get_expanded_location (unsigned int idx)
return m_expanded_location;
}
else
- return linemap_client_expand_location_to_spelling_point (get_loc (idx));
+ return linemap_client_expand_location_to_spelling_point
+ (get_loc (idx), LOCATION_ASPECT_CARET);
}
/* Set the column of the primary location, with 0 meaning
@@ -2331,9 +2335,11 @@ rich_location::maybe_add_fixit (source_location start,
/* Only allow fix-it hints that affect a single line in one file.
Compare the end-points. */
expanded_location exploc_start
- = linemap_client_expand_location_to_spelling_point (start);
+ = linemap_client_expand_location_to_spelling_point (start,
+ LOCATION_ASPECT_START);
expanded_location exploc_next_loc
- = linemap_client_expand_location_to_spelling_point (next_loc);
+ = linemap_client_expand_location_to_spelling_point (next_loc,
+ LOCATION_ASPECT_START);
/* They must be within the same file... */
if (exploc_start.file != exploc_next_loc.file)
{
@@ -2407,13 +2413,15 @@ bool
fixit_hint::affects_line_p (const char *file, int line) const
{
expanded_location exploc_start
- = linemap_client_expand_location_to_spelling_point (m_start);
+ = linemap_client_expand_location_to_spelling_point (m_start,
+ LOCATION_ASPECT_START);
if (file != exploc_start.file)
return false;
if (line < exploc_start.line)
return false;
expanded_location exploc_next_loc
- = linemap_client_expand_location_to_spelling_point (m_next_loc);
+ = linemap_client_expand_location_to_spelling_point (m_next_loc,
+ LOCATION_ASPECT_START);
if (file != exploc_next_loc.file)
return false;
if (line > exploc_next_loc.line)
diff --git a/libdecnumber/ChangeLog b/libdecnumber/ChangeLog
index 984c92d37c8..9886dd44420 100644
--- a/libdecnumber/ChangeLog
+++ b/libdecnumber/ChangeLog
@@ -1,3 +1,11 @@
+2017-05-29 Sylvestre Ledru <sylvestre@debian.org>
+
+ * bid/bid2dpd_dpd2bid.c (_bid_to_dpd32): Fix whitespace.
+ (_dpd_to_bid32): Simplify identical code on multiple branches.
+ Fix whitespace.
+ (_bid_to_dpd64, _dpd_to_bid64): Likewise.
+ (_bid_to_dpd128, _dpd_to_bid128): Likewise.
+
2017-04-03 Jonathan Wakely <jwakely@redhat.com>
* decCommon.c (decFloatFromPackedChecked): Fix typo in comment.
diff --git a/libdecnumber/bid/bid2dpd_dpd2bid.c b/libdecnumber/bid/bid2dpd_dpd2bid.c
index c335eb849a8..331500480ad 100644
--- a/libdecnumber/bid/bid2dpd_dpd2bid.c
+++ b/libdecnumber/bid/bid2dpd_dpd2bid.c
@@ -114,10 +114,10 @@ _bid_to_dpd32 (_Decimal32 *pres, _Decimal32 *px) {
b1 = b01 - 1000 * b0;
dcoeff = b2d[b2] | b2d2[b1];
if (b0 >= 8) { /* is b0 8 or 9? */
- res = sign | ((0x600 | ((exp >> 6) << 7) |
+ res = sign | ((0x600 | ((exp >> 6) << 7) |
((b0 & 1) << 6) | (exp & 0x3f)) << 20) | dcoeff;
} else { /* else b0 is 0..7 */
- res = sign | ((((exp >> 6) << 9) | (b0 << 6) |
+ res = sign | ((((exp >> 6) << 9) | (b0 << 6) |
(exp & 0x3f)) << 20) | dcoeff;
}
*pres = res;
@@ -138,29 +138,29 @@ _dpd_to_bid32 (_Decimal32 *pres, _Decimal32 *px) {
if ((x & 0x78000000) == 0x78000000) {
*pres = x;
return;
- } else { /* normal number */
- if ((x & 0x60000000) == 0x60000000) { /* G0..G1 = 11 -> d0 = 8 + G4 */
- d0 = d2b3[((x >> 26) & 1) | 8]; /* d0 = (comb & 0x0100 ? 9 : 8); */
- exp = (x >> 27) & 3; /* exp leading bits are G2..G3 */
- } else {
- d0 = d2b3[(x >> 26) & 0x7];
- exp = (x >> 29) & 3; /* exp loading bits are G0..G1 */
- }
- d1 = d2b2[(trailing >> 10) & 0x3ff];
- d2 = d2b[(trailing) & 0x3ff];
- bcoeff = d2 + d1 + d0;
- exp = (exp << 6) + ((x >> 20) & 0x3f);
- if (bcoeff < (1 << 23)) {
- r = exp;
- r <<= 23;
- r |= (bcoeff | sign);
- } else {
- r = exp;
- r <<= 21;
- r |= (sign | 0x60000000ul);
- /* add coeff, without leading bits */
- r |= (((unsigned int) bcoeff) & 0x1fffff);
- }
+ }
+ /* normal number */
+ if ((x & 0x60000000) == 0x60000000) { /* G0..G1 = 11 -> d0 = 8 + G4 */
+ d0 = d2b3[((x >> 26) & 1) | 8]; /* d0 = (comb & 0x0100 ? 9 : 8); */
+ exp = (x >> 27) & 3; /* exp leading bits are G2..G3 */
+ } else {
+ d0 = d2b3[(x >> 26) & 0x7];
+ exp = (x >> 29) & 3; /* exp loading bits are G0..G1 */
+ }
+ d1 = d2b2[(trailing >> 10) & 0x3ff];
+ d2 = d2b[(trailing) & 0x3ff];
+ bcoeff = d2 + d1 + d0;
+ exp = (exp << 6) + ((x >> 20) & 0x3f);
+ if (bcoeff < (1 << 23)) {
+ r = exp;
+ r <<= 23;
+ r |= (bcoeff | sign);
+ } else {
+ r = exp;
+ r <<= 21;
+ r |= (sign | 0x60000000ul);
+ /* add coeff, without leading bits */
+ r |= (((unsigned int) bcoeff) & 0x1fffff);
}
*pres = r;
}
@@ -184,40 +184,40 @@ _bid_to_dpd64 (_Decimal64 *pres, _Decimal64 *px) {
if ((comb & 0xf00) == 0xf00) {
*pres = x;
return;
- } else { /* Normal number */
- if ((comb & 0xc00) == 0xc00) { /* G0..G1 = 11 -> exp is G2..G11 */
- exp = (comb) & 0x3ff;
- bcoeff = (x & 0x0007ffffffffffffull) | 0x0020000000000000ull;
- } else {
- exp = (comb >> 2) & 0x3ff;
- bcoeff = (x & 0x001fffffffffffffull);
- }
- D61 = 2305843009ull; /* Floor(2^61 / 10^9) */
- /* Multiply the binary coefficient by ceil(2^64 / 1000), and take the upper
- 64-bits in order to compute a division by 1000. */
- yhi = (D61 * (UINT64)(bcoeff >> (UINT64)27)) >> (UINT64)34;
- ylo = bcoeff - 1000000000ull * yhi;
- if (ylo >= 1000000000) {
- ylo = ylo - 1000000000;
- yhi = yhi + 1;
- }
- d103 = 0x4189374c;
- B34 = ((UINT64) ylo * d103) >> (32 + 8);
- B01 = ((UINT64) yhi * d103) >> (32 + 8);
- b5 = ylo - B34 * 1000;
- b2 = yhi - B01 * 1000;
- b3 = ((UINT64) B34 * d103) >> (32 + 8);
- b0 = ((UINT64) B01 * d103) >> (32 + 8);
- b4 = (unsigned int) B34 - (unsigned int) b3 *1000;
- b1 = (unsigned int) B01 - (unsigned int) dm103[b0];
- dcoeff = b2d[b5] | b2d2[b4] | b2d3[b3] | b2d4[b2] | b2d5[b1];
- if (b0 >= 8) /* is b0 8 or 9? */
- res = sign | ((0x1800 | ((exp >> 8) << 9) | ((b0 & 1) << 8) |
- (exp & 0xff)) << 50) | dcoeff;
- else /* else b0 is 0..7 */
- res = sign | ((((exp >> 8) << 11) | (b0 << 8) |
- (exp & 0xff)) << 50) | dcoeff;
}
+ /* Normal number */
+ if ((comb & 0xc00) == 0xc00) { /* G0..G1 = 11 -> exp is G2..G11 */
+ exp = (comb) & 0x3ff;
+ bcoeff = (x & 0x0007ffffffffffffull) | 0x0020000000000000ull;
+ } else {
+ exp = (comb >> 2) & 0x3ff;
+ bcoeff = (x & 0x001fffffffffffffull);
+ }
+ D61 = 2305843009ull; /* Floor(2^61 / 10^9) */
+ /* Multiply the binary coefficient by ceil(2^64 / 1000), and take the upper
+ 64-bits in order to compute a division by 1000. */
+ yhi = (D61 * (UINT64)(bcoeff >> (UINT64)27)) >> (UINT64)34;
+ ylo = bcoeff - 1000000000ull * yhi;
+ if (ylo >= 1000000000) {
+ ylo = ylo - 1000000000;
+ yhi = yhi + 1;
+ }
+ d103 = 0x4189374c;
+ B34 = ((UINT64) ylo * d103) >> (32 + 8);
+ B01 = ((UINT64) yhi * d103) >> (32 + 8);
+ b5 = ylo - B34 * 1000;
+ b2 = yhi - B01 * 1000;
+ b3 = ((UINT64) B34 * d103) >> (32 + 8);
+ b0 = ((UINT64) B01 * d103) >> (32 + 8);
+ b4 = (unsigned int) B34 - (unsigned int) b3 *1000;
+ b1 = (unsigned int) B01 - (unsigned int) dm103[b0];
+ dcoeff = b2d[b5] | b2d2[b4] | b2d3[b3] | b2d4[b2] | b2d5[b1];
+ if (b0 >= 8) /* is b0 8 or 9? */
+ res = sign | ((0x1800 | ((exp >> 8) << 9) | ((b0 & 1) << 8) |
+ (exp & 0xff)) << 50) | dcoeff;
+ else /* else b0 is 0..7 */
+ res = sign | ((((exp >> 8) << 11) | (b0 << 8) |
+ (exp & 0xff)) << 50) | dcoeff;
*pres = res;
}
@@ -237,49 +237,41 @@ _dpd_to_bid64 (_Decimal64 *pres, _Decimal64 *px) {
comb = (x & 0x7ffc000000000000ull) >> 50;
trailing = (x & 0x0003ffffffffffffull);
if ((comb & 0x1e00) == 0x1e00) {
- if ((comb & 0x1f00) == 0x1f00) { /* G0..G4 = 11111 -> NaN */
- if (comb & 0x0100) { /* G5 = 1 -> sNaN */
- *pres = x;
- } else { /* G5 = 0 -> qNaN */
- *pres = x;
- }
- } else { /*if ((comb & 0x1e00) == 0x1e00); G0..G4 = 11110 -> INF */
- *pres = x;
- }
+ *pres = x;
return;
- } else { /* normal number */
- if ((comb & 0x1800) == 0x1800) { /* G0..G1 = 11 -> d0 = 8 + G4 */
- d0 = d2b6[((comb >> 8) & 1) | 8]; /* d0 = (comb & 0x0100 ? 9 : 8); */
- exp = (comb & 0x600) >> 1; /* exp = (comb & 0x0400 ? 1 : 0) * 0x200 +
- (comb & 0x0200 ? 1 : 0) * 0x100; exp leading bits are G2..G3 */
- } else {
- d0 = d2b6[(comb >> 8) & 0x7];
- exp = (comb & 0x1800) >> 3; /* exp = (comb & 0x1000 ? 1 : 0) * 0x200 +
- (comb & 0x0800 ? 1 : 0) * 0x100; exp loading bits are G0..G1 */
- }
- d1 = d2b5[(trailing >> 40) & 0x3ff];
- d2 = d2b4[(trailing >> 30) & 0x3ff];
- d3 = d2b3[(trailing >> 20) & 0x3ff];
- d4 = d2b2[(trailing >> 10) & 0x3ff];
- d5 = d2b[(trailing) & 0x3ff];
- bcoeff = (d5 + d4 + d3) + d2 + d1 + d0;
- exp += (comb & 0xff);
- mask = 1;
- mask <<= 53;
- if (bcoeff < mask) { /* check whether coefficient fits in 10*5+3 bits */
- res = exp;
- res <<= 53;
- res |= (bcoeff | sign);
- *pres = res;
- return;
- }
- /* special format */
- res = (exp << 51) | (sign | 0x6000000000000000ull);
- /* add coeff, without leading bits */
- mask = (mask >> 2) - 1;
- bcoeff &= mask;
- res |= bcoeff;
}
+ /* normal number */
+ if ((comb & 0x1800) == 0x1800) { /* G0..G1 = 11 -> d0 = 8 + G4 */
+ d0 = d2b6[((comb >> 8) & 1) | 8]; /* d0 = (comb & 0x0100 ? 9 : 8); */
+ exp = (comb & 0x600) >> 1; /* exp = (comb & 0x0400 ? 1 : 0) * 0x200 +
+ (comb & 0x0200 ? 1 : 0) * 0x100; exp leading bits are G2..G3 */
+ } else {
+ d0 = d2b6[(comb >> 8) & 0x7];
+ exp = (comb & 0x1800) >> 3; /* exp = (comb & 0x1000 ? 1 : 0) * 0x200 +
+ (comb & 0x0800 ? 1 : 0) * 0x100; exp loading bits are G0..G1 */
+ }
+ d1 = d2b5[(trailing >> 40) & 0x3ff];
+ d2 = d2b4[(trailing >> 30) & 0x3ff];
+ d3 = d2b3[(trailing >> 20) & 0x3ff];
+ d4 = d2b2[(trailing >> 10) & 0x3ff];
+ d5 = d2b[(trailing) & 0x3ff];
+ bcoeff = (d5 + d4 + d3) + d2 + d1 + d0;
+ exp += (comb & 0xff);
+ mask = 1;
+ mask <<= 53;
+ if (bcoeff < mask) { /* check whether coefficient fits in 10*5+3 bits */
+ res = exp;
+ res <<= 53;
+ res |= (bcoeff | sign);
+ *pres = res;
+ return;
+ }
+ /* special format */
+ res = (exp << 51) | (sign | 0x6000000000000000ull);
+ /* add coeff, without leading bits */
+ mask = (mask >> 2) - 1;
+ bcoeff &= mask;
+ res |= bcoeff;
*pres = res;
}
@@ -304,15 +296,7 @@ _bid_to_dpd128 (_Decimal128 *pres, _Decimal128 *px) {
comb = (x.w[1] /*& 0x7fffc00000000000ull */ ) >> 46;
exp = 0;
if ((comb & 0x1e000) == 0x1e000) {
- if ((comb & 0x1f000) == 0x1f000) { /* G0..G4 = 11111 -> NaN */
- if (comb & 0x01000) { /* G5 = 1 -> sNaN */
- res = x;
- } else { /* G5 = 0 -> qNaN */
- res = x;
- }
- } else { /* G0..G4 = 11110 -> INF */
- res = x;
- }
+ res = x;
} else { /* normal number */
exp = ((x.w[1] & 0x7fff000000000000ull) >> 49) & 0x3fff;
bcoeff.w[1] = (x.w[1] & 0x0001ffffffffffffull);
@@ -347,16 +331,16 @@ _bid_to_dpd128 (_Decimal128 *pres, _Decimal128 *px) {
BLL32 -= (unsigned int) k9 *1000000;
k10 = ((UINT64) BLL32 * d103) >> (32 + 8);
k11 = BLL32 - (unsigned int) k10 *1000;
- dcoeff.w[1] = (b2d[k5] >> 4) | (b2d[k4] << 6) | (b2d[k3] << 16) |
- (b2d[k2] << 26) | (b2d[k1] << 36);
- dcoeff.w[0] = b2d[k11] | (b2d[k10] << 10) | (b2d[k9] << 20) |
- (b2d[k8] << 30) | (b2d[k7] << 40) | (b2d[k6] << 50) | (b2d[k5] << 60);
+ dcoeff.w[1] = (b2d[k5] >> 4) | (b2d[k4] << 6) | (b2d[k3] << 16) |
+ (b2d[k2] << 26) | (b2d[k1] << 36);
+ dcoeff.w[0] = b2d[k11] | (b2d[k10] << 10) | (b2d[k9] << 20) |
+ (b2d[k8] << 30) | (b2d[k7] << 40) | (b2d[k6] << 50) | (b2d[k5] << 60);
res.w[0] = dcoeff.w[0];
if (k0 >= 8) {
- res.w[1] = sign.w[1] | ((0x18000 | ((exp >> 12) << 13) |
+ res.w[1] = sign.w[1] | ((0x18000 | ((exp >> 12) << 13) |
((k0 & 1) << 12) | (exp & 0xfff)) << 46) | dcoeff.w[1];
} else {
- res.w[1] = sign.w[1] | ((((exp >> 12) << 15) | (k0 << 12) |
+ res.w[1] = sign.w[1] | ((((exp >> 12) << 15) | (k0 << 12) |
(exp & 0xfff)) << 46) | dcoeff.w[1];
}
}
@@ -382,42 +366,33 @@ _dpd_to_bid128 (_Decimal128 *pres, _Decimal128 *px) {
trailing.w[1] = x.w[1];
trailing.w[0] = x.w[0];
if ((comb & 0x1e000) == 0x1e000) {
- if ((comb & 0x1f000) == 0x1f000) { /* G0..G4 = 11111 -> NaN */
- if (comb & 0x01000) { /* G5 = 1 -> sNaN */
- *pres = x;
- } else { /* G5 = 0 -> qNaN */
- *pres = x;
- }
- } else { /* G0..G4 = 11110 -> INF */
*pres = x;
- }
- return;
- } else { /* Normal number */
- if ((comb & 0x18000) == 0x18000) { /* G0..G1 = 11 -> d0 = 8 + G4 */
- d0 = d2b6[8 + ((comb & 0x01000) >> 12)];
- exp = (comb & 0x06000) >> 1; /* exp leading bits are G2..G3 */
- } else {
- d0 = d2b6[((comb & 0x07000) >> 12)];
- exp = (comb & 0x18000) >> 3; /* exp loading bits are G0..G1 */
- }
- d11 = d2b[(trailing.w[0]) & 0x3ff];
- d10 = d2b2[(trailing.w[0] >> 10) & 0x3ff];
- d9 = d2b3[(trailing.w[0] >> 20) & 0x3ff];
- d8 = d2b4[(trailing.w[0] >> 30) & 0x3ff];
- d7 = d2b5[(trailing.w[0] >> 40) & 0x3ff];
- d6 = d2b6[(trailing.w[0] >> 50) & 0x3ff];
- d5 = d2b[(trailing.w[0] >> 60) | ((trailing.w[1] & 0x3f) << 4)];
- d4 = d2b2[(trailing.w[1] >> 6) & 0x3ff];
- d3 = d2b3[(trailing.w[1] >> 16) & 0x3ff];
- d2 = d2b4[(trailing.w[1] >> 26) & 0x3ff];
- d1 = d2b5[(trailing.w[1] >> 36) & 0x3ff];
- tl = d11 + d10 + d9 + d8 + d7 + d6;
- th = d5 + d4 + d3 + d2 + d1 + d0;
- __mul_64x64_to_128 (bcoeff, th, 1000000000000000000ull);
- __add_128_64 (bcoeff, bcoeff, tl);
- exp += (comb & 0xfff);
- res.w[0] = bcoeff.w[0];
- res.w[1] = (exp << 49) | sign.w[1] | bcoeff.w[1];
+ return;
+ }
+ if ((comb & 0x18000) == 0x18000) { /* G0..G1 = 11 -> d0 = 8 + G4 */
+ d0 = d2b6[8 + ((comb & 0x01000) >> 12)];
+ exp = (comb & 0x06000) >> 1; /* exp leading bits are G2..G3 */
+ } else {
+ d0 = d2b6[((comb & 0x07000) >> 12)];
+ exp = (comb & 0x18000) >> 3; /* exp loading bits are G0..G1 */
}
+ d11 = d2b[(trailing.w[0]) & 0x3ff];
+ d10 = d2b2[(trailing.w[0] >> 10) & 0x3ff];
+ d9 = d2b3[(trailing.w[0] >> 20) & 0x3ff];
+ d8 = d2b4[(trailing.w[0] >> 30) & 0x3ff];
+ d7 = d2b5[(trailing.w[0] >> 40) & 0x3ff];
+ d6 = d2b6[(trailing.w[0] >> 50) & 0x3ff];
+ d5 = d2b[(trailing.w[0] >> 60) | ((trailing.w[1] & 0x3f) << 4)];
+ d4 = d2b2[(trailing.w[1] >> 6) & 0x3ff];
+ d3 = d2b3[(trailing.w[1] >> 16) & 0x3ff];
+ d2 = d2b4[(trailing.w[1] >> 26) & 0x3ff];
+ d1 = d2b5[(trailing.w[1] >> 36) & 0x3ff];
+ tl = d11 + d10 + d9 + d8 + d7 + d6;
+ th = d5 + d4 + d3 + d2 + d1 + d0;
+ __mul_64x64_to_128 (bcoeff, th, 1000000000000000000ull);
+ __add_128_64 (bcoeff, bcoeff, tl);
+ exp += (comb & 0xfff);
+ res.w[0] = bcoeff.w[0];
+ res.w[1] = (exp << 49) | sign.w[1] | bcoeff.w[1];
*pres = res;
}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 1b5d2b5a17d..fc7b878d95c 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,87 @@
+2017-07-28 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/rs6000/ibm-ldouble.c: Disable if defined __rtems__.
+
+2017-07-24 Daniel Santos <daniel.santos@pobox.com>
+
+ PR testsuite/80759
+ * config.host: include i386/t-msabi for darwin and solaris.
+ * config/i386/i386-asm.h
+ (ELFFN): Rename to FN_TYPE.
+ (FN_SIZE): New macro.
+ (FN_HIDDEN): Likewise.
+ (ASMNAME): Likewise.
+ (FUNC_START): Rename to FUNC_BEGIN, use ASMNAME, replace .global with
+ .globl.
+ (HIDDEN_FUNC): Use ASMNAME and .globl instead of .global.
+ (SSE_SAVE): Convert to cpp macro, hard-code offset (always 0x60).
+ * config/i386/resms64.S: Use SSE_SAVE as cpp macro instead of gas
+ .macro.
+ * config/i386/resms64f.S: Likewise.
+ * config/i386/resms64fx.S: Likewise.
+ * config/i386/resms64x.S: Likewise.
+ * config/i386/savms64.S: Likewise.
+ * config/i386/savms64f.S: Likewise.
+
+2017-07-19 John Marino <gnugcc@marino.st>
+
+ * config/i386/dragonfly-unwind.h: Handle sigtramp relocation.
+
+2017-07-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/81193
+ * configure.ac (PowerPC float128 hardware support): Test whether
+ we can use __builtin_cpu_supports before enabling the ifunc
+ handler.
+ * configure: Regenerate.
+
+2017-07-10 Vineet Gupta <vgupta@synopsys.com>
+
+ * config.host: Remove uclibc from arc target spec.
+
+2017-07-09 Krister Walfridsson <krister.walfridsson@gmail.com>
+
+ * config.host (*-*-netbsd*): Remove check for aout NetBSD releases.
+
+2017-07-07 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/float128-ifunc.c: Don't include auxv.h.
+ (have_ieee_hw_p): Delete function.
+ (SW_OR_HW) Use __builtin_cpu_supports().
+
+2017-07-06 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/lib1funcs.S: Defined __ARM_ARCH__ to 8 for ARMv8-R.
+
+2017-07-03 Olivier Hainque <hainque@adacore.com>
+
+ * config/t-vxworks7: New file, really.
+
+2017-06-28 Joseph Myers <joseph@codesourcery.com>
+
+ * config/aarch64/linux-unwind.h (aarch64_fallback_frame_state),
+ config/alpha/linux-unwind.h (alpha_fallback_frame_state),
+ config/bfin/linux-unwind.h (bfin_fallback_frame_state),
+ config/i386/linux-unwind.h (x86_64_fallback_frame_state,
+ x86_fallback_frame_state), config/m68k/linux-unwind.h (struct
+ uw_ucontext), config/nios2/linux-unwind.h (struct nios2_ucontext),
+ config/pa/linux-unwind.h (pa32_fallback_frame_state),
+ config/riscv/linux-unwind.h (riscv_fallback_frame_state),
+ config/sh/linux-unwind.h (sh_fallback_frame_state),
+ config/tilepro/linux-unwind.h (tile_fallback_frame_state),
+ config/xtensa/linux-unwind.h (xtensa_fallback_frame_state): Use
+ ucontext_t instead of struct ucontext.
+
+2017-06-27 Jerome Lambourg <lambourg@adacore.com>
+
+ * config.host (i*86-wrs-vxworks7): Handle new acceptable triplet.
+ (x86_64-wrs-vxworks7): Likewise.
+
+2017-06-27 Olivier Hainque <hainque@adacore.com>
+
+ * config/t-vxworks7: New file.
+ * config.host (*-*-vxworks7): Use it.
+
2017-06-22 Matt Turner <mattst88@gmail.com>
* config/i386/cpuinfo.c (get_intel_cpu): Add Kaby Lake models to
diff --git a/libgcc/config.host b/libgcc/config.host
index 7711abf2704..ae8836e8891 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -250,14 +250,7 @@ case ${host} in
tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip"
tmake_file="$tmake_file t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
tmake_file="$tmake_file t-slibgcc-libgcc"
- # NetBSD 1.7 and later are set up to use GCC's crtstuff for
- # ELF configurations. We will clear extra_parts in the
- # a.out configurations.
- case ${host} in
- *-*-netbsd*1.[7-9]* | *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
- ;;
- esac
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
;;
*-*-openbsd*)
tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip"
@@ -312,6 +305,9 @@ case ${host} in
tmake_file="vms/t-vms"
extra_parts="crt0.o crtbegin.o crtbeginS.o crtend.o crtendS.o"
;;
+*-*-vxworks7)
+ tmake_file=t-vxworks7
+ ;;
*-*-vxworks*)
tmake_file=t-vxworks
;;
@@ -387,7 +383,7 @@ arc*-*-elf*)
extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o"
extra_parts="$extra_parts crttls.o"
;;
-arc*-*-linux-uclibc*)
+arc*-*-linux*)
tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc-uClibc arc/t-arc"
extra_parts="$extra_parts crti.o crtn.o"
extra_parts="$extra_parts crttls.o"
@@ -585,12 +581,12 @@ hppa*-*-openbsd*)
tmake_file="$tmake_file pa/t-openbsd"
;;
i[34567]86-*-darwin*)
- tmake_file="$tmake_file i386/t-crtpc t-crtfm"
+ tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
x86_64-*-darwin*)
- tmake_file="$tmake_file i386/t-crtpc t-crtfm"
+ tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
@@ -667,12 +663,12 @@ i[34567]86-*-rtems*)
extra_parts="$extra_parts crti.o crtn.o"
;;
i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
- tmake_file="$tmake_file i386/t-crtpc t-crtfm"
+ tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
tm_file="${tm_file} i386/elf-lib.h"
md_unwind_header=i386/sol2-unwind.h
;;
-i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
+i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae|i[4567]86-wrs-vxworks7|x86_64-wrs-vxworks7)
;;
i[34567]86-*-cygwin*)
extra_parts="crtbegin.o crtbeginS.o crtend.o crtfastmath.o"
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index d5d6980442f..d46d5f53be3 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -55,7 +55,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context,
struct rt_sigframe
{
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
};
struct rt_sigframe *rt_;
diff --git a/libgcc/config/alpha/linux-unwind.h b/libgcc/config/alpha/linux-unwind.h
index a91a5f4fe26..7202516581d 100644
--- a/libgcc/config/alpha/linux-unwind.h
+++ b/libgcc/config/alpha/linux-unwind.h
@@ -51,7 +51,7 @@ alpha_fallback_frame_state (struct _Unwind_Context *context,
{
struct rt_sigframe {
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_ = context->cfa;
sc = &rt_->uc.uc_mcontext;
}
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index 89ebebcd68a..8d8c3cead5f 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -109,7 +109,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
#if defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8M_BASE__) \
- || defined(__ARM_ARCH_8M_MAIN__)
+ || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8R__)
# define __ARM_ARCH__ 8
#endif
diff --git a/libgcc/config/bfin/linux-unwind.h b/libgcc/config/bfin/linux-unwind.h
index 9412c7652b8..37e9feb6965 100644
--- a/libgcc/config/bfin/linux-unwind.h
+++ b/libgcc/config/bfin/linux-unwind.h
@@ -52,7 +52,7 @@ bfin_fallback_frame_state (struct _Unwind_Context *context,
void *puc;
char retcode[8];
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_ = context->cfa;
/* The void * cast is necessary to avoid an aliasing warning.
diff --git a/libgcc/config/i386/dragonfly-unwind.h b/libgcc/config/i386/dragonfly-unwind.h
index 18b90fcae56..ca1f46e92db 100644
--- a/libgcc/config/i386/dragonfly-unwind.h
+++ b/libgcc/config/i386/dragonfly-unwind.h
@@ -28,9 +28,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/param.h>
#include <signal.h>
#include <sys/ucontext.h>
#include <machine/sigframe.h>
+#if __DragonFly_version > 400800
+#include <sys/kinfo.h>
+#endif
#define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg
@@ -39,20 +43,44 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
-static void
-x86_64_sigtramp_range (unsigned char **start, unsigned char **end)
+static int
+x86_64_outside_sigtramp_range (unsigned char *pc)
{
- unsigned long ps_strings;
- int mib[2];
- size_t len;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PS_STRINGS;
- len = sizeof (ps_strings);
- sysctl (mib, 2, &ps_strings, &len, NULL, 0);
-
- *start = (unsigned char *)ps_strings - 32;
- *end = (unsigned char *)ps_strings;
+ static int sigtramp_range_determined = 0;
+ static unsigned char *sigtramp_start, *sigtramp_end;
+
+ if (sigtramp_range_determined == 0)
+ {
+#if __DragonFly_version > 400800
+ struct kinfo_sigtramp kst = {0};
+ size_t len = sizeof (kst);
+ int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP };
+
+ sigtramp_range_determined = 1;
+ if (sysctl (mib, 3, &kst, &len, NULL, 0) == 0)
+ {
+ sigtramp_range_determined = 2;
+ sigtramp_start = kst.ksigtramp_start;
+ sigtramp_end = kst.ksigtramp_end;
+ }
+#else
+ unsigned long ps_strings;
+ size_t len = sizeof (ps_strings);
+ int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
+
+ sigtramp_range_determined = 1;
+ if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
+ {
+ sigtramp_range_determined = 2;
+ sigtramp_start = (unsigned char *)ps_strings - 32;
+ sigtramp_end = (unsigned char *)ps_strings;
+ }
+#endif
+ }
+ if (sigtramp_range_determined < 2) /* sysctl failed if < 2 */
+ return 1;
+
+ return (pc < sigtramp_start || pc >= sigtramp_end );
}
@@ -60,13 +88,10 @@ static _Unwind_Reason_Code
x86_64_dragonfly_fallback_frame_state
(struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
- unsigned char *pc = context->ra;
- unsigned char *sigtramp_start, *sigtramp_end;
struct sigframe *sf;
long new_cfa;
- x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end);
- if (pc >= sigtramp_end || pc < sigtramp_start)
+ if (x86_64_outside_sigtramp_range(context->ra))
return _URC_END_OF_STACK;
sf = (struct sigframe *) context->cfa;
diff --git a/libgcc/config/i386/i386-asm.h b/libgcc/config/i386/i386-asm.h
index c613e9fd83d..1387fd24b4f 100644
--- a/libgcc/config/i386/i386-asm.h
+++ b/libgcc/config/i386/i386-asm.h
@@ -26,22 +26,45 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef I386_ASM_H
#define I386_ASM_H
+#include "auto-host.h"
+
+/* These macros currently support GNU/Linux, Solaris and Darwin. */
+
#ifdef __ELF__
-# define ELFFN(fn) .type fn,@function
+# define FN_TYPE(fn) .type fn,@function
+# define FN_SIZE(fn) .size fn,.-fn
+# ifdef HAVE_GAS_HIDDEN
+# define FN_HIDDEN(fn) .hidden fn
+# endif
+#else
+# define FN_TYPE(fn)
+# define FN_SIZE(fn)
+#endif
+
+#ifndef FN_HIDDEN
+# define FN_HIDDEN(fn)
+#endif
+
+#ifdef __USER_LABEL_PREFIX__
+# define ASMNAME2(prefix, name) prefix ## name
+# define ASMNAME1(prefix, name) ASMNAME2(prefix, name)
+# define ASMNAME(name) ASMNAME1(__USER_LABEL_PREFIX__, name)
#else
-# define ELFFN(fn)
+# define ASMNAME(name) name
#endif
-#define FUNC_START(fn) \
- .global fn; \
- ELFFN (fn); \
-fn:
+#define FUNC_BEGIN(fn) \
+ .globl ASMNAME(fn); \
+ FN_TYPE (ASMNAME(fn)); \
+ASMNAME(fn):
-#define HIDDEN_FUNC(fn)\
- FUNC_START (fn) \
- .hidden fn; \
+#define HIDDEN_FUNC(fn) \
+ .globl ASMNAME(fn); \
+ FN_TYPE(ASMNAME(fn)); \
+ FN_HIDDEN(ASMNAME(fn)); \
+ASMNAME(fn):
-#define FUNC_END(fn) .size fn,.-fn
+#define FUNC_END(fn) FN_SIZE(ASMNAME(fn))
#ifdef __SSE2__
# ifdef __AVX__
@@ -51,32 +74,30 @@ fn:
# endif
/* Save SSE registers 6-15. off is the offset of rax to get to xmm6. */
-.macro SSE_SAVE off=0
- MOVAPS %xmm15,(\off - 0x90)(%rax)
- MOVAPS %xmm14,(\off - 0x80)(%rax)
- MOVAPS %xmm13,(\off - 0x70)(%rax)
- MOVAPS %xmm12,(\off - 0x60)(%rax)
- MOVAPS %xmm11,(\off - 0x50)(%rax)
- MOVAPS %xmm10,(\off - 0x40)(%rax)
- MOVAPS %xmm9, (\off - 0x30)(%rax)
- MOVAPS %xmm8, (\off - 0x20)(%rax)
- MOVAPS %xmm7, (\off - 0x10)(%rax)
- MOVAPS %xmm6, \off(%rax)
-.endm
+#define SSE_SAVE \
+ MOVAPS %xmm15,-0x30(%rax); \
+ MOVAPS %xmm14,-0x20(%rax); \
+ MOVAPS %xmm13,-0x10(%rax); \
+ MOVAPS %xmm12, (%rax); \
+ MOVAPS %xmm11, 0x10(%rax); \
+ MOVAPS %xmm10, 0x20(%rax); \
+ MOVAPS %xmm9, 0x30(%rax); \
+ MOVAPS %xmm8, 0x40(%rax); \
+ MOVAPS %xmm7, 0x50(%rax); \
+ MOVAPS %xmm6, 0x60(%rax)
/* Restore SSE registers 6-15. off is the offset of rsi to get to xmm6. */
-.macro SSE_RESTORE off=0
- MOVAPS (\off - 0x90)(%rsi), %xmm15
- MOVAPS (\off - 0x80)(%rsi), %xmm14
- MOVAPS (\off - 0x70)(%rsi), %xmm13
- MOVAPS (\off - 0x60)(%rsi), %xmm12
- MOVAPS (\off - 0x50)(%rsi), %xmm11
- MOVAPS (\off - 0x40)(%rsi), %xmm10
- MOVAPS (\off - 0x30)(%rsi), %xmm9
- MOVAPS (\off - 0x20)(%rsi), %xmm8
- MOVAPS (\off - 0x10)(%rsi), %xmm7
- MOVAPS \off(%rsi), %xmm6
-.endm
+#define SSE_RESTORE \
+ MOVAPS -0x30(%rsi), %xmm15; \
+ MOVAPS -0x20(%rsi), %xmm14; \
+ MOVAPS -0x10(%rsi), %xmm13; \
+ MOVAPS (%rsi), %xmm12; \
+ MOVAPS 0x10(%rsi), %xmm11; \
+ MOVAPS 0x20(%rsi), %xmm10; \
+ MOVAPS 0x30(%rsi), %xmm9 ; \
+ MOVAPS 0x40(%rsi), %xmm8 ; \
+ MOVAPS 0x50(%rsi), %xmm7 ; \
+ MOVAPS 0x60(%rsi), %xmm6
#endif /* __SSE2__ */
#endif /* I386_ASM_H */
diff --git a/libgcc/config/i386/linux-unwind.h b/libgcc/config/i386/linux-unwind.h
index b1d5040a687..2009ad72260 100644
--- a/libgcc/config/i386/linux-unwind.h
+++ b/libgcc/config/i386/linux-unwind.h
@@ -58,7 +58,7 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context,
if (*(unsigned char *)(pc+0) == 0x48
&& *(unsigned long long *)(pc+1) == RT_SIGRETURN_SYSCALL)
{
- struct ucontext *uc_ = context->cfa;
+ ucontext_t *uc_ = context->cfa;
/* The void * cast is necessary to avoid an aliasing warning.
The aliasing warning is correct, but should not be a problem
because it does not alias anything. */
@@ -138,7 +138,7 @@ x86_fallback_frame_state (struct _Unwind_Context *context,
siginfo_t *pinfo;
void *puc;
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_ = context->cfa;
/* The void * cast is necessary to avoid an aliasing warning.
The aliasing warning is correct, but should not be a problem
diff --git a/libgcc/config/i386/resms64.S b/libgcc/config/i386/resms64.S
index f47e2f066fb..f842c20a77a 100644
--- a/libgcc/config/i386/resms64.S
+++ b/libgcc/config/i386/resms64.S
@@ -43,7 +43,7 @@ HIDDEN_FUNC(__resms64_13)
mov -0x48(%rsi),%rbx
HIDDEN_FUNC(__resms64_12)
mov -0x40(%rsi),%rdi
- SSE_RESTORE off=0x60
+ SSE_RESTORE
mov -0x38(%rsi),%rsi
ret
FUNC_END(__resms64_12)
diff --git a/libgcc/config/i386/resms64f.S b/libgcc/config/i386/resms64f.S
index 817da60cf15..81946cda944 100644
--- a/libgcc/config/i386/resms64f.S
+++ b/libgcc/config/i386/resms64f.S
@@ -42,7 +42,7 @@ HIDDEN_FUNC(__resms64f_13)
mov -0x48(%rsi),%rbx
HIDDEN_FUNC(__resms64f_12)
mov -0x40(%rsi),%rdi
- SSE_RESTORE off=0x60
+ SSE_RESTORE
mov -0x38(%rsi),%rsi
ret
FUNC_END(__resms64f_12)
diff --git a/libgcc/config/i386/resms64fx.S b/libgcc/config/i386/resms64fx.S
index 5dba5848dee..acf34fa0837 100644
--- a/libgcc/config/i386/resms64fx.S
+++ b/libgcc/config/i386/resms64fx.S
@@ -43,7 +43,7 @@ HIDDEN_FUNC(__resms64fx_13)
mov -0x48(%rsi),%rbx
HIDDEN_FUNC(__resms64fx_12)
mov -0x40(%rsi),%rdi
- SSE_RESTORE off=0x60
+ SSE_RESTORE
mov -0x38(%rsi),%rsi
leaveq
ret
diff --git a/libgcc/config/i386/resms64x.S b/libgcc/config/i386/resms64x.S
index 7770447cf38..e27aab7d881 100644
--- a/libgcc/config/i386/resms64x.S
+++ b/libgcc/config/i386/resms64x.S
@@ -44,7 +44,7 @@ HIDDEN_FUNC(__resms64x_13)
mov -0x48(%rsi),%rbx
HIDDEN_FUNC(__resms64x_12)
mov -0x40(%rsi),%rdi
- SSE_RESTORE off=0x60
+ SSE_RESTORE
mov -0x38(%rsi),%rsi
mov %r10,%rsp
ret
diff --git a/libgcc/config/i386/savms64.S b/libgcc/config/i386/savms64.S
index 2067dd8614f..44dda46ec54 100644
--- a/libgcc/config/i386/savms64.S
+++ b/libgcc/config/i386/savms64.S
@@ -44,7 +44,7 @@ HIDDEN_FUNC(__savms64_13)
HIDDEN_FUNC(__savms64_12)
mov %rdi,-0x40(%rax)
mov %rsi,-0x38(%rax)
- SSE_SAVE off=0x60
+ SSE_SAVE
ret
FUNC_END(__savms64_12)
FUNC_END(__savms64_13)
diff --git a/libgcc/config/i386/savms64f.S b/libgcc/config/i386/savms64f.S
index 81583b6eb68..64e91ac0394 100644
--- a/libgcc/config/i386/savms64f.S
+++ b/libgcc/config/i386/savms64f.S
@@ -43,7 +43,7 @@ HIDDEN_FUNC(__savms64f_13)
HIDDEN_FUNC(__savms64f_12)
mov %rdi,-0x40(%rax)
mov %rsi,-0x38(%rax)
- SSE_SAVE off=0x60
+ SSE_SAVE
ret
FUNC_END(__savms64f_12)
FUNC_END(__savms64f_13)
diff --git a/libgcc/config/m68k/linux-unwind.h b/libgcc/config/m68k/linux-unwind.h
index 82c7a297a6d..9ea39d454aa 100644
--- a/libgcc/config/m68k/linux-unwind.h
+++ b/libgcc/config/m68k/linux-unwind.h
@@ -33,7 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* <sys/ucontext.h> is unfortunately broken right now. */
struct uw_ucontext {
unsigned long uc_flags;
- struct ucontext *uc_link;
+ ucontext_t *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
unsigned long uc_filler[80];
diff --git a/libgcc/config/nios2/linux-unwind.h b/libgcc/config/nios2/linux-unwind.h
index ae82efd6de6..204359d7b92 100644
--- a/libgcc/config/nios2/linux-unwind.h
+++ b/libgcc/config/nios2/linux-unwind.h
@@ -38,7 +38,7 @@ struct nios2_mcontext {
struct nios2_ucontext {
unsigned long uc_flags;
- struct ucontext *uc_link;
+ ucontext_t *uc_link;
stack_t uc_stack;
struct nios2_mcontext uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
diff --git a/libgcc/config/pa/linux-unwind.h b/libgcc/config/pa/linux-unwind.h
index 580c18dad69..c2c3409bcc1 100644
--- a/libgcc/config/pa/linux-unwind.h
+++ b/libgcc/config/pa/linux-unwind.h
@@ -80,7 +80,7 @@ pa32_fallback_frame_state (struct _Unwind_Context *context,
struct sigcontext *sc;
struct rt_sigframe {
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *frame;
/* rt_sigreturn trampoline:
diff --git a/libgcc/config/riscv/linux-unwind.h b/libgcc/config/riscv/linux-unwind.h
index a051a2869d4..1c8aeff7ef0 100644
--- a/libgcc/config/riscv/linux-unwind.h
+++ b/libgcc/config/riscv/linux-unwind.h
@@ -42,7 +42,7 @@ riscv_fallback_frame_state (struct _Unwind_Context *context,
struct rt_sigframe
{
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
};
struct rt_sigframe *rt_;
diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c
index e456ab13ce8..882c56ef21e 100644
--- a/libgcc/config/rs6000/float128-ifunc.c
+++ b/libgcc/config/rs6000/float128-ifunc.c
@@ -45,47 +45,7 @@
#error "This module must not be compiled with IEEE 128-bit hardware support"
#endif
-#include <sys/auxv.h>
-
-/* Use the namespace clean version of getauxval. However, not all versions of
- sys/auxv.h declare it, so declare it here. This code is intended to be
- temporary until a suitable version of __builtin_cpu_supports is added that
- allows us to tell quickly if the machine supports IEEE 128-bit hardware. */
-extern unsigned long __getauxval (unsigned long);
-
-static int
-have_ieee_hw_p (void)
-{
- static int ieee_hw_p = -1;
-
- if (ieee_hw_p < 0)
- {
- char *p = (char *) __getauxval (AT_PLATFORM);
-
- ieee_hw_p = 0;
-
- /* Don't use atoi/strtol/strncmp/etc. These may require the normal
- environment to be setup to set errno to 0, and the ifunc resolvers run
- before the whole glibc environment is initialized. */
- if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e'
- && p[4] == 'r')
- {
- long n = 0;
- char ch;
-
- p += 5;
- while ((ch = *p++) >= '0' && (ch <= '9'))
- n = (n * 10) + (ch - '0');
-
- if (n >= 9)
- ieee_hw_p = 1;
- }
- }
-
- return ieee_hw_p;
-}
-
-#define SW_OR_HW(SW, HW) (have_ieee_hw_p () ? HW : SW)
+#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
/* Resolvers. */
diff --git a/libgcc/config/rs6000/ibm-ldouble.c b/libgcc/config/rs6000/ibm-ldouble.c
index 949b50c98ca..e99652e523f 100644
--- a/libgcc/config/rs6000/ibm-ldouble.c
+++ b/libgcc/config/rs6000/ibm-ldouble.c
@@ -45,7 +45,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
This code currently assumes the most significant double is in
the lower numbered register or lower addressed memory. */
-#if defined (__MACH__) || defined (__powerpc__) || defined (_AIX)
+#if (defined (__MACH__) || defined (__powerpc__) || defined (_AIX)) \
+ && !defined (__rtems__)
#define fabs(x) __builtin_fabs(x)
#define isless(x, y) __builtin_isless (x, y)
diff --git a/libgcc/config/sh/linux-unwind.h b/libgcc/config/sh/linux-unwind.h
index 1038caeb5c3..a8c98220282 100644
--- a/libgcc/config/sh/linux-unwind.h
+++ b/libgcc/config/sh/linux-unwind.h
@@ -82,7 +82,7 @@ sh_fallback_frame_state (struct _Unwind_Context *context,
{
struct rt_sigframe {
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_ = context->cfa;
/* The void * cast is necessary to avoid an aliasing warning.
The aliasing warning is correct, but should not be a problem
diff --git a/libgcc/config/t-vxworks7 b/libgcc/config/t-vxworks7
new file mode 100644
index 00000000000..77591cd642c
--- /dev/null
+++ b/libgcc/config/t-vxworks7
@@ -0,0 +1,16 @@
+# Don't build libgcc.a with debug info
+LIBGCC2_DEBUG_CFLAGS =
+
+# Extra libgcc2 modules used by gthr-vxworks.h functions
+LIB2ADDEH += $(srcdir)/config/vxlib.c $(srcdir)/config/vxlib-tls.c
+
+# This ensures that the correct target headers are used; some
+# VxWorks system headers have names that collide with GCC's
+# internal (host) headers, e.g. regs.h.
+LIBGCC2_INCLUDES = -nostdinc \
+ -I$(VSB_DIR)/h -I$(VSB_DIR)/share/h \
+ `case "/$(MULTIDIR)" in \
+ */mrtp*) echo -I$(VSB_DIR)/usr/h/public -I$(VSB_DIR)/usr/h ;; \
+ *) echo -I$(VSB_DIR)/krnl/h/system -I$(VSB_DIR)/krnl/h/public ;; \
+ esac`
+
diff --git a/libgcc/config/tilepro/linux-unwind.h b/libgcc/config/tilepro/linux-unwind.h
index a8dc4405715..dba3b410279 100644
--- a/libgcc/config/tilepro/linux-unwind.h
+++ b/libgcc/config/tilepro/linux-unwind.h
@@ -61,7 +61,7 @@ tile_fallback_frame_state (struct _Unwind_Context *context,
struct rt_sigframe {
unsigned char save_area[C_ABI_SAVE_AREA_SIZE];
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_;
/* Return if this is not a signal handler. */
diff --git a/libgcc/config/xtensa/linux-unwind.h b/libgcc/config/xtensa/linux-unwind.h
index 67c272820d0..2cb9eb1f739 100644
--- a/libgcc/config/xtensa/linux-unwind.h
+++ b/libgcc/config/xtensa/linux-unwind.h
@@ -67,7 +67,7 @@ xtensa_fallback_frame_state (struct _Unwind_Context *context,
struct rt_sigframe {
siginfo_t info;
- struct ucontext uc;
+ ucontext_t uc;
} *rt_;
/* movi a2, __NR_rt_sigreturn; syscall */
diff --git a/libgcc/configure b/libgcc/configure
index 42dda7fbeec..15d34b27cc0 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4975,10 +4975,10 @@ esac
esac
case ${host} in
-# At present, we cannot turn -mfloat128 on via #pragma GCC target,
-# so just check if we have VSX (ISA 2.06) support to build the
-# software libraries, and whether the assembler can handle xsaddqp
-# for hardware support.
+# At present, we cannot turn -mfloat128 on via #pragma GCC target, so just
+# check if we have VSX (ISA 2.06) support to build the software libraries, and
+# whether the assembler can handle xsaddqp for hardware support. Also check if
+# a new glibc is being used so that __builtin_cpu_supports can be used.
powerpc*-*-linux*)
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -mabi=altivec -mvsx -mfloat128"
@@ -5013,6 +5013,9 @@ else
#ifndef AT_PLATFORM
#error "AT_PLATFORM is not defined"
#endif
+ #ifndef __BUILTIN_CPU_SUPPORTS__
+ #error "__builtin_cpu_supports is not available"
+ #endif
vector unsigned char add (vector unsigned char a, vector unsigned char b)
{
vector unsigned char ret;
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 6bcaad651ff..da499716f8c 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -376,10 +376,10 @@ esac
esac
case ${host} in
-# At present, we cannot turn -mfloat128 on via #pragma GCC target,
-# so just check if we have VSX (ISA 2.06) support to build the
-# software libraries, and whether the assembler can handle xsaddqp
-# for hardware support.
+# At present, we cannot turn -mfloat128 on via #pragma GCC target, so just
+# check if we have VSX (ISA 2.06) support to build the software libraries, and
+# whether the assembler can handle xsaddqp for hardware support. Also check if
+# a new glibc is being used so that __builtin_cpu_supports can be used.
powerpc*-*-linux*)
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -mabi=altivec -mvsx -mfloat128"
@@ -398,6 +398,9 @@ powerpc*-*-linux*)
#ifndef AT_PLATFORM
#error "AT_PLATFORM is not defined"
#endif
+ #ifndef __BUILTIN_CPU_SUPPORTS__
+ #error "__builtin_cpu_supports is not available"
+ #endif
vector unsigned char add (vector unsigned char a, vector unsigned char b)
{
vector unsigned char ret;
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index de85da9bef6..3b3cf7f86f9 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,164 @@
+2017-07-31 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/81581
+ * m4/ifuntion.m4 (name`'rtype_qual`_'atype_code): Perform check
+ for dim.
+ (`m'name`'rtype_qual`_'atype_code): Likewise. Change type of rank
+ and tim to index_type.
+ (`s'name`'rtype_qual`_'atype_code): Perform check for dim.
+ * generated/iall_i16.c: Regenerated.
+ * generated/iall_i1.c: Regenerated.
+ * generated/iall_i2.c: Regenerated.
+ * generated/iall_i4.c: Regenerated.
+ * generated/iall_i8.c: Regenerated.
+ * generated/iany_i16.c: Regenerated.
+ * generated/iany_i1.c: Regenerated.
+ * generated/iany_i2.c: Regenerated.
+ * generated/iany_i4.c: Regenerated.
+ * generated/iany_i8.c: Regenerated.
+ * generated/iparity_i16.c: Regenerated.
+ * generated/iparity_i1.c: Regenerated.
+ * generated/iparity_i2.c: Regenerated.
+ * generated/iparity_i4.c: Regenerated.
+ * generated/iparity_i8.c: Regenerated.
+ * generated/maxloc1_16_i16.c: Regenerated.
+ * generated/maxloc1_16_i1.c: Regenerated.
+ * generated/maxloc1_16_i2.c: Regenerated.
+ * generated/maxloc1_16_i4.c: Regenerated.
+ * generated/maxloc1_16_i8.c: Regenerated.
+ * generated/maxloc1_16_r10.c: Regenerated.
+ * generated/maxloc1_16_r16.c: Regenerated.
+ * generated/maxloc1_16_r4.c: Regenerated.
+ * generated/maxloc1_16_r8.c: Regenerated.
+ * generated/maxloc1_4_i16.c: Regenerated.
+ * generated/maxloc1_4_i1.c: Regenerated.
+ * generated/maxloc1_4_i2.c: Regenerated.
+ * generated/maxloc1_4_i4.c: Regenerated.
+ * generated/maxloc1_4_i8.c: Regenerated.
+ * generated/maxloc1_4_r10.c: Regenerated.
+ * generated/maxloc1_4_r16.c: Regenerated.
+ * generated/maxloc1_4_r4.c: Regenerated.
+ * generated/maxloc1_4_r8.c: Regenerated.
+ * generated/maxloc1_8_i16.c: Regenerated.
+ * generated/maxloc1_8_i1.c: Regenerated.
+ * generated/maxloc1_8_i2.c: Regenerated.
+ * generated/maxloc1_8_i4.c: Regenerated.
+ * generated/maxloc1_8_i8.c: Regenerated.
+ * generated/maxloc1_8_r10.c: Regenerated.
+ * generated/maxloc1_8_r16.c: Regenerated.
+ * generated/maxloc1_8_r4.c: Regenerated.
+ * generated/maxloc1_8_r8.c: Regenerated.
+ * generated/maxval_i16.c: Regenerated.
+ * generated/maxval_i1.c: Regenerated.
+ * generated/maxval_i2.c: Regenerated.
+ * generated/maxval_i4.c: Regenerated.
+ * generated/maxval_i8.c: Regenerated.
+ * generated/maxval_r10.c: Regenerated.
+ * generated/maxval_r16.c: Regenerated.
+ * generated/maxval_r4.c: Regenerated.
+ * generated/maxval_r8.c: Regenerated.
+ * generated/minloc1_16_i16.c: Regenerated.
+ * generated/minloc1_16_i1.c: Regenerated.
+ * generated/minloc1_16_i2.c: Regenerated.
+ * generated/minloc1_16_i4.c: Regenerated.
+ * generated/minloc1_16_i8.c: Regenerated.
+ * generated/minloc1_16_r10.c: Regenerated.
+ * generated/minloc1_16_r16.c: Regenerated.
+ * generated/minloc1_16_r4.c: Regenerated.
+ * generated/minloc1_16_r8.c: Regenerated.
+ * generated/minloc1_4_i16.c: Regenerated.
+ * generated/minloc1_4_i1.c: Regenerated.
+ * generated/minloc1_4_i2.c: Regenerated.
+ * generated/minloc1_4_i4.c: Regenerated.
+ * generated/minloc1_4_i8.c: Regenerated.
+ * generated/minloc1_4_r10.c: Regenerated.
+ * generated/minloc1_4_r16.c: Regenerated.
+ * generated/minloc1_4_r4.c: Regenerated.
+ * generated/minloc1_4_r8.c: Regenerated.
+ * generated/minloc1_8_i16.c: Regenerated.
+ * generated/minloc1_8_i1.c: Regenerated.
+ * generated/minloc1_8_i2.c: Regenerated.
+ * generated/minloc1_8_i4.c: Regenerated.
+ * generated/minloc1_8_i8.c: Regenerated.
+ * generated/minloc1_8_r10.c: Regenerated.
+ * generated/minloc1_8_r16.c: Regenerated.
+ * generated/minloc1_8_r4.c: Regenerated.
+ * generated/minloc1_8_r8.c: Regenerated.
+ * generated/minval_i16.c: Regenerated.
+ * generated/minval_i1.c: Regenerated.
+ * generated/minval_i2.c: Regenerated.
+ * generated/minval_i4.c: Regenerated.
+ * generated/minval_i8.c: Regenerated.
+ * generated/minval_r10.c: Regenerated.
+ * generated/minval_r16.c: Regenerated.
+ * generated/minval_r4.c: Regenerated.
+ * generated/minval_r8.c: Regenerated.
+ * generated/norm2_r10.c: Regenerated.
+ * generated/norm2_r16.c: Regenerated.
+ * generated/norm2_r4.c: Regenerated.
+ * generated/norm2_r8.c: Regenerated.
+ * generated/parity_l16.c: Regenerated.
+ * generated/parity_l1.c: Regenerated.
+ * generated/parity_l2.c: Regenerated.
+ * generated/parity_l4.c: Regenerated.
+ * generated/parity_l8.c: Regenerated.
+ * generated/product_c10.c: Regenerated.
+ * generated/product_c16.c: Regenerated.
+ * generated/product_c4.c: Regenerated.
+ * generated/product_c8.c: Regenerated.
+ * generated/product_i16.c: Regenerated.
+ * generated/product_i1.c: Regenerated.
+ * generated/product_i2.c: Regenerated.
+ * generated/product_i4.c: Regenerated.
+ * generated/product_i8.c: Regenerated.
+ * generated/product_r10.c: Regenerated.
+ * generated/product_r16.c: Regenerated.
+ * generated/product_r4.c: Regenerated.
+ * generated/product_r8.c: Regenerated.
+ * generated/sum_c10.c: Regenerated.
+ * generated/sum_c16.c: Regenerated.
+ * generated/sum_c4.c: Regenerated.
+ * generated/sum_c8.c: Regenerated.
+ * generated/sum_i16.c: Regenerated.
+ * generated/sum_i1.c: Regenerated.
+ * generated/sum_i2.c: Regenerated.
+ * generated/sum_i4.c: Regenerated.
+ * generated/sum_i8.c: Regenerated.
+ * generated/sum_r10.c: Regenerated.
+ * generated/sum_r16.c: Regenerated.
+ * generated/sum_r4.c: Regenerated.
+ * generated/sum_r8.c: Regenerated.
+
+2017-07-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/80365
+ * io/unix.c (buf_write): Return early if there is
+ nothing to write.
+
+2017-07-09 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * intrinsics/eoshift2.c (eoshift2): Use memcpy
+ for innermost copy where possible.
+ * m4/eoshift1.m4 (eoshift1): Likewise.
+ * m4/eoshift3.m4 (eoshift3): Likewise.
+ * generated/eoshift1_16.c: Regenerated.
+ * generated/eoshift1_4.c: Regenerated.
+ * generated/eoshift1_8.c: Regenerated.
+ * generated/eoshift3_16.c: Regenerated.
+ * generated/eoshift3_4.c: Regenerated.
+ * generated/eoshift3_8.c: Regenerated.
+
+2017-07-02 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * intrinsics/eoshift0.c: For contiguous arrays, use
+ block algorithm. Use memcpy where possible.
+
+2017-06-26 Jim Wilson <jim.wilson@r3-a15.aus-colo>
+
+ PR libfortran/81195
+ * io/unit.c (get_unit): Call __gthread_mutex_lock before newunit_stack
+ and newunit_tos references. Call __gthread_mutex_unlock afterward.
+
2017-06-24 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/52473
diff --git a/libgfortran/generated/eoshift1_16.c b/libgfortran/generated/eoshift1_16.c
index 09059497c82..fe2e8ef66ac 100644
--- a/libgfortran/generated/eoshift1_16.c
+++ b/libgfortran/generated/eoshift1_16.c
@@ -183,12 +183,23 @@ eoshift1 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/eoshift1_4.c b/libgfortran/generated/eoshift1_4.c
index 1be49325895..a90fc2176de 100644
--- a/libgfortran/generated/eoshift1_4.c
+++ b/libgfortran/generated/eoshift1_4.c
@@ -183,12 +183,23 @@ eoshift1 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/eoshift1_8.c b/libgfortran/generated/eoshift1_8.c
index 51968e5abcd..8be1e050e3d 100644
--- a/libgfortran/generated/eoshift1_8.c
+++ b/libgfortran/generated/eoshift1_8.c
@@ -183,12 +183,23 @@ eoshift1 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/eoshift3_16.c b/libgfortran/generated/eoshift3_16.c
index 8040b1e71d4..621fd6f0dc8 100644
--- a/libgfortran/generated/eoshift3_16.c
+++ b/libgfortran/generated/eoshift3_16.c
@@ -198,12 +198,24 @@ eoshift3 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
+
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/eoshift3_4.c b/libgfortran/generated/eoshift3_4.c
index be5827efd70..ac4fd67f3c7 100644
--- a/libgfortran/generated/eoshift3_4.c
+++ b/libgfortran/generated/eoshift3_4.c
@@ -198,12 +198,24 @@ eoshift3 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
+
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/eoshift3_8.c b/libgfortran/generated/eoshift3_8.c
index b3aff0f62c3..7e9d8b48475 100644
--- a/libgfortran/generated/eoshift3_8.c
+++ b/libgfortran/generated/eoshift3_8.c
@@ -198,12 +198,24 @@ eoshift3 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
+
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/generated/iall_i1.c b/libgfortran/generated/iall_i1.c
index 619c833c33b..3453fd20c0f 100644
--- a/libgfortran/generated/iall_i1.c
+++ b/libgfortran/generated/iall_i1.c
@@ -52,8 +52,15 @@ iall_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miall_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miall_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siall_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iall_i16.c b/libgfortran/generated/iall_i16.c
index 4d37d9c80bf..9f6747aa99d 100644
--- a/libgfortran/generated/iall_i16.c
+++ b/libgfortran/generated/iall_i16.c
@@ -52,8 +52,15 @@ iall_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miall_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miall_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siall_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iall_i2.c b/libgfortran/generated/iall_i2.c
index 283ceffb2c9..5ac86ab9cea 100644
--- a/libgfortran/generated/iall_i2.c
+++ b/libgfortran/generated/iall_i2.c
@@ -52,8 +52,15 @@ iall_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miall_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miall_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siall_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iall_i4.c b/libgfortran/generated/iall_i4.c
index ef0ac58d3b9..0d3ba8aebca 100644
--- a/libgfortran/generated/iall_i4.c
+++ b/libgfortran/generated/iall_i4.c
@@ -52,8 +52,15 @@ iall_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miall_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miall_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siall_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iall_i8.c b/libgfortran/generated/iall_i8.c
index ef780b01c71..d3424a07df7 100644
--- a/libgfortran/generated/iall_i8.c
+++ b/libgfortran/generated/iall_i8.c
@@ -52,8 +52,15 @@ iall_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miall_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miall_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siall_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IALL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iany_i1.c b/libgfortran/generated/iany_i1.c
index b60d4f2d383..1009c1803e2 100644
--- a/libgfortran/generated/iany_i1.c
+++ b/libgfortran/generated/iany_i1.c
@@ -52,8 +52,15 @@ iany_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miany_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miany_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siany_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iany_i16.c b/libgfortran/generated/iany_i16.c
index f8fb40acd1c..6910040aa02 100644
--- a/libgfortran/generated/iany_i16.c
+++ b/libgfortran/generated/iany_i16.c
@@ -52,8 +52,15 @@ iany_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miany_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miany_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siany_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iany_i2.c b/libgfortran/generated/iany_i2.c
index ef931b35a57..09d8cc4a5a5 100644
--- a/libgfortran/generated/iany_i2.c
+++ b/libgfortran/generated/iany_i2.c
@@ -52,8 +52,15 @@ iany_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miany_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miany_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siany_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iany_i4.c b/libgfortran/generated/iany_i4.c
index d0ecaef23d0..4d18e791835 100644
--- a/libgfortran/generated/iany_i4.c
+++ b/libgfortran/generated/iany_i4.c
@@ -52,8 +52,15 @@ iany_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miany_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miany_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siany_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iany_i8.c b/libgfortran/generated/iany_i8.c
index c963165cf18..e857424d750 100644
--- a/libgfortran/generated/iany_i8.c
+++ b/libgfortran/generated/iany_i8.c
@@ -52,8 +52,15 @@ iany_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miany_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miany_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siany_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IANY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iparity_i1.c b/libgfortran/generated/iparity_i1.c
index 18e9fc24be1..ff5fbeb496b 100644
--- a/libgfortran/generated/iparity_i1.c
+++ b/libgfortran/generated/iparity_i1.c
@@ -52,8 +52,15 @@ iparity_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miparity_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miparity_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siparity_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iparity_i16.c b/libgfortran/generated/iparity_i16.c
index 5b8ea697483..fcd7bef68a1 100644
--- a/libgfortran/generated/iparity_i16.c
+++ b/libgfortran/generated/iparity_i16.c
@@ -52,8 +52,15 @@ iparity_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miparity_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miparity_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siparity_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iparity_i2.c b/libgfortran/generated/iparity_i2.c
index 0076667caba..9aa34e07780 100644
--- a/libgfortran/generated/iparity_i2.c
+++ b/libgfortran/generated/iparity_i2.c
@@ -52,8 +52,15 @@ iparity_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miparity_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miparity_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siparity_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iparity_i4.c b/libgfortran/generated/iparity_i4.c
index 20798423f5c..71835df9f3e 100644
--- a/libgfortran/generated/iparity_i4.c
+++ b/libgfortran/generated/iparity_i4.c
@@ -52,8 +52,15 @@ iparity_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miparity_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miparity_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siparity_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/iparity_i8.c b/libgfortran/generated/iparity_i8.c
index 60e390e99b7..e04360c0f54 100644
--- a/libgfortran/generated/iparity_i8.c
+++ b/libgfortran/generated/iparity_i8.c
@@ -52,8 +52,15 @@ iparity_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ miparity_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ miparity_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ siparity_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in IPARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_i1.c b/libgfortran/generated/maxloc1_16_i1.c
index 48f2fc01e59..f6bab618c7a 100644
--- a/libgfortran/generated/maxloc1_16_i1.c
+++ b/libgfortran/generated/maxloc1_16_i1.c
@@ -52,8 +52,15 @@ maxloc1_16_i1 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_i1 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_i1 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_i1 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_i16.c b/libgfortran/generated/maxloc1_16_i16.c
index 6c154fb84e7..b3b8b36826f 100644
--- a/libgfortran/generated/maxloc1_16_i16.c
+++ b/libgfortran/generated/maxloc1_16_i16.c
@@ -52,8 +52,15 @@ maxloc1_16_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_i2.c b/libgfortran/generated/maxloc1_16_i2.c
index 029e061e43c..fb38b2b43aa 100644
--- a/libgfortran/generated/maxloc1_16_i2.c
+++ b/libgfortran/generated/maxloc1_16_i2.c
@@ -52,8 +52,15 @@ maxloc1_16_i2 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_i2 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_i2 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_i2 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_i4.c b/libgfortran/generated/maxloc1_16_i4.c
index aceb7aeb69b..d17f4eb5d2a 100644
--- a/libgfortran/generated/maxloc1_16_i4.c
+++ b/libgfortran/generated/maxloc1_16_i4.c
@@ -52,8 +52,15 @@ maxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_i8.c b/libgfortran/generated/maxloc1_16_i8.c
index 000a0cf599c..f0bd1ace0f3 100644
--- a/libgfortran/generated/maxloc1_16_i8.c
+++ b/libgfortran/generated/maxloc1_16_i8.c
@@ -52,8 +52,15 @@ maxloc1_16_i8 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_i8 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_i8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_i8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_r10.c b/libgfortran/generated/maxloc1_16_r10.c
index 53378d958e2..db8ff10eb2f 100644
--- a/libgfortran/generated/maxloc1_16_r10.c
+++ b/libgfortran/generated/maxloc1_16_r10.c
@@ -52,8 +52,15 @@ maxloc1_16_r10 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_r10 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_r10 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_r10 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_r16.c b/libgfortran/generated/maxloc1_16_r16.c
index 4bdc4d66b89..1f48631547d 100644
--- a/libgfortran/generated/maxloc1_16_r16.c
+++ b/libgfortran/generated/maxloc1_16_r16.c
@@ -52,8 +52,15 @@ maxloc1_16_r16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_r16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_r16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_r16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_r4.c b/libgfortran/generated/maxloc1_16_r4.c
index 36d79e23ce3..c444f6b20c2 100644
--- a/libgfortran/generated/maxloc1_16_r4.c
+++ b/libgfortran/generated/maxloc1_16_r4.c
@@ -52,8 +52,15 @@ maxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_16_r8.c b/libgfortran/generated/maxloc1_16_r8.c
index 3993f77619b..33205ff21a0 100644
--- a/libgfortran/generated/maxloc1_16_r8.c
+++ b/libgfortran/generated/maxloc1_16_r8.c
@@ -52,8 +52,15 @@ maxloc1_16_r8 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_16_r8 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_16_r8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_16_r8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_i1.c b/libgfortran/generated/maxloc1_4_i1.c
index 05d2af4be3e..6e466e68fa1 100644
--- a/libgfortran/generated/maxloc1_4_i1.c
+++ b/libgfortran/generated/maxloc1_4_i1.c
@@ -52,8 +52,15 @@ maxloc1_4_i1 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_i1 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_i1 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_i1 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_i16.c b/libgfortran/generated/maxloc1_4_i16.c
index 67e8a9ca2c7..dfff85b1151 100644
--- a/libgfortran/generated/maxloc1_4_i16.c
+++ b/libgfortran/generated/maxloc1_4_i16.c
@@ -52,8 +52,15 @@ maxloc1_4_i16 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_i16 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_i16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_i16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_i2.c b/libgfortran/generated/maxloc1_4_i2.c
index 60ceaa698f4..1006c0046f1 100644
--- a/libgfortran/generated/maxloc1_4_i2.c
+++ b/libgfortran/generated/maxloc1_4_i2.c
@@ -52,8 +52,15 @@ maxloc1_4_i2 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_i2 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_i2 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_i2 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_i4.c b/libgfortran/generated/maxloc1_4_i4.c
index d2f30b7246a..4186654e169 100644
--- a/libgfortran/generated/maxloc1_4_i4.c
+++ b/libgfortran/generated/maxloc1_4_i4.c
@@ -52,8 +52,15 @@ maxloc1_4_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_i8.c b/libgfortran/generated/maxloc1_4_i8.c
index 13a7dc6d34c..01cfa7336b8 100644
--- a/libgfortran/generated/maxloc1_4_i8.c
+++ b/libgfortran/generated/maxloc1_4_i8.c
@@ -52,8 +52,15 @@ maxloc1_4_i8 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_i8 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_i8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_i8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_r10.c b/libgfortran/generated/maxloc1_4_r10.c
index 204229293c4..2992e2bd99a 100644
--- a/libgfortran/generated/maxloc1_4_r10.c
+++ b/libgfortran/generated/maxloc1_4_r10.c
@@ -52,8 +52,15 @@ maxloc1_4_r10 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_r10 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_r10 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_r10 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_r16.c b/libgfortran/generated/maxloc1_4_r16.c
index 95076481c10..325211a2ccf 100644
--- a/libgfortran/generated/maxloc1_4_r16.c
+++ b/libgfortran/generated/maxloc1_4_r16.c
@@ -52,8 +52,15 @@ maxloc1_4_r16 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_r16 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_r16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_r16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_r4.c b/libgfortran/generated/maxloc1_4_r4.c
index 87c6ca5eb40..9f48540eca5 100644
--- a/libgfortran/generated/maxloc1_4_r4.c
+++ b/libgfortran/generated/maxloc1_4_r4.c
@@ -52,8 +52,15 @@ maxloc1_4_r4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_r4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_r4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_r4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_4_r8.c b/libgfortran/generated/maxloc1_4_r8.c
index a13986a1fa8..f5f4145a3c4 100644
--- a/libgfortran/generated/maxloc1_4_r8.c
+++ b/libgfortran/generated/maxloc1_4_r8.c
@@ -52,8 +52,15 @@ maxloc1_4_r8 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_4_r8 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_4_r8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_4_r8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_i1.c b/libgfortran/generated/maxloc1_8_i1.c
index 71a5d97efe4..297a19b5775 100644
--- a/libgfortran/generated/maxloc1_8_i1.c
+++ b/libgfortran/generated/maxloc1_8_i1.c
@@ -52,8 +52,15 @@ maxloc1_8_i1 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_i1 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_i1 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_i1 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_i16.c b/libgfortran/generated/maxloc1_8_i16.c
index 92cf55c4e2c..773e3df1636 100644
--- a/libgfortran/generated/maxloc1_8_i16.c
+++ b/libgfortran/generated/maxloc1_8_i16.c
@@ -52,8 +52,15 @@ maxloc1_8_i16 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_i16 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_i16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_i16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_i2.c b/libgfortran/generated/maxloc1_8_i2.c
index fd1063c5df1..204d01044cd 100644
--- a/libgfortran/generated/maxloc1_8_i2.c
+++ b/libgfortran/generated/maxloc1_8_i2.c
@@ -52,8 +52,15 @@ maxloc1_8_i2 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_i2 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_i2 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_i2 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_i4.c b/libgfortran/generated/maxloc1_8_i4.c
index db82ae894ae..7c73244d39d 100644
--- a/libgfortran/generated/maxloc1_8_i4.c
+++ b/libgfortran/generated/maxloc1_8_i4.c
@@ -52,8 +52,15 @@ maxloc1_8_i4 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_i4 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_i4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_i4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_i8.c b/libgfortran/generated/maxloc1_8_i8.c
index 43b4af14792..a8965871a50 100644
--- a/libgfortran/generated/maxloc1_8_i8.c
+++ b/libgfortran/generated/maxloc1_8_i8.c
@@ -52,8 +52,15 @@ maxloc1_8_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_r10.c b/libgfortran/generated/maxloc1_8_r10.c
index 9ba6cb950e4..4bc66cdd121 100644
--- a/libgfortran/generated/maxloc1_8_r10.c
+++ b/libgfortran/generated/maxloc1_8_r10.c
@@ -52,8 +52,15 @@ maxloc1_8_r10 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_r10 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_r10 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_r10 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_r16.c b/libgfortran/generated/maxloc1_8_r16.c
index f7eb1ebf9be..959e3f98554 100644
--- a/libgfortran/generated/maxloc1_8_r16.c
+++ b/libgfortran/generated/maxloc1_8_r16.c
@@ -52,8 +52,15 @@ maxloc1_8_r16 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_r16 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_r16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_r16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_r4.c b/libgfortran/generated/maxloc1_8_r4.c
index 67b455bb735..06849640a77 100644
--- a/libgfortran/generated/maxloc1_8_r4.c
+++ b/libgfortran/generated/maxloc1_8_r4.c
@@ -52,8 +52,15 @@ maxloc1_8_r4 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_r4 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_r4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_r4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxloc1_8_r8.c b/libgfortran/generated/maxloc1_8_r8.c
index bd0913f4fea..ae40ff65ff9 100644
--- a/libgfortran/generated/maxloc1_8_r8.c
+++ b/libgfortran/generated/maxloc1_8_r8.c
@@ -52,8 +52,15 @@ maxloc1_8_r8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mmaxloc1_8_r8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mmaxloc1_8_r8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ smaxloc1_8_r8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_i1.c b/libgfortran/generated/maxval_i1.c
index 90ddf350378..fe4733518e6 100644
--- a/libgfortran/generated/maxval_i1.c
+++ b/libgfortran/generated/maxval_i1.c
@@ -52,8 +52,15 @@ maxval_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_i16.c b/libgfortran/generated/maxval_i16.c
index 6a54739e290..21174935b25 100644
--- a/libgfortran/generated/maxval_i16.c
+++ b/libgfortran/generated/maxval_i16.c
@@ -52,8 +52,15 @@ maxval_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_i2.c b/libgfortran/generated/maxval_i2.c
index 3cdb5b9d3ed..9a5a6b876a4 100644
--- a/libgfortran/generated/maxval_i2.c
+++ b/libgfortran/generated/maxval_i2.c
@@ -52,8 +52,15 @@ maxval_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_i4.c b/libgfortran/generated/maxval_i4.c
index d7ae9951a4a..5451a4e565b 100644
--- a/libgfortran/generated/maxval_i4.c
+++ b/libgfortran/generated/maxval_i4.c
@@ -52,8 +52,15 @@ maxval_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_i8.c b/libgfortran/generated/maxval_i8.c
index d622da09b27..93d81249d7b 100644
--- a/libgfortran/generated/maxval_i8.c
+++ b/libgfortran/generated/maxval_i8.c
@@ -52,8 +52,15 @@ maxval_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_r10.c b/libgfortran/generated/maxval_r10.c
index 9c4c6fbb26c..d3b10d123c8 100644
--- a/libgfortran/generated/maxval_r10.c
+++ b/libgfortran/generated/maxval_r10.c
@@ -52,8 +52,15 @@ maxval_r10 (gfc_array_r10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_r10 (gfc_array_r10 * const restrict retarray,
GFC_REAL_10 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_r16.c b/libgfortran/generated/maxval_r16.c
index f10573233e3..32e935a2d09 100644
--- a/libgfortran/generated/maxval_r16.c
+++ b/libgfortran/generated/maxval_r16.c
@@ -52,8 +52,15 @@ maxval_r16 (gfc_array_r16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_r16 (gfc_array_r16 * const restrict retarray,
GFC_REAL_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_r4.c b/libgfortran/generated/maxval_r4.c
index 94d4f335a19..92627190558 100644
--- a/libgfortran/generated/maxval_r4.c
+++ b/libgfortran/generated/maxval_r4.c
@@ -52,8 +52,15 @@ maxval_r4 (gfc_array_r4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_r4 (gfc_array_r4 * const restrict retarray,
GFC_REAL_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/maxval_r8.c b/libgfortran/generated/maxval_r8.c
index 5ba70b62edb..b12f34dd68a 100644
--- a/libgfortran/generated/maxval_r8.c
+++ b/libgfortran/generated/maxval_r8.c
@@ -52,8 +52,15 @@ maxval_r8 (gfc_array_r8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mmaxval_r8 (gfc_array_r8 * const restrict retarray,
GFC_REAL_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mmaxval_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ smaxval_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_i1.c b/libgfortran/generated/minloc1_16_i1.c
index bf6be092e85..b27e146c45f 100644
--- a/libgfortran/generated/minloc1_16_i1.c
+++ b/libgfortran/generated/minloc1_16_i1.c
@@ -52,8 +52,15 @@ minloc1_16_i1 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_i1 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_i1 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_i1 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_i16.c b/libgfortran/generated/minloc1_16_i16.c
index e4d9dab0b7f..be0cd693f14 100644
--- a/libgfortran/generated/minloc1_16_i16.c
+++ b/libgfortran/generated/minloc1_16_i16.c
@@ -52,8 +52,15 @@ minloc1_16_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_i2.c b/libgfortran/generated/minloc1_16_i2.c
index 450142f7a82..4b9dcac503f 100644
--- a/libgfortran/generated/minloc1_16_i2.c
+++ b/libgfortran/generated/minloc1_16_i2.c
@@ -52,8 +52,15 @@ minloc1_16_i2 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_i2 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_i2 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_i2 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_i4.c b/libgfortran/generated/minloc1_16_i4.c
index e1ca90f803b..b305ac8ad47 100644
--- a/libgfortran/generated/minloc1_16_i4.c
+++ b/libgfortran/generated/minloc1_16_i4.c
@@ -52,8 +52,15 @@ minloc1_16_i4 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_i4 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_i4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_i4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_i8.c b/libgfortran/generated/minloc1_16_i8.c
index b5212041d73..6a60af9f845 100644
--- a/libgfortran/generated/minloc1_16_i8.c
+++ b/libgfortran/generated/minloc1_16_i8.c
@@ -52,8 +52,15 @@ minloc1_16_i8 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_i8 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_i8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_i8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_r10.c b/libgfortran/generated/minloc1_16_r10.c
index 880bb7e2986..bb5546f45c8 100644
--- a/libgfortran/generated/minloc1_16_r10.c
+++ b/libgfortran/generated/minloc1_16_r10.c
@@ -52,8 +52,15 @@ minloc1_16_r10 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_r16.c b/libgfortran/generated/minloc1_16_r16.c
index 4343508d4a0..636195e80ed 100644
--- a/libgfortran/generated/minloc1_16_r16.c
+++ b/libgfortran/generated/minloc1_16_r16.c
@@ -52,8 +52,15 @@ minloc1_16_r16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_r16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_r16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_r16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_r4.c b/libgfortran/generated/minloc1_16_r4.c
index b2fb09c92e9..89f453fa0fa 100644
--- a/libgfortran/generated/minloc1_16_r4.c
+++ b/libgfortran/generated/minloc1_16_r4.c
@@ -52,8 +52,15 @@ minloc1_16_r4 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_r4 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_r4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_r4 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_16_r8.c b/libgfortran/generated/minloc1_16_r8.c
index f62cf337153..42ca7da88b2 100644
--- a/libgfortran/generated/minloc1_16_r8.c
+++ b/libgfortran/generated/minloc1_16_r8.c
@@ -52,8 +52,15 @@ minloc1_16_r8 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_16_r8 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_16_r8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_16_r8 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_i1.c b/libgfortran/generated/minloc1_4_i1.c
index 5bf2dbacdc4..3ff1eb16109 100644
--- a/libgfortran/generated/minloc1_4_i1.c
+++ b/libgfortran/generated/minloc1_4_i1.c
@@ -52,8 +52,15 @@ minloc1_4_i1 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_i1 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_i1 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_i1 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_i16.c b/libgfortran/generated/minloc1_4_i16.c
index c8925879e9c..10f07a136e1 100644
--- a/libgfortran/generated/minloc1_4_i16.c
+++ b/libgfortran/generated/minloc1_4_i16.c
@@ -52,8 +52,15 @@ minloc1_4_i16 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_i16 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_i16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_i16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_i2.c b/libgfortran/generated/minloc1_4_i2.c
index 42d5afaf3d2..344202db39e 100644
--- a/libgfortran/generated/minloc1_4_i2.c
+++ b/libgfortran/generated/minloc1_4_i2.c
@@ -52,8 +52,15 @@ minloc1_4_i2 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_i2 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_i2 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_i2 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_i4.c b/libgfortran/generated/minloc1_4_i4.c
index 456ea792b3f..ac9d44c8ecf 100644
--- a/libgfortran/generated/minloc1_4_i4.c
+++ b/libgfortran/generated/minloc1_4_i4.c
@@ -52,8 +52,15 @@ minloc1_4_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_i8.c b/libgfortran/generated/minloc1_4_i8.c
index a65195dcc3f..11d212062f9 100644
--- a/libgfortran/generated/minloc1_4_i8.c
+++ b/libgfortran/generated/minloc1_4_i8.c
@@ -52,8 +52,15 @@ minloc1_4_i8 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_r10.c b/libgfortran/generated/minloc1_4_r10.c
index b106e97dde8..3365e7ada6a 100644
--- a/libgfortran/generated/minloc1_4_r10.c
+++ b/libgfortran/generated/minloc1_4_r10.c
@@ -52,8 +52,15 @@ minloc1_4_r10 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_r10 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_r10 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_r10 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_r16.c b/libgfortran/generated/minloc1_4_r16.c
index b1ef3b3ee62..3b5989cce8f 100644
--- a/libgfortran/generated/minloc1_4_r16.c
+++ b/libgfortran/generated/minloc1_4_r16.c
@@ -52,8 +52,15 @@ minloc1_4_r16 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_r16 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_r16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_r16 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_r4.c b/libgfortran/generated/minloc1_4_r4.c
index 9ddf490d68b..d79f905a659 100644
--- a/libgfortran/generated/minloc1_4_r4.c
+++ b/libgfortran/generated/minloc1_4_r4.c
@@ -52,8 +52,15 @@ minloc1_4_r4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_r4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_r4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_r4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_4_r8.c b/libgfortran/generated/minloc1_4_r8.c
index 0619ac6f0a7..3175f331494 100644
--- a/libgfortran/generated/minloc1_4_r8.c
+++ b/libgfortran/generated/minloc1_4_r8.c
@@ -52,8 +52,15 @@ minloc1_4_r8 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_4_r8 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_4_r8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_4_r8 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_i1.c b/libgfortran/generated/minloc1_8_i1.c
index 27c7fa9e350..bfd935444e6 100644
--- a/libgfortran/generated/minloc1_8_i1.c
+++ b/libgfortran/generated/minloc1_8_i1.c
@@ -52,8 +52,15 @@ minloc1_8_i1 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_i1 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_i1 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_i1 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_i16.c b/libgfortran/generated/minloc1_8_i16.c
index 274b17e45f9..1fc912928f3 100644
--- a/libgfortran/generated/minloc1_8_i16.c
+++ b/libgfortran/generated/minloc1_8_i16.c
@@ -52,8 +52,15 @@ minloc1_8_i16 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_i16 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_i16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_i16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_i2.c b/libgfortran/generated/minloc1_8_i2.c
index 416622c36e7..5cf6eed7e69 100644
--- a/libgfortran/generated/minloc1_8_i2.c
+++ b/libgfortran/generated/minloc1_8_i2.c
@@ -52,8 +52,15 @@ minloc1_8_i2 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_i2 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_i2 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_i2 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_i4.c b/libgfortran/generated/minloc1_8_i4.c
index ff67899917c..8d7a8f3f8ec 100644
--- a/libgfortran/generated/minloc1_8_i4.c
+++ b/libgfortran/generated/minloc1_8_i4.c
@@ -52,8 +52,15 @@ minloc1_8_i4 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_i4 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_i4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_i4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_i8.c b/libgfortran/generated/minloc1_8_i8.c
index c4247ac7f17..00352634052 100644
--- a/libgfortran/generated/minloc1_8_i8.c
+++ b/libgfortran/generated/minloc1_8_i8.c
@@ -52,8 +52,15 @@ minloc1_8_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_r10.c b/libgfortran/generated/minloc1_8_r10.c
index c57f72aabe6..918c0b17388 100644
--- a/libgfortran/generated/minloc1_8_r10.c
+++ b/libgfortran/generated/minloc1_8_r10.c
@@ -52,8 +52,15 @@ minloc1_8_r10 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_r10 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_r10 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_r10 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_r16.c b/libgfortran/generated/minloc1_8_r16.c
index c1d2cd2a88e..c5b35955ac8 100644
--- a/libgfortran/generated/minloc1_8_r16.c
+++ b/libgfortran/generated/minloc1_8_r16.c
@@ -52,8 +52,15 @@ minloc1_8_r16 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_r16 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_r16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_r16 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_r4.c b/libgfortran/generated/minloc1_8_r4.c
index c1faa797d4c..2112352aa59 100644
--- a/libgfortran/generated/minloc1_8_r4.c
+++ b/libgfortran/generated/minloc1_8_r4.c
@@ -52,8 +52,15 @@ minloc1_8_r4 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_r4 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_r4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_r4 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minloc1_8_r8.c b/libgfortran/generated/minloc1_8_r8.c
index e7c5ee19ad1..d3d303ed082 100644
--- a/libgfortran/generated/minloc1_8_r8.c
+++ b/libgfortran/generated/minloc1_8_r8.c
@@ -52,8 +52,15 @@ minloc1_8_r8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -224,8 +231,8 @@ mminloc1_8_r8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -235,6 +242,14 @@ mminloc1_8_r8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -445,6 +460,13 @@ sminloc1_8_r8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_i1.c b/libgfortran/generated/minval_i1.c
index ccfdfa7670b..9c899bab4f6 100644
--- a/libgfortran/generated/minval_i1.c
+++ b/libgfortran/generated/minval_i1.c
@@ -52,8 +52,15 @@ minval_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_i16.c b/libgfortran/generated/minval_i16.c
index 9d3a1502e98..8b427f92004 100644
--- a/libgfortran/generated/minval_i16.c
+++ b/libgfortran/generated/minval_i16.c
@@ -52,8 +52,15 @@ minval_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_i2.c b/libgfortran/generated/minval_i2.c
index 0c335a06894..79f3c9b3086 100644
--- a/libgfortran/generated/minval_i2.c
+++ b/libgfortran/generated/minval_i2.c
@@ -52,8 +52,15 @@ minval_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_i4.c b/libgfortran/generated/minval_i4.c
index 73de782ef09..3b1830668d1 100644
--- a/libgfortran/generated/minval_i4.c
+++ b/libgfortran/generated/minval_i4.c
@@ -52,8 +52,15 @@ minval_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_i8.c b/libgfortran/generated/minval_i8.c
index 4a2a7150084..5d415f3a7f7 100644
--- a/libgfortran/generated/minval_i8.c
+++ b/libgfortran/generated/minval_i8.c
@@ -52,8 +52,15 @@ minval_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_r10.c b/libgfortran/generated/minval_r10.c
index 27966136955..c86d8c6c7bb 100644
--- a/libgfortran/generated/minval_r10.c
+++ b/libgfortran/generated/minval_r10.c
@@ -52,8 +52,15 @@ minval_r10 (gfc_array_r10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_r10 (gfc_array_r10 * const restrict retarray,
GFC_REAL_10 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_r16.c b/libgfortran/generated/minval_r16.c
index 8bc429b8d92..421026d7bd4 100644
--- a/libgfortran/generated/minval_r16.c
+++ b/libgfortran/generated/minval_r16.c
@@ -52,8 +52,15 @@ minval_r16 (gfc_array_r16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_r16 (gfc_array_r16 * const restrict retarray,
GFC_REAL_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_r4.c b/libgfortran/generated/minval_r4.c
index a5ecce21dd9..ff3d919a69b 100644
--- a/libgfortran/generated/minval_r4.c
+++ b/libgfortran/generated/minval_r4.c
@@ -52,8 +52,15 @@ minval_r4 (gfc_array_r4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_r4 (gfc_array_r4 * const restrict retarray,
GFC_REAL_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/minval_r8.c b/libgfortran/generated/minval_r8.c
index 78c751ef699..0970c31ba9a 100644
--- a/libgfortran/generated/minval_r8.c
+++ b/libgfortran/generated/minval_r8.c
@@ -52,8 +52,15 @@ minval_r8 (gfc_array_r8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -217,8 +224,8 @@ mminval_r8 (gfc_array_r8 * const restrict retarray,
GFC_REAL_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -228,6 +235,14 @@ mminval_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -433,6 +448,13 @@ sminval_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in MINVAL intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/norm2_r10.c b/libgfortran/generated/norm2_r10.c
index 4c5a2306285..4f6eceefe24 100644
--- a/libgfortran/generated/norm2_r10.c
+++ b/libgfortran/generated/norm2_r10.c
@@ -55,8 +55,15 @@ norm2_r10 (gfc_array_r10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in NORM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/norm2_r16.c b/libgfortran/generated/norm2_r16.c
index 5eaefb8a92d..596195fb85b 100644
--- a/libgfortran/generated/norm2_r16.c
+++ b/libgfortran/generated/norm2_r16.c
@@ -59,8 +59,15 @@ norm2_r16 (gfc_array_r16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in NORM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/norm2_r4.c b/libgfortran/generated/norm2_r4.c
index 0482b16ca2d..4f61ea33b01 100644
--- a/libgfortran/generated/norm2_r4.c
+++ b/libgfortran/generated/norm2_r4.c
@@ -55,8 +55,15 @@ norm2_r4 (gfc_array_r4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in NORM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/norm2_r8.c b/libgfortran/generated/norm2_r8.c
index 173faa63eb2..d325236b50b 100644
--- a/libgfortran/generated/norm2_r8.c
+++ b/libgfortran/generated/norm2_r8.c
@@ -55,8 +55,15 @@ norm2_r8 (gfc_array_r8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in NORM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/parity_l1.c b/libgfortran/generated/parity_l1.c
index 4fe64dec7db..34cac760a3d 100644
--- a/libgfortran/generated/parity_l1.c
+++ b/libgfortran/generated/parity_l1.c
@@ -52,8 +52,15 @@ parity_l1 (gfc_array_l1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/parity_l16.c b/libgfortran/generated/parity_l16.c
index d9e0a8efcdc..8aae3038e7b 100644
--- a/libgfortran/generated/parity_l16.c
+++ b/libgfortran/generated/parity_l16.c
@@ -52,8 +52,15 @@ parity_l16 (gfc_array_l16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/parity_l2.c b/libgfortran/generated/parity_l2.c
index 3cf26312f02..0d87c525028 100644
--- a/libgfortran/generated/parity_l2.c
+++ b/libgfortran/generated/parity_l2.c
@@ -52,8 +52,15 @@ parity_l2 (gfc_array_l2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/parity_l4.c b/libgfortran/generated/parity_l4.c
index 70cdd18aef9..5c524ad13a8 100644
--- a/libgfortran/generated/parity_l4.c
+++ b/libgfortran/generated/parity_l4.c
@@ -52,8 +52,15 @@ parity_l4 (gfc_array_l4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/parity_l8.c b/libgfortran/generated/parity_l8.c
index d22c9a55371..d655ebd0837 100644
--- a/libgfortran/generated/parity_l8.c
+++ b/libgfortran/generated/parity_l8.c
@@ -52,8 +52,15 @@ parity_l8 (gfc_array_l8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PARITY intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
diff --git a/libgfortran/generated/product_c10.c b/libgfortran/generated/product_c10.c
index 4e2f6f2b566..b84870cab32 100644
--- a/libgfortran/generated/product_c10.c
+++ b/libgfortran/generated/product_c10.c
@@ -52,8 +52,15 @@ product_c10 (gfc_array_c10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_c10 (gfc_array_c10 * const restrict retarray,
GFC_COMPLEX_10 * restrict dest;
const GFC_COMPLEX_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_c10 (gfc_array_c10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_c10 (gfc_array_c10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_c16.c b/libgfortran/generated/product_c16.c
index df73041f170..e1618c5a645 100644
--- a/libgfortran/generated/product_c16.c
+++ b/libgfortran/generated/product_c16.c
@@ -52,8 +52,15 @@ product_c16 (gfc_array_c16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_c16 (gfc_array_c16 * const restrict retarray,
GFC_COMPLEX_16 * restrict dest;
const GFC_COMPLEX_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_c16 (gfc_array_c16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_c16 (gfc_array_c16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_c4.c b/libgfortran/generated/product_c4.c
index 3d097a9a3ec..679670c9389 100644
--- a/libgfortran/generated/product_c4.c
+++ b/libgfortran/generated/product_c4.c
@@ -52,8 +52,15 @@ product_c4 (gfc_array_c4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_c4 (gfc_array_c4 * const restrict retarray,
GFC_COMPLEX_4 * restrict dest;
const GFC_COMPLEX_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_c4 (gfc_array_c4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_c4 (gfc_array_c4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_c8.c b/libgfortran/generated/product_c8.c
index 4bb1ddee0fe..1f4dd10796b 100644
--- a/libgfortran/generated/product_c8.c
+++ b/libgfortran/generated/product_c8.c
@@ -52,8 +52,15 @@ product_c8 (gfc_array_c8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_c8 (gfc_array_c8 * const restrict retarray,
GFC_COMPLEX_8 * restrict dest;
const GFC_COMPLEX_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_c8 (gfc_array_c8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_c8 (gfc_array_c8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_i1.c b/libgfortran/generated/product_i1.c
index fc03a48bc05..43e20b8dcb1 100644
--- a/libgfortran/generated/product_i1.c
+++ b/libgfortran/generated/product_i1.c
@@ -52,8 +52,15 @@ product_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_i16.c b/libgfortran/generated/product_i16.c
index 6a4e1aa29a3..d786c950686 100644
--- a/libgfortran/generated/product_i16.c
+++ b/libgfortran/generated/product_i16.c
@@ -52,8 +52,15 @@ product_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_i2.c b/libgfortran/generated/product_i2.c
index 82a650f6ec6..bdb875598ff 100644
--- a/libgfortran/generated/product_i2.c
+++ b/libgfortran/generated/product_i2.c
@@ -52,8 +52,15 @@ product_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_i4.c b/libgfortran/generated/product_i4.c
index 84f7c36e439..1328055736a 100644
--- a/libgfortran/generated/product_i4.c
+++ b/libgfortran/generated/product_i4.c
@@ -52,8 +52,15 @@ product_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_i8.c b/libgfortran/generated/product_i8.c
index 5ace17304e4..5adf2de1453 100644
--- a/libgfortran/generated/product_i8.c
+++ b/libgfortran/generated/product_i8.c
@@ -52,8 +52,15 @@ product_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_r10.c b/libgfortran/generated/product_r10.c
index 54e22915b88..404b1a5bf41 100644
--- a/libgfortran/generated/product_r10.c
+++ b/libgfortran/generated/product_r10.c
@@ -52,8 +52,15 @@ product_r10 (gfc_array_r10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_r10 (gfc_array_r10 * const restrict retarray,
GFC_REAL_10 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_r16.c b/libgfortran/generated/product_r16.c
index d3a2afdbdad..592a9b9bf50 100644
--- a/libgfortran/generated/product_r16.c
+++ b/libgfortran/generated/product_r16.c
@@ -52,8 +52,15 @@ product_r16 (gfc_array_r16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_r16 (gfc_array_r16 * const restrict retarray,
GFC_REAL_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_r4.c b/libgfortran/generated/product_r4.c
index 94a2f106038..882c0917f9b 100644
--- a/libgfortran/generated/product_r4.c
+++ b/libgfortran/generated/product_r4.c
@@ -52,8 +52,15 @@ product_r4 (gfc_array_r4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_r4 (gfc_array_r4 * const restrict retarray,
GFC_REAL_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/product_r8.c b/libgfortran/generated/product_r8.c
index 2daba7587bd..cc1454963a1 100644
--- a/libgfortran/generated/product_r8.c
+++ b/libgfortran/generated/product_r8.c
@@ -52,8 +52,15 @@ product_r8 (gfc_array_r8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ mproduct_r8 (gfc_array_r8 * const restrict retarray,
GFC_REAL_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ mproduct_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ sproduct_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in PRODUCT intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_c10.c b/libgfortran/generated/sum_c10.c
index 9d16db231b4..d3e8550e57d 100644
--- a/libgfortran/generated/sum_c10.c
+++ b/libgfortran/generated/sum_c10.c
@@ -52,8 +52,15 @@ sum_c10 (gfc_array_c10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_c10 (gfc_array_c10 * const restrict retarray,
GFC_COMPLEX_10 * restrict dest;
const GFC_COMPLEX_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_c10 (gfc_array_c10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_c10 (gfc_array_c10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_c16.c b/libgfortran/generated/sum_c16.c
index 58111014100..280c2ff89c6 100644
--- a/libgfortran/generated/sum_c16.c
+++ b/libgfortran/generated/sum_c16.c
@@ -52,8 +52,15 @@ sum_c16 (gfc_array_c16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_c16 (gfc_array_c16 * const restrict retarray,
GFC_COMPLEX_16 * restrict dest;
const GFC_COMPLEX_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_c16 (gfc_array_c16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_c16 (gfc_array_c16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_c4.c b/libgfortran/generated/sum_c4.c
index 27438bf4bac..0e3a74da851 100644
--- a/libgfortran/generated/sum_c4.c
+++ b/libgfortran/generated/sum_c4.c
@@ -52,8 +52,15 @@ sum_c4 (gfc_array_c4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_c4 (gfc_array_c4 * const restrict retarray,
GFC_COMPLEX_4 * restrict dest;
const GFC_COMPLEX_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_c4 (gfc_array_c4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_c4 (gfc_array_c4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_c8.c b/libgfortran/generated/sum_c8.c
index cb58bbf5724..f04f374ee12 100644
--- a/libgfortran/generated/sum_c8.c
+++ b/libgfortran/generated/sum_c8.c
@@ -52,8 +52,15 @@ sum_c8 (gfc_array_c8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_c8 (gfc_array_c8 * const restrict retarray,
GFC_COMPLEX_8 * restrict dest;
const GFC_COMPLEX_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_c8 (gfc_array_c8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_c8 (gfc_array_c8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_i1.c b/libgfortran/generated/sum_i1.c
index 1980383b5db..b7e8a981319 100644
--- a/libgfortran/generated/sum_i1.c
+++ b/libgfortran/generated/sum_i1.c
@@ -52,8 +52,15 @@ sum_i1 (gfc_array_i1 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_i1 (gfc_array_i1 * const restrict retarray,
GFC_INTEGER_1 * restrict dest;
const GFC_INTEGER_1 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_i1 (gfc_array_i1 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_i16.c b/libgfortran/generated/sum_i16.c
index 0abaff00ade..489b9bbcdf7 100644
--- a/libgfortran/generated/sum_i16.c
+++ b/libgfortran/generated/sum_i16.c
@@ -52,8 +52,15 @@ sum_i16 (gfc_array_i16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_i16 (gfc_array_i16 * const restrict retarray,
GFC_INTEGER_16 * restrict dest;
const GFC_INTEGER_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_i16 (gfc_array_i16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_i2.c b/libgfortran/generated/sum_i2.c
index 6332b647743..40304c846ce 100644
--- a/libgfortran/generated/sum_i2.c
+++ b/libgfortran/generated/sum_i2.c
@@ -52,8 +52,15 @@ sum_i2 (gfc_array_i2 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_i2 (gfc_array_i2 * const restrict retarray,
GFC_INTEGER_2 * restrict dest;
const GFC_INTEGER_2 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_i2 (gfc_array_i2 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_i4.c b/libgfortran/generated/sum_i4.c
index 27dd47ee8c5..736ccd17710 100644
--- a/libgfortran/generated/sum_i4.c
+++ b/libgfortran/generated/sum_i4.c
@@ -52,8 +52,15 @@ sum_i4 (gfc_array_i4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_i4 (gfc_array_i4 * const restrict retarray,
GFC_INTEGER_4 * restrict dest;
const GFC_INTEGER_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_i4 (gfc_array_i4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_i8.c b/libgfortran/generated/sum_i8.c
index f7639db0ae7..0eb9e3f92e0 100644
--- a/libgfortran/generated/sum_i8.c
+++ b/libgfortran/generated/sum_i8.c
@@ -52,8 +52,15 @@ sum_i8 (gfc_array_i8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_i8 (gfc_array_i8 * const restrict retarray,
GFC_INTEGER_8 * restrict dest;
const GFC_INTEGER_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_i8 (gfc_array_i8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_r10.c b/libgfortran/generated/sum_r10.c
index 07caf236034..e37dd26a029 100644
--- a/libgfortran/generated/sum_r10.c
+++ b/libgfortran/generated/sum_r10.c
@@ -52,8 +52,15 @@ sum_r10 (gfc_array_r10 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_r10 (gfc_array_r10 * const restrict retarray,
GFC_REAL_10 * restrict dest;
const GFC_REAL_10 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_r10 (gfc_array_r10 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_r16.c b/libgfortran/generated/sum_r16.c
index 374c2b326f3..b3058035cc9 100644
--- a/libgfortran/generated/sum_r16.c
+++ b/libgfortran/generated/sum_r16.c
@@ -52,8 +52,15 @@ sum_r16 (gfc_array_r16 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_r16 (gfc_array_r16 * const restrict retarray,
GFC_REAL_16 * restrict dest;
const GFC_REAL_16 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_r16 (gfc_array_r16 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_r4.c b/libgfortran/generated/sum_r4.c
index 4b5caeede98..c53dc7e198a 100644
--- a/libgfortran/generated/sum_r4.c
+++ b/libgfortran/generated/sum_r4.c
@@ -52,8 +52,15 @@ sum_r4 (gfc_array_r4 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_r4 (gfc_array_r4 * const restrict retarray,
GFC_REAL_4 * restrict dest;
const GFC_REAL_4 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_r4 (gfc_array_r4 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/generated/sum_r8.c b/libgfortran/generated/sum_r8.c
index 18872d7d535..4657def97e4 100644
--- a/libgfortran/generated/sum_r8.c
+++ b/libgfortran/generated/sum_r8.c
@@ -52,8 +52,15 @@ sum_r8 (gfc_array_r8 * const restrict retarray,
int continue_loop;
/* Make dim zero based to avoid confusion. */
- dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ dim = (*pdim) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
@@ -203,8 +210,8 @@ msum_r8 (gfc_array_r8 * const restrict retarray,
GFC_REAL_8 * restrict dest;
const GFC_REAL_8 * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -214,6 +221,14 @@ msum_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -391,6 +406,13 @@ ssum_r8 (gfc_array_r8 * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in SUM intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgfortran/intrinsics/eoshift0.c b/libgfortran/intrinsics/eoshift0.c
index 53a9a89f5f9..24a23c30fda 100644
--- a/libgfortran/intrinsics/eoshift0.c
+++ b/libgfortran/intrinsics/eoshift0.c
@@ -53,7 +53,8 @@ eoshift0 (gfc_array_char * ret, const gfc_array_char * array,
index_type len;
index_type n;
index_type arraysize;
-
+ bool do_blocked;
+
/* The compiler cannot figure out that these are set, initialize
them to avoid warnings. */
len = 0;
@@ -102,38 +103,93 @@ eoshift0 (gfc_array_char * ret, const gfc_array_char * array,
count[0] = 0;
sstride[0] = -1;
rstride[0] = -1;
- n = 0;
- for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
+
+ if (which > 0)
{
- if (dim == which)
- {
- roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
- if (roffset == 0)
- roffset = size;
- soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
- if (soffset == 0)
- soffset = size;
- len = GFC_DESCRIPTOR_EXTENT(array,dim);
- }
- else
- {
- count[n] = 0;
- extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
- rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
- sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
- n++;
- }
+ /* Test if both ret and array are contiguous. */
+ size_t r_ex, a_ex;
+ r_ex = 1;
+ a_ex = 1;
+ do_blocked = true;
+ dim = GFC_DESCRIPTOR_RANK (array);
+ for (n = 0; n < dim; n ++)
+ {
+ index_type rs, as;
+ rs = GFC_DESCRIPTOR_STRIDE (ret, n);
+ if (rs != r_ex)
+ {
+ do_blocked = false;
+ break;
+ }
+ as = GFC_DESCRIPTOR_STRIDE (array, n);
+ if (as != a_ex)
+ {
+ do_blocked = false;
+ break;
+ }
+ r_ex *= GFC_DESCRIPTOR_EXTENT (ret, n);
+ a_ex *= GFC_DESCRIPTOR_EXTENT (array, n);
+ }
}
- if (sstride[0] == 0)
- sstride[0] = size;
- if (rstride[0] == 0)
- rstride[0] = size;
+ else
+ do_blocked = false;
- dim = GFC_DESCRIPTOR_RANK (array);
- rstride0 = rstride[0];
- sstride0 = sstride[0];
- rptr = ret->base_addr;
- sptr = array->base_addr;
+ n = 0;
+
+ if (do_blocked)
+ {
+ /* For contiguous arrays, use the relationship that
+
+ dimension(n1,n2,n3) :: a, b
+ b = eoshift(a,sh,3)
+
+ can be dealt with as if
+
+ dimension(n1*n2*n3) :: an, bn
+ bn = eoshift(a,sh*n1*n2,1)
+
+ so a block move can be used for dim>1. */
+ len = GFC_DESCRIPTOR_STRIDE(array, which)
+ * GFC_DESCRIPTOR_EXTENT(array, which);
+ shift *= GFC_DESCRIPTOR_STRIDE(array, which);
+ roffset = size;
+ soffset = size;
+ for (dim = which + 1; dim < GFC_DESCRIPTOR_RANK (array); dim++)
+ {
+ count[n] = 0;
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
+ rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
+ sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
+ n++;
+ }
+ count[n] = 0;
+ dim = GFC_DESCRIPTOR_RANK (array) - which;
+ }
+ else
+ {
+ for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
+ {
+ if (dim == which)
+ {
+ roffset = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
+ if (roffset == 0)
+ roffset = size;
+ soffset = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
+ if (soffset == 0)
+ soffset = size;
+ len = GFC_DESCRIPTOR_EXTENT(array,dim);
+ }
+ else
+ {
+ count[n] = 0;
+ extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
+ rstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(ret,dim);
+ sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
+ n++;
+ }
+ }
+ dim = GFC_DESCRIPTOR_RANK (array);
+ }
if ((shift >= 0 ? shift : -shift) > len)
{
@@ -148,6 +204,11 @@ eoshift0 (gfc_array_char * ret, const gfc_array_char * array,
len = len + shift;
}
+ rstride0 = rstride[0];
+ sstride0 = sstride[0];
+ rptr = ret->base_addr;
+ sptr = array->base_addr;
+
while (rptr)
{
/* Do the shift for this dimension. */
@@ -161,12 +222,23 @@ eoshift0 (gfc_array_char * ret, const gfc_array_char * array,
src = sptr;
dest = &rptr[-shift * roffset];
}
- for (n = 0; n < len; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+ /* If the elements are contiguous, perform a single block move. */
+
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * len;
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (shift >= 0)
{
n = shift;
diff --git a/libgfortran/intrinsics/eoshift2.c b/libgfortran/intrinsics/eoshift2.c
index badba7509ec..5d949dda8bb 100644
--- a/libgfortran/intrinsics/eoshift2.c
+++ b/libgfortran/intrinsics/eoshift2.c
@@ -181,12 +181,23 @@ eoshift2 (gfc_array_char *ret, const gfc_array_char *array,
src = sptr;
dest = &rptr[-shift * roffset];
}
- for (n = 0; n < len; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * len;
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (shift >= 0)
{
n = shift;
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index bcc1e37e2e3..ef94294526a 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -583,14 +583,17 @@ get_unit (st_parameter_dt *dtp, int do_create)
}
else
{
+ __gthread_mutex_lock (&unit_lock);
if (newunit_tos)
{
dtp->common.unit = newunit_stack[newunit_tos].unit_number;
unit = newunit_stack[newunit_tos--].unit;
+ __gthread_mutex_unlock (&unit_lock);
unit->fbuf->act = unit->fbuf->pos = 0;
}
else
{
+ __gthread_mutex_unlock (&unit_lock);
dtp->common.unit = newunit_alloc ();
unit = xcalloc (1, sizeof (gfc_unit));
fbuf_init (unit, 128);
@@ -603,12 +606,15 @@ get_unit (st_parameter_dt *dtp, int do_create)
/* If an internal unit number is passed from the parent to the child
it should have been stashed on the newunit_stack ready to be used.
Check for it now and return the internal unit if found. */
+ __gthread_mutex_lock (&unit_lock);
if (newunit_tos && (dtp->common.unit <= NEWUNIT_START)
&& (dtp->common.unit == newunit_stack[newunit_tos].unit_number))
{
unit = newunit_stack[newunit_tos--].unit;
+ __gthread_mutex_unlock (&unit_lock);
return unit;
}
+ __gthread_mutex_unlock (&unit_lock);
/* Has to be an external unit. */
dtp->u.p.unit_is_internal = 0;
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index c76b427387a..61e9f7997b2 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -582,6 +582,9 @@ buf_read (unix_stream *s, void *buf, ssize_t nbyte)
static ssize_t
buf_write (unix_stream *s, const void *buf, ssize_t nbyte)
{
+ if (nbyte == 0)
+ return 0;
+
if (s->ndirty == 0)
s->buffer_offset = s->logical_offset;
diff --git a/libgfortran/m4/eoshift1.m4 b/libgfortran/m4/eoshift1.m4
index 3e47d90436e..69504601b35 100644
--- a/libgfortran/m4/eoshift1.m4
+++ b/libgfortran/m4/eoshift1.m4
@@ -184,12 +184,23 @@ eoshift1 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/m4/eoshift3.m4 b/libgfortran/m4/eoshift3.m4
index b29fbccf8d3..9e7f78755b1 100644
--- a/libgfortran/m4/eoshift3.m4
+++ b/libgfortran/m4/eoshift3.m4
@@ -199,12 +199,24 @@ eoshift3 (gfc_array_char * const restrict ret,
src = sptr;
dest = &rptr[delta * roffset];
}
- for (n = 0; n < len - delta; n++)
- {
- memcpy (dest, src, size);
- dest += roffset;
- src += soffset;
- }
+
+ /* If the elements are contiguous, perform a single block move. */
+ if (soffset == size && roffset == size)
+ {
+ size_t chunk = size * (len - delta);
+ memcpy (dest, src, chunk);
+ dest += chunk;
+ }
+ else
+ {
+ for (n = 0; n < len - delta; n++)
+ {
+ memcpy (dest, src, size);
+ dest += roffset;
+ src += soffset;
+ }
+ }
+
if (sh < 0)
dest = rptr;
n = delta;
diff --git a/libgfortran/m4/ifunction.m4 b/libgfortran/m4/ifunction.m4
index 43d8775d04c..91cfd28d5d1 100644
--- a/libgfortran/m4/ifunction.m4
+++ b/libgfortran/m4/ifunction.m4
@@ -45,6 +45,13 @@ name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in u_name intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len < 0)
len = 0;
@@ -193,8 +200,8 @@ void
rtype_name * restrict dest;
const atype_name * restrict base;
const GFC_LOGICAL_1 * restrict mbase;
- int rank;
- int dim;
+ index_type rank;
+ index_type dim;
index_type n;
index_type len;
index_type delta;
@@ -204,6 +211,14 @@ void
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in u_name intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
len = GFC_DESCRIPTOR_EXTENT(array,dim);
if (len <= 0)
return;
@@ -380,6 +395,13 @@ void
dim = (*pdim) - 1;
rank = GFC_DESCRIPTOR_RANK (array) - 1;
+ if (unlikely (dim < 0 || dim > rank))
+ {
+ runtime_error ("Dim argument incorrect in u_name intrinsic: "
+ "is %ld, should be between 1 and %ld",
+ (long int) dim + 1, (long int) rank + 1);
+ }
+
for (n = 0; n < dim; n++)
{
extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 0f9881ffaa4..9800d20bd9b 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -399,12 +399,6 @@ rtems_task_variable_add_file =
endif
if LIBGO_IS_LINUX
-runtime_thread_files = runtime/thread-linux.c
-else
-runtime_thread_files = runtime/thread-sema.c
-endif
-
-if LIBGO_IS_LINUX
runtime_getncpu_file = runtime/getncpu-linux.c
else
if LIBGO_IS_DARWIN
@@ -469,7 +463,6 @@ runtime_files = \
runtime/runtime_c.c \
runtime/stack.c \
runtime/thread.c \
- $(runtime_thread_files) \
runtime/yield.c \
$(rtems_task_variable_add_file) \
$(runtime_getncpu_file)
@@ -543,6 +536,8 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
+# semt is a Go translation of the C type sem_t; it fails to convert on
+# some systems and need not be exported back to C.
# sigset conflicts with system type sigset on AIX, so we need to rename it
runtime.inc: s-runtime-inc; @true
s-runtime-inc: runtime.lo Makefile
@@ -551,7 +546,7 @@ s-runtime-inc: runtime.lo Makefile
for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \
grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \
done
- for TYPE in _Complex_lock _Reader_lock; do \
+ for TYPE in _Complex_lock _Reader_lock semt; do \
sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \
mv runtime.inc.tmp3 runtime.inc.tmp2; \
done
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 2452f967252..9a2bd47ff7b 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -183,19 +183,17 @@ am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) \
$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3)
libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
-@LIBGO_IS_LINUX_FALSE@am__objects_1 = thread-sema.lo
-@LIBGO_IS_LINUX_TRUE@am__objects_1 = thread-linux.lo
-@LIBGO_IS_RTEMS_TRUE@am__objects_2 = rtems-task-variable-add.lo
-@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-none.lo
-@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-aix.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-bsd.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-bsd.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_3 = getncpu-solaris.lo
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = getncpu-irix.lo
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = \
+@LIBGO_IS_RTEMS_TRUE@am__objects_1 = rtems-task-variable-add.lo
+@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = getncpu-none.lo
+@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = getncpu-aix.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = getncpu-bsd.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = getncpu-bsd.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_2 = getncpu-solaris.lo
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_2 = getncpu-irix.lo
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_2 = \
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo
-@LIBGO_IS_LINUX_TRUE@am__objects_3 = getncpu-linux.lo
-am__objects_4 = aeshash.lo go-assert.lo go-caller.lo go-callers.lo \
+@LIBGO_IS_LINUX_TRUE@am__objects_2 = getncpu-linux.lo
+am__objects_3 = aeshash.lo go-assert.lo go-caller.lo go-callers.lo \
go-cdiv.lo go-cgo.lo go-construct-map.lo go-ffi.lo \
go-fieldtrack.lo go-matherr.lo go-memclr.lo go-memcmp.lo \
go-memequal.lo go-memmove.lo go-nanotime.lo go-now.lo \
@@ -203,16 +201,15 @@ am__objects_4 = aeshash.lo go-assert.lo go-caller.lo go-callers.lo \
go-setenv.lo go-signal.lo go-strslice.lo go-typedesc-equal.lo \
go-unsafe-pointer.lo go-unsetenv.lo go-unwind.lo go-varargs.lo \
env_posix.lo panic.lo print.lo proc.lo runtime_c.lo stack.lo \
- thread.lo $(am__objects_1) yield.lo $(am__objects_2) \
- $(am__objects_3)
-am_libgo_llgo_la_OBJECTS = $(am__objects_4)
+ thread.lo yield.lo $(am__objects_1) $(am__objects_2)
+am_libgo_llgo_la_OBJECTS = $(am__objects_3)
libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@
@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir)
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
-am_libgo_la_OBJECTS = $(am__objects_4)
+am_libgo_la_OBJECTS = $(am__objects_3)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \
@@ -765,8 +762,6 @@ toolexeclibgounicode_DATA = \
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
-@LIBGO_IS_LINUX_FALSE@runtime_thread_files = runtime/thread-sema.c
-@LIBGO_IS_LINUX_TRUE@runtime_thread_files = runtime/thread-linux.c
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-aix.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@@ -810,7 +805,6 @@ runtime_files = \
runtime/runtime_c.c \
runtime/stack.c \
runtime/thread.c \
- $(runtime_thread_files) \
runtime/yield.c \
$(rtems_task_variable_add_file) \
$(runtime_getncpu_file)
@@ -1525,8 +1519,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtems-task-variable-add.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime_c.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-linux.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yield.Plo@am__quote@
@@ -1831,20 +1823,6 @@ thread.lo: runtime/thread.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
-thread-sema.lo: runtime/thread-sema.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-sema.lo -MD -MP -MF $(DEPDIR)/thread-sema.Tpo -c -o thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread-sema.Tpo $(DEPDIR)/thread-sema.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/thread-sema.c' object='thread-sema.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
-
-thread-linux.lo: runtime/thread-linux.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-linux.lo -MD -MP -MF $(DEPDIR)/thread-linux.Tpo -c -o thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread-linux.Tpo $(DEPDIR)/thread-linux.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/thread-linux.c' object='thread-linux.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
-
yield.lo: runtime/yield.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT yield.lo -MD -MP -MF $(DEPDIR)/yield.Tpo -c -o yield.lo `test -f 'runtime/yield.c' || echo '$(srcdir)/'`runtime/yield.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yield.Tpo $(DEPDIR)/yield.Plo
@@ -3093,6 +3071,8 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
+# semt is a Go translation of the C type sem_t; it fails to convert on
+# some systems and need not be exported back to C.
# sigset conflicts with system type sigset on AIX, so we need to rename it
runtime.inc: s-runtime-inc; @true
s-runtime-inc: runtime.lo Makefile
@@ -3101,7 +3081,7 @@ s-runtime-inc: runtime.lo Makefile
for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \
grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \
done
- for TYPE in _Complex_lock _Reader_lock; do \
+ for TYPE in _Complex_lock _Reader_lock semt; do \
sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \
mv runtime.inc.tmp3 runtime.inc.tmp2; \
done
diff --git a/libgo/configure b/libgo/configure
index 48feebdb10d..cfdcd7409c5 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -13773,7 +13773,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
esac
case "${host}" in
mips*el-*-*)
- GOARCH="${GOARCH}le"
+ GOARCH="${GOARCH}le"
;;
*)
GOARCH_BIGENDIAN=1
diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/build.go
index 7e98379675f..9623b9c32be 100644
--- a/libgo/go/cmd/go/build.go
+++ b/libgo/go/cmd/go/build.go
@@ -342,16 +342,20 @@ func buildModeInit() {
}
return p
}
- switch platform {
- case "darwin/arm", "darwin/arm64":
- codegenArg = "-shared"
- default:
- switch goos {
- case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
- // Use -shared so that the result is
- // suitable for inclusion in a PIE or
- // shared library.
+ if gccgo {
+ codegenArg = "-fPIC"
+ } else {
+ switch platform {
+ case "darwin/arm", "darwin/arm64":
codegenArg = "-shared"
+ default:
+ switch goos {
+ case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
+ // Use -shared so that the result is
+ // suitable for inclusion in a PIE or
+ // shared library.
+ codegenArg = "-shared"
+ }
}
}
exeSuffix = ".a"
@@ -374,10 +378,14 @@ func buildModeInit() {
case "default":
switch platform {
case "android/arm", "android/arm64", "android/amd64", "android/386":
- codegenArg = "-shared"
+ if !gccgo {
+ codegenArg = "-shared"
+ }
ldBuildmode = "pie"
case "darwin/arm", "darwin/arm64":
- codegenArg = "-shared"
+ if !gccgo {
+ codegenArg = "-shared"
+ }
fallthrough
default:
ldBuildmode = "exe"
@@ -387,7 +395,7 @@ func buildModeInit() {
ldBuildmode = "exe"
case "pie":
if gccgo {
- fatalf("-buildmode=pie not supported by gccgo")
+ codegenArg = "-fPIE"
} else {
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
@@ -1053,7 +1061,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
// Install header for cgo in c-archive and c-shared modes.
if p.usesCgo() && (buildBuildmode == "c-archive" || buildBuildmode == "c-shared") {
hdrTarget := a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h"
- if buildContext.Compiler == "gccgo" {
+ if buildContext.Compiler == "gccgo" && *buildO == "" {
// For the header file, remove the "lib"
// added by go/build, so we generate pkg.h
// rather than libpkg.h.
@@ -3025,6 +3033,8 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
case "shared":
ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
+ case "pie":
+ ldflags = append(ldflags, "-pie")
default:
fatalf("-buildmode=%s not supported for gccgo", buildmode)
@@ -3082,8 +3092,7 @@ func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile stri
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}
- switch goarch {
- case "386", "amd64":
+ if b.gccSupportsFlag("-fsplit-stack") {
defs = append(defs, "-fsplit-stack")
}
defs = tools.maybePIC(defs)
@@ -3100,7 +3109,7 @@ func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile stri
// maybePIC adds -fPIC to the list of arguments if needed.
func (tools gccgoToolchain) maybePIC(args []string) []string {
switch buildBuildmode {
- case "c-shared", "shared", "plugin":
+ case "c-archive", "c-shared", "shared", "plugin":
args = append(args, "-fPIC")
}
return args
@@ -3418,8 +3427,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
}
if _, ok := buildToolchain.(gccgoToolchain); ok {
- switch goarch {
- case "386", "amd64":
+ if b.gccSupportsFlag("-fsplit-stack") {
cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
}
cgoflags = append(cgoflags, "-gccgo")
diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go
index 05a69c98aad..3912fc2da58 100644
--- a/libgo/go/runtime/malloc.go
+++ b/libgo/go/runtime/malloc.go
@@ -291,6 +291,8 @@ func mallocinit() {
// allocation at 0x40 << 32 because when using 4k pages with 3-level
// translation buffers, the user address space is limited to 39 bits
// On darwin/arm64, the address space is even smaller.
+ // On AIX, mmap adresses range start at 0x07000000_00000000 for 64 bits
+ // processes.
arenaSize := round(_MaxMem, _PageSize)
bitmapSize = arenaSize / (sys.PtrSize * 8 / 2)
spansSize = arenaSize / _PageSize * sys.PtrSize
@@ -301,12 +303,15 @@ func mallocinit() {
p = uintptr(i)<<40 | uintptrMask&(0x0013<<28)
case GOARCH == "arm64":
p = uintptr(i)<<40 | uintptrMask&(0x0040<<32)
+ case GOOS == "aix":
+ i = 1
+ p = uintptr(i)<<32 | uintptrMask&(0x70<<52)
default:
p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32)
}
pSize = bitmapSize + spansSize + arenaSize + _PageSize
p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved))
- if p != 0 {
+ if p != 0 || GOOS == "aix" { // Useless to loop on AIX, as i is forced to 1
break
}
}
diff --git a/libgo/go/runtime/mem_gccgo.go b/libgo/go/runtime/mem_gccgo.go
index 161ff26b137..ea3e5ebab4e 100644
--- a/libgo/go/runtime/mem_gccgo.go
+++ b/libgo/go/runtime/mem_gccgo.go
@@ -270,6 +270,11 @@ func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
return
}
+ if GOOS == "aix" {
+ // AIX does not allow mapping a range that is already mapped.
+ // So always unmap first even if it is already unmapped.
+ munmap(v, n)
+ }
p := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, mmapFD, 0)
if uintptr(p) == _MAP_FAILED && errno() == _ENOMEM {
throw("runtime: out of memory")
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index a3d091811d5..30d87c4121b 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -422,13 +422,13 @@ func getPanicking() uint32 {
return panicking
}
-// Temporary for gccgo until we initialize ncpu in Go.
+// Called by C code to set the number of CPUs.
//go:linkname setncpu runtime.setncpu
func setncpu(n int32) {
ncpu = n
}
-// Temporary for gccgo until we reliably initialize physPageSize in Go.
+// Called by C code to set the page size.
//go:linkname setpagesize runtime.setpagesize
func setpagesize(s uintptr) {
if physPageSize == 0 {
diff --git a/libgo/go/runtime/testdata/testprogcgo/callback.go b/libgo/go/runtime/testdata/testprogcgo/callback.go
index 7b58f4a207e..a49fc19b284 100644
--- a/libgo/go/runtime/testdata/testprogcgo/callback.go
+++ b/libgo/go/runtime/testdata/testprogcgo/callback.go
@@ -23,7 +23,9 @@ static void foo() {
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 256 << 10);
+ // For gccgo use a stack size large enough for all the callbacks,
+ // in case we are on a platform that does not support -fsplit-stack.
+ pthread_attr_setstacksize(&attr, 512 * 10000);
pthread_create(&th, &attr, thr, 0);
pthread_join(th, 0);
}
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
index b58b2ddd6ea..5f4778400b0 100644
--- a/libgo/go/syscall/libcall_linux.go
+++ b/libgo/go/syscall/libcall_linux.go
@@ -212,7 +212,7 @@ func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
//flock(fd _C_int, how _C_int) _C_int
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
-//fstatfs(fd _C_int, buf *Statfs_t) _C_int
+//fstatfs64(fd _C_int, buf *Statfs_t) _C_int
func Gettid() (tid int) {
r1, _, _ := Syscall(SYS_GETTID, 0, 0, 0)
@@ -360,7 +360,7 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
}
//sys Statfs(path string, buf *Statfs_t) (err error)
-//statfs(path *byte, buf *Statfs_t) _C_int
+//statfs64(path *byte, buf *Statfs_t) _C_int
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
//sync_file_range(fd _C_int, off Offset_t, n Offset_t, flags _C_uint) _C_int
diff --git a/libgo/go/syscall/syscall_linux_alpha.go b/libgo/go/syscall/syscall_linux_alpha.go
index 713546cb057..5115b9b7c21 100644
--- a/libgo/go/syscall/syscall_linux_alpha.go
+++ b/libgo/go/syscall/syscall_linux_alpha.go
@@ -8,38 +8,6 @@ package syscall
import "unsafe"
-type PtraceRegs struct {
- R0 uint64
- R1 uint64
- R2 uint64
- R3 uint64
- R4 uint64
- R5 uint64
- R6 uint64
- R7 uint64
- R8 uint64
- R19 uint64
- R20 uint64
- R21 uint64
- R22 uint64
- R23 uint64
- R24 uint64
- R25 uint64
- R26 uint64
- R27 uint64
- R28 uint64
- Hae uint64
- Trap_a0 uint64
- Trap_a1 uint64
- Trap_a2 uint64
- Ps uint64
- Pc uint64
- Gp uint64
- R16 uint64
- R17 uint64
- R18 uint64
-}
-
func (r *PtraceRegs) PC() uint64 {
return r.Pc
}
diff --git a/libgo/go/syscall/syscall_linux_s390.go b/libgo/go/syscall/syscall_linux_s390.go
index a744f6b7841..8b005427eef 100644
--- a/libgo/go/syscall/syscall_linux_s390.go
+++ b/libgo/go/syscall/syscall_linux_s390.go
@@ -4,18 +4,30 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// See the s390x version for why we don't use GETREGSET/SETREGSET
+
package syscall
import "unsafe"
-func (r *PtraceRegs) PC() uint64 { return uint64(r.Psw.Addr) }
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Psw.addr) }
-func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = uint32(pc) }
+func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.addr = uint32(pc) }
-func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
- return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+func PtraceGetRegs(pid int, regs *PtraceRegs) (err error) {
+ parea := _ptrace_area{
+ _sizeof_ptrace_area,
+ 0,
+ uint32(uintptr(unsafe.Pointer(regs))),
+ }
+ return ptrace(PTRACE_PEEKUSR_AREA, pid, uintptr(unsafe.Pointer(&parea)), 0)
}
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
- return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+ parea := _ptrace_area{
+ _sizeof_ptrace_area,
+ 0,
+ uint32(uintptr(unsafe.Pointer(regs))),
+ }
+ return ptrace(PTRACE_POKEUSR_AREA, pid, uintptr(unsafe.Pointer(&parea)), 0)
}
diff --git a/libgo/go/syscall/syscall_linux_s390x.go b/libgo/go/syscall/syscall_linux_s390x.go
index 44d567983c8..1767a6e5c61 100644
--- a/libgo/go/syscall/syscall_linux_s390x.go
+++ b/libgo/go/syscall/syscall_linux_s390x.go
@@ -4,18 +4,45 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The PtraceRegs struct generated for go looks like this:
+//
+// type PtraceRegs struct
+// {
+// Psw _psw_t;
+// Gprs [15+1]uint64;
+// Acrs [15+1]uint32;
+// Orig_gpr2 uint64;
+// Fp_regs _s390_fp_regs;
+// Per_info _per_struct;
+// Ieee_instruction_pointer uint64;
+// }
+//
+// The GETREGSET/SETREGSET ptrace commands on S/390 only read/write
+// the content up to Orig_gpr2. Hence, we use
+// PEEKUSR_AREA/POKEUSR_AREA like GDB does.
+
package syscall
import "unsafe"
-func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
+func (r *PtraceRegs) PC() uint64 { return r.Psw.addr }
-func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
+func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.addr = pc }
-func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
- return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+func PtraceGetRegs(pid int, regs *PtraceRegs) (err error) {
+ parea := _ptrace_area{
+ _sizeof_ptrace_area,
+ 0,
+ uint64(uintptr(unsafe.Pointer(regs))),
+ }
+ return ptrace(PTRACE_PEEKUSR_AREA, pid, uintptr(unsafe.Pointer(&parea)), 0)
}
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
- return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+ parea := _ptrace_area{
+ _sizeof_ptrace_area,
+ 0,
+ uint64(uintptr(unsafe.Pointer(regs))),
+ }
+ return ptrace(PTRACE_POKEUSR_AREA, pid, uintptr(unsafe.Pointer(&parea)), 0)
}
diff --git a/libgo/merge.sh b/libgo/merge.sh
index bdf0043f12b..bc24504e2a0 100755
--- a/libgo/merge.sh
+++ b/libgo/merge.sh
@@ -182,6 +182,13 @@ done
done
done
+(cd ${NEWDIR}/misc/cgo && find . -type f -print) | while read f; do
+ oldfile=${OLDDIR}/misc/cgo/$f
+ newfile=${NEWDIR}/misc/cgo/$f
+ libgofile=misc/cgo/$f
+ merge $f ${oldfile} ${newfile} ${libgofile}
+done
+
(cd ${OLDDIR}/src && find . -name '*.go' -print) | while read f; do
oldfile=${OLDDIR}/src/$f
newfile=${NEWDIR}/src/$f
@@ -197,5 +204,20 @@ done
git rm ${libgofile}
done
+(cd ${OLDDIR}/misc/cgo && find . -type f -print) | while read f; do
+ oldfile=${OLDDIR}/misc/cgo/$f
+ newfile=${NEWDIR}/misc/cgo/$f
+ libgofile=misc/cgo/$f
+ if test -f ${newfile}; then
+ continue
+ fi
+ if ! test -f ${libgofile}; then
+ continue
+ fi
+ echo "merge.sh: ${libgofile}: REMOVED"
+ rm -f ${libgofile}
+ git rm ${libgofile}
+done
+
(echo ${new_rev}; sed -ne '2,$p' MERGE) > MERGE.tmp
mv MERGE.tmp MERGE
diff --git a/libgo/misc/cgo/errors/err1.go b/libgo/misc/cgo/errors/err1.go
new file mode 100644
index 00000000000..61bbcd29577
--- /dev/null
+++ b/libgo/misc/cgo/errors/err1.go
@@ -0,0 +1,18 @@
+// 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.
+
+package main
+
+/*
+#cgo LDFLAGS: -c
+
+void test() {
+ xxx; // ERROR HERE
+}
+*/
+import "C"
+
+func main() {
+ C.test()
+}
diff --git a/libgo/misc/cgo/errors/err2.go b/libgo/misc/cgo/errors/err2.go
new file mode 100644
index 00000000000..3ab410bbaac
--- /dev/null
+++ b/libgo/misc/cgo/errors/err2.go
@@ -0,0 +1,13 @@
+// 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.
+
+package main
+
+import "C"
+
+func main() {
+ s := ""
+ _ = s
+ C.malloc(s) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/err3.go b/libgo/misc/cgo/errors/err3.go
new file mode 100644
index 00000000000..609e1a0b748
--- /dev/null
+++ b/libgo/misc/cgo/errors/err3.go
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+package main
+
+/*
+typedef struct foo foo_t;
+typedef struct bar bar_t;
+
+foo_t *foop;
+*/
+import "C"
+
+func main() {
+ x := (*C.bar_t)(nil)
+ C.foop = x // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue11097a.go b/libgo/misc/cgo/errors/issue11097a.go
new file mode 100644
index 00000000000..028d10ce5cb
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue11097a.go
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+ var a = C.enum_test(1) // ERROR HERE
+ _ = a
+}
diff --git a/libgo/misc/cgo/errors/issue11097b.go b/libgo/misc/cgo/errors/issue11097b.go
new file mode 100644
index 00000000000..b00f24fc103
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue11097b.go
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+ p := new(C.enum_test) // ERROR HERE
+ _ = p
+}
diff --git a/libgo/misc/cgo/errors/issue13129.go b/libgo/misc/cgo/errors/issue13129.go
new file mode 100644
index 00000000000..f7ad7a7e149
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue13129.go
@@ -0,0 +1,14 @@
+// Copyright 2015 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.
+
+// issue 13129: used to output error about C.unsignedshort with CC=clang
+
+package main
+
+import "C"
+
+func main() {
+ var x C.ushort
+ x = int(0) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue13423.go b/libgo/misc/cgo/errors/issue13423.go
new file mode 100644
index 00000000000..fc191572376
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue13423.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+package main
+
+// #include <stdio.h>
+import "C"
+
+func main() {
+ _ = C.fopen() // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue13635.go b/libgo/misc/cgo/errors/issue13635.go
new file mode 100644
index 00000000000..0ce2b1e83a1
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue13635.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// issue 13635: used to output error about C.unsignedchar.
+// This test tests all such types.
+
+package pkg
+
+import "C"
+
+func main() {
+ var (
+ _ C.uchar = "uc" // ERROR HERE
+ _ C.schar = "sc" // ERROR HERE
+ _ C.ushort = "us" // ERROR HERE
+ _ C.uint = "ui" // ERROR HERE
+ _ C.ulong = "ul" // ERROR HERE
+ _ C.longlong = "ll" // ERROR HERE
+ _ C.ulonglong = "ull" // ERROR HERE
+ _ C.complexfloat = "cf" // ERROR HERE
+ _ C.complexdouble = "cd" // ERROR HERE
+ )
+}
diff --git a/libgo/misc/cgo/errors/issue13830.go b/libgo/misc/cgo/errors/issue13830.go
new file mode 100644
index 00000000000..ac20c82b81b
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue13830.go
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// cgo converts C void* to Go unsafe.Pointer, so despite appearances C
+// void** is Go *unsafe.Pointer. This test verifies that we detect the
+// problem at build time.
+
+package main
+
+// typedef void v;
+// void F(v** p) {}
+import "C"
+
+import "unsafe"
+
+type v [0]byte
+
+func f(p **v) {
+ C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE
+}
+
+func main() {
+ var p *v
+ f(&p)
+}
diff --git a/libgo/misc/cgo/errors/issue14669.go b/libgo/misc/cgo/errors/issue14669.go
new file mode 100644
index 00000000000..04d2bcb631d
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue14669.go
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+// Issue 14669: test that fails when build with CGO_CFLAGS selecting
+// optimization.
+
+package p
+
+/*
+const int E = 1;
+
+typedef struct s {
+ int c;
+} s;
+*/
+import "C"
+
+func F() {
+ _ = C.s{
+ c: C.E,
+ }
+}
diff --git a/libgo/misc/cgo/errors/issue16116.go b/libgo/misc/cgo/errors/issue16116.go
new file mode 100644
index 00000000000..1e01cab844e
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue16116.go
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// void f(void *p, int x) {}
+import "C"
+
+func main() {
+ _ = C.f(1) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue16591.go b/libgo/misc/cgo/errors/issue16591.go
new file mode 100644
index 00000000000..10eb8403cf8
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue16591.go
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+// Issue 16591: Test that we detect an invalid call that was being
+// hidden by a type conversion inserted by cgo checking.
+
+package p
+
+// void f(int** p) { }
+import "C"
+
+type x *C.int
+
+func F(p *x) {
+ C.f(p) // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue7757.go b/libgo/misc/cgo/errors/issue7757.go
new file mode 100644
index 00000000000..0426e9fb7ef
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue7757.go
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+package main
+
+/*
+void foo() {}
+*/
+import "C"
+
+func main() {
+ C.foo = C.foo // ERROR HERE
+}
diff --git a/libgo/misc/cgo/errors/issue8442.go b/libgo/misc/cgo/errors/issue8442.go
new file mode 100644
index 00000000000..60477ad345e
--- /dev/null
+++ b/libgo/misc/cgo/errors/issue8442.go
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+package main
+
+// Issue 8442. Cgo output unhelpful error messages for
+// invalid C preambles.
+
+/*
+void issue8442foo(UNDEF*); // ERROR HERE
+*/
+import "C"
+
+func main() {
+ C.issue8442foo(nil)
+}
diff --git a/libgo/misc/cgo/errors/malloc.go b/libgo/misc/cgo/errors/malloc.go
new file mode 100644
index 00000000000..65da0208b97
--- /dev/null
+++ b/libgo/misc/cgo/errors/malloc.go
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Test that C.malloc does not return nil.
+
+package main
+
+// #include <stdlib.h>
+import "C"
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func main() {
+ var size C.size_t
+ size--
+
+ // The Dragonfly libc succeeds when asked to allocate
+ // 0xffffffffffffffff bytes, so pass a different value that
+ // causes it to fail.
+ if runtime.GOOS == "dragonfly" {
+ size = C.size_t(0x7fffffff << (32 * (^uintptr(0) >> 63)))
+ }
+
+ p := C.malloc(size)
+ if p == nil {
+ fmt.Println("malloc: C.malloc returned nil")
+ // Just exit normally--the test script expects this
+ // program to crash, so exiting normally indicates failure.
+ }
+}
diff --git a/libgo/misc/cgo/errors/ptr.go b/libgo/misc/cgo/errors/ptr.go
new file mode 100644
index 00000000000..4dafbdf3c01
--- /dev/null
+++ b/libgo/misc/cgo/errors/ptr.go
@@ -0,0 +1,576 @@
+// Copyright 2015 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.
+
+// Tests that cgo detects invalid pointer passing at runtime.
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+// ptrTest is the tests without the boilerplate.
+type ptrTest struct {
+ name string // for reporting
+ c string // the cgo comment
+ imports []string // a list of imports
+ support string // supporting functions
+ body string // the body of the main function
+ extra []extra // extra files
+ fail bool // whether the test should fail
+ expensive bool // whether the test requires the expensive check
+}
+
+type extra struct {
+ name string
+ contents string
+}
+
+var ptrTests = []ptrTest{
+ {
+ // Passing a pointer to a struct that contains a Go pointer.
+ name: "ptr1",
+ c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
+ body: `C.f(&C.s{new(C.int)})`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to a struct that contains a Go pointer.
+ name: "ptr2",
+ c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
+ body: `p := &C.s{new(C.int)}; C.f(p)`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to an int field of a Go struct
+ // that (irrelevantly) contains a Go pointer.
+ name: "ok1",
+ c: `struct s { int i; int *p; }; void f(int *p) {}`,
+ body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`,
+ fail: false,
+ },
+ {
+ // Passing a pointer to a pointer field of a Go struct.
+ name: "ptr-field",
+ c: `struct s { int i; int *p; }; void f(int **p) {}`,
+ body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`,
+ fail: true,
+ },
+ {
+ // Passing a pointer to a pointer field of a Go
+ // struct, where the field does not contain a Go
+ // pointer, but another field (irrelevantly) does.
+ name: "ptr-field-ok",
+ c: `struct s { int *p1; int *p2; }; void f(int **p) {}`,
+ body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice with no Go pointers.
+ name: "slice-ok-1",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `s := []unsafe.Pointer{nil}; C.f(&s[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice with a Go pointer.
+ name: "slice-ptr-1",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`,
+ fail: true,
+ },
+ {
+ // Passing the address of a slice with a Go pointer,
+ // where we are passing the address of an element that
+ // is not a Go pointer.
+ name: "slice-ptr-2",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`,
+ fail: true,
+ },
+ {
+ // Passing the address of a slice that is an element
+ // in a struct only looks at the slice.
+ name: "slice-ok-2",
+ c: `void f(void **p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; s []unsafe.Pointer }`,
+ body: `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice of an array that is
+ // an element in a struct, with a type conversion.
+ name: "slice-ok-3",
+ c: `void f(void* p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [4]byte }`,
+ body: `i := 0; p := &S{p:&i}; s := p.a[:]; C.f(unsafe.Pointer(&s[0]))`,
+ fail: false,
+ },
+ {
+ // Passing the address of a slice of an array that is
+ // an element in a struct, with a type conversion.
+ name: "slice-ok-4",
+ c: `typedef void* PV; void f(PV p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [4]byte }`,
+ body: `i := 0; p := &S{p:&i}; C.f(C.PV(unsafe.Pointer(&p.a[0])))`,
+ fail: false,
+ },
+ {
+ // Passing the address of a static variable with no
+ // pointers doesn't matter.
+ name: "varok",
+ c: `void f(char** parg) {}`,
+ support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`,
+ body: `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`,
+ fail: false,
+ },
+ {
+ // Passing the address of a static variable with
+ // pointers does matter.
+ name: "var",
+ c: `void f(char*** parg) {}`,
+ support: `var hello = [...]*C.char{new(C.char)}`,
+ body: `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`,
+ fail: true,
+ },
+ {
+ // Storing a Go pointer into C memory should fail.
+ name: "barrier",
+ c: `#include <stdlib.h>
+ char **f1() { return malloc(sizeof(char*)); }
+ void f2(char **p) {}`,
+ body: `p := C.f1(); *p = new(C.char); C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Storing a Go pointer into C memory by assigning a
+ // large value should fail.
+ name: "barrier-struct",
+ c: `#include <stdlib.h>
+ struct s { char *a[10]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Storing a Go pointer into C memory using a slice
+ // copy should fail.
+ name: "barrier-slice",
+ c: `#include <stdlib.h>
+ struct s { char *a[10]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // A very large value uses a GC program, which is a
+ // different code path.
+ name: "barrier-gcprog-array",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}`,
+ body: `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Similar case, with a source on the heap.
+ name: "barrier-gcprog-array-heap",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s *f1() { return malloc(sizeof(struct s)); }
+ void f2(struct s *p) {}
+ void f3(void *p) {}`,
+ imports: []string{"unsafe"},
+ body: `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // A GC program with a struct.
+ name: "barrier-gcprog-struct",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s2 { struct s f; };
+ struct s2 *f1() { return malloc(sizeof(struct s2)); }
+ void f2(struct s2 *p) {}`,
+ body: `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Similar case, with a source on the heap.
+ name: "barrier-gcprog-struct-heap",
+ c: `#include <stdlib.h>
+ struct s { char *a[32769]; };
+ struct s2 { struct s f; };
+ struct s2 *f1() { return malloc(sizeof(struct s2)); }
+ void f2(struct s2 *p) {}
+ void f3(void *p) {}`,
+ imports: []string{"unsafe"},
+ body: `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`,
+ fail: true,
+ expensive: true,
+ },
+ {
+ // Exported functions may not return Go pointers.
+ name: "export1",
+ c: `extern unsigned char *GoFn();`,
+ support: `//export GoFn
+ func GoFn() *byte { return new(byte) }`,
+ body: `C.GoFn()`,
+ fail: true,
+ },
+ {
+ // Returning a C pointer is fine.
+ name: "exportok",
+ c: `#include <stdlib.h>
+ extern unsigned char *GoFn();`,
+ support: `//export GoFn
+ func GoFn() *byte { return (*byte)(C.malloc(1)) }`,
+ body: `C.GoFn()`,
+ },
+ {
+ // Passing a Go string is fine.
+ name: "pass-string",
+ c: `#include <stddef.h>
+ typedef struct { const char *p; ptrdiff_t n; } gostring;
+ gostring f(gostring s) { return s; }`,
+ imports: []string{"unsafe"},
+ body: `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`,
+ },
+ {
+ // Passing a slice of Go strings fails.
+ name: "pass-string-slice",
+ c: `void f(void *p) {}`,
+ imports: []string{"strings", "unsafe"},
+ support: `type S struct { a [1]string }`,
+ body: `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))`,
+ fail: true,
+ },
+ {
+ // Exported functions may not return strings.
+ name: "ret-string",
+ c: `extern void f();`,
+ imports: []string{"strings"},
+ support: `//export GoStr
+ func GoStr() string { return strings.Repeat("a", 2) }`,
+ body: `C.f()`,
+ extra: []extra{
+ {
+ "call.c",
+ `#include <stddef.h>
+ typedef struct { const char *p; ptrdiff_t n; } gostring;
+ extern gostring GoStr();
+ void f() { GoStr(); }`,
+ },
+ },
+ fail: true,
+ },
+ {
+ // Don't check non-pointer data.
+ // Uses unsafe code to get a pointer we shouldn't check.
+ // Although we use unsafe, the uintptr represents an integer
+ // that happens to have the same representation as a pointer;
+ // that is, we are testing something that is not unsafe.
+ name: "ptrdata1",
+ c: `#include <stdlib.h>
+ void f(void* p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [8*8]byte; u uintptr }`,
+ body: `i := 0; p := &S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f(unsafe.Pointer(q))`,
+ fail: false,
+ },
+ {
+ // Like ptrdata1, but with a type that uses a GC program.
+ name: "ptrdata2",
+ c: `#include <stdlib.h>
+ void f(void* p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [32769*8]byte; q *int; u uintptr }`,
+ body: `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`,
+ fail: false,
+ },
+ {
+ // Check deferred pointers when they are used, not
+ // when the defer statement is run.
+ name: "defer",
+ c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
+ body: `p := &C.s{}; defer C.f(p); p.p = new(C.int)`,
+ fail: true,
+ },
+ {
+ // Check a pointer to a union if the union has any
+ // pointer fields.
+ name: "union1",
+ c: `typedef union { char **p; unsigned long i; } u; void f(u *pu) {}`,
+ imports: []string{"unsafe"},
+ body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
+ fail: true,
+ },
+ {
+ // Don't check a pointer to a union if the union does
+ // not have any pointer fields.
+ // Like ptrdata1 above, the uintptr represents an
+ // integer that happens to have the same
+ // representation as a pointer.
+ name: "union2",
+ c: `typedef union { unsigned long i; } u; void f(u *pu) {}`,
+ imports: []string{"unsafe"},
+ body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
+ fail: false,
+ },
+}
+
+func main() {
+ os.Exit(doTests())
+}
+
+func doTests() int {
+ gopath, err := ioutil.TempDir("", "cgoerrors")
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return 2
+ }
+ defer os.RemoveAll(gopath)
+
+ if err := os.MkdirAll(filepath.Join(gopath, "src"), 0777); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return 2
+ }
+
+ workers := runtime.NumCPU() + 1
+
+ var wg sync.WaitGroup
+ c := make(chan int)
+ errs := make(chan int)
+ for i := 0; i < workers; i++ {
+ wg.Add(1)
+ go func() {
+ worker(gopath, c, errs)
+ wg.Done()
+ }()
+ }
+
+ for i := range ptrTests {
+ c <- i
+ }
+ close(c)
+
+ go func() {
+ wg.Wait()
+ close(errs)
+ }()
+
+ tot := 0
+ for e := range errs {
+ tot += e
+ }
+ return tot
+}
+
+func worker(gopath string, c, errs chan int) {
+ e := 0
+ for i := range c {
+ if !doOne(gopath, i) {
+ e++
+ }
+ }
+ if e > 0 {
+ errs <- e
+ }
+}
+
+func doOne(gopath string, i int) bool {
+ t := &ptrTests[i]
+
+ dir := filepath.Join(gopath, "src", fmt.Sprintf("dir%d", i))
+ if err := os.Mkdir(dir, 0777); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return false
+ }
+
+ name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
+ f, err := os.Create(name)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return false
+ }
+
+ b := bufio.NewWriter(f)
+ fmt.Fprintln(b, `package main`)
+ fmt.Fprintln(b)
+ fmt.Fprintln(b, `/*`)
+ fmt.Fprintln(b, t.c)
+ fmt.Fprintln(b, `*/`)
+ fmt.Fprintln(b, `import "C"`)
+ fmt.Fprintln(b)
+ for _, imp := range t.imports {
+ fmt.Fprintln(b, `import "`+imp+`"`)
+ }
+ if len(t.imports) > 0 {
+ fmt.Fprintln(b)
+ }
+ if len(t.support) > 0 {
+ fmt.Fprintln(b, t.support)
+ fmt.Fprintln(b)
+ }
+ fmt.Fprintln(b, `func main() {`)
+ fmt.Fprintln(b, t.body)
+ fmt.Fprintln(b, `}`)
+
+ if err := b.Flush(); err != nil {
+ fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
+ return false
+ }
+ if err := f.Close(); err != nil {
+ fmt.Fprintf(os.Stderr, "closing %s: %v\n", name, err)
+ return false
+ }
+
+ for _, e := range t.extra {
+ if err := ioutil.WriteFile(filepath.Join(dir, e.name), []byte(e.contents), 0644); err != nil {
+ fmt.Fprintf(os.Stderr, "writing %s: %v\n", e.name, err)
+ return false
+ }
+ }
+
+ ok := true
+
+ cmd := exec.Command("go", "build")
+ cmd.Dir = dir
+ cmd.Env = addEnv("GOPATH", gopath)
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "test %s failed to build: %v\n%s", t.name, err, buf)
+ return false
+ }
+
+ exe := filepath.Join(dir, filepath.Base(dir))
+ cmd = exec.Command(exe)
+ cmd.Dir = dir
+
+ if t.expensive {
+ cmd.Env = cgocheckEnv("1")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ if t.fail {
+ fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
+ } else {
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
+ }
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+
+ cmd = exec.Command(exe)
+ cmd.Dir = dir
+ }
+
+ if t.expensive {
+ cmd.Env = cgocheckEnv("2")
+ }
+
+ buf, err = cmd.CombinedOutput()
+
+ if t.fail {
+ if err == nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ } else if !bytes.Contains(buf, []byte("Go pointer")) {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ } else {
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+
+ if !t.expensive && ok {
+ // Make sure it passes with the expensive checks.
+ cmd := exec.Command(exe)
+ cmd.Dir = dir
+ cmd.Env = cgocheckEnv("2")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ }
+ }
+
+ if t.fail && ok {
+ cmd = exec.Command(exe)
+ cmd.Dir = dir
+ cmd.Env = cgocheckEnv("0")
+ buf, err := cmd.CombinedOutput()
+ if err != nil {
+ var errbuf bytes.Buffer
+ fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
+ reportTestOutput(&errbuf, t.name, buf)
+ os.Stderr.Write(errbuf.Bytes())
+ ok = false
+ }
+ }
+
+ return ok
+}
+
+func reportTestOutput(w io.Writer, name string, buf []byte) {
+ fmt.Fprintf(w, "=== test %s output ===\n", name)
+ fmt.Fprintf(w, "%s", buf)
+ fmt.Fprintf(w, "=== end of test %s output ===\n", name)
+}
+
+func cgocheckEnv(val string) []string {
+ return addEnv("GODEBUG", "cgocheck="+val)
+}
+
+func addEnv(key, val string) []string {
+ env := []string{key + "=" + val}
+ look := key + "="
+ for _, e := range os.Environ() {
+ if !strings.HasPrefix(e, look) {
+ env = append(env, e)
+ }
+ }
+ return env
+}
diff --git a/libgo/misc/cgo/errors/test.bash b/libgo/misc/cgo/errors/test.bash
new file mode 100644
index 00000000000..05261e9d767
--- /dev/null
+++ b/libgo/misc/cgo/errors/test.bash
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+
+# 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.
+
+check() {
+ file=$1
+ line=$(grep -n 'ERROR HERE' $file | sed 's/:.*//')
+ if [ "$line" = "" ]; then
+ echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
+ exit 1
+ fi
+ expect $file $file:$line:
+}
+
+expect() {
+ file=$1
+ shift
+ if go build $file >errs 2>&1; then
+ echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
+ exit 1
+ fi
+ if ! test -s errs; then
+ echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file but saw none
+ exit 1
+ fi
+ for error; do
+ if ! fgrep $error errs >/dev/null 2>&1; then
+ echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file to contain \"$error\" but saw:
+ cat 1>&2 errs
+ exit 1
+ fi
+ done
+}
+
+check err1.go
+check err2.go
+check err3.go
+check issue7757.go
+check issue8442.go
+check issue11097a.go
+check issue11097b.go
+expect issue13129.go C.ushort
+check issue13423.go
+expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
+check issue13830.go
+check issue16116.go
+check issue16591.go
+
+if ! go build issue14669.go; then
+ exit 1
+fi
+if ! CGO_CFLAGS="-O" go build issue14669.go; then
+ exit 1
+fi
+
+if ! go run ptr.go; then
+ exit 1
+fi
+
+# The malloc.go test should crash.
+rm -f malloc.out
+if go run malloc.go >malloc.out 2>&1; then
+ echo '`go run malloc.go` succeeded unexpectedly'
+ cat malloc.out
+ rm -f malloc.out
+ exit 1
+fi
+rm -f malloc.out
+
+rm -rf errs _obj
+exit 0
diff --git a/libgo/misc/cgo/fortran/answer.f90 b/libgo/misc/cgo/fortran/answer.f90
new file mode 100644
index 00000000000..b3717ee27a6
--- /dev/null
+++ b/libgo/misc/cgo/fortran/answer.f90
@@ -0,0 +1,9 @@
+! Copyright 2016 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.
+
+function the_answer() result(j) bind(C)
+ use iso_c_binding, only: c_int
+ integer(c_int) :: j ! output
+ j = 42
+end function the_answer
diff --git a/libgo/misc/cgo/fortran/fortran.go b/libgo/misc/cgo/fortran/fortran.go
new file mode 100644
index 00000000000..0079b535d94
--- /dev/null
+++ b/libgo/misc/cgo/fortran/fortran.go
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package fortran
+
+// int the_answer();
+import "C"
+
+func TheAnswer() int {
+ return int(C.the_answer())
+}
diff --git a/libgo/misc/cgo/fortran/fortran_test.go b/libgo/misc/cgo/fortran/fortran_test.go
new file mode 100644
index 00000000000..d0cb9f22463
--- /dev/null
+++ b/libgo/misc/cgo/fortran/fortran_test.go
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+package fortran
+
+import "testing"
+
+func TestFortran(t *testing.T) {
+ if a := TheAnswer(); a != 42 {
+ t.Errorf("Unexpected result for The Answer. Got: %d Want: 42", a)
+ }
+}
diff --git a/libgo/misc/cgo/fortran/helloworld/helloworld.f90 b/libgo/misc/cgo/fortran/helloworld/helloworld.f90
new file mode 100644
index 00000000000..cbc34c16ef7
--- /dev/null
+++ b/libgo/misc/cgo/fortran/helloworld/helloworld.f90
@@ -0,0 +1,3 @@
+ program HelloWorldF90
+ write(*,*) "Hello World!"
+ end program HelloWorldF90
diff --git a/libgo/misc/cgo/fortran/test.bash b/libgo/misc/cgo/fortran/test.bash
new file mode 100644
index 00000000000..3d1bc9de8e9
--- /dev/null
+++ b/libgo/misc/cgo/fortran/test.bash
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+# Copyright 2016 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.
+
+# This directory is intended to test the use of Fortran with cgo.
+
+set -e
+
+FC=$1
+
+goos=$(go env GOOS)
+
+libext="so"
+if [ "$goos" == "darwin" ]; then
+ libext="dylib"
+fi
+
+case "$FC" in
+*gfortran*)
+ libpath=$(dirname $($FC -print-file-name=libgfortran.$libext))
+ export CGO_LDFLAGS="$CGO_LDFLAGS -Wl,-rpath,$libpath -L $libpath"
+ ;;
+esac
+
+if ! $FC helloworld/helloworld.f90 -o main.exe >& /dev/null; then
+ echo "skipping Fortran test: could not build helloworld.f90 with $FC"
+ exit 0
+fi
+rm -f main.exe
+
+status=0
+
+if ! go test; then
+ echo "FAIL: go test"
+ status=1
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/gmp/fib.go b/libgo/misc/cgo/gmp/fib.go
new file mode 100644
index 00000000000..f1091b1c54f
--- /dev/null
+++ b/libgo/misc/cgo/gmp/fib.go
@@ -0,0 +1,45 @@
+// Copyright 2009 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.
+
+// +build ignore
+
+// Compute Fibonacci numbers with two goroutines
+// that pass integers back and forth. No actual
+// concurrency, just threads and synchronization
+// and foreign code on multiple pthreads.
+
+package main
+
+import (
+ big "."
+ "runtime"
+)
+
+func fibber(c chan *big.Int, out chan string, n int64) {
+ // Keep the fibbers in dedicated operating system
+ // threads, so that this program tests coordination
+ // between pthreads and not just goroutines.
+ runtime.LockOSThread()
+
+ i := big.NewInt(n)
+ if n == 0 {
+ c <- i
+ }
+ for {
+ j := <-c
+ out <- j.String()
+ i.Add(i, j)
+ c <- i
+ }
+}
+
+func main() {
+ c := make(chan *big.Int)
+ out := make(chan string)
+ go fibber(c, out, 0)
+ go fibber(c, out, 1)
+ for i := 0; i < 200; i++ {
+ println(<-out)
+ }
+}
diff --git a/libgo/misc/cgo/gmp/gmp.go b/libgo/misc/cgo/gmp/gmp.go
new file mode 100644
index 00000000000..971a10aaac6
--- /dev/null
+++ b/libgo/misc/cgo/gmp/gmp.go
@@ -0,0 +1,380 @@
+// Copyright 2009 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.
+
+/*
+An example of wrapping a C library in Go. This is the GNU
+multiprecision library gmp's integer type mpz_t wrapped to look like
+the Go package big's integer type Int.
+
+This is a syntactically valid Go program—it can be parsed with the Go
+parser and processed by godoc—but it is not compiled directly by gc.
+Instead, a separate tool, cgo, processes it to produce three output
+files. The first two, 6g.go and 6c.c, are a Go source file for 6g and
+a C source file for 6c; both compile as part of the named package
+(gmp, in this example). The third, gcc.c, is a C source file for gcc;
+it compiles into a shared object (.so) that is dynamically linked into
+any 6.out that imports the first two files.
+
+The stanza
+
+ // #include <gmp.h>
+ import "C"
+
+is a signal to cgo. The doc comment on the import of "C" provides
+additional context for the C file. Here it is just a single #include
+but it could contain arbitrary C definitions to be imported and used.
+
+Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
+find the definition of xxx. If xxx is a type, cgo replaces C.xxx with
+a Go translation. C arithmetic types translate to precisely-sized Go
+arithmetic types. A C struct translates to a Go struct, field by
+field; unrepresentable fields are replaced with opaque byte arrays. A
+C union translates into a struct containing the first union member and
+perhaps additional padding. C arrays become Go arrays. C pointers
+become Go pointers. C function pointers become Go's uintptr.
+C void pointers become Go's unsafe.Pointer.
+
+For example, mpz_t is defined in <gmp.h> as:
+
+ typedef unsigned long int mp_limb_t;
+
+ typedef struct
+ {
+ int _mp_alloc;
+ int _mp_size;
+ mp_limb_t *_mp_d;
+ } __mpz_struct;
+
+ typedef __mpz_struct mpz_t[1];
+
+Cgo generates:
+
+ type _C_int int32
+ type _C_mp_limb_t uint64
+ type _C___mpz_struct struct {
+ _mp_alloc _C_int;
+ _mp_size _C_int;
+ _mp_d *_C_mp_limb_t;
+ }
+ type _C_mpz_t [1]_C___mpz_struct
+
+and then replaces each occurrence of a type C.xxx with _C_xxx.
+
+If xxx is data, cgo arranges for C.xxx to refer to the C variable,
+with the type translated as described above. To do this, cgo must
+introduce a Go variable that points at the C variable (the linker can
+be told to initialize this pointer). For example, if the gmp library
+provided
+
+ mpz_t zero;
+
+then cgo would rewrite a reference to C.zero by introducing
+
+ var _C_zero *C.mpz_t
+
+and then replacing all instances of C.zero with (*_C_zero).
+
+Cgo's most interesting translation is for functions. If xxx is a C
+function, then cgo rewrites C.xxx into a new function _C_xxx that
+calls the C xxx in a standard pthread. The new function translates
+its arguments, calls xxx, and translates the return value.
+
+Translation of parameters and the return value follows the type
+translation above except that arrays passed as parameters translate
+explicitly in Go to pointers to arrays, as they do (implicitly) in C.
+
+Garbage collection is the big problem. It is fine for the Go world to
+have pointers into the C world and to free those pointers when they
+are no longer needed. To help, the Go code can define Go objects
+holding the C pointers and use runtime.SetFinalizer on those Go objects.
+
+It is much more difficult for the C world to have pointers into the Go
+world, because the Go garbage collector is unaware of the memory
+allocated by C. The most important consideration is not to
+constrain future implementations, so the rule is that Go code can
+hand a Go pointer to C code but must separately arrange for
+Go to hang on to a reference to the pointer until C is done with it.
+*/
+package gmp
+
+/*
+#cgo LDFLAGS: -lgmp
+#include <gmp.h>
+#include <stdlib.h>
+
+// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
+// so, to support older versions, we wrap these two functions.
+void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
+ mpz_mul_2exp(a, b, n);
+}
+void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
+ mpz_div_2exp(a, b, n);
+}
+*/
+import "C"
+
+import (
+ "os"
+ "unsafe"
+)
+
+/*
+ * one of a kind
+ */
+
+// An Int represents a signed multi-precision integer.
+// The zero value for an Int represents the value 0.
+type Int struct {
+ i C.mpz_t
+ init bool
+}
+
+// NewInt returns a new Int initialized to x.
+func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
+
+// Int promises that the zero value is a 0, but in gmp
+// the zero value is a crash. To bridge the gap, the
+// init bool says whether this is a valid gmp value.
+// doinit initializes z.i if it needs it. This is not inherent
+// to FFI, just a mismatch between Go's convention of
+// making zero values useful and gmp's decision not to.
+func (z *Int) doinit() {
+ if z.init {
+ return
+ }
+ z.init = true
+ C.mpz_init(&z.i[0])
+}
+
+// Bytes returns z's representation as a big-endian byte array.
+func (z *Int) Bytes() []byte {
+ b := make([]byte, (z.Len()+7)/8)
+ n := C.size_t(len(b))
+ C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
+ return b[0:n]
+}
+
+// Len returns the length of z in bits. 0 is considered to have length 1.
+func (z *Int) Len() int {
+ z.doinit()
+ return int(C.mpz_sizeinbase(&z.i[0], 2))
+}
+
+// Set sets z = x and returns z.
+func (z *Int) Set(x *Int) *Int {
+ z.doinit()
+ C.mpz_set(&z.i[0], &x.i[0])
+ return z
+}
+
+// SetBytes interprets b as the bytes of a big-endian integer
+// and sets z to that value.
+func (z *Int) SetBytes(b []byte) *Int {
+ z.doinit()
+ if len(b) == 0 {
+ z.SetInt64(0)
+ } else {
+ C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
+ }
+ return z
+}
+
+// SetInt64 sets z = x and returns z.
+func (z *Int) SetInt64(x int64) *Int {
+ z.doinit()
+ // TODO(rsc): more work on 32-bit platforms
+ C.mpz_set_si(&z.i[0], C.long(x))
+ return z
+}
+
+// SetString interprets s as a number in the given base
+// and sets z to that value. The base must be in the range [2,36].
+// SetString returns an error if s cannot be parsed or the base is invalid.
+func (z *Int) SetString(s string, base int) error {
+ z.doinit()
+ if base < 2 || base > 36 {
+ return os.ErrInvalid
+ }
+ p := C.CString(s)
+ defer C.free(unsafe.Pointer(p))
+ if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
+ return os.ErrInvalid
+ }
+ return nil
+}
+
+// String returns the decimal representation of z.
+func (z *Int) String() string {
+ if z == nil {
+ return "nil"
+ }
+ z.doinit()
+ p := C.mpz_get_str(nil, 10, &z.i[0])
+ s := C.GoString(p)
+ C.free(unsafe.Pointer(p))
+ return s
+}
+
+func (z *Int) destroy() {
+ if z.init {
+ C.mpz_clear(&z.i[0])
+ }
+ z.init = false
+}
+
+/*
+ * arithmetic
+ */
+
+// Add sets z = x + y and returns z.
+func (z *Int) Add(x, y *Int) *Int {
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
+ return z
+}
+
+// Sub sets z = x - y and returns z.
+func (z *Int) Sub(x, y *Int) *Int {
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
+ return z
+}
+
+// Mul sets z = x * y and returns z.
+func (z *Int) Mul(x, y *Int) *Int {
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
+ return z
+}
+
+// Div sets z = x / y, rounding toward zero, and returns z.
+func (z *Int) Div(x, y *Int) *Int {
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
+ return z
+}
+
+// Mod sets z = x % y and returns z.
+// Like the result of the Go % operator, z has the same sign as x.
+func (z *Int) Mod(x, y *Int) *Int {
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
+ return z
+}
+
+// Lsh sets z = x << s and returns z.
+func (z *Int) Lsh(x *Int, s uint) *Int {
+ x.doinit()
+ z.doinit()
+ C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
+ return z
+}
+
+// Rsh sets z = x >> s and returns z.
+func (z *Int) Rsh(x *Int, s uint) *Int {
+ x.doinit()
+ z.doinit()
+ C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
+ return z
+}
+
+// Exp sets z = x^y % m and returns z.
+// If m == nil, Exp sets z = x^y.
+func (z *Int) Exp(x, y, m *Int) *Int {
+ m.doinit()
+ x.doinit()
+ y.doinit()
+ z.doinit()
+ if m == nil {
+ C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
+ } else {
+ C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
+ }
+ return z
+}
+
+func (z *Int) Int64() int64 {
+ if !z.init {
+ return 0
+ }
+ return int64(C.mpz_get_si(&z.i[0]))
+}
+
+// Neg sets z = -x and returns z.
+func (z *Int) Neg(x *Int) *Int {
+ x.doinit()
+ z.doinit()
+ C.mpz_neg(&z.i[0], &x.i[0])
+ return z
+}
+
+// Abs sets z to the absolute value of x and returns z.
+func (z *Int) Abs(x *Int) *Int {
+ x.doinit()
+ z.doinit()
+ C.mpz_abs(&z.i[0], &x.i[0])
+ return z
+}
+
+/*
+ * functions without a clear receiver
+ */
+
+// CmpInt compares x and y. The result is
+//
+// -1 if x < y
+// 0 if x == y
+// +1 if x > y
+//
+func CmpInt(x, y *Int) int {
+ x.doinit()
+ y.doinit()
+ switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
+ case cmp < 0:
+ return -1
+ case cmp == 0:
+ return 0
+ }
+ return +1
+}
+
+// DivModInt sets q = x / y and r = x % y.
+func DivModInt(q, r, x, y *Int) {
+ q.doinit()
+ r.doinit()
+ x.doinit()
+ y.doinit()
+ C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
+}
+
+// GcdInt sets d to the greatest common divisor of a and b,
+// which must be positive numbers.
+// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
+// If either a or b is not positive, GcdInt sets d = x = y = 0.
+func GcdInt(d, x, y, a, b *Int) {
+ d.doinit()
+ x.doinit()
+ y.doinit()
+ a.doinit()
+ b.doinit()
+ C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
+}
+
+// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
+// If it returns true, z is prime with probability 1 - 1/4^n.
+// If it returns false, z is not prime.
+func (z *Int) ProbablyPrime(n int) bool {
+ z.doinit()
+ return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
+}
diff --git a/libgo/misc/cgo/gmp/pi.go b/libgo/misc/cgo/gmp/pi.go
new file mode 100644
index 00000000000..d5851e8e6bd
--- /dev/null
+++ b/libgo/misc/cgo/gmp/pi.go
@@ -0,0 +1,73 @@
+// Copyright 2009 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.
+
+// +build ignore
+
+package main
+
+import (
+ big "."
+ "fmt"
+ "runtime"
+)
+
+var (
+ tmp1 = big.NewInt(0)
+ tmp2 = big.NewInt(0)
+ numer = big.NewInt(1)
+ accum = big.NewInt(0)
+ denom = big.NewInt(1)
+ ten = big.NewInt(10)
+)
+
+func extractDigit() int64 {
+ if big.CmpInt(numer, accum) > 0 {
+ return -1
+ }
+ tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum)
+ big.DivModInt(tmp1, tmp2, tmp1, denom)
+ tmp2.Add(tmp2, numer)
+ if big.CmpInt(tmp2, denom) >= 0 {
+ return -1
+ }
+ return tmp1.Int64()
+}
+
+func nextTerm(k int64) {
+ y2 := k*2 + 1
+ accum.Add(accum, tmp1.Lsh(numer, 1))
+ accum.Mul(accum, tmp1.SetInt64(y2))
+ numer.Mul(numer, tmp1.SetInt64(k))
+ denom.Mul(denom, tmp1.SetInt64(y2))
+}
+
+func eliminateDigit(d int64) {
+ accum.Sub(accum, tmp1.Mul(denom, tmp1.SetInt64(d)))
+ accum.Mul(accum, ten)
+ numer.Mul(numer, ten)
+}
+
+func main() {
+ i := 0
+ k := int64(0)
+ for {
+ d := int64(-1)
+ for d < 0 {
+ k++
+ nextTerm(k)
+ d = extractDigit()
+ }
+ eliminateDigit(d)
+ fmt.Printf("%c", d+'0')
+
+ if i++; i%50 == 0 {
+ fmt.Printf("\n")
+ if i >= 1000 {
+ break
+ }
+ }
+ }
+
+ fmt.Printf("\n%d calls; bit sizes: %d %d %d\n", runtime.NumCgoCall(), numer.Len(), accum.Len(), denom.Len())
+}
diff --git a/libgo/misc/cgo/life/c-life.c b/libgo/misc/cgo/life/c-life.c
new file mode 100644
index 00000000000..f853163e2f0
--- /dev/null
+++ b/libgo/misc/cgo/life/c-life.c
@@ -0,0 +1,56 @@
+// Copyright 2010 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.
+
+#include <assert.h>
+#include "life.h"
+#include "_cgo_export.h"
+
+const int MYCONST = 0;
+
+// Do the actual manipulation of the life board in C. This could be
+// done easily in Go, we are just using C for demonstration
+// purposes.
+void
+Step(int x, int y, int *a, int *n)
+{
+ struct GoStart_return r;
+
+ // Use Go to start 4 goroutines each of which handles 1/4 of the
+ // board.
+ r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n);
+ assert(r.r0 == 0 && r.r1 == 100); // test multiple returns
+ r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n);
+ assert(r.r0 == 1 && r.r1 == 101); // test multiple returns
+ GoStart(2, x, y, 0, x / 2, y / 2, y, a, n);
+ GoStart(3, x, y, x / 2, x, y / 2, y, a, n);
+ GoWait(0);
+ GoWait(1);
+ GoWait(2);
+ GoWait(3);
+}
+
+// The actual computation. This is called in parallel.
+void
+DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n)
+{
+ int x, y, c, i, j;
+
+ for(x = xstart; x < xend; x++) {
+ for(y = ystart; y < yend; y++) {
+ c = 0;
+ for(i = -1; i <= 1; i++) {
+ for(j = -1; j <= 1; j++) {
+ if(x+i >= 0 && x+i < xdim &&
+ y+j >= 0 && y+j < ydim &&
+ (i != 0 || j != 0))
+ c += a[(x+i)*xdim + (y+j)] != 0;
+ }
+ }
+ if(c == 3 || (c == 2 && a[x*xdim + y] != 0))
+ n[x*xdim + y] = 1;
+ else
+ n[x*xdim + y] = 0;
+ }
+ }
+}
diff --git a/libgo/misc/cgo/life/life.go b/libgo/misc/cgo/life/life.go
new file mode 100644
index 00000000000..170a620c878
--- /dev/null
+++ b/libgo/misc/cgo/life/life.go
@@ -0,0 +1,41 @@
+// skip
+
+// Copyright 2010 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.
+
+package life
+
+// #include "life.h"
+import "C"
+
+import "unsafe"
+
+func Run(gen, x, y int, a []int32) {
+ n := make([]int32, x*y)
+ for i := 0; i < gen; i++ {
+ C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
+ copy(a, n)
+ }
+}
+
+// Keep the channels visible from Go.
+var chans [4]chan bool
+
+//export GoStart
+// Double return value is just for testing.
+func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) {
+ c := make(chan bool, int(C.MYCONST))
+ go func() {
+ C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n)
+ c <- true
+ }()
+ chans[i] = c
+ return int(i), int(i + 100)
+}
+
+//export GoWait
+func GoWait(i C.int) {
+ <-chans[i]
+ chans[i] = nil
+}
diff --git a/libgo/misc/cgo/life/life.h b/libgo/misc/cgo/life/life.h
new file mode 100644
index 00000000000..11d2b972267
--- /dev/null
+++ b/libgo/misc/cgo/life/life.h
@@ -0,0 +1,7 @@
+// Copyright 2010 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.
+
+extern void Step(int, int, int *, int *);
+extern void DoStep(int, int, int, int, int, int, int *, int *);
+extern const int MYCONST;
diff --git a/libgo/misc/cgo/life/main.go b/libgo/misc/cgo/life/main.go
new file mode 100644
index 00000000000..aa2f6d116b3
--- /dev/null
+++ b/libgo/misc/cgo/life/main.go
@@ -0,0 +1,48 @@
+// cmpout
+
+// Copyright 2010 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.
+
+// +build test_run
+
+// Run the game of life in C using Go for parallelization.
+
+package main
+
+import (
+ "."
+ "flag"
+ "fmt"
+)
+
+const MAXDIM = 100
+
+var dim = flag.Int("dim", 16, "board dimensions")
+var gen = flag.Int("gen", 10, "generations")
+
+func main() {
+ flag.Parse()
+
+ var a [MAXDIM * MAXDIM]int32
+ for i := 2; i < *dim; i += 8 {
+ for j := 2; j < *dim-3; j += 8 {
+ for y := 0; y < 3; y++ {
+ a[i**dim+j+y] = 1
+ }
+ }
+ }
+
+ life.Run(*gen, *dim, *dim, a[:])
+
+ for i := 0; i < *dim; i++ {
+ for j := 0; j < *dim; j++ {
+ if a[i**dim+j] == 0 {
+ fmt.Print(" ")
+ } else {
+ fmt.Print("X")
+ }
+ }
+ fmt.Print("\n")
+ }
+}
diff --git a/libgo/misc/cgo/life/main.out b/libgo/misc/cgo/life/main.out
new file mode 100644
index 00000000000..26fc9c6e3ff
--- /dev/null
+++ b/libgo/misc/cgo/life/main.out
@@ -0,0 +1,16 @@
+
+
+ XXX XXX
+
+
+
+
+
+
+
+ XXX XXX
+
+
+
+
+
diff --git a/libgo/misc/cgo/nocgo/nocgo.go b/libgo/misc/cgo/nocgo/nocgo.go
new file mode 100644
index 00000000000..00ae5e9c862
--- /dev/null
+++ b/libgo/misc/cgo/nocgo/nocgo.go
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+// Test that -static works when not using cgo. This test is in
+// misc/cgo to take advantage of the testing framework support for
+// when -static is expected to work.
+
+package nocgo
+
+func NoCgo() int {
+ c := make(chan int)
+
+ // The test is run with external linking, which means that
+ // goroutines will be created via the runtime/cgo package.
+ // Make sure that works.
+ go func() {
+ c <- 42
+ }()
+
+ return <-c
+}
diff --git a/libgo/misc/cgo/nocgo/nocgo_test.go b/libgo/misc/cgo/nocgo/nocgo_test.go
new file mode 100644
index 00000000000..45d247cf954
--- /dev/null
+++ b/libgo/misc/cgo/nocgo/nocgo_test.go
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+package nocgo
+
+import "testing"
+
+func TestNop(t *testing.T) {
+ i := NoCgo()
+ if i != 42 {
+ t.Errorf("got %d, want %d", i, 42)
+ }
+}
diff --git a/libgo/misc/cgo/stdio/chain.go b/libgo/misc/cgo/stdio/chain.go
new file mode 100644
index 00000000000..03cddb76888
--- /dev/null
+++ b/libgo/misc/cgo/stdio/chain.go
@@ -0,0 +1,48 @@
+// cmpout
+
+// Copyright 2009 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.
+
+// +build test_run
+
+// Pass numbers along a chain of threads.
+
+package main
+
+import (
+ "runtime"
+ "strconv"
+
+ "../stdio"
+)
+
+const N = 10
+const R = 5
+
+func link(left chan<- int, right <-chan int) {
+ // Keep the links in dedicated operating system
+ // threads, so that this program tests coordination
+ // between pthreads and not just goroutines.
+ runtime.LockOSThread()
+ for {
+ v := <-right
+ stdio.Stdout.WriteString(strconv.Itoa(v) + "\n")
+ left <- 1 + v
+ }
+}
+
+func main() {
+ leftmost := make(chan int)
+ var left chan int
+ right := leftmost
+ for i := 0; i < N; i++ {
+ left, right = right, make(chan int)
+ go link(left, right)
+ }
+ for i := 0; i < R; i++ {
+ right <- 0
+ x := <-leftmost
+ stdio.Stdout.WriteString(strconv.Itoa(x) + "\n")
+ }
+}
diff --git a/libgo/misc/cgo/stdio/chain.out b/libgo/misc/cgo/stdio/chain.out
new file mode 100644
index 00000000000..963cf9b6679
--- /dev/null
+++ b/libgo/misc/cgo/stdio/chain.out
@@ -0,0 +1,55 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/libgo/misc/cgo/stdio/fib.go b/libgo/misc/cgo/stdio/fib.go
new file mode 100644
index 00000000000..61a1b83728c
--- /dev/null
+++ b/libgo/misc/cgo/stdio/fib.go
@@ -0,0 +1,52 @@
+// cmpout
+
+// Copyright 2009 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.
+
+// +build test_run
+
+// Compute Fibonacci numbers with two goroutines
+// that pass integers back and forth. No actual
+// concurrency, just threads and synchronization
+// and foreign code on multiple pthreads.
+
+package main
+
+import (
+ "runtime"
+ "strconv"
+
+ "../stdio"
+)
+
+func fibber(c, out chan int64, i int64) {
+ // Keep the fibbers in dedicated operating system
+ // threads, so that this program tests coordination
+ // between pthreads and not just goroutines.
+ runtime.LockOSThread()
+
+ if i == 0 {
+ c <- i
+ }
+ for {
+ j := <-c
+ stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n")
+ out <- j
+ <-out
+ i += j
+ c <- i
+ }
+}
+
+func main() {
+ c := make(chan int64)
+ out := make(chan int64)
+ go fibber(c, out, 0)
+ go fibber(c, out, 1)
+ <-out
+ for i := 0; i < 90; i++ {
+ out <- 1
+ <-out
+ }
+}
diff --git a/libgo/misc/cgo/stdio/fib.out b/libgo/misc/cgo/stdio/fib.out
new file mode 100644
index 00000000000..17ff503356d
--- /dev/null
+++ b/libgo/misc/cgo/stdio/fib.out
@@ -0,0 +1,91 @@
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
+1346269
+2178309
+3524578
+5702887
+9227465
+14930352
+24157817
+39088169
+63245986
+102334155
+165580141
+267914296
+433494437
+701408733
+1134903170
+1836311903
+2971215073
+4807526976
+7778742049
+12586269025
+20365011074
+32951280099
+53316291173
+86267571272
+139583862445
+225851433717
+365435296162
+591286729879
+956722026041
+1548008755920
+2504730781961
+4052739537881
+6557470319842
+10610209857723
+17167680177565
+27777890035288
+44945570212853
+72723460248141
+117669030460994
+190392490709135
+308061521170129
+498454011879264
+806515533049393
+1304969544928657
+2111485077978050
+3416454622906707
+5527939700884757
+8944394323791464
+14472334024676221
+23416728348467685
+37889062373143906
+61305790721611591
+99194853094755497
+160500643816367088
+259695496911122585
+420196140727489673
+679891637638612258
+1100087778366101931
+1779979416004714189
+2880067194370816120
diff --git a/libgo/misc/cgo/stdio/file.go b/libgo/misc/cgo/stdio/file.go
new file mode 100644
index 00000000000..a024f2c361c
--- /dev/null
+++ b/libgo/misc/cgo/stdio/file.go
@@ -0,0 +1,44 @@
+// skip
+
+// Copyright 2009 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.
+
+/*
+A trivial example of wrapping a C library in Go.
+For a more complex example and explanation,
+see ../gmp/gmp.go.
+*/
+
+package stdio
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+char* greeting = "hello, world";
+*/
+import "C"
+import "unsafe"
+
+type File C.FILE
+
+// Test reference to library symbol.
+// Stdout and stderr are too special to be a reliable test.
+//var = C.environ
+
+func (f *File) WriteString(s string) {
+ p := C.CString(s)
+ C.fputs(p, (*C.FILE)(f))
+ C.free(unsafe.Pointer(p))
+ f.Flush()
+}
+
+func (f *File) Flush() {
+ C.fflush((*C.FILE)(f))
+}
+
+var Greeting = C.GoString(C.greeting)
+var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting)))
diff --git a/libgo/misc/cgo/stdio/hello.go b/libgo/misc/cgo/stdio/hello.go
new file mode 100644
index 00000000000..47179ba4827
--- /dev/null
+++ b/libgo/misc/cgo/stdio/hello.go
@@ -0,0 +1,15 @@
+// cmpout
+
+// Copyright 2009 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.
+
+// +build test_run
+
+package main
+
+import "../stdio"
+
+func main() {
+ stdio.Stdout.WriteString(stdio.Greeting + "\n")
+}
diff --git a/libgo/misc/cgo/stdio/hello.out b/libgo/misc/cgo/stdio/hello.out
new file mode 100644
index 00000000000..4b5fa63702d
--- /dev/null
+++ b/libgo/misc/cgo/stdio/hello.out
@@ -0,0 +1 @@
+hello, world
diff --git a/libgo/misc/cgo/stdio/run.out b/libgo/misc/cgo/stdio/run.out
new file mode 100644
index 00000000000..c0e496547ed
--- /dev/null
+++ b/libgo/misc/cgo/stdio/run.out
@@ -0,0 +1,150 @@
+* hello
+hello, world
+* fib
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
+1346269
+2178309
+3524578
+5702887
+9227465
+14930352
+24157817
+39088169
+63245986
+102334155
+165580141
+267914296
+433494437
+701408733
+1134903170
+1836311903
+2971215073
+4807526976
+7778742049
+12586269025
+20365011074
+32951280099
+53316291173
+86267571272
+139583862445
+225851433717
+365435296162
+591286729879
+956722026041
+1548008755920
+2504730781961
+4052739537881
+6557470319842
+10610209857723
+17167680177565
+27777890035288
+44945570212853
+72723460248141
+117669030460994
+190392490709135
+308061521170129
+498454011879264
+806515533049393
+1304969544928657
+2111485077978050
+3416454622906707
+5527939700884757
+8944394323791464
+14472334024676221
+23416728348467685
+37889062373143906
+61305790721611591
+99194853094755497
+160500643816367088
+259695496911122585
+420196140727489673
+679891637638612258
+1100087778366101931
+1779979416004714189
+2880067194370816120
+* chain
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/libgo/misc/cgo/stdio/stdio.go b/libgo/misc/cgo/stdio/stdio.go
new file mode 100644
index 00000000000..d216e44fe7c
--- /dev/null
+++ b/libgo/misc/cgo/stdio/stdio.go
@@ -0,0 +1,22 @@
+// skip
+
+// Copyright 2009 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.
+
+package stdio
+
+/*
+#include <stdio.h>
+
+// on mingw, stderr and stdout are defined as &_iob[FILENO]
+// on netbsd, they are defined as &__sF[FILENO]
+// and cgo doesn't recognize them, so write a function to get them,
+// instead of depending on internals of libc implementation.
+FILE *getStdout(void) { return stdout; }
+FILE *getStderr(void) { return stderr; }
+*/
+import "C"
+
+var Stdout = (*File)(C.getStdout())
+var Stderr = (*File)(C.getStderr())
diff --git a/libgo/misc/cgo/test/align.go b/libgo/misc/cgo/test/align.go
new file mode 100644
index 00000000000..a23b44fc38c
--- /dev/null
+++ b/libgo/misc/cgo/test/align.go
@@ -0,0 +1,76 @@
+// Copyright 2010 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.
+
+package cgotest
+
+/*
+#include <stdio.h>
+
+typedef unsigned char Uint8;
+typedef unsigned short Uint16;
+
+typedef enum {
+ MOD1 = 0x0000,
+ MODX = 0x8000
+} SDLMod;
+
+typedef enum {
+ A = 1,
+ B = 322,
+ SDLK_LAST
+} SDLKey;
+
+typedef struct SDL_keysym {
+ Uint8 scancode;
+ SDLKey sym;
+ SDLMod mod;
+ Uint16 unicode;
+} SDL_keysym;
+
+typedef struct SDL_KeyboardEvent {
+ Uint8 typ;
+ Uint8 which;
+ Uint8 state;
+ SDL_keysym keysym;
+} SDL_KeyboardEvent;
+
+void makeEvent(SDL_KeyboardEvent *event) {
+ unsigned char *p;
+ int i;
+
+ p = (unsigned char*)event;
+ for (i=0; i<sizeof *event; i++) {
+ p[i] = i;
+ }
+}
+
+int same(SDL_KeyboardEvent* e, Uint8 typ, Uint8 which, Uint8 state, Uint8 scan, SDLKey sym, SDLMod mod, Uint16 uni) {
+ return e->typ == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni;
+}
+
+void cTest(SDL_KeyboardEvent *event) {
+ printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state,
+ event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode);
+ fflush(stdout);
+}
+
+*/
+import "C"
+
+import (
+ "testing"
+)
+
+func testAlign(t *testing.T) {
+ var evt C.SDL_KeyboardEvent
+ C.makeEvent(&evt)
+ if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 {
+ t.Error("*** bad alignment")
+ C.cTest(&evt)
+ t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n",
+ evt.typ, evt.which, evt.state, evt.keysym.scancode,
+ evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode)
+ t.Error(evt)
+ }
+}
diff --git a/libgo/misc/cgo/test/api.go b/libgo/misc/cgo/test/api.go
new file mode 100644
index 00000000000..d2b09cbeffe
--- /dev/null
+++ b/libgo/misc/cgo/test/api.go
@@ -0,0 +1,30 @@
+// 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.
+
+// API Compatibility Checks for cgo
+
+package cgotest
+
+// #include <stdlib.h>
+//
+// // Test for issue 17723.
+// typedef char *cstring_pointer;
+// static void cstring_pointer_fun(cstring_pointer dummy) { }
+//
+// const char *api_hello = "hello!";
+import "C"
+import "unsafe"
+
+func testAPI() {
+ var cs *C.char
+ cs = C.CString("hello")
+ defer C.free(unsafe.Pointer(cs))
+ var s string
+ s = C.GoString((*C.char)(C.api_hello))
+ s = C.GoStringN((*C.char)(C.api_hello), C.int(6))
+ var b []byte
+ b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6))
+ _, _ = s, b
+ C.cstring_pointer_fun(nil)
+}
diff --git a/libgo/misc/cgo/test/backdoor.go b/libgo/misc/cgo/test/backdoor.go
new file mode 100644
index 00000000000..6fb33d66cb2
--- /dev/null
+++ b/libgo/misc/cgo/test/backdoor.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+package cgotest
+
+import _ "unsafe"
+
+//go:linkname lockedOSThread runtime.lockedOSThread
+//extern runtime_lockedOSThread
+func lockedOSThread() bool
diff --git a/libgo/misc/cgo/test/basic.go b/libgo/misc/cgo/test/basic.go
new file mode 100644
index 00000000000..3ceb4ce8470
--- /dev/null
+++ b/libgo/misc/cgo/test/basic.go
@@ -0,0 +1,167 @@
+// Copyright 2010 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.
+
+// Basic test cases for cgo.
+
+package cgotest
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define SHIFT(x, y) ((x)<<(y))
+#define KILO SHIFT(1, 10)
+#define UINT32VAL 0xc008427bU
+
+enum E {
+ Enum1 = 1,
+ Enum2 = 2,
+};
+
+typedef unsigned char cgo_uuid_t[20];
+
+void uuid_generate(cgo_uuid_t x) {
+ x[0] = 0;
+}
+
+struct S {
+ int x;
+};
+
+extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter);
+
+enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; }
+
+// issue 1222
+typedef union {
+ long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+ union {
+ int x;
+ } element;
+};
+
+struct ibv_context {
+ xxpthread_mutex_t mutex;
+};
+
+int add(int x, int y) {
+ return x+y;
+};
+*/
+import "C"
+import (
+ "runtime"
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+const EINVAL = C.EINVAL /* test #define */
+
+var KILO = C.KILO
+
+func uuidgen() {
+ var uuid C.cgo_uuid_t
+ C.uuid_generate(&uuid[0])
+}
+
+func Strtol(s string, base int) (int, error) {
+ p := C.CString(s)
+ n, err := C.strtol(p, nil, C.int(base))
+ C.free(unsafe.Pointer(p))
+ return int(n), err
+}
+
+func Atol(s string) int {
+ p := C.CString(s)
+ n := C.atol(p)
+ C.free(unsafe.Pointer(p))
+ return int(n)
+}
+
+func testConst(t *testing.T) {
+ C.myConstFunc(nil, 0, nil)
+}
+
+func testEnum(t *testing.T) {
+ if C.Enum1 != 1 || C.Enum2 != 2 {
+ t.Error("bad enum", C.Enum1, C.Enum2)
+ }
+}
+
+func testAtol(t *testing.T) {
+ l := Atol("123")
+ if l != 123 {
+ t.Error("Atol 123: ", l)
+ }
+}
+
+func testErrno(t *testing.T) {
+ p := C.CString("no-such-file")
+ m := C.CString("r")
+ f, err := C.fopen(p, m)
+ C.free(unsafe.Pointer(p))
+ C.free(unsafe.Pointer(m))
+ if err == nil {
+ C.fclose(f)
+ t.Fatalf("C.fopen: should fail")
+ }
+ if err != syscall.ENOENT {
+ t.Fatalf("C.fopen: unexpected error: %v", err)
+ }
+}
+
+func testMultipleAssign(t *testing.T) {
+ p := C.CString("234")
+ n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10)
+ if runtime.GOOS == "openbsd" {
+ // Bug in OpenBSD strtol(3) - base > 36 succeeds.
+ if (n != 0 && n != 239089) || m != 234 {
+ t.Fatal("Strtol x2: ", n, m)
+ }
+ } else if n != 0 || m != 234 {
+ t.Fatal("Strtol x2: ", n, m)
+ }
+ C.free(unsafe.Pointer(p))
+}
+
+var (
+ cuint = (C.uint)(0)
+ culong C.ulong
+ cchar C.char
+)
+
+type Context struct {
+ ctx *C.struct_ibv_context
+}
+
+func benchCgoCall(b *testing.B) {
+ const x = C.int(2)
+ const y = C.int(3)
+ for i := 0; i < b.N; i++ {
+ C.add(x, y)
+ }
+}
+
+// Issue 2470.
+func testUnsignedInt(t *testing.T) {
+ a := (int64)(C.UINT32VAL)
+ b := (int64)(0xc008427b)
+ if a != b {
+ t.Errorf("Incorrect unsigned int - got %x, want %x", a, b)
+ }
+}
+
+// Static (build-time) test that syntax traversal visits all operands of s[i:j:k].
+func sliceOperands(array [2000]int) {
+ _ = array[C.KILO:C.KILO:C.KILO] // no type error
+}
+
+// set in cgo_thread_lock.go init
+var testThreadLockFunc = func(*testing.T) {}
diff --git a/libgo/misc/cgo/test/buildid_linux.go b/libgo/misc/cgo/test/buildid_linux.go
new file mode 100644
index 00000000000..47dd87128ff
--- /dev/null
+++ b/libgo/misc/cgo/test/buildid_linux.go
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+package cgotest
+
+// Test that we have no more than one build ID. In the past we used
+// to generate a separate build ID for each package using cgo, and the
+// linker concatenated them all. We don't want that--we only want
+// one.
+
+import (
+ "bytes"
+ "debug/elf"
+ "os"
+ "testing"
+)
+
+func testBuildID(t *testing.T) {
+ f, err := elf.Open("/proc/self/exe")
+ if err != nil {
+ if os.IsNotExist(err) {
+ t.Skip("no /proc/self/exe")
+ }
+ t.Fatal("opening /proc/self/exe: ", err)
+ }
+ defer f.Close()
+
+ c := 0
+ for i, s := range f.Sections {
+ if s.Type != elf.SHT_NOTE {
+ continue
+ }
+
+ d, err := s.Data()
+ if err != nil {
+ t.Logf("reading data of note section %d: %v", i, err)
+ continue
+ }
+
+ for len(d) > 0 {
+
+ // ELF standards differ as to the sizes in
+ // note sections. Both the GNU linker and
+ // gold always generate 32-bit sizes, so that
+ // is what we assume here.
+
+ if len(d) < 12 {
+ t.Logf("note section %d too short (%d < 12)", i, len(d))
+ continue
+ }
+
+ namesz := f.ByteOrder.Uint32(d)
+ descsz := f.ByteOrder.Uint32(d[4:])
+ typ := f.ByteOrder.Uint32(d[8:])
+
+ an := (namesz + 3) &^ 3
+ ad := (descsz + 3) &^ 3
+
+ if int(12+an+ad) > len(d) {
+ t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
+ continue
+ }
+
+ // 3 == NT_GNU_BUILD_ID
+ if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
+ c++
+ }
+
+ d = d[12+an+ad:]
+ }
+ }
+
+ if c > 1 {
+ t.Errorf("found %d build ID notes", c)
+ }
+}
diff --git a/libgo/misc/cgo/test/callback.go b/libgo/misc/cgo/test/callback.go
new file mode 100644
index 00000000000..b88bf134bc1
--- /dev/null
+++ b/libgo/misc/cgo/test/callback.go
@@ -0,0 +1,1782 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+void callback(void *f);
+void callGoFoo(void);
+void callGoStackCheck(void);
+void callPanic(void);
+int callGoReturnVal(void);
+int returnAfterGrow(void);
+int returnAfterGrowFromGo(void);
+void callGoWithString(void);
+*/
+import "C"
+
+import (
+ "path"
+ "runtime"
+ "strings"
+ "sync"
+ "testing"
+ "unsafe"
+)
+
+// Pass a func value from nestedCall to goCallback using an integer token.
+var callbackMutex sync.Mutex
+var callbackToken int
+var callbackFuncs = make(map[int]func())
+
+// nestedCall calls into C, back into Go, and finally to f.
+func nestedCall(f func()) {
+ // callback(x) calls goCallback(x)
+ callbackMutex.Lock()
+ callbackToken++
+ i := callbackToken
+ callbackFuncs[i] = f
+ callbackMutex.Unlock()
+
+ // Pass the address of i because the C function was written to
+ // take a pointer. We could pass an int if we felt like
+ // rewriting the C code.
+ C.callback(unsafe.Pointer(&i))
+
+ callbackMutex.Lock()
+ delete(callbackFuncs, i)
+ callbackMutex.Unlock()
+}
+
+//export goCallback
+func goCallback(p unsafe.Pointer) {
+ i := *(*int)(p)
+
+ callbackMutex.Lock()
+ f := callbackFuncs[i]
+ callbackMutex.Unlock()
+
+ if f == nil {
+ panic("missing callback function")
+ }
+ f()
+}
+
+func testCallback(t *testing.T) {
+ var x = false
+ nestedCall(func() { x = true })
+ if !x {
+ t.Fatal("nestedCall did not call func")
+ }
+}
+
+func testCallbackGC(t *testing.T) {
+ nestedCall(runtime.GC)
+}
+
+func testCallbackPanic(t *testing.T) {
+ // Make sure panic during callback unwinds properly.
+ if lockedOSThread() {
+ t.Fatal("locked OS thread on entry to TestCallbackPanic")
+ }
+ defer func() {
+ s := recover()
+ if s == nil {
+ t.Fatal("did not panic")
+ }
+ if s.(string) != "callback panic" {
+ t.Fatal("wrong panic:", s)
+ }
+ if lockedOSThread() {
+ t.Fatal("locked OS thread on exit from TestCallbackPanic")
+ }
+ }()
+ nestedCall(func() { panic("callback panic") })
+ panic("nestedCall returned")
+}
+
+func testCallbackPanicLoop(t *testing.T) {
+ // Make sure we don't blow out m->g0 stack.
+ for i := 0; i < 100000; i++ {
+ testCallbackPanic(t)
+ }
+}
+
+func testCallbackPanicLocked(t *testing.T) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if !lockedOSThread() {
+ t.Fatal("runtime.LockOSThread didn't")
+ }
+ defer func() {
+ s := recover()
+ if s == nil {
+ t.Fatal("did not panic")
+ }
+ if s.(string) != "callback panic" {
+ t.Fatal("wrong panic:", s)
+ }
+ if !lockedOSThread() {
+ t.Fatal("lost lock on OS thread after panic")
+ }
+ }()
+ nestedCall(func() { panic("callback panic") })
+ panic("nestedCall returned")
+}
+
+// Callback with zero arguments used to make the stack misaligned,
+// which broke the garbage collector and other things.
+func testZeroArgCallback(t *testing.T) {
+ defer func() {
+ s := recover()
+ if s != nil {
+ t.Fatal("panic during callback:", s)
+ }
+ }()
+ C.callGoFoo()
+}
+
+//export goFoo
+func goFoo() {
+ x := 1
+ for i := 0; i < 10000; i++ {
+ // variadic call mallocs + writes to
+ variadic(x, x, x)
+ if x != 1 {
+ panic("bad x")
+ }
+ }
+}
+
+func variadic(x ...interface{}) {}
+
+func testBlocking(t *testing.T) {
+ c := make(chan int)
+ go func() {
+ for i := 0; i < 10; i++ {
+ c <- <-c
+ }
+ }()
+ nestedCall(func() {
+ for i := 0; i < 10; i++ {
+ c <- i
+ if j := <-c; j != i {
+ t.Errorf("out of sync %d != %d", j, i)
+ }
+ }
+ })
+}
+
+// Test that the stack can be unwound through a call out and call back
+// into Go.
+func testCallbackCallers(t *testing.T) {
+ if runtime.Compiler != "gc" {
+ // The exact function names are not going to be the same.
+ t.Skip("skipping for non-gc toolchain")
+ }
+ pc := make([]uintptr, 100)
+ n := 0
+ name := []string{
+ "runtime.call16",
+ "runtime.cgocallbackg1",
+ "runtime.cgocallbackg",
+ "runtime.cgocallback_gofunc",
+ "runtime.asmcgocall",
+ "runtime.cgocall",
+ "test._Cfunc_callback",
+ "test.nestedCall.func1",
+ "test.nestedCall",
+ "test.testCallbackCallers",
+ "test.TestCallbackCallers",
+ "testing.tRunner",
+ "runtime.goexit",
+ }
+ if unsafe.Sizeof((*byte)(nil)) == 8 {
+ name[0] = "runtime.call32"
+ }
+ nestedCall(func() {
+ n = runtime.Callers(4, pc)
+ })
+ if n != len(name) {
+ t.Errorf("expected %d frames, got %d", len(name), n)
+ }
+ for i := 0; i < n; i++ {
+ f := runtime.FuncForPC(pc[i])
+ if f == nil {
+ t.Fatalf("expected non-nil Func for pc %d", pc[i])
+ }
+ fname := f.Name()
+ // Remove the prepended pathname from automatically
+ // generated cgo function names.
+ if strings.HasPrefix(fname, "_") {
+ fname = path.Base(f.Name()[1:])
+ }
+ namei := ""
+ if i < len(name) {
+ namei = name[i]
+ }
+ if fname != namei {
+ t.Errorf("stk[%d] = %q, want %q", i, fname, namei)
+ }
+ }
+}
+
+func testPanicFromC(t *testing.T) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ t.Fatal("did not panic")
+ }
+ if r.(string) != "panic from C" {
+ t.Fatal("wrong panic:", r)
+ }
+ }()
+ C.callPanic()
+}
+
+// Test that C code can return a value if it calls a Go function that
+// causes a stack copy.
+func testReturnAfterGrow(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrow())
+ }()
+ if got, want := <-c, 123456; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+// Test that we can return a value from Go->C->Go if the Go code
+// causes a stack copy.
+func testReturnAfterGrowFromGo(t *testing.T) {
+ // Use a new goroutine so that we get a small stack.
+ c := make(chan int)
+ go func() {
+ c <- int(C.returnAfterGrowFromGo())
+ }()
+ if got, want := <-c, 129*128/2; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}
+
+//export goReturnVal
+func goReturnVal() (r C.int) {
+ // Force a stack copy.
+ var f func(int) int
+ f = func(i int) int {
+ var buf [256]byte
+ use(buf[:])
+ if i == 0 {
+ return 0
+ }
+ return i + f(i-1)
+ }
+ r = C.int(f(128))
+ return
+}
+
+// Test that C can pass in a Go string from a string constant.
+func testCallGoWithString(t *testing.T) {
+ C.callGoWithString()
+ want := "string passed from C to Go"
+ if stringFromGo != want {
+ t.Errorf("string passed through C is %s, want %s", stringFromGo, want)
+ }
+}
+
+var stringFromGo string
+
+//export goWithString
+func goWithString(s string) {
+ stringFromGo = s
+}
+
+func testCallbackStack(t *testing.T) {
+ // Make cgo call and callback with different amount of stack stack available.
+ // We do not do any explicit checks, just ensure that it does not crash.
+ for _, f := range splitTests {
+ f()
+ }
+}
+
+//export goStackCheck
+func goStackCheck() {
+ // use some stack memory to trigger split stack check
+ var buf [256]byte
+ use(buf[:])
+}
+
+var Used byte
+
+func use(buf []byte) {
+ for _, c := range buf {
+ Used += c
+ }
+}
+
+var splitTests = []func(){
+ // Edit .+1,/^}/-1|seq 4 4 5000 | sed 's/.*/ stack&,/' | fmt
+ stack4, stack8, stack12, stack16, stack20, stack24, stack28,
+ stack32, stack36, stack40, stack44, stack48, stack52, stack56,
+ stack60, stack64, stack68, stack72, stack76, stack80, stack84,
+ stack88, stack92, stack96, stack100, stack104, stack108, stack112,
+ stack116, stack120, stack124, stack128, stack132, stack136,
+ stack140, stack144, stack148, stack152, stack156, stack160,
+ stack164, stack168, stack172, stack176, stack180, stack184,
+ stack188, stack192, stack196, stack200, stack204, stack208,
+ stack212, stack216, stack220, stack224, stack228, stack232,
+ stack236, stack240, stack244, stack248, stack252, stack256,
+ stack260, stack264, stack268, stack272, stack276, stack280,
+ stack284, stack288, stack292, stack296, stack300, stack304,
+ stack308, stack312, stack316, stack320, stack324, stack328,
+ stack332, stack336, stack340, stack344, stack348, stack352,
+ stack356, stack360, stack364, stack368, stack372, stack376,
+ stack380, stack384, stack388, stack392, stack396, stack400,
+ stack404, stack408, stack412, stack416, stack420, stack424,
+ stack428, stack432, stack436, stack440, stack444, stack448,
+ stack452, stack456, stack460, stack464, stack468, stack472,
+ stack476, stack480, stack484, stack488, stack492, stack496,
+ stack500, stack504, stack508, stack512, stack516, stack520,
+ stack524, stack528, stack532, stack536, stack540, stack544,
+ stack548, stack552, stack556, stack560, stack564, stack568,
+ stack572, stack576, stack580, stack584, stack588, stack592,
+ stack596, stack600, stack604, stack608, stack612, stack616,
+ stack620, stack624, stack628, stack632, stack636, stack640,
+ stack644, stack648, stack652, stack656, stack660, stack664,
+ stack668, stack672, stack676, stack680, stack684, stack688,
+ stack692, stack696, stack700, stack704, stack708, stack712,
+ stack716, stack720, stack724, stack728, stack732, stack736,
+ stack740, stack744, stack748, stack752, stack756, stack760,
+ stack764, stack768, stack772, stack776, stack780, stack784,
+ stack788, stack792, stack796, stack800, stack804, stack808,
+ stack812, stack816, stack820, stack824, stack828, stack832,
+ stack836, stack840, stack844, stack848, stack852, stack856,
+ stack860, stack864, stack868, stack872, stack876, stack880,
+ stack884, stack888, stack892, stack896, stack900, stack904,
+ stack908, stack912, stack916, stack920, stack924, stack928,
+ stack932, stack936, stack940, stack944, stack948, stack952,
+ stack956, stack960, stack964, stack968, stack972, stack976,
+ stack980, stack984, stack988, stack992, stack996, stack1000,
+ stack1004, stack1008, stack1012, stack1016, stack1020, stack1024,
+ stack1028, stack1032, stack1036, stack1040, stack1044, stack1048,
+ stack1052, stack1056, stack1060, stack1064, stack1068, stack1072,
+ stack1076, stack1080, stack1084, stack1088, stack1092, stack1096,
+ stack1100, stack1104, stack1108, stack1112, stack1116, stack1120,
+ stack1124, stack1128, stack1132, stack1136, stack1140, stack1144,
+ stack1148, stack1152, stack1156, stack1160, stack1164, stack1168,
+ stack1172, stack1176, stack1180, stack1184, stack1188, stack1192,
+ stack1196, stack1200, stack1204, stack1208, stack1212, stack1216,
+ stack1220, stack1224, stack1228, stack1232, stack1236, stack1240,
+ stack1244, stack1248, stack1252, stack1256, stack1260, stack1264,
+ stack1268, stack1272, stack1276, stack1280, stack1284, stack1288,
+ stack1292, stack1296, stack1300, stack1304, stack1308, stack1312,
+ stack1316, stack1320, stack1324, stack1328, stack1332, stack1336,
+ stack1340, stack1344, stack1348, stack1352, stack1356, stack1360,
+ stack1364, stack1368, stack1372, stack1376, stack1380, stack1384,
+ stack1388, stack1392, stack1396, stack1400, stack1404, stack1408,
+ stack1412, stack1416, stack1420, stack1424, stack1428, stack1432,
+ stack1436, stack1440, stack1444, stack1448, stack1452, stack1456,
+ stack1460, stack1464, stack1468, stack1472, stack1476, stack1480,
+ stack1484, stack1488, stack1492, stack1496, stack1500, stack1504,
+ stack1508, stack1512, stack1516, stack1520, stack1524, stack1528,
+ stack1532, stack1536, stack1540, stack1544, stack1548, stack1552,
+ stack1556, stack1560, stack1564, stack1568, stack1572, stack1576,
+ stack1580, stack1584, stack1588, stack1592, stack1596, stack1600,
+ stack1604, stack1608, stack1612, stack1616, stack1620, stack1624,
+ stack1628, stack1632, stack1636, stack1640, stack1644, stack1648,
+ stack1652, stack1656, stack1660, stack1664, stack1668, stack1672,
+ stack1676, stack1680, stack1684, stack1688, stack1692, stack1696,
+ stack1700, stack1704, stack1708, stack1712, stack1716, stack1720,
+ stack1724, stack1728, stack1732, stack1736, stack1740, stack1744,
+ stack1748, stack1752, stack1756, stack1760, stack1764, stack1768,
+ stack1772, stack1776, stack1780, stack1784, stack1788, stack1792,
+ stack1796, stack1800, stack1804, stack1808, stack1812, stack1816,
+ stack1820, stack1824, stack1828, stack1832, stack1836, stack1840,
+ stack1844, stack1848, stack1852, stack1856, stack1860, stack1864,
+ stack1868, stack1872, stack1876, stack1880, stack1884, stack1888,
+ stack1892, stack1896, stack1900, stack1904, stack1908, stack1912,
+ stack1916, stack1920, stack1924, stack1928, stack1932, stack1936,
+ stack1940, stack1944, stack1948, stack1952, stack1956, stack1960,
+ stack1964, stack1968, stack1972, stack1976, stack1980, stack1984,
+ stack1988, stack1992, stack1996, stack2000, stack2004, stack2008,
+ stack2012, stack2016, stack2020, stack2024, stack2028, stack2032,
+ stack2036, stack2040, stack2044, stack2048, stack2052, stack2056,
+ stack2060, stack2064, stack2068, stack2072, stack2076, stack2080,
+ stack2084, stack2088, stack2092, stack2096, stack2100, stack2104,
+ stack2108, stack2112, stack2116, stack2120, stack2124, stack2128,
+ stack2132, stack2136, stack2140, stack2144, stack2148, stack2152,
+ stack2156, stack2160, stack2164, stack2168, stack2172, stack2176,
+ stack2180, stack2184, stack2188, stack2192, stack2196, stack2200,
+ stack2204, stack2208, stack2212, stack2216, stack2220, stack2224,
+ stack2228, stack2232, stack2236, stack2240, stack2244, stack2248,
+ stack2252, stack2256, stack2260, stack2264, stack2268, stack2272,
+ stack2276, stack2280, stack2284, stack2288, stack2292, stack2296,
+ stack2300, stack2304, stack2308, stack2312, stack2316, stack2320,
+ stack2324, stack2328, stack2332, stack2336, stack2340, stack2344,
+ stack2348, stack2352, stack2356, stack2360, stack2364, stack2368,
+ stack2372, stack2376, stack2380, stack2384, stack2388, stack2392,
+ stack2396, stack2400, stack2404, stack2408, stack2412, stack2416,
+ stack2420, stack2424, stack2428, stack2432, stack2436, stack2440,
+ stack2444, stack2448, stack2452, stack2456, stack2460, stack2464,
+ stack2468, stack2472, stack2476, stack2480, stack2484, stack2488,
+ stack2492, stack2496, stack2500, stack2504, stack2508, stack2512,
+ stack2516, stack2520, stack2524, stack2528, stack2532, stack2536,
+ stack2540, stack2544, stack2548, stack2552, stack2556, stack2560,
+ stack2564, stack2568, stack2572, stack2576, stack2580, stack2584,
+ stack2588, stack2592, stack2596, stack2600, stack2604, stack2608,
+ stack2612, stack2616, stack2620, stack2624, stack2628, stack2632,
+ stack2636, stack2640, stack2644, stack2648, stack2652, stack2656,
+ stack2660, stack2664, stack2668, stack2672, stack2676, stack2680,
+ stack2684, stack2688, stack2692, stack2696, stack2700, stack2704,
+ stack2708, stack2712, stack2716, stack2720, stack2724, stack2728,
+ stack2732, stack2736, stack2740, stack2744, stack2748, stack2752,
+ stack2756, stack2760, stack2764, stack2768, stack2772, stack2776,
+ stack2780, stack2784, stack2788, stack2792, stack2796, stack2800,
+ stack2804, stack2808, stack2812, stack2816, stack2820, stack2824,
+ stack2828, stack2832, stack2836, stack2840, stack2844, stack2848,
+ stack2852, stack2856, stack2860, stack2864, stack2868, stack2872,
+ stack2876, stack2880, stack2884, stack2888, stack2892, stack2896,
+ stack2900, stack2904, stack2908, stack2912, stack2916, stack2920,
+ stack2924, stack2928, stack2932, stack2936, stack2940, stack2944,
+ stack2948, stack2952, stack2956, stack2960, stack2964, stack2968,
+ stack2972, stack2976, stack2980, stack2984, stack2988, stack2992,
+ stack2996, stack3000, stack3004, stack3008, stack3012, stack3016,
+ stack3020, stack3024, stack3028, stack3032, stack3036, stack3040,
+ stack3044, stack3048, stack3052, stack3056, stack3060, stack3064,
+ stack3068, stack3072, stack3076, stack3080, stack3084, stack3088,
+ stack3092, stack3096, stack3100, stack3104, stack3108, stack3112,
+ stack3116, stack3120, stack3124, stack3128, stack3132, stack3136,
+ stack3140, stack3144, stack3148, stack3152, stack3156, stack3160,
+ stack3164, stack3168, stack3172, stack3176, stack3180, stack3184,
+ stack3188, stack3192, stack3196, stack3200, stack3204, stack3208,
+ stack3212, stack3216, stack3220, stack3224, stack3228, stack3232,
+ stack3236, stack3240, stack3244, stack3248, stack3252, stack3256,
+ stack3260, stack3264, stack3268, stack3272, stack3276, stack3280,
+ stack3284, stack3288, stack3292, stack3296, stack3300, stack3304,
+ stack3308, stack3312, stack3316, stack3320, stack3324, stack3328,
+ stack3332, stack3336, stack3340, stack3344, stack3348, stack3352,
+ stack3356, stack3360, stack3364, stack3368, stack3372, stack3376,
+ stack3380, stack3384, stack3388, stack3392, stack3396, stack3400,
+ stack3404, stack3408, stack3412, stack3416, stack3420, stack3424,
+ stack3428, stack3432, stack3436, stack3440, stack3444, stack3448,
+ stack3452, stack3456, stack3460, stack3464, stack3468, stack3472,
+ stack3476, stack3480, stack3484, stack3488, stack3492, stack3496,
+ stack3500, stack3504, stack3508, stack3512, stack3516, stack3520,
+ stack3524, stack3528, stack3532, stack3536, stack3540, stack3544,
+ stack3548, stack3552, stack3556, stack3560, stack3564, stack3568,
+ stack3572, stack3576, stack3580, stack3584, stack3588, stack3592,
+ stack3596, stack3600, stack3604, stack3608, stack3612, stack3616,
+ stack3620, stack3624, stack3628, stack3632, stack3636, stack3640,
+ stack3644, stack3648, stack3652, stack3656, stack3660, stack3664,
+ stack3668, stack3672, stack3676, stack3680, stack3684, stack3688,
+ stack3692, stack3696, stack3700, stack3704, stack3708, stack3712,
+ stack3716, stack3720, stack3724, stack3728, stack3732, stack3736,
+ stack3740, stack3744, stack3748, stack3752, stack3756, stack3760,
+ stack3764, stack3768, stack3772, stack3776, stack3780, stack3784,
+ stack3788, stack3792, stack3796, stack3800, stack3804, stack3808,
+ stack3812, stack3816, stack3820, stack3824, stack3828, stack3832,
+ stack3836, stack3840, stack3844, stack3848, stack3852, stack3856,
+ stack3860, stack3864, stack3868, stack3872, stack3876, stack3880,
+ stack3884, stack3888, stack3892, stack3896, stack3900, stack3904,
+ stack3908, stack3912, stack3916, stack3920, stack3924, stack3928,
+ stack3932, stack3936, stack3940, stack3944, stack3948, stack3952,
+ stack3956, stack3960, stack3964, stack3968, stack3972, stack3976,
+ stack3980, stack3984, stack3988, stack3992, stack3996, stack4000,
+ stack4004, stack4008, stack4012, stack4016, stack4020, stack4024,
+ stack4028, stack4032, stack4036, stack4040, stack4044, stack4048,
+ stack4052, stack4056, stack4060, stack4064, stack4068, stack4072,
+ stack4076, stack4080, stack4084, stack4088, stack4092, stack4096,
+ stack4100, stack4104, stack4108, stack4112, stack4116, stack4120,
+ stack4124, stack4128, stack4132, stack4136, stack4140, stack4144,
+ stack4148, stack4152, stack4156, stack4160, stack4164, stack4168,
+ stack4172, stack4176, stack4180, stack4184, stack4188, stack4192,
+ stack4196, stack4200, stack4204, stack4208, stack4212, stack4216,
+ stack4220, stack4224, stack4228, stack4232, stack4236, stack4240,
+ stack4244, stack4248, stack4252, stack4256, stack4260, stack4264,
+ stack4268, stack4272, stack4276, stack4280, stack4284, stack4288,
+ stack4292, stack4296, stack4300, stack4304, stack4308, stack4312,
+ stack4316, stack4320, stack4324, stack4328, stack4332, stack4336,
+ stack4340, stack4344, stack4348, stack4352, stack4356, stack4360,
+ stack4364, stack4368, stack4372, stack4376, stack4380, stack4384,
+ stack4388, stack4392, stack4396, stack4400, stack4404, stack4408,
+ stack4412, stack4416, stack4420, stack4424, stack4428, stack4432,
+ stack4436, stack4440, stack4444, stack4448, stack4452, stack4456,
+ stack4460, stack4464, stack4468, stack4472, stack4476, stack4480,
+ stack4484, stack4488, stack4492, stack4496, stack4500, stack4504,
+ stack4508, stack4512, stack4516, stack4520, stack4524, stack4528,
+ stack4532, stack4536, stack4540, stack4544, stack4548, stack4552,
+ stack4556, stack4560, stack4564, stack4568, stack4572, stack4576,
+ stack4580, stack4584, stack4588, stack4592, stack4596, stack4600,
+ stack4604, stack4608, stack4612, stack4616, stack4620, stack4624,
+ stack4628, stack4632, stack4636, stack4640, stack4644, stack4648,
+ stack4652, stack4656, stack4660, stack4664, stack4668, stack4672,
+ stack4676, stack4680, stack4684, stack4688, stack4692, stack4696,
+ stack4700, stack4704, stack4708, stack4712, stack4716, stack4720,
+ stack4724, stack4728, stack4732, stack4736, stack4740, stack4744,
+ stack4748, stack4752, stack4756, stack4760, stack4764, stack4768,
+ stack4772, stack4776, stack4780, stack4784, stack4788, stack4792,
+ stack4796, stack4800, stack4804, stack4808, stack4812, stack4816,
+ stack4820, stack4824, stack4828, stack4832, stack4836, stack4840,
+ stack4844, stack4848, stack4852, stack4856, stack4860, stack4864,
+ stack4868, stack4872, stack4876, stack4880, stack4884, stack4888,
+ stack4892, stack4896, stack4900, stack4904, stack4908, stack4912,
+ stack4916, stack4920, stack4924, stack4928, stack4932, stack4936,
+ stack4940, stack4944, stack4948, stack4952, stack4956, stack4960,
+ stack4964, stack4968, stack4972, stack4976, stack4980, stack4984,
+ stack4988, stack4992, stack4996, stack5000,
+}
+
+// Edit .+1,$ | seq 4 4 5000 | sed 's/.*/func stack&() { var buf [&]byte; use(buf[:]); C.callGoStackCheck() }/'
+func stack4() { var buf [4]byte; use(buf[:]); C.callGoStackCheck() }
+func stack8() { var buf [8]byte; use(buf[:]); C.callGoStackCheck() }
+func stack12() { var buf [12]byte; use(buf[:]); C.callGoStackCheck() }
+func stack16() { var buf [16]byte; use(buf[:]); C.callGoStackCheck() }
+func stack20() { var buf [20]byte; use(buf[:]); C.callGoStackCheck() }
+func stack24() { var buf [24]byte; use(buf[:]); C.callGoStackCheck() }
+func stack28() { var buf [28]byte; use(buf[:]); C.callGoStackCheck() }
+func stack32() { var buf [32]byte; use(buf[:]); C.callGoStackCheck() }
+func stack36() { var buf [36]byte; use(buf[:]); C.callGoStackCheck() }
+func stack40() { var buf [40]byte; use(buf[:]); C.callGoStackCheck() }
+func stack44() { var buf [44]byte; use(buf[:]); C.callGoStackCheck() }
+func stack48() { var buf [48]byte; use(buf[:]); C.callGoStackCheck() }
+func stack52() { var buf [52]byte; use(buf[:]); C.callGoStackCheck() }
+func stack56() { var buf [56]byte; use(buf[:]); C.callGoStackCheck() }
+func stack60() { var buf [60]byte; use(buf[:]); C.callGoStackCheck() }
+func stack64() { var buf [64]byte; use(buf[:]); C.callGoStackCheck() }
+func stack68() { var buf [68]byte; use(buf[:]); C.callGoStackCheck() }
+func stack72() { var buf [72]byte; use(buf[:]); C.callGoStackCheck() }
+func stack76() { var buf [76]byte; use(buf[:]); C.callGoStackCheck() }
+func stack80() { var buf [80]byte; use(buf[:]); C.callGoStackCheck() }
+func stack84() { var buf [84]byte; use(buf[:]); C.callGoStackCheck() }
+func stack88() { var buf [88]byte; use(buf[:]); C.callGoStackCheck() }
+func stack92() { var buf [92]byte; use(buf[:]); C.callGoStackCheck() }
+func stack96() { var buf [96]byte; use(buf[:]); C.callGoStackCheck() }
+func stack100() { var buf [100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack104() { var buf [104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack108() { var buf [108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack112() { var buf [112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack116() { var buf [116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack120() { var buf [120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack124() { var buf [124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack128() { var buf [128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack132() { var buf [132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack136() { var buf [136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack140() { var buf [140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack144() { var buf [144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack148() { var buf [148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack152() { var buf [152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack156() { var buf [156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack160() { var buf [160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack164() { var buf [164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack168() { var buf [168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack172() { var buf [172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack176() { var buf [176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack180() { var buf [180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack184() { var buf [184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack188() { var buf [188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack192() { var buf [192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack196() { var buf [196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack200() { var buf [200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack204() { var buf [204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack208() { var buf [208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack212() { var buf [212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack216() { var buf [216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack220() { var buf [220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack224() { var buf [224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack228() { var buf [228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack232() { var buf [232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack236() { var buf [236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack240() { var buf [240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack244() { var buf [244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack248() { var buf [248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack252() { var buf [252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack256() { var buf [256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack260() { var buf [260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack264() { var buf [264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack268() { var buf [268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack272() { var buf [272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack276() { var buf [276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack280() { var buf [280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack284() { var buf [284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack288() { var buf [288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack292() { var buf [292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack296() { var buf [296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack300() { var buf [300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack304() { var buf [304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack308() { var buf [308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack312() { var buf [312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack316() { var buf [316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack320() { var buf [320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack324() { var buf [324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack328() { var buf [328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack332() { var buf [332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack336() { var buf [336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack340() { var buf [340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack344() { var buf [344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack348() { var buf [348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack352() { var buf [352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack356() { var buf [356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack360() { var buf [360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack364() { var buf [364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack368() { var buf [368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack372() { var buf [372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack376() { var buf [376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack380() { var buf [380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack384() { var buf [384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack388() { var buf [388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack392() { var buf [392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack396() { var buf [396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack400() { var buf [400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack404() { var buf [404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack408() { var buf [408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack412() { var buf [412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack416() { var buf [416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack420() { var buf [420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack424() { var buf [424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack428() { var buf [428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack432() { var buf [432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack436() { var buf [436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack440() { var buf [440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack444() { var buf [444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack448() { var buf [448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack452() { var buf [452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack456() { var buf [456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack460() { var buf [460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack464() { var buf [464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack468() { var buf [468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack472() { var buf [472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack476() { var buf [476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack480() { var buf [480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack484() { var buf [484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack488() { var buf [488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack492() { var buf [492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack496() { var buf [496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack500() { var buf [500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack504() { var buf [504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack508() { var buf [508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack512() { var buf [512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack516() { var buf [516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack520() { var buf [520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack524() { var buf [524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack528() { var buf [528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack532() { var buf [532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack536() { var buf [536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack540() { var buf [540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack544() { var buf [544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack548() { var buf [548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack552() { var buf [552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack556() { var buf [556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack560() { var buf [560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack564() { var buf [564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack568() { var buf [568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack572() { var buf [572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack576() { var buf [576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack580() { var buf [580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack584() { var buf [584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack588() { var buf [588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack592() { var buf [592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack596() { var buf [596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack600() { var buf [600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack604() { var buf [604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack608() { var buf [608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack612() { var buf [612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack616() { var buf [616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack620() { var buf [620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack624() { var buf [624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack628() { var buf [628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack632() { var buf [632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack636() { var buf [636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack640() { var buf [640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack644() { var buf [644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack648() { var buf [648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack652() { var buf [652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack656() { var buf [656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack660() { var buf [660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack664() { var buf [664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack668() { var buf [668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack672() { var buf [672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack676() { var buf [676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack680() { var buf [680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack684() { var buf [684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack688() { var buf [688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack692() { var buf [692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack696() { var buf [696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack700() { var buf [700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack704() { var buf [704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack708() { var buf [708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack712() { var buf [712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack716() { var buf [716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack720() { var buf [720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack724() { var buf [724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack728() { var buf [728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack732() { var buf [732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack736() { var buf [736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack740() { var buf [740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack744() { var buf [744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack748() { var buf [748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack752() { var buf [752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack756() { var buf [756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack760() { var buf [760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack764() { var buf [764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack768() { var buf [768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack772() { var buf [772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack776() { var buf [776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack780() { var buf [780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack784() { var buf [784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack788() { var buf [788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack792() { var buf [792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack796() { var buf [796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack800() { var buf [800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack804() { var buf [804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack808() { var buf [808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack812() { var buf [812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack816() { var buf [816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack820() { var buf [820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack824() { var buf [824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack828() { var buf [828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack832() { var buf [832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack836() { var buf [836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack840() { var buf [840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack844() { var buf [844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack848() { var buf [848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack852() { var buf [852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack856() { var buf [856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack860() { var buf [860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack864() { var buf [864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack868() { var buf [868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack872() { var buf [872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack876() { var buf [876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack880() { var buf [880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack884() { var buf [884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack888() { var buf [888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack892() { var buf [892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack896() { var buf [896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack900() { var buf [900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack904() { var buf [904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack908() { var buf [908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack912() { var buf [912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack916() { var buf [916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack920() { var buf [920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack924() { var buf [924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack928() { var buf [928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack932() { var buf [932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack936() { var buf [936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack940() { var buf [940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack944() { var buf [944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack948() { var buf [948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack952() { var buf [952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack956() { var buf [956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack960() { var buf [960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack964() { var buf [964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack968() { var buf [968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack972() { var buf [972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack976() { var buf [976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack980() { var buf [980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack984() { var buf [984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack988() { var buf [988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack992() { var buf [992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack996() { var buf [996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1000() { var buf [1000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1004() { var buf [1004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1008() { var buf [1008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1012() { var buf [1012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1016() { var buf [1016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1020() { var buf [1020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1024() { var buf [1024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1028() { var buf [1028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1032() { var buf [1032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1036() { var buf [1036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1040() { var buf [1040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1044() { var buf [1044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1048() { var buf [1048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1052() { var buf [1052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1056() { var buf [1056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1060() { var buf [1060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1064() { var buf [1064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1068() { var buf [1068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1072() { var buf [1072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1076() { var buf [1076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1080() { var buf [1080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1084() { var buf [1084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1088() { var buf [1088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1092() { var buf [1092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1096() { var buf [1096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1100() { var buf [1100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1104() { var buf [1104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1108() { var buf [1108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1112() { var buf [1112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1116() { var buf [1116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1120() { var buf [1120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1124() { var buf [1124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1128() { var buf [1128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1132() { var buf [1132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1136() { var buf [1136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1140() { var buf [1140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1144() { var buf [1144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1148() { var buf [1148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1152() { var buf [1152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1156() { var buf [1156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1160() { var buf [1160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1164() { var buf [1164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1168() { var buf [1168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1172() { var buf [1172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1176() { var buf [1176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1180() { var buf [1180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1184() { var buf [1184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1188() { var buf [1188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1192() { var buf [1192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1196() { var buf [1196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1200() { var buf [1200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1204() { var buf [1204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1208() { var buf [1208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1212() { var buf [1212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1216() { var buf [1216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1220() { var buf [1220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1224() { var buf [1224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1228() { var buf [1228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1232() { var buf [1232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1236() { var buf [1236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1240() { var buf [1240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1244() { var buf [1244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1248() { var buf [1248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1252() { var buf [1252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1256() { var buf [1256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1260() { var buf [1260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1264() { var buf [1264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1268() { var buf [1268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1272() { var buf [1272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1276() { var buf [1276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1280() { var buf [1280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1284() { var buf [1284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1288() { var buf [1288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1292() { var buf [1292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1296() { var buf [1296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1300() { var buf [1300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1304() { var buf [1304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1308() { var buf [1308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1312() { var buf [1312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1316() { var buf [1316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1320() { var buf [1320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1324() { var buf [1324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1328() { var buf [1328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1332() { var buf [1332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1336() { var buf [1336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1340() { var buf [1340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1344() { var buf [1344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1348() { var buf [1348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1352() { var buf [1352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1356() { var buf [1356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1360() { var buf [1360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1364() { var buf [1364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1368() { var buf [1368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1372() { var buf [1372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1376() { var buf [1376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1380() { var buf [1380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1384() { var buf [1384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1388() { var buf [1388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1392() { var buf [1392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1396() { var buf [1396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1400() { var buf [1400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1404() { var buf [1404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1408() { var buf [1408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1412() { var buf [1412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1416() { var buf [1416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1420() { var buf [1420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1424() { var buf [1424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1428() { var buf [1428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1432() { var buf [1432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1436() { var buf [1436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1440() { var buf [1440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1444() { var buf [1444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1448() { var buf [1448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1452() { var buf [1452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1456() { var buf [1456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1460() { var buf [1460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1464() { var buf [1464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1468() { var buf [1468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1472() { var buf [1472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1476() { var buf [1476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1480() { var buf [1480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1484() { var buf [1484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1488() { var buf [1488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1492() { var buf [1492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1496() { var buf [1496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1500() { var buf [1500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1504() { var buf [1504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1508() { var buf [1508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1512() { var buf [1512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1516() { var buf [1516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1520() { var buf [1520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1524() { var buf [1524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1528() { var buf [1528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1532() { var buf [1532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1536() { var buf [1536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1540() { var buf [1540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1544() { var buf [1544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1548() { var buf [1548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1552() { var buf [1552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1556() { var buf [1556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1560() { var buf [1560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1564() { var buf [1564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1568() { var buf [1568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1572() { var buf [1572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1576() { var buf [1576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1580() { var buf [1580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1584() { var buf [1584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1588() { var buf [1588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1592() { var buf [1592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1596() { var buf [1596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1600() { var buf [1600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1604() { var buf [1604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1608() { var buf [1608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1612() { var buf [1612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1616() { var buf [1616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1620() { var buf [1620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1624() { var buf [1624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1628() { var buf [1628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1632() { var buf [1632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1636() { var buf [1636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1640() { var buf [1640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1644() { var buf [1644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1648() { var buf [1648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1652() { var buf [1652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1656() { var buf [1656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1660() { var buf [1660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1664() { var buf [1664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1668() { var buf [1668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1672() { var buf [1672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1676() { var buf [1676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1680() { var buf [1680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1684() { var buf [1684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1688() { var buf [1688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1692() { var buf [1692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1696() { var buf [1696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1700() { var buf [1700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1704() { var buf [1704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1708() { var buf [1708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1712() { var buf [1712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1716() { var buf [1716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1720() { var buf [1720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1724() { var buf [1724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1728() { var buf [1728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1732() { var buf [1732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1736() { var buf [1736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1740() { var buf [1740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1744() { var buf [1744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1748() { var buf [1748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1752() { var buf [1752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1756() { var buf [1756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1760() { var buf [1760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1764() { var buf [1764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1768() { var buf [1768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1772() { var buf [1772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1776() { var buf [1776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1780() { var buf [1780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1784() { var buf [1784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1788() { var buf [1788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1792() { var buf [1792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1796() { var buf [1796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1800() { var buf [1800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1804() { var buf [1804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1808() { var buf [1808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1812() { var buf [1812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1816() { var buf [1816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1820() { var buf [1820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1824() { var buf [1824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1828() { var buf [1828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1832() { var buf [1832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1836() { var buf [1836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1840() { var buf [1840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1844() { var buf [1844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1848() { var buf [1848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1852() { var buf [1852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1856() { var buf [1856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1860() { var buf [1860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1864() { var buf [1864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1868() { var buf [1868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1872() { var buf [1872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1876() { var buf [1876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1880() { var buf [1880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1884() { var buf [1884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1888() { var buf [1888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1892() { var buf [1892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1896() { var buf [1896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1900() { var buf [1900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1904() { var buf [1904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1908() { var buf [1908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1912() { var buf [1912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1916() { var buf [1916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1920() { var buf [1920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1924() { var buf [1924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1928() { var buf [1928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1932() { var buf [1932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1936() { var buf [1936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1940() { var buf [1940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1944() { var buf [1944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1948() { var buf [1948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1952() { var buf [1952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1956() { var buf [1956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1960() { var buf [1960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1964() { var buf [1964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1968() { var buf [1968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1972() { var buf [1972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1976() { var buf [1976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1980() { var buf [1980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1984() { var buf [1984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1988() { var buf [1988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1992() { var buf [1992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack1996() { var buf [1996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2000() { var buf [2000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2004() { var buf [2004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2008() { var buf [2008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2012() { var buf [2012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2016() { var buf [2016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2020() { var buf [2020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2024() { var buf [2024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2028() { var buf [2028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2032() { var buf [2032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2036() { var buf [2036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2040() { var buf [2040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2044() { var buf [2044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2048() { var buf [2048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2052() { var buf [2052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2056() { var buf [2056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2060() { var buf [2060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2064() { var buf [2064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2068() { var buf [2068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2072() { var buf [2072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2076() { var buf [2076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2080() { var buf [2080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2084() { var buf [2084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2088() { var buf [2088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2092() { var buf [2092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2096() { var buf [2096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2100() { var buf [2100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2104() { var buf [2104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2108() { var buf [2108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2112() { var buf [2112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2116() { var buf [2116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2120() { var buf [2120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2124() { var buf [2124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2128() { var buf [2128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2132() { var buf [2132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2136() { var buf [2136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2140() { var buf [2140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2144() { var buf [2144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2148() { var buf [2148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2152() { var buf [2152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2156() { var buf [2156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2160() { var buf [2160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2164() { var buf [2164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2168() { var buf [2168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2172() { var buf [2172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2176() { var buf [2176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2180() { var buf [2180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2184() { var buf [2184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2188() { var buf [2188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2192() { var buf [2192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2196() { var buf [2196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2200() { var buf [2200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2204() { var buf [2204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2208() { var buf [2208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2212() { var buf [2212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2216() { var buf [2216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2220() { var buf [2220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2224() { var buf [2224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2228() { var buf [2228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2232() { var buf [2232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2236() { var buf [2236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2240() { var buf [2240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2244() { var buf [2244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2248() { var buf [2248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2252() { var buf [2252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2256() { var buf [2256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2260() { var buf [2260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2264() { var buf [2264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2268() { var buf [2268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2272() { var buf [2272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2276() { var buf [2276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2280() { var buf [2280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2284() { var buf [2284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2288() { var buf [2288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2292() { var buf [2292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2296() { var buf [2296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2300() { var buf [2300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2304() { var buf [2304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2308() { var buf [2308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2312() { var buf [2312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2316() { var buf [2316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2320() { var buf [2320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2324() { var buf [2324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2328() { var buf [2328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2332() { var buf [2332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2336() { var buf [2336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2340() { var buf [2340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2344() { var buf [2344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2348() { var buf [2348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2352() { var buf [2352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2356() { var buf [2356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2360() { var buf [2360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2364() { var buf [2364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2368() { var buf [2368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2372() { var buf [2372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2376() { var buf [2376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2380() { var buf [2380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2384() { var buf [2384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2388() { var buf [2388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2392() { var buf [2392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2396() { var buf [2396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2400() { var buf [2400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2404() { var buf [2404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2408() { var buf [2408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2412() { var buf [2412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2416() { var buf [2416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2420() { var buf [2420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2424() { var buf [2424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2428() { var buf [2428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2432() { var buf [2432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2436() { var buf [2436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2440() { var buf [2440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2444() { var buf [2444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2448() { var buf [2448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2452() { var buf [2452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2456() { var buf [2456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2460() { var buf [2460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2464() { var buf [2464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2468() { var buf [2468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2472() { var buf [2472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2476() { var buf [2476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2480() { var buf [2480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2484() { var buf [2484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2488() { var buf [2488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2492() { var buf [2492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2496() { var buf [2496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2500() { var buf [2500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2504() { var buf [2504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2508() { var buf [2508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2512() { var buf [2512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2516() { var buf [2516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2520() { var buf [2520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2524() { var buf [2524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2528() { var buf [2528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2532() { var buf [2532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2536() { var buf [2536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2540() { var buf [2540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2544() { var buf [2544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2548() { var buf [2548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2552() { var buf [2552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2556() { var buf [2556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2560() { var buf [2560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2564() { var buf [2564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2568() { var buf [2568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2572() { var buf [2572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2576() { var buf [2576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2580() { var buf [2580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2584() { var buf [2584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2588() { var buf [2588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2592() { var buf [2592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2596() { var buf [2596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2600() { var buf [2600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2604() { var buf [2604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2608() { var buf [2608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2612() { var buf [2612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2616() { var buf [2616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2620() { var buf [2620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2624() { var buf [2624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2628() { var buf [2628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2632() { var buf [2632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2636() { var buf [2636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2640() { var buf [2640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2644() { var buf [2644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2648() { var buf [2648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2652() { var buf [2652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2656() { var buf [2656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2660() { var buf [2660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2664() { var buf [2664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2668() { var buf [2668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2672() { var buf [2672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2676() { var buf [2676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2680() { var buf [2680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2684() { var buf [2684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2688() { var buf [2688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2692() { var buf [2692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2696() { var buf [2696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2700() { var buf [2700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2704() { var buf [2704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2708() { var buf [2708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2712() { var buf [2712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2716() { var buf [2716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2720() { var buf [2720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2724() { var buf [2724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2728() { var buf [2728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2732() { var buf [2732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2736() { var buf [2736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2740() { var buf [2740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2744() { var buf [2744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2748() { var buf [2748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2752() { var buf [2752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2756() { var buf [2756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2760() { var buf [2760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2764() { var buf [2764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2768() { var buf [2768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2772() { var buf [2772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2776() { var buf [2776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2780() { var buf [2780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2784() { var buf [2784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2788() { var buf [2788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2792() { var buf [2792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2796() { var buf [2796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2800() { var buf [2800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2804() { var buf [2804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2808() { var buf [2808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2812() { var buf [2812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2816() { var buf [2816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2820() { var buf [2820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2824() { var buf [2824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2828() { var buf [2828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2832() { var buf [2832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2836() { var buf [2836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2840() { var buf [2840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2844() { var buf [2844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2848() { var buf [2848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2852() { var buf [2852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2856() { var buf [2856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2860() { var buf [2860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2864() { var buf [2864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2868() { var buf [2868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2872() { var buf [2872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2876() { var buf [2876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2880() { var buf [2880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2884() { var buf [2884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2888() { var buf [2888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2892() { var buf [2892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2896() { var buf [2896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2900() { var buf [2900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2904() { var buf [2904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2908() { var buf [2908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2912() { var buf [2912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2916() { var buf [2916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2920() { var buf [2920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2924() { var buf [2924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2928() { var buf [2928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2932() { var buf [2932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2936() { var buf [2936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2940() { var buf [2940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2944() { var buf [2944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2948() { var buf [2948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2952() { var buf [2952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2956() { var buf [2956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2960() { var buf [2960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2964() { var buf [2964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2968() { var buf [2968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2972() { var buf [2972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2976() { var buf [2976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2980() { var buf [2980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2984() { var buf [2984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2988() { var buf [2988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2992() { var buf [2992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack2996() { var buf [2996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3000() { var buf [3000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3004() { var buf [3004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3008() { var buf [3008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3012() { var buf [3012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3016() { var buf [3016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3020() { var buf [3020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3024() { var buf [3024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3028() { var buf [3028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3032() { var buf [3032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3036() { var buf [3036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3040() { var buf [3040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3044() { var buf [3044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3048() { var buf [3048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3052() { var buf [3052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3056() { var buf [3056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3060() { var buf [3060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3064() { var buf [3064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3068() { var buf [3068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3072() { var buf [3072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3076() { var buf [3076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3080() { var buf [3080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3084() { var buf [3084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3088() { var buf [3088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3092() { var buf [3092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3096() { var buf [3096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3100() { var buf [3100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3104() { var buf [3104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3108() { var buf [3108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3112() { var buf [3112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3116() { var buf [3116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3120() { var buf [3120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3124() { var buf [3124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3128() { var buf [3128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3132() { var buf [3132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3136() { var buf [3136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3140() { var buf [3140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3144() { var buf [3144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3148() { var buf [3148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3152() { var buf [3152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3156() { var buf [3156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3160() { var buf [3160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3164() { var buf [3164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3168() { var buf [3168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3172() { var buf [3172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3176() { var buf [3176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3180() { var buf [3180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3184() { var buf [3184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3188() { var buf [3188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3192() { var buf [3192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3196() { var buf [3196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3200() { var buf [3200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3204() { var buf [3204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3208() { var buf [3208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3212() { var buf [3212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3216() { var buf [3216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3220() { var buf [3220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3224() { var buf [3224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3228() { var buf [3228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3232() { var buf [3232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3236() { var buf [3236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3240() { var buf [3240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3244() { var buf [3244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3248() { var buf [3248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3252() { var buf [3252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3256() { var buf [3256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3260() { var buf [3260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3264() { var buf [3264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3268() { var buf [3268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3272() { var buf [3272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3276() { var buf [3276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3280() { var buf [3280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3284() { var buf [3284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3288() { var buf [3288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3292() { var buf [3292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3296() { var buf [3296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3300() { var buf [3300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3304() { var buf [3304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3308() { var buf [3308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3312() { var buf [3312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3316() { var buf [3316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3320() { var buf [3320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3324() { var buf [3324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3328() { var buf [3328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3332() { var buf [3332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3336() { var buf [3336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3340() { var buf [3340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3344() { var buf [3344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3348() { var buf [3348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3352() { var buf [3352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3356() { var buf [3356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3360() { var buf [3360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3364() { var buf [3364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3368() { var buf [3368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3372() { var buf [3372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3376() { var buf [3376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3380() { var buf [3380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3384() { var buf [3384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3388() { var buf [3388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3392() { var buf [3392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3396() { var buf [3396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3400() { var buf [3400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3404() { var buf [3404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3408() { var buf [3408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3412() { var buf [3412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3416() { var buf [3416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3420() { var buf [3420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3424() { var buf [3424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3428() { var buf [3428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3432() { var buf [3432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3436() { var buf [3436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3440() { var buf [3440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3444() { var buf [3444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3448() { var buf [3448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3452() { var buf [3452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3456() { var buf [3456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3460() { var buf [3460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3464() { var buf [3464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3468() { var buf [3468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3472() { var buf [3472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3476() { var buf [3476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3480() { var buf [3480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3484() { var buf [3484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3488() { var buf [3488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3492() { var buf [3492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3496() { var buf [3496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3500() { var buf [3500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3504() { var buf [3504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3508() { var buf [3508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3512() { var buf [3512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3516() { var buf [3516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3520() { var buf [3520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3524() { var buf [3524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3528() { var buf [3528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3532() { var buf [3532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3536() { var buf [3536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3540() { var buf [3540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3544() { var buf [3544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3548() { var buf [3548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3552() { var buf [3552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3556() { var buf [3556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3560() { var buf [3560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3564() { var buf [3564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3568() { var buf [3568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3572() { var buf [3572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3576() { var buf [3576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3580() { var buf [3580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3584() { var buf [3584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3588() { var buf [3588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3592() { var buf [3592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3596() { var buf [3596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3600() { var buf [3600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3604() { var buf [3604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3608() { var buf [3608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3612() { var buf [3612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3616() { var buf [3616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3620() { var buf [3620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3624() { var buf [3624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3628() { var buf [3628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3632() { var buf [3632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3636() { var buf [3636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3640() { var buf [3640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3644() { var buf [3644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3648() { var buf [3648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3652() { var buf [3652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3656() { var buf [3656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3660() { var buf [3660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3664() { var buf [3664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3668() { var buf [3668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3672() { var buf [3672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3676() { var buf [3676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3680() { var buf [3680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3684() { var buf [3684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3688() { var buf [3688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3692() { var buf [3692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3696() { var buf [3696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3700() { var buf [3700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3704() { var buf [3704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3708() { var buf [3708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3712() { var buf [3712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3716() { var buf [3716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3720() { var buf [3720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3724() { var buf [3724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3728() { var buf [3728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3732() { var buf [3732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3736() { var buf [3736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3740() { var buf [3740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3744() { var buf [3744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3748() { var buf [3748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3752() { var buf [3752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3756() { var buf [3756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3760() { var buf [3760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3764() { var buf [3764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3768() { var buf [3768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3772() { var buf [3772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3776() { var buf [3776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3780() { var buf [3780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3784() { var buf [3784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3788() { var buf [3788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3792() { var buf [3792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3796() { var buf [3796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3800() { var buf [3800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3804() { var buf [3804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3808() { var buf [3808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3812() { var buf [3812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3816() { var buf [3816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3820() { var buf [3820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3824() { var buf [3824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3828() { var buf [3828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3832() { var buf [3832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3836() { var buf [3836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3840() { var buf [3840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3844() { var buf [3844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3848() { var buf [3848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3852() { var buf [3852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3856() { var buf [3856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3860() { var buf [3860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3864() { var buf [3864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3868() { var buf [3868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3872() { var buf [3872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3876() { var buf [3876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3880() { var buf [3880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3884() { var buf [3884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3888() { var buf [3888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3892() { var buf [3892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3896() { var buf [3896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3900() { var buf [3900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3904() { var buf [3904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3908() { var buf [3908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3912() { var buf [3912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3916() { var buf [3916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3920() { var buf [3920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3924() { var buf [3924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3928() { var buf [3928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3932() { var buf [3932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3936() { var buf [3936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3940() { var buf [3940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3944() { var buf [3944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3948() { var buf [3948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3952() { var buf [3952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3956() { var buf [3956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3960() { var buf [3960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3964() { var buf [3964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3968() { var buf [3968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3972() { var buf [3972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3976() { var buf [3976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3980() { var buf [3980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3984() { var buf [3984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3988() { var buf [3988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3992() { var buf [3992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack3996() { var buf [3996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4000() { var buf [4000]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4004() { var buf [4004]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4008() { var buf [4008]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4012() { var buf [4012]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4016() { var buf [4016]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4020() { var buf [4020]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4024() { var buf [4024]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4028() { var buf [4028]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4032() { var buf [4032]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4036() { var buf [4036]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4040() { var buf [4040]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4044() { var buf [4044]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4048() { var buf [4048]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4052() { var buf [4052]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4056() { var buf [4056]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4060() { var buf [4060]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4064() { var buf [4064]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4068() { var buf [4068]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4072() { var buf [4072]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4076() { var buf [4076]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4080() { var buf [4080]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4084() { var buf [4084]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4088() { var buf [4088]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4092() { var buf [4092]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4096() { var buf [4096]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4100() { var buf [4100]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4104() { var buf [4104]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4108() { var buf [4108]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4112() { var buf [4112]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4116() { var buf [4116]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4120() { var buf [4120]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4124() { var buf [4124]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4128() { var buf [4128]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4132() { var buf [4132]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4136() { var buf [4136]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4140() { var buf [4140]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4144() { var buf [4144]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4148() { var buf [4148]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4152() { var buf [4152]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4156() { var buf [4156]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4160() { var buf [4160]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4164() { var buf [4164]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4168() { var buf [4168]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4172() { var buf [4172]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4176() { var buf [4176]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4180() { var buf [4180]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4184() { var buf [4184]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4188() { var buf [4188]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4192() { var buf [4192]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4196() { var buf [4196]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4200() { var buf [4200]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4204() { var buf [4204]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4208() { var buf [4208]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4212() { var buf [4212]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4216() { var buf [4216]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4220() { var buf [4220]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4224() { var buf [4224]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4228() { var buf [4228]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4232() { var buf [4232]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4236() { var buf [4236]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4240() { var buf [4240]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4244() { var buf [4244]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4248() { var buf [4248]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4252() { var buf [4252]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4256() { var buf [4256]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4260() { var buf [4260]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4264() { var buf [4264]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4268() { var buf [4268]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4272() { var buf [4272]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4276() { var buf [4276]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4280() { var buf [4280]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4284() { var buf [4284]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4288() { var buf [4288]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4292() { var buf [4292]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4296() { var buf [4296]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4300() { var buf [4300]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4304() { var buf [4304]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4308() { var buf [4308]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4312() { var buf [4312]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4316() { var buf [4316]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4320() { var buf [4320]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4324() { var buf [4324]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4328() { var buf [4328]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4332() { var buf [4332]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4336() { var buf [4336]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4340() { var buf [4340]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4344() { var buf [4344]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4348() { var buf [4348]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4352() { var buf [4352]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4356() { var buf [4356]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4360() { var buf [4360]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4364() { var buf [4364]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4368() { var buf [4368]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4372() { var buf [4372]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4376() { var buf [4376]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4380() { var buf [4380]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4384() { var buf [4384]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4388() { var buf [4388]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4392() { var buf [4392]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4396() { var buf [4396]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4400() { var buf [4400]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4404() { var buf [4404]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4408() { var buf [4408]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4412() { var buf [4412]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4416() { var buf [4416]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4420() { var buf [4420]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4424() { var buf [4424]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4428() { var buf [4428]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4432() { var buf [4432]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4436() { var buf [4436]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4440() { var buf [4440]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4444() { var buf [4444]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4448() { var buf [4448]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4452() { var buf [4452]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4456() { var buf [4456]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4460() { var buf [4460]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4464() { var buf [4464]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4468() { var buf [4468]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4472() { var buf [4472]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4476() { var buf [4476]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4480() { var buf [4480]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4484() { var buf [4484]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4488() { var buf [4488]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4492() { var buf [4492]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4496() { var buf [4496]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4500() { var buf [4500]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4504() { var buf [4504]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4508() { var buf [4508]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4512() { var buf [4512]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4516() { var buf [4516]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4520() { var buf [4520]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4524() { var buf [4524]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4528() { var buf [4528]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4532() { var buf [4532]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4536() { var buf [4536]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4540() { var buf [4540]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4544() { var buf [4544]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4548() { var buf [4548]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4552() { var buf [4552]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4556() { var buf [4556]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4560() { var buf [4560]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4564() { var buf [4564]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4568() { var buf [4568]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4572() { var buf [4572]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4576() { var buf [4576]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4580() { var buf [4580]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4584() { var buf [4584]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4588() { var buf [4588]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4592() { var buf [4592]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4596() { var buf [4596]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4600() { var buf [4600]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4604() { var buf [4604]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4608() { var buf [4608]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4612() { var buf [4612]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4616() { var buf [4616]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4620() { var buf [4620]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4624() { var buf [4624]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4628() { var buf [4628]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4632() { var buf [4632]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4636() { var buf [4636]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4640() { var buf [4640]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4644() { var buf [4644]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4648() { var buf [4648]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4652() { var buf [4652]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4656() { var buf [4656]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4660() { var buf [4660]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4664() { var buf [4664]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4668() { var buf [4668]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4672() { var buf [4672]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4676() { var buf [4676]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4680() { var buf [4680]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4684() { var buf [4684]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4688() { var buf [4688]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4692() { var buf [4692]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4696() { var buf [4696]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4700() { var buf [4700]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4704() { var buf [4704]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4708() { var buf [4708]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4712() { var buf [4712]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4716() { var buf [4716]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4720() { var buf [4720]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4724() { var buf [4724]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4728() { var buf [4728]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4732() { var buf [4732]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4736() { var buf [4736]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4740() { var buf [4740]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4744() { var buf [4744]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4748() { var buf [4748]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4752() { var buf [4752]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4756() { var buf [4756]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4760() { var buf [4760]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4764() { var buf [4764]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4768() { var buf [4768]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4772() { var buf [4772]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4776() { var buf [4776]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4780() { var buf [4780]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4784() { var buf [4784]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4788() { var buf [4788]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4792() { var buf [4792]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4796() { var buf [4796]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4800() { var buf [4800]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4804() { var buf [4804]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4808() { var buf [4808]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4812() { var buf [4812]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4816() { var buf [4816]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4820() { var buf [4820]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4824() { var buf [4824]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4828() { var buf [4828]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4832() { var buf [4832]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4836() { var buf [4836]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4840() { var buf [4840]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4844() { var buf [4844]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4848() { var buf [4848]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4852() { var buf [4852]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4856() { var buf [4856]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4860() { var buf [4860]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4864() { var buf [4864]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4868() { var buf [4868]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4872() { var buf [4872]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4876() { var buf [4876]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4880() { var buf [4880]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4884() { var buf [4884]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4888() { var buf [4888]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4892() { var buf [4892]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4896() { var buf [4896]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4900() { var buf [4900]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4904() { var buf [4904]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4908() { var buf [4908]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4912() { var buf [4912]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4916() { var buf [4916]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4920() { var buf [4920]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4924() { var buf [4924]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4928() { var buf [4928]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4932() { var buf [4932]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4936() { var buf [4936]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4940() { var buf [4940]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4944() { var buf [4944]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4948() { var buf [4948]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4952() { var buf [4952]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4956() { var buf [4956]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4960() { var buf [4960]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4964() { var buf [4964]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4968() { var buf [4968]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4972() { var buf [4972]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4976() { var buf [4976]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4980() { var buf [4980]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4984() { var buf [4984]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4988() { var buf [4988]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4992() { var buf [4992]byte; use(buf[:]); C.callGoStackCheck() }
+func stack4996() { var buf [4996]byte; use(buf[:]); C.callGoStackCheck() }
+func stack5000() { var buf [5000]byte; use(buf[:]); C.callGoStackCheck() }
diff --git a/libgo/misc/cgo/test/callback_c.c b/libgo/misc/cgo/test/callback_c.c
new file mode 100644
index 00000000000..8921b7306c6
--- /dev/null
+++ b/libgo/misc/cgo/test/callback_c.c
@@ -0,0 +1,90 @@
+// Copyright 2011 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.
+
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "_cgo_export.h"
+
+void
+callback(void *f)
+{
+ // use some stack space
+ volatile char data[64*1024];
+
+ data[0] = 0;
+ goCallback(f);
+ data[sizeof(data)-1] = 0;
+}
+
+void
+callGoFoo(void)
+{
+ extern void goFoo(void);
+ goFoo();
+}
+
+void
+IntoC(void)
+{
+ BackIntoGo();
+}
+
+#ifdef WIN32
+#include <windows.h>
+long long
+mysleep(int seconds) {
+ long long st = GetTickCount();
+ Sleep(1000 * seconds);
+ return st;
+}
+#else
+#include <sys/time.h>
+long long
+mysleep(int seconds) {
+ long long st;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ st = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ sleep(seconds);
+ return st;
+}
+#endif
+
+long long
+twoSleep(int n)
+{
+ BackgroundSleep(n);
+ return mysleep(n);
+}
+
+void
+callGoStackCheck(void)
+{
+ extern void goStackCheck(void);
+ goStackCheck();
+}
+
+int
+returnAfterGrow(void)
+{
+ extern int goReturnVal(void);
+ goReturnVal();
+ return 123456;
+}
+
+int
+returnAfterGrowFromGo(void)
+{
+ extern int goReturnVal(void);
+ return goReturnVal();
+}
+
+void
+callGoWithString(void)
+{
+ extern void goWithString(GoString);
+ const char *str = "string passed from C to Go";
+ goWithString((GoString){str, strlen(str)});
+}
diff --git a/libgo/misc/cgo/test/callback_c_gc.c b/libgo/misc/cgo/test/callback_c_gc.c
new file mode 100644
index 00000000000..eb720eba7c4
--- /dev/null
+++ b/libgo/misc/cgo/test/callback_c_gc.c
@@ -0,0 +1,25 @@
+// 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.
+
+// +build gc
+
+#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test calling panic from C. This is what SWIG does. */
+
+extern void crosscall2(void (*fn)(void *, int), void *, int);
+extern void _cgo_panic(void *, int);
+extern void _cgo_allocate(void *, int);
+
+void
+callPanic(void)
+{
+ struct { const char *p; } a;
+ a.p = "panic from C";
+ crosscall2(_cgo_panic, &a, sizeof a);
+ *(int*)1 = 1;
+}
diff --git a/libgo/misc/cgo/test/callback_c_gccgo.c b/libgo/misc/cgo/test/callback_c_gccgo.c
new file mode 100644
index 00000000000..4eaa8184b30
--- /dev/null
+++ b/libgo/misc/cgo/test/callback_c_gccgo.c
@@ -0,0 +1,21 @@
+// 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.
+
+// +build gccgo
+
+#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test calling panic from C. This is what SWIG does. */
+
+extern void _cgo_panic(const char *);
+extern void *_cgo_allocate(size_t);
+
+void
+callPanic(void)
+{
+ _cgo_panic("panic from C");
+}
diff --git a/libgo/misc/cgo/test/cflags.go b/libgo/misc/cgo/test/cflags.go
new file mode 100644
index 00000000000..bc290bfcd5a
--- /dev/null
+++ b/libgo/misc/cgo/test/cflags.go
@@ -0,0 +1,32 @@
+// 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.
+
+// Test that the #cgo CFLAGS directive works,
+// with and without platform filters.
+// See https://golang.org/issue/5224 for details.
+package cgotest
+
+/*
+#cgo CFLAGS: -DCOMMON_VALUE=123
+#cgo windows CFLAGS: -DIS_WINDOWS=1
+#cgo !windows CFLAGS: -DIS_WINDOWS=0
+int common = COMMON_VALUE;
+int is_windows = IS_WINDOWS;
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func testCflags(t *testing.T) {
+ is_windows := C.is_windows == 1
+ if is_windows != (runtime.GOOS == "windows") {
+ t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS)
+ }
+ if C.common != 123 {
+ t.Errorf("common: %v (expected 123)", C.common)
+ }
+}
diff --git a/libgo/misc/cgo/test/cgo_linux_test.go b/libgo/misc/cgo/test/cgo_linux_test.go
new file mode 100644
index 00000000000..9c15f69e401
--- /dev/null
+++ b/libgo/misc/cgo/test/cgo_linux_test.go
@@ -0,0 +1,12 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "testing"
+
+func TestSetgid(t *testing.T) { testSetgid(t) }
+func Test6997(t *testing.T) { test6997(t) }
+func TestBuildID(t *testing.T) { testBuildID(t) }
+func Test9400(t *testing.T) { test9400(t) }
diff --git a/libgo/misc/cgo/test/cgo_stubs_android_test.go b/libgo/misc/cgo/test/cgo_stubs_android_test.go
new file mode 100644
index 00000000000..710e094cf77
--- /dev/null
+++ b/libgo/misc/cgo/test/cgo_stubs_android_test.go
@@ -0,0 +1,13 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "testing"
+
+// Stubs for tests that fails to build on Android
+func test6997(t *testing.T) {}
+func test3775(t *testing.T) {}
+func test8694(t *testing.T) {}
+func testSigaltstack(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/cgo_test.go b/libgo/misc/cgo/test/cgo_test.go
new file mode 100644
index 00000000000..a6de999752b
--- /dev/null
+++ b/libgo/misc/cgo/test/cgo_test.go
@@ -0,0 +1,80 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "testing"
+
+// The actual test functions are in non-_test.go files
+// so that they can use cgo (import "C").
+// These wrappers are here for gotest to find.
+
+func TestAlign(t *testing.T) { testAlign(t) }
+func TestConst(t *testing.T) { testConst(t) }
+func TestEnum(t *testing.T) { testEnum(t) }
+func TestAtol(t *testing.T) { testAtol(t) }
+func TestErrno(t *testing.T) { testErrno(t) }
+func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
+func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
+func TestCallback(t *testing.T) { testCallback(t) }
+func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
+func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
+func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T) { testBlocking(t) }
+func Test1328(t *testing.T) { test1328(t) }
+func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
+func TestSetEnv(t *testing.T) { testSetEnv(t) }
+func TestHelpers(t *testing.T) { testHelpers(t) }
+func TestLibgcc(t *testing.T) { testLibgcc(t) }
+func Test1635(t *testing.T) { test1635(t) }
+func TestPrintf(t *testing.T) { testPrintf(t) }
+func Test4029(t *testing.T) { test4029(t) }
+func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
+func Test3729(t *testing.T) { test3729(t) }
+func Test3775(t *testing.T) { test3775(t) }
+func TestCthread(t *testing.T) { testCthread(t) }
+func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
+func Test5227(t *testing.T) { test5227(t) }
+func TestCflags(t *testing.T) { testCflags(t) }
+func Test5337(t *testing.T) { test5337(t) }
+func Test5548(t *testing.T) { test5548(t) }
+func Test5603(t *testing.T) { test5603(t) }
+func Test6833(t *testing.T) { test6833(t) }
+func Test3250(t *testing.T) { test3250(t) }
+func TestCallbackStack(t *testing.T) { testCallbackStack(t) }
+func TestFpVar(t *testing.T) { testFpVar(t) }
+func Test4339(t *testing.T) { test4339(t) }
+func Test6390(t *testing.T) { test6390(t) }
+func Test5986(t *testing.T) { test5986(t) }
+func Test7665(t *testing.T) { test7665(t) }
+func TestNaming(t *testing.T) { testNaming(t) }
+func Test7560(t *testing.T) { test7560(t) }
+func Test5242(t *testing.T) { test5242(t) }
+func Test8092(t *testing.T) { test8092(t) }
+func Test7978(t *testing.T) { test7978(t) }
+func Test8694(t *testing.T) { test8694(t) }
+func Test8517(t *testing.T) { test8517(t) }
+func Test8811(t *testing.T) { test8811(t) }
+func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) }
+func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
+func Test9026(t *testing.T) { test9026(t) }
+func Test9510(t *testing.T) { test9510(t) }
+func Test9557(t *testing.T) { test9557(t) }
+func Test10303(t *testing.T) { test10303(t, 10) }
+func Test11925(t *testing.T) { test11925(t) }
+func Test12030(t *testing.T) { test12030(t) }
+func TestGCC68255(t *testing.T) { testGCC68255(t) }
+func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) }
+func Test14838(t *testing.T) { test14838(t) }
+func Test8756(t *testing.T) { test8756(t) }
+func Test17065(t *testing.T) { test17065(t) }
+func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
+func TestCheckConst(t *testing.T) { testCheckConst(t) }
+func Test17537(t *testing.T) { test17537(t) }
+func Test18126(t *testing.T) { test18126(t) }
+
+func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/libgo/misc/cgo/test/cgo_thread_lock.go b/libgo/misc/cgo/test/cgo_thread_lock.go
new file mode 100644
index 00000000000..b1050685182
--- /dev/null
+++ b/libgo/misc/cgo/test/cgo_thread_lock.go
@@ -0,0 +1,53 @@
+// Copyright 2016 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.
+
+// +build linux,freebsd,openbsd
+
+package cgotest
+
+/*
+#include <unistd.h>
+#include <sys/syscall.h>
+void Gosched(void);
+static int Ctid(void) { Gosched(); return syscall(SYS_gettid); }
+*/
+import "C"
+
+import (
+ "runtime"
+ "syscall"
+ "testing"
+ "time"
+)
+
+//export Gosched
+func Gosched() {
+ runtime.Gosched()
+}
+
+func init() {
+ testThreadLockFunc = testThreadLock
+}
+
+func testThreadLock(t *testing.T) {
+ stop := make(chan int)
+ go func() {
+ // We need the G continue running,
+ // so the M has a chance to run this G.
+ for {
+ select {
+ case <-stop:
+ return
+ case <-time.After(time.Millisecond * 100):
+ }
+ }
+ }()
+ defer close(stop)
+
+ for i := 0; i < 1000; i++ {
+ if C.int(syscall.Gettid()) != C.Ctid() {
+ t.Fatalf("cgo has not locked OS thread")
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/cgo_unix_test.go b/libgo/misc/cgo/test/cgo_unix_test.go
new file mode 100644
index 00000000000..e3d59166498
--- /dev/null
+++ b/libgo/misc/cgo/test/cgo_unix_test.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+package cgotest
+
+import "testing"
+
+func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
+func TestSigprocmask(t *testing.T) { testSigprocmask(t) }
+func Test18146(t *testing.T) { test18146(t) }
diff --git a/libgo/misc/cgo/test/checkconst.go b/libgo/misc/cgo/test/checkconst.go
new file mode 100644
index 00000000000..0160c1e0ced
--- /dev/null
+++ b/libgo/misc/cgo/test/checkconst.go
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// Test a constant in conjunction with pointer checking.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+#define CheckConstVal 0
+
+typedef struct {
+ int *p;
+} CheckConstStruct;
+
+static void CheckConstFunc(CheckConstStruct *p, int e) {
+}
+*/
+import "C"
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func testCheckConst(t *testing.T) {
+ // The test is that this compiles successfully.
+ p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0))))
+ defer C.free(p)
+ C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal)
+}
diff --git a/libgo/misc/cgo/test/complex.go b/libgo/misc/cgo/test/complex.go
new file mode 100644
index 00000000000..ca0a97d9b34
--- /dev/null
+++ b/libgo/misc/cgo/test/complex.go
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+package cgotest
+
+/*
+struct {
+ float x;
+ _Complex float y;
+} cplxAlign = { 3.14, 2.17 };
+*/
+import "C"
+
+import "testing"
+
+func TestComplexAlign(t *testing.T) {
+ if C.cplxAlign.x != 3.14 {
+ t.Errorf("got %v, expected 3.14", C.cplxAlign.x)
+ }
+ if C.cplxAlign.y != 2.17 {
+ t.Errorf("got %v, expected 2.17", C.cplxAlign.y)
+ }
+}
diff --git a/libgo/misc/cgo/test/cthread.go b/libgo/misc/cgo/test/cthread.go
new file mode 100644
index 00000000000..af44911756a
--- /dev/null
+++ b/libgo/misc/cgo/test/cthread.go
@@ -0,0 +1,44 @@
+// 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.
+
+package cgotest
+
+// extern void doAdd(int, int);
+import "C"
+
+import (
+ "runtime"
+ "sync"
+ "testing"
+)
+
+var sum struct {
+ sync.Mutex
+ i int
+}
+
+//export Add
+func Add(x int) {
+ defer func() {
+ recover()
+ }()
+ sum.Lock()
+ sum.i += x
+ sum.Unlock()
+ var p *int
+ *p = 2
+}
+
+func testCthread(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
+ }
+ sum.i = 0
+ C.doAdd(10, 6)
+
+ want := 10 * (10 - 1) / 2 * 6
+ if sum.i != want {
+ t.Fatalf("sum=%d, want %d", sum.i, want)
+ }
+}
diff --git a/libgo/misc/cgo/test/cthread_unix.c b/libgo/misc/cgo/test/cthread_unix.c
new file mode 100644
index 00000000000..6323e4980e8
--- /dev/null
+++ b/libgo/misc/cgo/test/cthread_unix.c
@@ -0,0 +1,34 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+#include <pthread.h>
+#include "_cgo_export.h"
+
+static void*
+addThread(void *p)
+{
+ int i, max;
+
+ max = *(int*)p;
+ for(i=0; i<max; i++)
+ Add(i);
+ return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+ enum { MaxThread = 20 };
+ int i;
+ pthread_t thread_id[MaxThread];
+
+ if(nthread > MaxThread)
+ nthread = MaxThread;
+ for(i=0; i<nthread; i++)
+ pthread_create(&thread_id[i], 0, addThread, &max);
+ for(i=0; i<nthread; i++)
+ pthread_join(thread_id[i], 0);
+}
diff --git a/libgo/misc/cgo/test/cthread_windows.c b/libgo/misc/cgo/test/cthread_windows.c
new file mode 100644
index 00000000000..3a62ddd3730
--- /dev/null
+++ b/libgo/misc/cgo/test/cthread_windows.c
@@ -0,0 +1,37 @@
+// 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.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include "_cgo_export.h"
+
+__stdcall
+static unsigned int
+addThread(void *p)
+{
+ int i, max;
+
+ max = *(int*)p;
+ for(i=0; i<max; i++)
+ Add(i);
+ return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+ enum { MaxThread = 20 };
+ int i;
+ uintptr_t thread_id[MaxThread];
+
+ if(nthread > MaxThread)
+ nthread = MaxThread;
+ for(i=0; i<nthread; i++)
+ thread_id[i] = _beginthreadex(0, 0, addThread, &max, 0, 0);
+ for(i=0; i<nthread; i++) {
+ WaitForSingleObject((HANDLE)thread_id[i], INFINITE);
+ CloseHandle((HANDLE)thread_id[i]);
+ }
+}
diff --git a/libgo/misc/cgo/test/duplicate_symbol.go b/libgo/misc/cgo/test/duplicate_symbol.go
new file mode 100644
index 00000000000..61442713215
--- /dev/null
+++ b/libgo/misc/cgo/test/duplicate_symbol.go
@@ -0,0 +1,21 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+int base_symbol = 0;
+
+#define alias_one base_symbol
+#define alias_two base_symbol
+*/
+import "C"
+
+import "fmt"
+
+func duplicateSymbols() {
+ fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two)
+}
diff --git a/libgo/misc/cgo/test/env.go b/libgo/misc/cgo/test/env.go
new file mode 100644
index 00000000000..b2081b72837
--- /dev/null
+++ b/libgo/misc/cgo/test/env.go
@@ -0,0 +1,41 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+*/
+import "C"
+import (
+ "os"
+ "runtime"
+ "testing"
+ "unsafe"
+)
+
+// This is really an os package test but here for convenience.
+func testSetEnv(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ // Go uses SetEnvironmentVariable on windows. Howerver,
+ // C runtime takes a *copy* at process startup of thei
+ // OS environment, and stores it in environ/envp.
+ // It is this copy that getenv/putenv manipulate.
+ t.Logf("skipping test")
+ return
+ }
+ const key = "CGO_OS_TEST_KEY"
+ const val = "CGO_OS_TEST_VALUE"
+ os.Setenv(key, val)
+ keyc := C.CString(key)
+ defer C.free(unsafe.Pointer(keyc))
+ v := C.getenv(keyc)
+ if uintptr(unsafe.Pointer(v)) == 0 {
+ t.Fatal("getenv returned NULL")
+ }
+ vs := C.GoString(v)
+ if vs != val {
+ t.Fatalf("getenv() = %q; want %q", vs, val)
+ }
+}
diff --git a/libgo/misc/cgo/test/exports.go b/libgo/misc/cgo/test/exports.go
new file mode 100644
index 00000000000..71e5dcdd3df
--- /dev/null
+++ b/libgo/misc/cgo/test/exports.go
@@ -0,0 +1,18 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "C"
+import "runtime"
+
+//export ReturnIntLong
+func ReturnIntLong() (int, C.long) {
+ return 1, 2
+}
+
+//export gc
+func gc() {
+ runtime.GC()
+}
diff --git a/libgo/misc/cgo/test/fpvar.go b/libgo/misc/cgo/test/fpvar.go
new file mode 100644
index 00000000000..7aab8ca2fc2
--- /dev/null
+++ b/libgo/misc/cgo/test/fpvar.go
@@ -0,0 +1,50 @@
+// 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.
+
+// This file contains test cases for cgo with function pointer variables.
+
+package cgotest
+
+/*
+typedef int (*intFunc) ();
+
+int
+bridge_int_func(intFunc f)
+{
+ return f();
+}
+
+int fortytwo()
+{
+ return 42;
+}
+
+*/
+import "C"
+import "testing"
+
+func callBridge(f C.intFunc) int {
+ return int(C.bridge_int_func(f))
+}
+
+func callCBridge(f C.intFunc) C.int {
+ return C.bridge_int_func(f)
+}
+
+func testFpVar(t *testing.T) {
+ const expected = 42
+ f := C.intFunc(C.fortytwo)
+ res1 := C.bridge_int_func(f)
+ if r1 := int(res1); r1 != expected {
+ t.Errorf("got %d, want %d", r1, expected)
+ }
+ res2 := callCBridge(f)
+ if r2 := int(res2); r2 != expected {
+ t.Errorf("got %d, want %d", r2, expected)
+ }
+ r3 := callBridge(f)
+ if r3 != expected {
+ t.Errorf("got %d, want %d", r3, expected)
+ }
+}
diff --git a/libgo/misc/cgo/test/gcc68255.go b/libgo/misc/cgo/test/gcc68255.go
new file mode 100644
index 00000000000..23e103dc109
--- /dev/null
+++ b/libgo/misc/cgo/test/gcc68255.go
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+package cgotest
+
+import (
+ "testing"
+
+ "./gcc68255"
+)
+
+func testGCC68255(t *testing.T) {
+ if !gcc68255.F() {
+ t.Error("C global variable was not initialized")
+ }
+}
diff --git a/libgo/misc/cgo/test/gcc68255/a.go b/libgo/misc/cgo/test/gcc68255/a.go
new file mode 100644
index 00000000000..e106dee3ec0
--- /dev/null
+++ b/libgo/misc/cgo/test/gcc68255/a.go
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// Test that it's OK to have C code that does nothing other than
+// initialize a global variable. This used to fail with gccgo.
+
+package gcc68255
+
+/*
+#include "c.h"
+*/
+import "C"
+
+func F() bool {
+ return C.v != nil
+}
diff --git a/libgo/misc/cgo/test/gcc68255/c.c b/libgo/misc/cgo/test/gcc68255/c.c
new file mode 100644
index 00000000000..a4fe193825b
--- /dev/null
+++ b/libgo/misc/cgo/test/gcc68255/c.c
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+
+static void f(void) {
+}
+
+void (*v)(void) = f;
diff --git a/libgo/misc/cgo/test/gcc68255/c.h b/libgo/misc/cgo/test/gcc68255/c.h
new file mode 100644
index 00000000000..05ecd8187c7
--- /dev/null
+++ b/libgo/misc/cgo/test/gcc68255/c.h
@@ -0,0 +1,5 @@
+// Copyright 2015 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.
+
+extern void (*v)(void);
diff --git a/libgo/misc/cgo/test/helpers.go b/libgo/misc/cgo/test/helpers.go
new file mode 100644
index 00000000000..f6a822a1065
--- /dev/null
+++ b/libgo/misc/cgo/test/helpers.go
@@ -0,0 +1,35 @@
+// Copyright 2011 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.
+
+package cgotest
+
+// const char *greeting = "hello, world";
+import "C"
+
+import (
+ "reflect"
+ "testing"
+ "unsafe"
+)
+
+const greeting = "hello, world"
+
+type testPair struct {
+ Name string
+ Got, Want interface{}
+}
+
+var testPairs = []testPair{
+ {"GoString", C.GoString(C.greeting), greeting},
+ {"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]},
+ {"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])},
+}
+
+func testHelpers(t *testing.T) {
+ for _, pair := range testPairs {
+ if !reflect.DeepEqual(pair.Got, pair.Want) {
+ t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want)
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue10303.go b/libgo/misc/cgo/test/issue10303.go
new file mode 100644
index 00000000000..66e2644d066
--- /dev/null
+++ b/libgo/misc/cgo/test/issue10303.go
@@ -0,0 +1,76 @@
+// Copyright 2015 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.
+
+// Issue 10303. Pointers passed to C were not marked as escaping (bug in cgo).
+
+package cgotest
+
+import "runtime"
+
+/*
+typedef int *intptr;
+
+void setintstar(int *x) {
+ *x = 1;
+}
+
+void setintptr(intptr x) {
+ *x = 1;
+}
+
+void setvoidptr(void *x) {
+ *(int*)x = 1;
+}
+
+typedef struct Struct Struct;
+struct Struct {
+ int *P;
+};
+
+void setstruct(Struct s) {
+ *s.P = 1;
+}
+
+*/
+import "C"
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func test10303(t *testing.T, n int) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("gccgo permits C pointers on the stack")
+ }
+
+ // Run at a few different stack depths just to avoid an unlucky pass
+ // due to variables ending up on different pages.
+ if n > 0 {
+ test10303(t, n-1)
+ }
+ if t.Failed() {
+ return
+ }
+ var x, y, z, v, si C.int
+ var s C.Struct
+ C.setintstar(&x)
+ C.setintptr(&y)
+ C.setvoidptr(unsafe.Pointer(&v))
+ s.P = &si
+ C.setstruct(s)
+
+ if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+ t.Error("C int* argument on stack")
+ }
+ if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+ t.Error("C intptr argument on stack")
+ }
+ if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+ t.Error("C void* argument on stack")
+ }
+ if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff {
+ t.Error("C struct field pointer on stack")
+ }
+}
diff --git a/libgo/misc/cgo/test/issue11925.go b/libgo/misc/cgo/test/issue11925.go
new file mode 100644
index 00000000000..c5c8a269f79
--- /dev/null
+++ b/libgo/misc/cgo/test/issue11925.go
@@ -0,0 +1,37 @@
+// Copyright 2015 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.
+
+// Issue 11925. Structs with zero-length trailing fields are now
+// padded by the Go compiler.
+
+package cgotest
+
+/*
+struct a11925 {
+ int i;
+ char a[0];
+ char b[0];
+};
+
+struct b11925 {
+ int i;
+ char a[0];
+ char b[];
+};
+*/
+import "C"
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func test11925(t *testing.T) {
+ if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) {
+ t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{}))
+ }
+ if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) {
+ t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{}))
+ }
+}
diff --git a/libgo/misc/cgo/test/issue12030.go b/libgo/misc/cgo/test/issue12030.go
new file mode 100644
index 00000000000..f863c58aa2a
--- /dev/null
+++ b/libgo/misc/cgo/test/issue12030.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+// Issue 12030. sprintf is defined in both ntdll and msvcrt,
+// Normally we want the one in the msvcrt.
+
+package cgotest
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+void issue12030conv(char *buf, double x) {
+ sprintf(buf, "d=%g", x);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "testing"
+ "unsafe"
+)
+
+func test12030(t *testing.T) {
+ buf := (*C.char)(C.malloc(256))
+ defer C.free(unsafe.Pointer(buf))
+ for _, f := range []float64{1.0, 2.0, 3.14} {
+ C.issue12030conv(buf, C.double(f))
+ got := C.GoString(buf)
+ if want := fmt.Sprintf("d=%g", f); got != want {
+ t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want)
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue1222.go b/libgo/misc/cgo/test/issue1222.go
new file mode 100644
index 00000000000..4868da8e185
--- /dev/null
+++ b/libgo/misc/cgo/test/issue1222.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+// issue 1222
+typedef union {
+ long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+ union {
+ int x;
+ } element;
+};
+
+struct ibv_context {
+ xxpthread_mutex_t mutex;
+};
+*/
+import "C"
+
+type AsyncEvent struct {
+ event C.struct_ibv_async_event
+}
diff --git a/libgo/misc/cgo/test/issue1328.go b/libgo/misc/cgo/test/issue1328.go
new file mode 100644
index 00000000000..2401c10e300
--- /dev/null
+++ b/libgo/misc/cgo/test/issue1328.go
@@ -0,0 +1,30 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "testing"
+
+// extern void BackIntoGo(void);
+// void IntoC(void);
+import "C"
+
+//export BackIntoGo
+func BackIntoGo() {
+ x := 1
+
+ for i := 0; i < 10000; i++ {
+ xvariadic(x)
+ if x != 1 {
+ panic("x is not 1?")
+ }
+ }
+}
+
+func xvariadic(x ...interface{}) {
+}
+
+func test1328(t *testing.T) {
+ C.IntoC()
+}
diff --git a/libgo/misc/cgo/test/issue13402.go b/libgo/misc/cgo/test/issue13402.go
new file mode 100644
index 00000000000..3af24c2d3c2
--- /dev/null
+++ b/libgo/misc/cgo/test/issue13402.go
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package cgotest
+
+import "C"
+
+var _ C.complexfloat
+var _ C.complexdouble
diff --git a/libgo/misc/cgo/test/issue13930.go b/libgo/misc/cgo/test/issue13930.go
new file mode 100644
index 00000000000..c4a08ee7c9e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue13930.go
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+// Issue 13930. Test that cgo's multiple-value special form for
+// C function calls works in variable declaration statements.
+
+package cgotest
+
+// #include <stdlib.h>
+import "C"
+
+var _, _ = C.abs(0)
diff --git a/libgo/misc/cgo/test/issue14838.go b/libgo/misc/cgo/test/issue14838.go
new file mode 100644
index 00000000000..c8e1681295e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue14838.go
@@ -0,0 +1,37 @@
+// Copyright 2016 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.
+
+// Issue 14838. add CBytes function
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+int check_cbytes(char *b, size_t l) {
+ int i;
+ for (i = 0; i < l; i++) {
+ if (b[i] != i) {
+ return 0;
+ }
+ }
+ return 1;
+}
+*/
+import "C"
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func test14838(t *testing.T) {
+ data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+ cData := C.CBytes(data)
+ defer C.free(cData)
+
+ if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 {
+ t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:])
+ }
+}
diff --git a/libgo/misc/cgo/test/issue1560.go b/libgo/misc/cgo/test/issue1560.go
new file mode 100644
index 00000000000..30f61522257
--- /dev/null
+++ b/libgo/misc/cgo/test/issue1560.go
@@ -0,0 +1,50 @@
+// Copyright 2011 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.
+
+package cgotest
+
+/*
+// mysleep returns the absolute start time in ms.
+long long mysleep(int seconds);
+
+// twoSleep returns the absolute start time of the first sleep
+// in ms.
+long long twoSleep(int);
+*/
+import "C"
+
+import (
+ "testing"
+ "time"
+)
+
+var sleepDone = make(chan int64)
+
+// parallelSleep returns the absolute difference between the start time
+// of the two sleeps.
+func parallelSleep(n int) int64 {
+ t := int64(C.twoSleep(C.int(n))) - <-sleepDone
+ if t < 0 {
+ return -t
+ }
+ return t
+}
+
+//export BackgroundSleep
+func BackgroundSleep(n int32) {
+ go func() {
+ sleepDone <- int64(C.mysleep(C.int(n)))
+ }()
+}
+
+func testParallelSleep(t *testing.T) {
+ sleepSec := 1
+ dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond
+ t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt)
+ // bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
+ // we detect if the start times of those sleeps are > 0.5*sleepSec-second.
+ if dt >= time.Duration(sleepSec)*time.Second/2 {
+ t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())
+ }
+}
diff --git a/libgo/misc/cgo/test/issue1635.go b/libgo/misc/cgo/test/issue1635.go
new file mode 100644
index 00000000000..25899271c93
--- /dev/null
+++ b/libgo/misc/cgo/test/issue1635.go
@@ -0,0 +1,38 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+// Mac OS X's gcc will generate scattered relocation 2/1 for
+// this function on Darwin/386, and 8l couldn't handle it.
+// this example is in issue 1635
+#include <stdio.h>
+void scatter() {
+ void *p = scatter;
+ printf("scatter = %p\n", p);
+}
+
+// Adding this explicit extern declaration makes this a test for
+// https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 .
+// It used to cause a cgo error when building with GCC 6.
+extern int hola;
+
+// this example is in issue 3253
+int hola = 0;
+int testHola() { return hola; }
+*/
+import "C"
+
+import "testing"
+
+func test1635(t *testing.T) {
+ C.scatter()
+ if v := C.hola; v != 0 {
+ t.Fatalf("C.hola is %d, should be 0", v)
+ }
+ if v := C.testHola(); v != 0 {
+ t.Fatalf("C.testHola() is %d, should be 0", v)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue17065.go b/libgo/misc/cgo/test/issue17065.go
new file mode 100644
index 00000000000..ede30bc3e63
--- /dev/null
+++ b/libgo/misc/cgo/test/issue17065.go
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+package cgotest
+
+/*
+// Test that C symbols larger than a page play nicely with the race detector.
+// See issue 17065.
+
+int ii[65537];
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+var sink C.int
+
+func test17065(t *testing.T) {
+ if runtime.GOOS == "darwin" {
+ t.Skip("broken on darwin; issue 17065")
+ }
+ for i := range C.ii {
+ sink = C.ii[i]
+ }
+}
diff --git a/libgo/misc/cgo/test/issue17537.go b/libgo/misc/cgo/test/issue17537.go
new file mode 100644
index 00000000000..777104e5122
--- /dev/null
+++ b/libgo/misc/cgo/test/issue17537.go
@@ -0,0 +1,58 @@
+// Copyright 2016 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.
+
+// Issue 17537. The void* cast introduced by cgo to avoid problems
+// with const/volatile qualifiers breaks C preprocessor macros that
+// emulate functions.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+typedef struct {
+ int i;
+} S17537;
+
+int I17537(S17537 *p);
+
+#define I17537(p) ((p)->i)
+
+// Calling this function used to fail without the cast.
+const int F17537(const char **p) {
+ return **p;
+}
+
+// Calling this function used to trigger an error from the C compiler
+// (issue 18298).
+void F18298(const void *const *p) {
+}
+
+// Test that conversions between typedefs work as they used to.
+typedef const void *T18298_1;
+struct S18298 { int i; };
+typedef const struct S18298 *T18298_2;
+void G18298(T18298_1 t) {
+}
+*/
+import "C"
+
+import "testing"
+
+func test17537(t *testing.T) {
+ v := C.S17537{i: 17537}
+ if got, want := C.I17537(&v), C.int(17537); got != want {
+ t.Errorf("got %d, want %d", got, want)
+ }
+
+ p := (*C.char)(C.malloc(1))
+ *p = 17
+ if got, want := C.F17537(&p), C.int(17); got != want {
+ t.Errorf("got %d, want %d", got, want)
+ }
+
+ C.F18298(nil)
+ var v18298 C.T18298_2
+ C.G18298(C.T18298_1(v18298))
+}
diff --git a/libgo/misc/cgo/test/issue18126.go b/libgo/misc/cgo/test/issue18126.go
new file mode 100644
index 00000000000..ac94a66aab7
--- /dev/null
+++ b/libgo/misc/cgo/test/issue18126.go
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// Issue 18126: cgo check of void function returning errno.
+
+package cgotest
+
+/*
+#include <stdlib.h>
+
+void Issue18126C(void **p) {
+}
+*/
+import "C"
+
+import (
+ "testing"
+)
+
+func test18126(t *testing.T) {
+ p := C.malloc(1)
+ _, err := C.Issue18126C(&p)
+ C.free(p)
+ _ = err
+}
diff --git a/libgo/misc/cgo/test/issue18146.go b/libgo/misc/cgo/test/issue18146.go
new file mode 100644
index 00000000000..3c600463f03
--- /dev/null
+++ b/libgo/misc/cgo/test/issue18146.go
@@ -0,0 +1,128 @@
+// Copyright 2016 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.
+
+// +build !windows
+
+// Issue 18146: pthread_create failure during syscall.Exec.
+
+package cgotest
+
+import "C"
+
+import (
+ "bytes"
+ "crypto/md5"
+ "os"
+ "os/exec"
+ "runtime"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func test18146(t *testing.T) {
+ if runtime.GOOS == "darwin" {
+ t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
+ }
+
+ if runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
+ t.Skipf("skipping on %s", runtime.GOARCH)
+ }
+
+ attempts := 1000
+ threads := 4
+
+ if testing.Short() {
+ attempts = 100
+ }
+
+ // Restrict the number of attempts based on RLIMIT_NPROC.
+ // Tediously, RLIMIT_NPROC was left out of the syscall package,
+ // probably because it is not in POSIX.1, so we define it here.
+ // It is not defined on Solaris.
+ var nproc int
+ setNproc := true
+ switch runtime.GOOS {
+ default:
+ setNproc = false
+ case "linux":
+ nproc = 6
+ case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
+ nproc = 7
+ }
+ if setNproc {
+ var rlim syscall.Rlimit
+ if syscall.Getrlimit(nproc, &rlim) == nil {
+ max := int(rlim.Cur) / (threads + 5)
+ if attempts > max {
+ t.Logf("lowering attempts from %d to %d for RLIMIT_NPROC", attempts, max)
+ attempts = max
+ }
+ }
+ }
+
+ if os.Getenv("test18146") == "exec" {
+ runtime.GOMAXPROCS(1)
+ for n := threads; n > 0; n-- {
+ go func() {
+ for {
+ _ = md5.Sum([]byte("Hello, !"))
+ }
+ }()
+ }
+ runtime.GOMAXPROCS(threads)
+ argv := append(os.Args, "-test.run=NoSuchTestExists")
+ if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ var cmds []*exec.Cmd
+ defer func() {
+ for _, cmd := range cmds {
+ cmd.Process.Kill()
+ }
+ }()
+
+ args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
+ for n := attempts; n > 0; n-- {
+ cmd := exec.Command(os.Args[0], args...)
+ cmd.Env = append(os.Environ(), "test18146=exec")
+ buf := bytes.NewBuffer(nil)
+ cmd.Stdout = buf
+ cmd.Stderr = buf
+ if err := cmd.Start(); err != nil {
+ // We are starting so many processes that on
+ // some systems (problem seen on Darwin,
+ // Dragonfly, OpenBSD) the fork call will fail
+ // with EAGAIN.
+ if pe, ok := err.(*os.PathError); ok {
+ err = pe.Err
+ }
+ if se, ok := err.(syscall.Errno); ok && (se == syscall.EAGAIN || se == syscall.EMFILE) {
+ time.Sleep(time.Millisecond)
+ continue
+ }
+
+ t.Error(err)
+ return
+ }
+ cmds = append(cmds, cmd)
+ }
+
+ failures := 0
+ for _, cmd := range cmds {
+ err := cmd.Wait()
+ if err == nil {
+ continue
+ }
+
+ t.Errorf("syscall.Exec failed: %v\n%s", err, cmd.Stdout)
+ failures++
+ }
+
+ if failures > 0 {
+ t.Logf("Failed %v of %v attempts.", failures, len(cmds))
+ }
+}
diff --git a/libgo/misc/cgo/test/issue2462.go b/libgo/misc/cgo/test/issue2462.go
new file mode 100644
index 00000000000..febca1eb085
--- /dev/null
+++ b/libgo/misc/cgo/test/issue2462.go
@@ -0,0 +1,102 @@
+// Copyright 2011 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.
+
+package cgotest
+
+import "C"
+
+//export exportbyte
+func exportbyte() byte {
+ return 0
+}
+
+//export exportbool
+func exportbool() bool {
+ return false
+}
+
+//export exportrune
+func exportrune() rune {
+ return 0
+}
+
+//export exporterror
+func exporterror() error {
+ return nil
+}
+
+//export exportint
+func exportint() int {
+ return 0
+}
+
+//export exportuint
+func exportuint() uint {
+ return 0
+}
+
+//export exportuintptr
+func exportuintptr() uintptr {
+ return (uintptr)(0)
+}
+
+//export exportint8
+func exportint8() int8 {
+ return 0
+}
+
+//export exportuint8
+func exportuint8() uint8 {
+ return 0
+}
+
+//export exportint16
+func exportint16() int16 {
+ return 0
+}
+
+//export exportuint16
+func exportuint16() uint16 {
+ return 0
+}
+
+//export exportint32
+func exportint32() int32 {
+ return 0
+}
+
+//export exportuint32
+func exportuint32() uint32 {
+ return 0
+}
+
+//export exportint64
+func exportint64() int64 {
+ return 0
+}
+
+//export exportuint64
+func exportuint64() uint64 {
+ return 0
+}
+
+//export exportfloat32
+func exportfloat32() float32 {
+ return 0
+}
+
+//export exportfloat64
+func exportfloat64() float64 {
+ return 0
+}
+
+//export exportcomplex64
+func exportcomplex64() complex64 {
+ return 0
+}
+
+//export exportcomplex128
+func exportcomplex128() complex128 {
+ return 0
+}
diff --git a/libgo/misc/cgo/test/issue3250.go b/libgo/misc/cgo/test/issue3250.go
new file mode 100644
index 00000000000..f85c16b2dce
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3250.go
@@ -0,0 +1,95 @@
+// 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.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void *thread(void *p) {
+ const int M = 100;
+ int i;
+ (void)p;
+ for (i = 0; i < M; i++) {
+ pthread_kill(pthread_self(), SIGCHLD);
+ usleep(rand() % 20 + 5);
+ }
+ return NULL;
+}
+void testSendSIG() {
+ const int N = 20;
+ int i;
+ pthread_t tid[N];
+ for (i = 0; i < N; i++) {
+ usleep(rand() % 200 + 100);
+ pthread_create(&tid[i], 0, thread, NULL);
+ }
+ for (i = 0; i < N; i++)
+ pthread_join(tid[i], 0);
+}
+*/
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func test3250(t *testing.T) {
+ t.Skip("skipped, see golang.org/issue/5885")
+ const (
+ thres = 1
+ sig = syscall.SIGCHLD
+ )
+ type result struct {
+ n int
+ sig os.Signal
+ }
+ var (
+ sigCh = make(chan os.Signal, 10)
+ waitStart = make(chan struct{})
+ waitDone = make(chan result)
+ )
+
+ signal.Notify(sigCh, sig)
+
+ go func() {
+ n := 0
+ alarm := time.After(time.Second * 3)
+ for {
+ select {
+ case <-waitStart:
+ waitStart = nil
+ case v := <-sigCh:
+ n++
+ if v != sig || n > thres {
+ waitDone <- result{n, v}
+ return
+ }
+ case <-alarm:
+ waitDone <- result{n, sig}
+ return
+ }
+ }
+ }()
+
+ waitStart <- struct{}{}
+ C.testSendSIG()
+ r := <-waitDone
+ if r.sig != sig {
+ t.Fatalf("received signal %v, but want %v", r.sig, sig)
+ }
+ t.Logf("got %d signals\n", r.n)
+ if r.n <= thres {
+ t.Fatalf("expected more than %d", thres)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue3250w.go b/libgo/misc/cgo/test/issue3250w.go
new file mode 100644
index 00000000000..c2193aa1f1c
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3250w.go
@@ -0,0 +1,11 @@
+// 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.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test3250(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/issue3261.go b/libgo/misc/cgo/test/issue3261.go
new file mode 100644
index 00000000000..71375698d37
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3261.go
@@ -0,0 +1,49 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+// libgcc on ARM might be compiled as thumb code, but our 5l
+// can't handle that, so we have to disable this test on arm.
+#ifdef __ARMEL__
+#include <stdio.h>
+int vabs(int x) {
+ puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library.");
+ return (x < 0) ? -x : x;
+}
+#elif defined(__arm64__) && defined(__clang__)
+#include <stdio.h>
+int vabs(int x) {
+ puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc.");
+ return (x < 0) ? -x : x;
+}
+#else
+int __absvsi2(int); // dummy prototype for libgcc function
+// we shouldn't name the function abs, as gcc might use
+// the builtin one.
+int vabs(int x) { return __absvsi2(x); }
+#endif
+*/
+import "C"
+
+import "testing"
+
+func testLibgcc(t *testing.T) {
+ var table = []struct {
+ in, out C.int
+ }{
+ {0, 0},
+ {1, 1},
+ {-42, 42},
+ {1000300, 1000300},
+ {1 - 1<<31, 1<<31 - 1},
+ }
+ for _, v := range table {
+ if o := C.vabs(v.in); o != v.out {
+ t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out)
+ return
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue3729.go b/libgo/misc/cgo/test/issue3729.go
new file mode 100644
index 00000000000..947b90a00de
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3729.go
@@ -0,0 +1,47 @@
+// Copyright 2012 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.
+
+// Issue 3729: cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <errno.h>
+
+void g(void) {
+ errno = E2BIG;
+}
+
+// try to pass some non-trivial arguments to function g2
+const char _expA = 0x42;
+const float _expB = 3.14159;
+const short _expC = 0x55aa;
+const int _expD = 0xdeadbeef;
+void g2(int x, char a, float b, short c, int d) {
+ if (a == _expA && b == _expB && c == _expC && d == _expD)
+ errno = x;
+ else
+ errno = -1;
+}
+*/
+import "C"
+
+import (
+ "syscall"
+ "testing"
+)
+
+func test3729(t *testing.T) {
+ _, e := C.g()
+ if e != syscall.E2BIG {
+ t.Errorf("got %q, expect %q", e, syscall.E2BIG)
+ }
+ _, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD)
+ if e != syscall.EINVAL {
+ t.Errorf("got %q, expect %q", e, syscall.EINVAL)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue3729w.go b/libgo/misc/cgo/test/issue3729w.go
new file mode 100644
index 00000000000..69296b506e7
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3729w.go
@@ -0,0 +1,16 @@
+// Copyright 2012 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.
+
+// Issue 3729: cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test3729(t *testing.T) {
+ t.Log("skip errno test on Windows")
+}
diff --git a/libgo/misc/cgo/test/issue3741.go b/libgo/misc/cgo/test/issue3741.go
new file mode 100644
index 00000000000..314038c1fe8
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3741.go
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+package cgotest
+
+import "C"
+
+//export exportSliceIn
+func exportSliceIn(s []byte) bool {
+ return len(s) == cap(s)
+}
+
+//export exportSliceOut
+func exportSliceOut() []byte {
+ return []byte{1}
+}
+
+//export exportSliceInOut
+func exportSliceInOut(s []byte) []byte {
+ return s
+}
diff --git a/libgo/misc/cgo/test/issue3775.go b/libgo/misc/cgo/test/issue3775.go
new file mode 100644
index 00000000000..5aca7602c03
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3775.go
@@ -0,0 +1,39 @@
+// +build !android
+
+package cgotest
+
+/*
+void lockOSThreadCallback(void);
+inline static void lockOSThreadC(void)
+{
+ lockOSThreadCallback();
+}
+int usleep(unsigned usec);
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func init() {
+ // Same as test3775 but run during init so that
+ // there are two levels of internal runtime lock
+ // (1 for init, 1 for cgo).
+ // This would have been broken by CL 11663043.
+ C.lockOSThreadC()
+}
+
+func test3775(t *testing.T) {
+ // Used to panic because of the UnlockOSThread below.
+ C.lockOSThreadC()
+}
+
+//export lockOSThreadCallback
+func lockOSThreadCallback() {
+ runtime.LockOSThread()
+ runtime.UnlockOSThread()
+ go C.usleep(10000)
+ runtime.Gosched()
+}
diff --git a/libgo/misc/cgo/test/issue3945.go b/libgo/misc/cgo/test/issue3945.go
new file mode 100644
index 00000000000..2f9fe23b8dc
--- /dev/null
+++ b/libgo/misc/cgo/test/issue3945.go
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+package cgotest
+
+// Test that cgo reserves enough stack space during cgo call.
+// See https://golang.org/issue/3945 for details.
+
+// #include <stdio.h>
+//
+// void say() {
+// printf("%s from C\n", "hello");
+// }
+//
+import "C"
+
+import "testing"
+
+func testPrintf(t *testing.T) {
+ C.say()
+}
diff --git a/libgo/misc/cgo/test/issue4029.c b/libgo/misc/cgo/test/issue4029.c
new file mode 100644
index 00000000000..eab36834501
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4029.c
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+void call4029(void *arg) {
+ void (*fn)(void) = arg;
+ fn();
+}
diff --git a/libgo/misc/cgo/test/issue4029.go b/libgo/misc/cgo/test/issue4029.go
new file mode 100644
index 00000000000..5789b99ef67
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4029.go
@@ -0,0 +1,68 @@
+// Copyright 2012 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.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <dlfcn.h>
+#cgo linux LDFLAGS: -ldl
+
+extern void call4029(void *arg);
+*/
+import "C"
+
+import (
+ "testing"
+)
+
+var callbacks int
+
+//export IMPIsOpaque
+func IMPIsOpaque() {
+ callbacks++
+}
+
+//export IMPInitWithFrame
+func IMPInitWithFrame() {
+ callbacks++
+}
+
+//export IMPDrawRect
+func IMPDrawRect() {
+ callbacks++
+}
+
+//export IMPWindowResize
+func IMPWindowResize() {
+ callbacks++
+}
+
+func test4029(t *testing.T) {
+ loadThySelf(t, "IMPWindowResize")
+ loadThySelf(t, "IMPDrawRect")
+ loadThySelf(t, "IMPInitWithFrame")
+ loadThySelf(t, "IMPIsOpaque")
+ if callbacks != 4 {
+ t.Errorf("got %d callbacks, expected 4", callbacks)
+ }
+}
+
+func loadThySelf(t *testing.T, symbol string) {
+ this_process := C.dlopen(nil, C.RTLD_NOW)
+ if this_process == nil {
+ t.Error("dlopen:", C.GoString(C.dlerror()))
+ return
+ }
+ defer C.dlclose(this_process)
+
+ symbol_address := C.dlsym(this_process, C.CString(symbol))
+ if symbol_address == nil {
+ t.Error("dlsym:", C.GoString(C.dlerror()))
+ return
+ }
+ t.Log(symbol, symbol_address)
+ C.call4029(symbol_address)
+}
diff --git a/libgo/misc/cgo/test/issue4029w.go b/libgo/misc/cgo/test/issue4029w.go
new file mode 100644
index 00000000000..18c720191be
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4029w.go
@@ -0,0 +1,12 @@
+// Copyright 2012 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.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test4029(t *testing.T) {
+}
diff --git a/libgo/misc/cgo/test/issue4054a.go b/libgo/misc/cgo/test/issue4054a.go
new file mode 100644
index 00000000000..2abdac59047
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4054a.go
@@ -0,0 +1,23 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+typedef enum {
+ A = 0,
+ B,
+ C,
+ D,
+ E,
+ F,
+ G,
+ H,
+ I,
+ J,
+} issue4054a;
+*/
+import "C"
+
+var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/libgo/misc/cgo/test/issue4054b.go b/libgo/misc/cgo/test/issue4054b.go
new file mode 100644
index 00000000000..048964c8937
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4054b.go
@@ -0,0 +1,23 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+typedef enum {
+ A = 0,
+ B,
+ C,
+ D,
+ E,
+ F,
+ G,
+ H,
+ I,
+ J,
+} issue4054b;
+*/
+import "C"
+
+var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/libgo/misc/cgo/test/issue4273.c b/libgo/misc/cgo/test/issue4273.c
new file mode 100644
index 00000000000..cac98768dea
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4273.c
@@ -0,0 +1,10 @@
+// Copyright 2012 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.
+
+#ifdef __ELF__
+__attribute__((weak))
+__attribute__((visibility("hidden")))
+void _compilerrt_abort_impl(const char *file, int line, const char *func) {
+}
+#endif
diff --git a/libgo/misc/cgo/test/issue4273b.c b/libgo/misc/cgo/test/issue4273b.c
new file mode 100644
index 00000000000..71e3f0d976a
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4273b.c
@@ -0,0 +1,11 @@
+// Copyright 2012 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.
+
+#ifdef __ELF__
+extern void _compilerrt_abort_impl(const char *file, int line, const char *func);
+
+void __my_abort(const char *file, int line, const char *func) {
+ _compilerrt_abort_impl(file, line, func);
+}
+#endif
diff --git a/libgo/misc/cgo/test/issue4339.c b/libgo/misc/cgo/test/issue4339.c
new file mode 100644
index 00000000000..15d0004078c
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4339.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "issue4339.h"
+
+static void
+impl(void)
+{
+ //printf("impl\n");
+}
+
+Issue4339 exported4339 = {"bar", impl};
+
+void
+handle4339(Issue4339 *x)
+{
+ //printf("handle\n");
+ x->bar();
+ //printf("done\n");
+}
diff --git a/libgo/misc/cgo/test/issue4339.go b/libgo/misc/cgo/test/issue4339.go
new file mode 100644
index 00000000000..4fa4b2bbd7e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4339.go
@@ -0,0 +1,16 @@
+// 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.
+
+package cgotest
+
+/*
+#include "issue4339.h"
+*/
+import "C"
+
+import "testing"
+
+func test4339(t *testing.T) {
+ C.handle4339(&C.exported4339)
+}
diff --git a/libgo/misc/cgo/test/issue4339.h b/libgo/misc/cgo/test/issue4339.h
new file mode 100644
index 00000000000..20f6cebb6b5
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4339.h
@@ -0,0 +1,9 @@
+typedef struct Issue4339 Issue4339;
+
+struct Issue4339 {
+ char *name;
+ void (*bar)(void);
+};
+
+extern Issue4339 exported4339;
+void handle4339(Issue4339*);
diff --git a/libgo/misc/cgo/test/issue4417.go b/libgo/misc/cgo/test/issue4417.go
new file mode 100644
index 00000000000..9b182870d8e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4417.go
@@ -0,0 +1,42 @@
+// Copyright 2012 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.
+
+// Issue 4417: cmd/cgo: bool alignment/padding issue.
+// bool alignment is wrong and causing wrong arguments when calling functions.
+//
+
+package cgotest
+
+/*
+#include <stdbool.h>
+
+static int c_bool(bool a, bool b, int c, bool d, bool e) {
+ return c;
+}
+*/
+import "C"
+import "testing"
+
+func testBoolAlign(t *testing.T) {
+ b := C.c_bool(true, true, 10, true, false)
+ if b != 10 {
+ t.Fatalf("found %d expected 10\n", b)
+ }
+ b = C.c_bool(true, true, 5, true, true)
+ if b != 5 {
+ t.Fatalf("found %d expected 5\n", b)
+ }
+ b = C.c_bool(true, true, 3, true, false)
+ if b != 3 {
+ t.Fatalf("found %d expected 3\n", b)
+ }
+ b = C.c_bool(false, false, 1, true, false)
+ if b != 1 {
+ t.Fatalf("found %d expected 1\n", b)
+ }
+ b = C.c_bool(false, true, 200, true, false)
+ if b != 200 {
+ t.Fatalf("found %d expected 200\n", b)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue4857.go b/libgo/misc/cgo/test/issue4857.go
new file mode 100644
index 00000000000..b18979b5f7a
--- /dev/null
+++ b/libgo/misc/cgo/test/issue4857.go
@@ -0,0 +1,15 @@
+// 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.
+
+package cgotest
+
+/*
+#cgo CFLAGS: -Werror
+const struct { int a; } *issue4857() { return (void *)0; }
+*/
+import "C"
+
+func test4857() {
+ _ = C.issue4857()
+}
diff --git a/libgo/misc/cgo/test/issue5227.go b/libgo/misc/cgo/test/issue5227.go
new file mode 100644
index 00000000000..53c3bf12d74
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5227.go
@@ -0,0 +1,38 @@
+// 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.
+
+// Issue 5227: linker incorrectly treats common symbols and
+// leaves them undefined.
+
+package cgotest
+
+/*
+typedef struct {
+ int Count;
+} Fontinfo;
+
+Fontinfo SansTypeface;
+
+extern void init();
+
+Fontinfo loadfont() {
+ Fontinfo f = {0};
+ return f;
+}
+
+void init() {
+ SansTypeface = loadfont();
+}
+*/
+import "C"
+
+import "testing"
+
+func test5227(t *testing.T) {
+ C.init()
+}
+
+func selectfont() C.Fontinfo {
+ return C.SansTypeface
+}
diff --git a/libgo/misc/cgo/test/issue5242.go b/libgo/misc/cgo/test/issue5242.go
new file mode 100644
index 00000000000..c81cd409199
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5242.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+// Issue 5242. Cgo incorrectly computed the alignment of structs
+// with no Go accessible fields as 0, and then panicked on
+// modulo-by-zero computations.
+
+package cgotest
+
+/*
+typedef struct {
+} foo;
+
+typedef struct {
+ int x : 1;
+} bar;
+
+int issue5242(foo f, bar b) {
+ return 5242;
+}
+*/
+import "C"
+
+import "testing"
+
+func test5242(t *testing.T) {
+ if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 {
+ t.Errorf("got %v", got)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue5337.go b/libgo/misc/cgo/test/issue5337.go
new file mode 100644
index 00000000000..9041d95168d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5337.go
@@ -0,0 +1,31 @@
+// 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.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <pthread.h>
+
+static void *thread1(void *p) {
+ (void)p;
+ pthread_kill(pthread_self(), SIGPROF);
+ return NULL;
+}
+void test5337() {
+ pthread_t tid;
+ pthread_create(&tid, 0, thread1, NULL);
+ pthread_join(tid, 0);
+}
+*/
+import "C"
+
+import "testing"
+
+// Verify that we can withstand SIGPROF received on foreign threads
+func test5337(t *testing.T) {
+ C.test5337()
+}
diff --git a/libgo/misc/cgo/test/issue5337w.go b/libgo/misc/cgo/test/issue5337w.go
new file mode 100644
index 00000000000..7b467577007
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5337w.go
@@ -0,0 +1,11 @@
+// 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.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test5337(t *testing.T) {}
diff --git a/libgo/misc/cgo/test/issue5548.go b/libgo/misc/cgo/test/issue5548.go
new file mode 100644
index 00000000000..0710da79507
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5548.go
@@ -0,0 +1,27 @@
+// 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.
+
+package cgotest
+
+import "testing"
+
+/*
+extern int issue5548_in_c(void);
+*/
+import "C"
+
+//export issue5548FromC
+func issue5548FromC(s string, i int) int {
+ if len(s) == 4 && s == "test" && i == 42 {
+ return 12345
+ }
+ println("got", len(s), i)
+ return 9876
+}
+
+func test5548(t *testing.T) {
+ if x := C.issue5548_in_c(); x != 12345 {
+ t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue5548_c.c b/libgo/misc/cgo/test/issue5548_c.c
new file mode 100644
index 00000000000..84115266ffd
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5548_c.c
@@ -0,0 +1,24 @@
+// 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.
+
+#include "_cgo_export.h"
+
+static void clobber_stack() {
+ volatile char a[1024];
+ int i;
+ for(i = 0; i < sizeof a; i++)
+ a[i] = 0xff;
+}
+
+static int call_go() {
+ GoString s;
+ s.p = "test";
+ s.n = 4;
+ return issue5548FromC(s, 42);
+}
+
+int issue5548_in_c() {
+ clobber_stack();
+ return call_go();
+}
diff --git a/libgo/misc/cgo/test/issue5603.go b/libgo/misc/cgo/test/issue5603.go
new file mode 100644
index 00000000000..ab84339e101
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5603.go
@@ -0,0 +1,32 @@
+// 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.
+
+package cgotest
+
+/*
+const long long issue5603exp = 0x12345678;
+long long issue5603foo0() { return issue5603exp; }
+long long issue5603foo1(void *p) { return issue5603exp; }
+long long issue5603foo2(void *p, void *q) { return issue5603exp; }
+long long issue5603foo3(void *p, void *q, void *r) { return issue5603exp; }
+long long issue5603foo4(void *p, void *q, void *r, void *s) { return issue5603exp; }
+*/
+import "C"
+
+import "testing"
+
+func test5603(t *testing.T) {
+ var x [5]int64
+ exp := int64(C.issue5603exp)
+ x[0] = int64(C.issue5603foo0())
+ x[1] = int64(C.issue5603foo1(nil))
+ x[2] = int64(C.issue5603foo2(nil, nil))
+ x[3] = int64(C.issue5603foo3(nil, nil, nil))
+ x[4] = int64(C.issue5603foo4(nil, nil, nil, nil))
+ for i, v := range x {
+ if v != exp {
+ t.Errorf("issue5603foo%d() returns %v, expected %v", i, v, exp)
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue5740.go b/libgo/misc/cgo/test/issue5740.go
new file mode 100644
index 00000000000..059e316119d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5740.go
@@ -0,0 +1,15 @@
+// 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.
+
+package cgotest
+
+// int test5740a(void), test5740b(void);
+import "C"
+import "testing"
+
+func test5740(t *testing.T) {
+ if v := C.test5740a() + C.test5740b(); v != 5 {
+ t.Errorf("expected 5, got %v", v)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue5740a.c b/libgo/misc/cgo/test/issue5740a.c
new file mode 100644
index 00000000000..a6a7d0c9601
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5740a.c
@@ -0,0 +1,9 @@
+// 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.
+
+static int volatile val = 2;
+
+int test5740a() {
+ return val;
+}
diff --git a/libgo/misc/cgo/test/issue5740b.c b/libgo/misc/cgo/test/issue5740b.c
new file mode 100644
index 00000000000..c2ff5fbc4a5
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5740b.c
@@ -0,0 +1,9 @@
+// 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.
+
+static int volatile val = 3;
+
+int test5740b() {
+ return val;
+}
diff --git a/libgo/misc/cgo/test/issue5986.go b/libgo/misc/cgo/test/issue5986.go
new file mode 100644
index 00000000000..9be1614233e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue5986.go
@@ -0,0 +1,33 @@
+// 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.
+
+package cgotest
+
+/*
+#cgo LDFLAGS: -lm
+#include <stdio.h>
+#include <math.h>
+
+static void output5986()
+{
+ int current_row = 0, row_count = 0;
+ double sum_squares = 0;
+ double d;
+ do {
+ if (current_row == 10) {
+ current_row = 0;
+ }
+ ++row_count;
+ }
+ while (current_row++ != 1);
+ d = sqrt(sum_squares / row_count);
+ printf("sqrt is: %g\n", d);
+}
+*/
+import "C"
+import "testing"
+
+func test5986(t *testing.T) {
+ C.output5986()
+}
diff --git a/libgo/misc/cgo/test/issue6128.go b/libgo/misc/cgo/test/issue6128.go
new file mode 100644
index 00000000000..9832d799b94
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6128.go
@@ -0,0 +1,20 @@
+// 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.
+
+package cgotest
+
+// Test handling of #defined names in clang.
+// golang.org/issue/6128.
+
+/*
+// NOTE: Must use hex, or else a shortcut for decimals
+// in cgo avoids trying to pass this to clang.
+#define X 0x1
+*/
+import "C"
+
+func test6128() {
+ // nothing to run, just make sure this compiles.
+ _ = C.X
+}
diff --git a/libgo/misc/cgo/test/issue6390.go b/libgo/misc/cgo/test/issue6390.go
new file mode 100644
index 00000000000..5642899c587
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6390.go
@@ -0,0 +1,23 @@
+// 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.
+
+package cgotest
+
+// #include <stdlib.h>
+import "C"
+
+import "testing"
+
+func test6390(t *testing.T) {
+ p1 := C.malloc(1024)
+ if p1 == nil {
+ t.Fatalf("C.malloc(1024) returned nil")
+ }
+ p2 := C.malloc(0)
+ if p2 == nil {
+ t.Fatalf("C.malloc(0) returned nil")
+ }
+ C.free(p1)
+ C.free(p2)
+}
diff --git a/libgo/misc/cgo/test/issue6472.go b/libgo/misc/cgo/test/issue6472.go
new file mode 100644
index 00000000000..d416a05e29d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6472.go
@@ -0,0 +1,22 @@
+// 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.
+
+package cgotest
+
+/*
+typedef struct
+{
+ struct
+ {
+ int x;
+ } y[16];
+} z;
+*/
+import "C"
+
+func test6472() {
+ // nothing to run, just make sure this compiles
+ s := new(C.z)
+ println(s.y[0].x)
+}
diff --git a/libgo/misc/cgo/test/issue6506.go b/libgo/misc/cgo/test/issue6506.go
new file mode 100644
index 00000000000..c54b54b64fc
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6506.go
@@ -0,0 +1,36 @@
+// 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.
+
+package cgotest
+
+// Test handling of size_t in the face of incorrect clang debug information.
+// golang.org/issue/6506.
+
+/*
+#include <stdlib.h>
+#include <string.h>
+*/
+import "C"
+
+func test6506() {
+ // nothing to run, just make sure this compiles
+ var x C.size_t
+
+ C.calloc(x, x)
+ C.malloc(x)
+ C.realloc(nil, x)
+ C.memcpy(nil, nil, x)
+ C.memcmp(nil, nil, x)
+ C.memmove(nil, nil, x)
+ C.strncpy(nil, nil, x)
+ C.strncmp(nil, nil, x)
+ C.strncat(nil, nil, x)
+ x = C.strxfrm(nil, nil, x)
+ C.memchr(nil, 0, x)
+ x = C.strcspn(nil, nil)
+ x = C.strspn(nil, nil)
+ C.memset(nil, 0, x)
+ x = C.strlen(nil)
+ _ = x
+}
diff --git a/libgo/misc/cgo/test/issue6612.go b/libgo/misc/cgo/test/issue6612.go
new file mode 100644
index 00000000000..c337f911d90
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6612.go
@@ -0,0 +1,93 @@
+// 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.
+
+// golang.org/issue/6612
+// Test new scheme for deciding whether C.name is an expression, type, constant.
+// Clang silences some warnings when the name is a #defined macro, so test those too
+// (even though we now use errors exclusively, not warnings).
+
+package cgotest
+
+/*
+void myfunc(void) {}
+int myvar = 5;
+const char *mytext = "abcdef";
+typedef int mytype;
+enum {
+ myenum = 1234,
+};
+
+#define myfunc_def myfunc
+#define myvar_def myvar
+#define mytext_def mytext
+#define mytype_def mytype
+#define myenum_def myenum
+#define myint_def 12345
+#define myfloat_def 1.5
+#define mystring_def "hello"
+*/
+import "C"
+
+import "testing"
+
+func testNaming(t *testing.T) {
+ C.myfunc()
+ C.myfunc_def()
+ if v := C.myvar; v != 5 {
+ t.Errorf("C.myvar = %d, want 5", v)
+ }
+ if v := C.myvar_def; v != 5 {
+ t.Errorf("C.myvar_def = %d, want 5", v)
+ }
+ if s := C.GoString(C.mytext); s != "abcdef" {
+ t.Errorf("C.mytext = %q, want %q", s, "abcdef")
+ }
+ if s := C.GoString(C.mytext_def); s != "abcdef" {
+ t.Errorf("C.mytext_def = %q, want %q", s, "abcdef")
+ }
+ if c := C.myenum; c != 1234 {
+ t.Errorf("C.myenum = %v, want 1234", c)
+ }
+ if c := C.myenum_def; c != 1234 {
+ t.Errorf("C.myenum_def = %v, want 1234", c)
+ }
+ {
+ const c = C.myenum
+ if c != 1234 {
+ t.Errorf("C.myenum as const = %v, want 1234", c)
+ }
+ }
+ {
+ const c = C.myenum_def
+ if c != 1234 {
+ t.Errorf("C.myenum as const = %v, want 1234", c)
+ }
+ }
+ if c := C.myint_def; c != 12345 {
+ t.Errorf("C.myint_def = %v, want 12345", c)
+ }
+ {
+ const c = C.myint_def
+ if c != 12345 {
+ t.Errorf("C.myint as const = %v, want 12345", c)
+ }
+ }
+
+ // This would be nice, but it has never worked.
+ /*
+ if c := C.myfloat_def; c != 1.5 {
+ t.Errorf("C.myint_def = %v, want 1.5", c)
+ }
+ {
+ const c = C.myfloat_def
+ if c != 1.5 {
+ t.Errorf("C.myint as const = %v, want 1.5", c)
+ }
+ }
+ */
+
+ if s := C.mystring_def; s != "hello" {
+ t.Errorf("C.mystring_def = %q, want %q", s, "hello")
+ }
+}
diff --git a/libgo/misc/cgo/test/issue6833.go b/libgo/misc/cgo/test/issue6833.go
new file mode 100644
index 00000000000..de60dbfcf20
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6833.go
@@ -0,0 +1,27 @@
+// 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.
+
+package cgotest
+
+/*
+extern unsigned long long issue6833Func(unsigned int, unsigned long long);
+*/
+import "C"
+
+import "testing"
+
+//export GoIssue6833Func
+func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
+ return aui64 + uint64(aui)
+}
+
+func test6833(t *testing.T) {
+ ui := 7
+ ull := uint64(0x4000300020001000)
+ v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull)))
+ exp := uint64(ui) + ull
+ if v != exp {
+ t.Errorf("issue6833Func() returns %x, expected %x", v, exp)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue6833_c.c b/libgo/misc/cgo/test/issue6833_c.c
new file mode 100644
index 00000000000..c94c2c6d457
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6833_c.c
@@ -0,0 +1,10 @@
+// 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.
+
+#include "_cgo_export.h"
+
+unsigned long long
+issue6833Func(unsigned int aui, unsigned long long aull) {
+ return GoIssue6833Func(aui, aull);
+}
diff --git a/libgo/misc/cgo/test/issue6997_linux.c b/libgo/misc/cgo/test/issue6997_linux.c
new file mode 100644
index 00000000000..de803d296e9
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6997_linux.c
@@ -0,0 +1,28 @@
+// Copyright 2014 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.
+
+// +build !android
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static pthread_t thread;
+
+static void* threadfunc(void* dummy) {
+ while(1) {
+ sleep(1);
+ }
+}
+
+int StartThread() {
+ return pthread_create(&thread, NULL, &threadfunc, NULL);
+}
+
+int CancelThread() {
+ void *r;
+ pthread_cancel(thread);
+ pthread_join(thread, &r);
+ return (r == PTHREAD_CANCELED);
+}
diff --git a/libgo/misc/cgo/test/issue6997_linux.go b/libgo/misc/cgo/test/issue6997_linux.go
new file mode 100644
index 00000000000..0c98ea0794e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue6997_linux.go
@@ -0,0 +1,42 @@
+// Copyright 2014 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.
+
+// +build !android
+
+// Test that pthread_cancel works as expected
+// (NPTL uses SIGRTMIN to implement thread cancelation)
+// See https://golang.org/issue/6997
+package cgotest
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+extern int StartThread();
+extern int CancelThread();
+*/
+import "C"
+
+import "testing"
+import "time"
+
+func test6997(t *testing.T) {
+ r := C.StartThread()
+ if r != 0 {
+ t.Error("pthread_create failed")
+ }
+ c := make(chan C.int)
+ go func() {
+ time.Sleep(500 * time.Millisecond)
+ c <- C.CancelThread()
+ }()
+
+ select {
+ case r = <-c:
+ if r == 0 {
+ t.Error("pthread finished but wasn't canceled??")
+ }
+ case <-time.After(30 * time.Second):
+ t.Error("hung in pthread_cancel/pthread_join")
+ }
+}
diff --git a/libgo/misc/cgo/test/issue7234_test.go b/libgo/misc/cgo/test/issue7234_test.go
new file mode 100644
index 00000000000..c191a1a66fe
--- /dev/null
+++ b/libgo/misc/cgo/test/issue7234_test.go
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+package cgotest
+
+import "testing"
+
+// This test actually doesn't have anything to do with cgo. It is a
+// test of https://golang.org/issue/7234, a compiler/linker bug in
+// handling string constants when using -linkmode=external. The test
+// is in this directory because we routinely test -linkmode=external
+// here.
+
+var v7234 = [...]string{"runtime/cgo"}
+
+func Test7234(t *testing.T) {
+ if v7234[0] != "runtime/cgo" {
+ t.Errorf("bad string constant %q", v7234[0])
+ }
+}
diff --git a/libgo/misc/cgo/test/issue7560.go b/libgo/misc/cgo/test/issue7560.go
new file mode 100644
index 00000000000..f36d8a10234
--- /dev/null
+++ b/libgo/misc/cgo/test/issue7560.go
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+package cgotest
+
+/*
+#include <stdint.h>
+
+typedef struct {
+ char x;
+ long y;
+} __attribute__((__packed__)) misaligned;
+
+int
+offset7560(void)
+{
+ return (uintptr_t)&((misaligned*)0)->y;
+}
+*/
+import "C"
+
+import (
+ "reflect"
+ "testing"
+)
+
+func test7560(t *testing.T) {
+ // some mingw don't implement __packed__ correctly.
+ if C.offset7560() != 1 {
+ t.Skip("C compiler did not pack struct")
+ }
+
+ // C.misaligned should have x but then a padding field to get to the end of the struct.
+ // There should not be a field named 'y'.
+ var v C.misaligned
+ rt := reflect.TypeOf(&v).Elem()
+ if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" {
+ t.Errorf("unexpected fields in C.misaligned:\n")
+ for i := 0; i < rt.NumField(); i++ {
+ t.Logf("%+v\n", rt.Field(i))
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue7665.go b/libgo/misc/cgo/test/issue7665.go
new file mode 100644
index 00000000000..ce0345845f9
--- /dev/null
+++ b/libgo/misc/cgo/test/issue7665.go
@@ -0,0 +1,25 @@
+// 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.
+
+package cgotest
+
+import (
+ "testing"
+ "unsafe"
+)
+
+// extern void f7665(void);
+import "C"
+
+//export f7665
+func f7665() {}
+
+var bad7665 unsafe.Pointer = C.f7665
+var good7665 uintptr = uintptr(C.f7665)
+
+func test7665(t *testing.T) {
+ if bad7665 == nil || uintptr(bad7665) != good7665 {
+ t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue7786.go b/libgo/misc/cgo/test/issue7786.go
new file mode 100644
index 00000000000..1344e9eda62
--- /dev/null
+++ b/libgo/misc/cgo/test/issue7786.go
@@ -0,0 +1,51 @@
+// 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.
+
+// Issue 7786. No runtime test, just make sure that typedef and struct/union/class are interchangeable at compile time.
+
+package cgotest
+
+// struct test7786;
+// typedef struct test7786 typedef_test7786;
+// void f7786(struct test7786 *ctx) {}
+// void g7786(typedef_test7786 *ctx) {}
+//
+// typedef struct body7786 typedef_body7786;
+// struct body7786 { int x; };
+// void b7786(struct body7786 *ctx) {}
+// void c7786(typedef_body7786 *ctx) {}
+//
+// typedef union union7786 typedef_union7786;
+// void u7786(union union7786 *ctx) {}
+// void v7786(typedef_union7786 *ctx) {}
+import "C"
+
+func f() {
+ var x1 *C.typedef_test7786
+ var x2 *C.struct_test7786
+ x1 = x2
+ x2 = x1
+ C.f7786(x1)
+ C.f7786(x2)
+ C.g7786(x1)
+ C.g7786(x2)
+
+ var b1 *C.typedef_body7786
+ var b2 *C.struct_body7786
+ b1 = b2
+ b2 = b1
+ C.b7786(b1)
+ C.b7786(b2)
+ C.c7786(b1)
+ C.c7786(b2)
+
+ var u1 *C.typedef_union7786
+ var u2 *C.union_union7786
+ u1 = u2
+ u2 = u1
+ C.u7786(u1)
+ C.u7786(u2)
+ C.v7786(u1)
+ C.v7786(u2)
+}
diff --git a/libgo/misc/cgo/test/issue7978.go b/libgo/misc/cgo/test/issue7978.go
new file mode 100644
index 00000000000..7fb62e807ba
--- /dev/null
+++ b/libgo/misc/cgo/test/issue7978.go
@@ -0,0 +1,138 @@
+// Copyright 2014 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.
+
+// Issue 7978. Stack tracing didn't work during cgo code after calling a Go
+// callback. Make sure GC works and the stack trace is correct.
+
+package cgotest
+
+/*
+#include <stdint.h>
+
+void issue7978cb(void);
+
+#if defined(__APPLE__) && defined(__arm__)
+// on Darwin/ARM, libSystem doesn't provide implementation of the __sync_fetch_and_add
+// primitive, and although gcc supports it, it doesn't inline its definition.
+// Clang could inline its definition, so we require clang on Darwin/ARM.
+#if defined(__clang__)
+#define HAS_SYNC_FETCH_AND_ADD 1
+#else
+#define HAS_SYNC_FETCH_AND_ADD 0
+#endif
+#else
+#define HAS_SYNC_FETCH_AND_ADD 1
+#endif
+
+// use ugly atomic variable sync since that doesn't require calling back into
+// Go code or OS dependencies
+static void issue7978c(uint32_t *sync) {
+#if HAS_SYNC_FETCH_AND_ADD
+ while(__sync_fetch_and_add(sync, 0) != 0)
+ ;
+ __sync_fetch_and_add(sync, 1);
+ while(__sync_fetch_and_add(sync, 0) != 2)
+ ;
+ issue7978cb();
+ __sync_fetch_and_add(sync, 1);
+ while(__sync_fetch_and_add(sync, 0) != 6)
+ ;
+#endif
+}
+*/
+import "C"
+
+import (
+ "os"
+ "runtime"
+ "strings"
+ "sync/atomic"
+ "testing"
+)
+
+var issue7978sync uint32
+
+func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
+ runtime.GC()
+ buf := make([]byte, 65536)
+ trace := string(buf[:runtime.Stack(buf, true)])
+ for _, goroutine := range strings.Split(trace, "\n\n") {
+ if strings.Contains(goroutine, "test.issue7978go") {
+ trace := strings.Split(goroutine, "\n")
+ // look for the expected function in the stack
+ for i := 0; i < depth; i++ {
+ if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
+ t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
+ return
+ }
+ if strings.Contains(trace[1+2*i], wantFunc) {
+ return
+ }
+ }
+ t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
+ return
+ }
+ }
+ t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
+}
+
+func issue7978wait(store uint32, wait uint32) {
+ if store != 0 {
+ atomic.StoreUint32(&issue7978sync, store)
+ }
+ for atomic.LoadUint32(&issue7978sync) != wait {
+ runtime.Gosched()
+ }
+}
+
+//export issue7978cb
+func issue7978cb() {
+ // Force a stack growth from the callback to put extra
+ // pressure on the runtime. See issue #17785.
+ growStack(64)
+ issue7978wait(3, 4)
+}
+
+func growStack(n int) int {
+ var buf [128]int
+ if n == 0 {
+ return 0
+ }
+ return buf[growStack(n-1)]
+}
+
+func issue7978go() {
+ C.issue7978c((*C.uint32_t)(&issue7978sync))
+ issue7978wait(7, 8)
+}
+
+func test7978(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("gccgo can not do stack traces of C code")
+ }
+ if C.HAS_SYNC_FETCH_AND_ADD == 0 {
+ t.Skip("clang required for __sync_fetch_and_add support on darwin/arm")
+ }
+ if runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skip("GOTRACEBACK is not passed on to the exec wrapper")
+ }
+ if os.Getenv("GOTRACEBACK") != "2" {
+ t.Fatalf("GOTRACEBACK must be 2")
+ }
+ issue7978sync = 0
+ go issue7978go()
+ // test in c code, before callback
+ issue7978wait(0, 1)
+ issue7978check(t, "_Cfunc_issue7978c(", "", 1)
+ // test in go code, during callback
+ issue7978wait(2, 3)
+ issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
+ // test in c code, after callback
+ issue7978wait(4, 5)
+ issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
+ // test in go code, after return from cgo
+ issue7978wait(6, 7)
+ issue7978check(t, "test.issue7978go(", "", 3)
+ atomic.StoreUint32(&issue7978sync, 8)
+}
diff --git a/libgo/misc/cgo/test/issue8092.go b/libgo/misc/cgo/test/issue8092.go
new file mode 100644
index 00000000000..19123e79cfa
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8092.go
@@ -0,0 +1,36 @@
+// Copyright 2014 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.
+
+// Issue 8092. Test that linker defined symbols (e.g., text, data) don't
+// conflict with C symbols.
+
+package cgotest
+
+/*
+char text[] = "text";
+char data[] = "data";
+char *ctext(void) { return text; }
+char *cdata(void) { return data; }
+*/
+import "C"
+
+import "testing"
+
+func test8092(t *testing.T) {
+ tests := []struct {
+ s string
+ a, b *C.char
+ }{
+ {"text", &C.text[0], C.ctext()},
+ {"data", &C.data[0], C.cdata()},
+ }
+ for _, test := range tests {
+ if test.a != test.b {
+ t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b)
+ }
+ if got := C.GoString(test.a); got != test.s {
+ t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s)
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue8148.go b/libgo/misc/cgo/test/issue8148.go
new file mode 100644
index 00000000000..f704788aef8
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8148.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+// Issue 8148. A typedef of an unnamed struct didn't work when used
+// with an exported Go function. No runtime test; just make sure it
+// compiles.
+
+package cgotest
+
+/*
+typedef struct { int i; } T;
+
+int issue8148Callback(T*);
+
+static int get() {
+ T t;
+ t.i = 42;
+ return issue8148Callback(&t);
+}
+*/
+import "C"
+
+//export issue8148Callback
+func issue8148Callback(t *C.T) C.int {
+ return t.i
+}
+
+func Issue8148() int {
+ return int(C.get())
+}
diff --git a/libgo/misc/cgo/test/issue8331.h b/libgo/misc/cgo/test/issue8331.h
new file mode 100644
index 00000000000..8065be08904
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8331.h
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+typedef struct {
+ int i;
+} issue8331;
diff --git a/libgo/misc/cgo/test/issue8331a.go b/libgo/misc/cgo/test/issue8331a.go
new file mode 100644
index 00000000000..92e2579e7ae
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8331a.go
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+// Issue 8331. A typedef of an unnamed struct is the same struct when
+// #include'd twice. No runtime test; just make sure it compiles.
+
+package cgotest
+
+// #include "issue8331.h"
+import "C"
+
+func issue8331a() C.issue8331 {
+ return issue8331Var
+}
diff --git a/libgo/misc/cgo/test/issue8331b.go b/libgo/misc/cgo/test/issue8331b.go
new file mode 100644
index 00000000000..5324aa2a175
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8331b.go
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+
+// Issue 8331. A typedef of an unnamed struct is the same struct when
+// #include'd twice. No runtime test; just make sure it compiles.
+
+package cgotest
+
+// #include "issue8331.h"
+import "C"
+
+var issue8331Var C.issue8331
diff --git a/libgo/misc/cgo/test/issue8428.go b/libgo/misc/cgo/test/issue8428.go
new file mode 100644
index 00000000000..2e5a555b582
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8428.go
@@ -0,0 +1,55 @@
+// Copyright 2014 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.
+
+// This test fails on older versions of OS X because they use older buggy
+// versions of Clang that emit ambiguous DWARF info. See issue 8611.
+// +build !darwin
+
+package cgotest
+
+// Issue 8428. Cgo inconsistently translated zero size arrays.
+
+/*
+struct issue8428one {
+ char b;
+ char rest[];
+};
+
+struct issue8428two {
+ void *p;
+ char b;
+ char rest[0];
+ char pad;
+};
+
+struct issue8428three {
+ char w[1][2][3][0];
+ char x[2][3][0][1];
+ char y[3][0][1][2];
+ char z[0][1][2][3];
+};
+*/
+import "C"
+
+import "unsafe"
+
+var _ = C.struct_issue8428one{
+ b: C.char(0),
+ // The trailing rest field is not available in cgo.
+ // See issue 11925.
+ // rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428two{
+ p: unsafe.Pointer(nil),
+ b: C.char(0),
+ rest: [0]C.char{},
+}
+
+var _ = C.struct_issue8428three{
+ w: [1][2][3][0]C.char{},
+ x: [2][3][0][1]C.char{},
+ y: [3][0][1][2]C.char{},
+ z: [0][1][2][3]C.char{},
+}
diff --git a/libgo/misc/cgo/test/issue8441.go b/libgo/misc/cgo/test/issue8441.go
new file mode 100644
index 00000000000..4489ca9eb67
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8441.go
@@ -0,0 +1,27 @@
+// Copyright 2014 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.
+
+// Issue 8368 and 8441. Recursive struct definitions didn't work.
+// No runtime test; just make sure it compiles.
+
+package cgotest
+
+/*
+typedef struct one one;
+typedef struct two two;
+struct one {
+ two *x;
+};
+struct two {
+ one *x;
+};
+*/
+import "C"
+
+func issue8368(one *C.struct_one, two *C.struct_two) {
+}
+
+func issue8441(one *C.one, two *C.two) {
+ issue8441(two.x, one.x)
+}
diff --git a/libgo/misc/cgo/test/issue8517.go b/libgo/misc/cgo/test/issue8517.go
new file mode 100644
index 00000000000..4e431df921d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8517.go
@@ -0,0 +1,13 @@
+// Copyright 2014 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.
+
+// +build !windows
+
+package cgotest
+
+import "testing"
+
+func test8517(t *testing.T) {
+ t.Skip("skipping windows only test")
+}
diff --git a/libgo/misc/cgo/test/issue8517_windows.c b/libgo/misc/cgo/test/issue8517_windows.c
new file mode 100644
index 00000000000..a0b94c126f6
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8517_windows.c
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+#include "windows.h"
+
+extern void testHandleLeaksCallback();
+
+DWORD WINAPI testHandleLeaksFunc(LPVOID lpThreadParameter)
+{
+ int i;
+ for(i = 0; i < 100; i++) {
+ testHandleLeaksCallback();
+ }
+ return 0;
+}
+
+void testHandleLeaks()
+{
+ HANDLE h;
+ h = CreateThread(NULL, 0, &testHandleLeaksFunc, 0, 0, NULL);
+ WaitForSingleObject(h, INFINITE);
+ CloseHandle(h);
+}
diff --git a/libgo/misc/cgo/test/issue8517_windows.go b/libgo/misc/cgo/test/issue8517_windows.go
new file mode 100644
index 00000000000..3782631e91b
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8517_windows.go
@@ -0,0 +1,45 @@
+// Copyright 2014 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.
+
+package cgotest
+
+//void testHandleLeaks();
+import "C"
+
+import (
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+var issue8517counter int
+
+var (
+ kernel32 = syscall.MustLoadDLL("kernel32.dll")
+ getProcessHandleCount = kernel32.MustFindProc("GetProcessHandleCount")
+)
+
+func processHandleCount(t *testing.T) int {
+ const current_process = ^uintptr(0)
+ var c uint32
+ r, _, err := getProcessHandleCount.Call(current_process, uintptr(unsafe.Pointer(&c)))
+ if r == 0 {
+ t.Fatal(err)
+ }
+ return int(c)
+}
+
+func test8517(t *testing.T) {
+ c1 := processHandleCount(t)
+ C.testHandleLeaks()
+ c2 := processHandleCount(t)
+ if c1+issue8517counter <= c2 {
+ t.Fatalf("too many handles leaked: issue8517counter=%v c1=%v c2=%v", issue8517counter, c1, c2)
+ }
+}
+
+//export testHandleLeaksCallback
+func testHandleLeaksCallback() {
+ issue8517counter++
+}
diff --git a/libgo/misc/cgo/test/issue8694.go b/libgo/misc/cgo/test/issue8694.go
new file mode 100644
index 00000000000..89be7ea0907
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8694.go
@@ -0,0 +1,40 @@
+// Copyright 2014 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.
+
+// +build !android
+
+package cgotest
+
+/*
+#include <complex.h>
+
+complex float complexFloatSquared(complex float a) { return a*a; }
+complex double complexDoubleSquared(complex double a) { return a*a; }
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func test8694(t *testing.T) {
+ if runtime.GOARCH == "arm" {
+ t.Skip("test8694 is disabled on ARM because 5l cannot handle thumb library.")
+ }
+ // Really just testing that this compiles, but check answer anyway.
+ x := C.complexfloat(2 + 3i)
+ x2 := x * x
+ cx2 := C.complexFloatSquared(x)
+ if cx2 != x2 {
+ t.Errorf("C.complexFloatSquared(%v) = %v, want %v", x, cx2, x2)
+ }
+
+ y := C.complexdouble(2 + 3i)
+ y2 := y * y
+ cy2 := C.complexDoubleSquared(y)
+ if cy2 != y2 {
+ t.Errorf("C.complexDoubleSquared(%v) = %v, want %v", y, cy2, y2)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue8756.go b/libgo/misc/cgo/test/issue8756.go
new file mode 100644
index 00000000000..d8ee3b8213d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8756.go
@@ -0,0 +1,17 @@
+package cgotest
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+import (
+ "testing"
+
+ "./issue8756"
+)
+
+func test8756(t *testing.T) {
+ issue8756.Pow()
+ C.pow(1, 2)
+}
diff --git a/libgo/misc/cgo/test/issue8756/issue8756.go b/libgo/misc/cgo/test/issue8756/issue8756.go
new file mode 100644
index 00000000000..5f6b7778ff6
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8756/issue8756.go
@@ -0,0 +1,11 @@
+package issue8756
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+
+func Pow() {
+ C.pow(1, 2)
+}
diff --git a/libgo/misc/cgo/test/issue8811.c b/libgo/misc/cgo/test/issue8811.c
new file mode 100644
index 00000000000..41b3c7c8ea3
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8811.c
@@ -0,0 +1,8 @@
+// Copyright 2014 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.
+
+int issue8811Initialized = 0;
+
+void issue8811Init() {
+}
diff --git a/libgo/misc/cgo/test/issue8811.go b/libgo/misc/cgo/test/issue8811.go
new file mode 100644
index 00000000000..f812732cfd7
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8811.go
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+package cgotest
+
+/*
+extern int issue8811Initialized;
+extern void issue8811Init();
+
+void issue8811Execute() {
+ if(!issue8811Initialized)
+ issue8811Init();
+}
+*/
+import "C"
+
+import "testing"
+
+func test8811(t *testing.T) {
+ C.issue8811Execute()
+}
diff --git a/libgo/misc/cgo/test/issue8828.go b/libgo/misc/cgo/test/issue8828.go
new file mode 100644
index 00000000000..304797c929c
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8828.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2014 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.
+
+// Issue 8828: compiling a file with -compiler=gccgo fails if a .c file
+// has the same name as compiled directory.
+
+package cgotest
+
+import "./issue8828"
+
+func p() {
+ issue8828.Bar()
+}
diff --git a/libgo/misc/cgo/test/issue8828/issue8828.c b/libgo/misc/cgo/test/issue8828/issue8828.c
new file mode 100644
index 00000000000..27ec23a2605
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8828/issue8828.c
@@ -0,0 +1,7 @@
+// Copyright 2014 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.
+
+void foo()
+{
+}
diff --git a/libgo/misc/cgo/test/issue8828/trivial.go b/libgo/misc/cgo/test/issue8828/trivial.go
new file mode 100644
index 00000000000..e7b9a4e573d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8828/trivial.go
@@ -0,0 +1,8 @@
+package issue8828
+
+//void foo();
+import "C"
+
+func Bar() {
+ C.foo()
+}
diff --git a/libgo/misc/cgo/test/issue8945.go b/libgo/misc/cgo/test/issue8945.go
new file mode 100644
index 00000000000..57a5b2db44b
--- /dev/null
+++ b/libgo/misc/cgo/test/issue8945.go
@@ -0,0 +1,16 @@
+// Copyright 2014 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.
+
+// +build gccgo
+
+package cgotest
+
+//typedef void (*PFunc)();
+//PFunc success_cb;
+import "C"
+
+//export Test
+func Test() {
+ _ = C.success_cb
+}
diff --git a/libgo/misc/cgo/test/issue9026.go b/libgo/misc/cgo/test/issue9026.go
new file mode 100644
index 00000000000..8848d0e8118
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9026.go
@@ -0,0 +1,9 @@
+package cgotest
+
+import (
+ "testing"
+
+ "./issue9026"
+)
+
+func test9026(t *testing.T) { issue9026.Test(t) }
diff --git a/libgo/misc/cgo/test/issue9026/issue9026.go b/libgo/misc/cgo/test/issue9026/issue9026.go
new file mode 100644
index 00000000000..0af86e64da4
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9026/issue9026.go
@@ -0,0 +1,36 @@
+package issue9026
+
+// This file appears in its own package since the assertion tests the
+// per-package counter used to create fresh identifiers.
+
+/*
+typedef struct {} git_merge_file_input;
+
+typedef struct {} git_merge_file_options;
+
+void git_merge_file(
+ git_merge_file_input *in,
+ git_merge_file_options *opts) {}
+*/
+import "C"
+import (
+ "fmt"
+ "testing"
+)
+
+func Test(t *testing.T) {
+ var in C.git_merge_file_input
+ var opts *C.git_merge_file_options
+ C.git_merge_file(&in, opts)
+
+ // Test that the generated type names are deterministic.
+ // (Previously this would fail about 10% of the time.)
+ //
+ // Brittle: the assertion may fail spuriously when the algorithm
+ // changes, but should remain stable otherwise.
+ got := fmt.Sprintf("%T %T", in, opts)
+ want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1"
+ if got != want {
+ t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
+ }
+}
diff --git a/libgo/misc/cgo/test/issue9400/asm_386.s b/libgo/misc/cgo/test/issue9400/asm_386.s
new file mode 100644
index 00000000000..7f158b5c39d
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_386.s
@@ -0,0 +1,27 @@
+// Copyright 2014 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.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$0-0
+ MOVL $·Baton(SB), BX
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADDL $(1024 * 8), SP
+
+ // Ask signaller to setgid
+ MOVL $1, (BX)
+
+ // Wait for setgid completion
+loop:
+ PAUSE
+ MOVL (BX), AX
+ CMPL AX, $0
+ JNE loop
+
+ // Restore stack
+ SUBL $(1024 * 8), SP
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_amd64x.s b/libgo/misc/cgo/test/issue9400/asm_amd64x.s
new file mode 100644
index 00000000000..48b86190a59
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_amd64x.s
@@ -0,0 +1,27 @@
+// Copyright 2014 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.
+
+// +build amd64 amd64p32
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$0-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADDQ $(1024 * 8), SP
+
+ // Ask signaller to setgid
+ MOVL $1, ·Baton(SB)
+
+ // Wait for setgid completion
+loop:
+ PAUSE
+ MOVL ·Baton(SB), AX
+ CMPL AX, $0
+ JNE loop
+
+ // Restore stack
+ SUBQ $(1024 * 8), SP
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_arm.s b/libgo/misc/cgo/test/issue9400/asm_arm.s
new file mode 100644
index 00000000000..166d53f304e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_arm.s
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT cas<>(SB),NOSPLIT,$0
+ MOVW $0xffff0fc0, R15 // R15 is PC
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$-4-0
+ // Save link register
+ MOVW R14, R4
+
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADD $(1024 * 8), R13
+
+ // Ask signaller to setgid
+ MOVW $·Baton(SB), R2
+storeloop:
+ MOVW 0(R2), R0
+ MOVW $1, R1
+ BL cas<>(SB)
+ BCC storeloop
+
+ // Wait for setgid completion
+loop:
+ MOVW $0, R0
+ MOVW $0, R1
+ BL cas<>(SB)
+ BCC loop
+
+ // Restore stack
+ SUB $(1024 * 8), R13
+
+ MOVW R4, R14
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_arm64.s b/libgo/misc/cgo/test/issue9400/asm_arm64.s
new file mode 100644
index 00000000000..9bb50816b44
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_arm64.s
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$-8-0
+ // Save link register
+ MOVD R30, R9
+
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADD $(1024 * 8), RSP
+
+ // Ask signaller to setgid
+ MOVD $·Baton(SB), R0
+ MOVD $1, R1
+storeloop:
+ LDAXRW (R0), R2
+ STLXRW R1, (R0), R3
+ CBNZ R3, storeloop
+
+ // Wait for setgid completion
+ MOVW $0, R1
+ MOVW $0, R2
+loop:
+ LDAXRW (R0), R3
+ CMPW R1, R3
+ BNE loop
+ STLXRW R2, (R0), R3
+ CBNZ R3, loop
+
+ // Restore stack
+ SUB $(1024 * 8), RSP
+
+ MOVD R9, R30
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_mips64x.s b/libgo/misc/cgo/test/issue9400/asm_mips64x.s
new file mode 100644
index 00000000000..63dc90605e6
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_mips64x.s
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// +build mips64 mips64le
+// +build !gccgo
+
+#include "textflag.h"
+
+#define SYNC WORD $0xf
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADDV $(1024*8), R29
+
+ // Ask signaller to setgid
+ MOVW $1, R1
+ SYNC
+ MOVW R1, ·Baton(SB)
+ SYNC
+
+ // Wait for setgid completion
+loop:
+ SYNC
+ MOVW ·Baton(SB), R1
+ OR R2, R2, R2 // hint that we're in a spin loop
+ BNE R1, loop
+ SYNC
+
+ // Restore stack
+ ADDV $(-1024*8), R29
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_mipsx.s b/libgo/misc/cgo/test/issue9400/asm_mipsx.s
new file mode 100644
index 00000000000..ddf33e9f8e5
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_mipsx.s
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+// +build mips mipsle
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$-4-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADDU $(1024*8), R29
+
+ // Ask signaller to setgid
+ MOVW $1, R1
+ SYNC
+ MOVW R1, ·Baton(SB)
+ SYNC
+
+ // Wait for setgid completion
+loop:
+ SYNC
+ MOVW ·Baton(SB), R1
+ OR R2, R2, R2 // hint that we're in a spin loop
+ BNE R1, loop
+ SYNC
+
+ // Restore stack
+ ADDU $(-1024*8), R29
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_ppc64x.s b/libgo/misc/cgo/test/issue9400/asm_ppc64x.s
new file mode 100644
index 00000000000..c88ec3b21e7
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_ppc64x.s
@@ -0,0 +1,32 @@
+// Copyright 2014 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.
+
+// +build ppc64 ppc64le
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADD $(1024 * 8), R1
+
+ // Ask signaller to setgid
+ MOVW $1, R3
+ SYNC
+ MOVW R3, ·Baton(SB)
+
+ // Wait for setgid completion
+loop:
+ SYNC
+ MOVW ·Baton(SB), R3
+ CMP R3, $0
+ // Hint that we're in a spin loop
+ OR R1, R1, R1
+ BNE loop
+ ISYNC
+
+ // Restore stack
+ SUB $(1024 * 8), R1
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/asm_s390x.s b/libgo/misc/cgo/test/issue9400/asm_s390x.s
new file mode 100644
index 00000000000..fc9ad724c15
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/asm_s390x.s
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+TEXT ·RewindAndSetgid(SB),NOSPLIT,$0-0
+ // Rewind stack pointer so anything that happens on the stack
+ // will clobber the test pattern created by the caller
+ ADD $(1024 * 8), R15
+
+ // Ask signaller to setgid
+ MOVD $·Baton(SB), R5
+ MOVW $1, 0(R5)
+
+ // Wait for setgid completion
+loop:
+ SYNC
+ MOVW ·Baton(SB), R3
+ CMPBNE R3, $0, loop
+
+ // Restore stack
+ SUB $(1024 * 8), R15
+ RET
diff --git a/libgo/misc/cgo/test/issue9400/gccgo.go b/libgo/misc/cgo/test/issue9400/gccgo.go
new file mode 100644
index 00000000000..0ef3a8cacf3
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/gccgo.go
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+// +build gccgo
+
+package issue9400
+
+import (
+ "runtime"
+ "sync/atomic"
+)
+
+// The test for the gc compiler resets the stack pointer so that the
+// stack gets modified. We don't have a way to do that for gccgo
+// without writing more assembly code, which we haven't bothered to
+// do. So this is not much of a test.
+
+func RewindAndSetgid() {
+ atomic.StoreInt32(&Baton, 1)
+ for atomic.LoadInt32(&Baton) != 0 {
+ runtime.Gosched()
+ }
+}
diff --git a/libgo/misc/cgo/test/issue9400/stubs.go b/libgo/misc/cgo/test/issue9400/stubs.go
new file mode 100644
index 00000000000..60193dc4117
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400/stubs.go
@@ -0,0 +1,9 @@
+// Copyright 2014 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.
+
+package issue9400
+
+var Baton int32
+
+func RewindAndSetgid()
diff --git a/libgo/misc/cgo/test/issue9400_linux.go b/libgo/misc/cgo/test/issue9400_linux.go
new file mode 100644
index 00000000000..34eb4983a41
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9400_linux.go
@@ -0,0 +1,58 @@
+// Copyright 2014 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.
+
+// Test that SIGSETXID runs on signal stack, since it's likely to
+// overflow if it runs on the Go stack.
+
+package cgotest
+
+/*
+#include <sys/types.h>
+#include <unistd.h>
+*/
+import "C"
+
+import (
+ "runtime"
+ "sync/atomic"
+ "testing"
+
+ "./issue9400"
+)
+
+func test9400(t *testing.T) {
+ // We synchronize through a shared variable, so we need two procs
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+
+ // Start signaller
+ atomic.StoreInt32(&issue9400.Baton, 0)
+ go func() {
+ // Wait for RewindAndSetgid
+ for atomic.LoadInt32(&issue9400.Baton) == 0 {
+ runtime.Gosched()
+ }
+ // Broadcast SIGSETXID
+ runtime.LockOSThread()
+ C.setgid(0)
+ // Indicate that signalling is done
+ atomic.StoreInt32(&issue9400.Baton, 0)
+ }()
+
+ // Grow the stack and put down a test pattern
+ const pattern = 0x123456789abcdef
+ var big [1024]uint64 // len must match assmebly
+ for i := range big {
+ big[i] = pattern
+ }
+
+ // Temporarily rewind the stack and trigger SIGSETXID
+ issue9400.RewindAndSetgid()
+
+ // Check test pattern
+ for i := range big {
+ if big[i] != pattern {
+ t.Fatalf("entry %d of test pattern is wrong; %#x != %#x", i, big[i], uint64(pattern))
+ }
+ }
+}
diff --git a/libgo/misc/cgo/test/issue9510.go b/libgo/misc/cgo/test/issue9510.go
new file mode 100644
index 00000000000..efd3f770b6a
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9510.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// Test that we can link together two different cgo packages that both
+// use the same libgcc function.
+
+package cgotest
+
+import (
+ "runtime"
+ "testing"
+
+ "./issue9510a"
+ "./issue9510b"
+)
+
+func test9510(t *testing.T) {
+ if runtime.GOARCH == "arm" {
+ t.Skip("skipping because libgcc may be a Thumb library")
+ }
+ issue9510a.F(1, 1)
+ issue9510b.F(1, 1)
+}
diff --git a/libgo/misc/cgo/test/issue9510a/a.go b/libgo/misc/cgo/test/issue9510a/a.go
new file mode 100644
index 00000000000..1a5224b8c68
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9510a/a.go
@@ -0,0 +1,15 @@
+package issue9510a
+
+/*
+static double csquare(double a, double b) {
+ __complex__ double d;
+ __real__ d = a;
+ __imag__ d = b;
+ return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+ return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/libgo/misc/cgo/test/issue9510b/b.go b/libgo/misc/cgo/test/issue9510b/b.go
new file mode 100644
index 00000000000..5016b39597e
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9510b/b.go
@@ -0,0 +1,15 @@
+package issue9510b
+
+/*
+static double csquare(double a, double b) {
+ __complex__ double d;
+ __real__ d = a;
+ __imag__ d = b;
+ return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+ return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/libgo/misc/cgo/test/issue9557.go b/libgo/misc/cgo/test/issue9557.go
new file mode 100644
index 00000000000..4e8922a69c6
--- /dev/null
+++ b/libgo/misc/cgo/test/issue9557.go
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// cgo rewrote C.var to *_Cvar_var, but left
+// C.var.field as _Cvar.var.field. It now rewrites
+// the latter as (*_Cvar_var).field.
+// See https://golang.org/issue/9557.
+
+package cgotest
+
+// struct issue9557_t {
+// int a;
+// } test9557bar = { 42 };
+//
+// struct issue9557_t *issue9557foo = &test9557bar;
+import "C"
+import "testing"
+
+func test9557(t *testing.T) {
+ // implicitly dereference a Go variable
+ foo := C.issue9557foo
+ if v := foo.a; v != 42 {
+ t.Fatalf("foo.a expected 42, but got %d", v)
+ }
+
+ // explicitly dereference a C variable
+ if v := (*C.issue9557foo).a; v != 42 {
+ t.Fatalf("(*C.issue9557foo).a expected 42, but is %d", v)
+ }
+
+ // implicitly dereference a C variable
+ if v := C.issue9557foo.a; v != 42 {
+ t.Fatalf("C.issue9557foo.a expected 42, but is %d", v)
+ }
+}
diff --git a/libgo/misc/cgo/test/setgid_linux.go b/libgo/misc/cgo/test/setgid_linux.go
new file mode 100644
index 00000000000..6773f94d3d6
--- /dev/null
+++ b/libgo/misc/cgo/test/setgid_linux.go
@@ -0,0 +1,49 @@
+// Copyright 2012 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.
+
+// Test that setgid does not hang on GNU/Linux.
+// See https://golang.org/issue/3871 for details.
+
+package cgotest
+
+/*
+#include <sys/types.h>
+#include <unistd.h>
+*/
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func runTestSetgid() bool {
+ c := make(chan bool)
+ go func() {
+ C.setgid(0)
+ c <- true
+ }()
+ select {
+ case <-c:
+ return true
+ case <-time.After(5 * time.Second):
+ return false
+ }
+
+}
+
+func testSetgid(t *testing.T) {
+ if !runTestSetgid() {
+ t.Error("setgid hung")
+ }
+
+ // Now try it again after using signal.Notify.
+ signal.Notify(make(chan os.Signal, 1), syscall.SIGINT)
+ if !runTestSetgid() {
+ t.Error("setgid hung after signal.Notify")
+ }
+}
diff --git a/libgo/misc/cgo/test/sigaltstack.go b/libgo/misc/cgo/test/sigaltstack.go
new file mode 100644
index 00000000000..2b7a1ec9ad0
--- /dev/null
+++ b/libgo/misc/cgo/test/sigaltstack.go
@@ -0,0 +1,73 @@
+// Copyright 2015 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.
+
+// +build !windows,!android
+
+// Test that the Go runtime still works if C code changes the signal stack.
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static stack_t oss;
+static char signalStack[SIGSTKSZ];
+
+static void changeSignalStack(void) {
+ stack_t ss;
+ memset(&ss, 0, sizeof ss);
+ ss.ss_sp = signalStack;
+ ss.ss_flags = 0;
+ ss.ss_size = SIGSTKSZ;
+ if (sigaltstack(&ss, &oss) < 0) {
+ perror("sigaltstack");
+ abort();
+ }
+}
+
+static void restoreSignalStack(void) {
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
+ // The Darwin C library enforces a minimum that the kernel does not.
+ // This is OK since we allocated this much space in mpreinit,
+ // it was just removed from the buffer by stackalloc.
+ oss.ss_size = MINSIGSTKSZ;
+#endif
+ if (sigaltstack(&oss, NULL) < 0) {
+ perror("sigaltstack restore");
+ abort();
+ }
+}
+
+static int zero(void) {
+ return 0;
+}
+*/
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func testSigaltstack(t *testing.T) {
+ switch {
+ case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
+ t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+ case runtime.GOOS == "darwin" && runtime.GOARCH == "386":
+ t.Skipf("sigaltstack fails on darwin/386")
+ }
+
+ C.changeSignalStack()
+ defer C.restoreSignalStack()
+ defer func() {
+ if recover() == nil {
+ t.Error("did not see expected panic")
+ }
+ }()
+ v := 1 / int(C.zero())
+ t.Errorf("unexpected success of division by zero == %d", v)
+}
diff --git a/libgo/misc/cgo/test/sigprocmask.c b/libgo/misc/cgo/test/sigprocmask.c
new file mode 100644
index 00000000000..bd99647d2b3
--- /dev/null
+++ b/libgo/misc/cgo/test/sigprocmask.c
@@ -0,0 +1,38 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern void IntoGoAndBack();
+
+int CheckBlocked() {
+ sigset_t mask;
+ sigprocmask(SIG_BLOCK, NULL, &mask);
+ return sigismember(&mask, SIGIO);
+}
+
+static void* sigthreadfunc(void* unused) {
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGIO);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+ IntoGoAndBack();
+ return NULL;
+}
+
+int RunSigThread() {
+ pthread_t thread;
+ int r;
+
+ r = pthread_create(&thread, NULL, &sigthreadfunc, NULL);
+ if (r != 0)
+ return r;
+ return pthread_join(thread, NULL);
+}
diff --git a/libgo/misc/cgo/test/sigprocmask.go b/libgo/misc/cgo/test/sigprocmask.go
new file mode 100644
index 00000000000..39b658e96c3
--- /dev/null
+++ b/libgo/misc/cgo/test/sigprocmask.go
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+package cgotest
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+extern int RunSigThread();
+extern int CheckBlocked();
+*/
+import "C"
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "testing"
+)
+
+var blocked bool
+
+//export IntoGoAndBack
+func IntoGoAndBack() {
+ // Verify that SIGIO stays blocked on the C thread
+ // even when unblocked for signal.Notify().
+ signal.Notify(make(chan os.Signal), syscall.SIGIO)
+ blocked = C.CheckBlocked() != 0
+}
+
+func testSigprocmask(t *testing.T) {
+ if r := C.RunSigThread(); r != 0 {
+ t.Error("pthread_create/pthread_join failed")
+ }
+ if !blocked {
+ t.Error("Go runtime unblocked SIGIO")
+ }
+}
diff --git a/libgo/misc/cgo/testasan/main.go b/libgo/misc/cgo/testasan/main.go
new file mode 100644
index 00000000000..1837c6cc81d
--- /dev/null
+++ b/libgo/misc/cgo/testasan/main.go
@@ -0,0 +1,49 @@
+// 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.
+
+package main
+
+/*
+#include <sys/mman.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void ctor(void) __attribute__((constructor));
+static void* thread(void*);
+
+void
+ctor(void)
+{
+ // occupy memory where Go runtime would normally map heap
+ mmap((void*)0x00c000000000, 64<<10, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+
+ // allocate 4K every 10us
+ pthread_t t;
+ pthread_create(&t, 0, thread, 0);
+}
+
+static void*
+thread(void *p)
+{
+ for(;;) {
+ usleep(10000);
+ mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ }
+ return 0;
+}
+*/
+import "C"
+
+import (
+ "time"
+)
+
+func main() {
+ // ensure that we can function normally
+ var v [][]byte
+ for i := 0; i < 1000; i++ {
+ time.Sleep(10 * time.Microsecond)
+ v = append(v, make([]byte, 64<<10))
+ }
+}
diff --git a/libgo/misc/cgo/testcarchive/carchive_test.go b/libgo/misc/cgo/testcarchive/carchive_test.go
new file mode 100644
index 00000000000..a2ad9c56418
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/carchive_test.go
@@ -0,0 +1,587 @@
+// Copyright 2016 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.
+
+package carchive_test
+
+import (
+ "bufio"
+ "debug/elf"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "syscall"
+ "testing"
+ "time"
+ "unicode"
+)
+
+// Program to run.
+var bin []string
+
+// C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)).
+var cc []string
+
+// An environment with GOPATH=$(pwd).
+var gopathEnv []string
+
+// ".exe" on Windows.
+var exeSuffix string
+
+var GOOS, GOARCH string
+var libgodir string
+
+func init() {
+ GOOS = goEnv("GOOS")
+ GOARCH = goEnv("GOARCH")
+ bin = cmdToRun("./testp")
+
+ ccOut := goEnv("CC")
+ cc = []string{string(ccOut)}
+
+ out := goEnv("GOGCCFLAGS")
+ quote := '\000'
+ start := 0
+ lastSpace := true
+ backslash := false
+ s := string(out)
+ for i, c := range s {
+ if quote == '\000' && unicode.IsSpace(c) {
+ if !lastSpace {
+ cc = append(cc, s[start:i])
+ lastSpace = true
+ }
+ } else {
+ if lastSpace {
+ start = i
+ lastSpace = false
+ }
+ if quote == '\000' && !backslash && (c == '"' || c == '\'') {
+ quote = c
+ backslash = false
+ } else if !backslash && quote == c {
+ quote = '\000'
+ } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
+ backslash = true
+ } else {
+ backslash = false
+ }
+ }
+ }
+ if !lastSpace {
+ cc = append(cc, s[start:])
+ }
+
+ if GOOS == "darwin" {
+ // For Darwin/ARM.
+ // TODO(crawshaw): can we do better?
+ cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
+ }
+ libgodir = GOOS + "_" + GOARCH
+ if runtime.Compiler == "gccgo" {
+ libgodir = "gccgo_" + libgodir + "_fPIC"
+ } else {
+ switch GOOS {
+ case "darwin":
+ if GOARCH == "arm" || GOARCH == "arm64" {
+ libgodir += "_shared"
+ }
+ case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
+ libgodir += "_shared"
+ }
+ }
+ cc = append(cc, "-I", filepath.Join("pkg", libgodir))
+
+ // Build an environment with GOPATH=$(pwd)
+ env := os.Environ()
+ var n []string
+ for _, e := range env {
+ if !strings.HasPrefix(e, "GOPATH=") {
+ n = append(n, e)
+ }
+ }
+ dir, err := os.Getwd()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(2)
+ }
+ n = append(n, "GOPATH="+dir)
+ gopathEnv = n
+
+ if GOOS == "windows" {
+ exeSuffix = ".exe"
+ }
+}
+
+func goEnv(key string) string {
+ out, err := exec.Command("go", "env", key).Output()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "go env %s failed:\n%s", key, err)
+ fmt.Fprintf(os.Stderr, "%s", err.(*exec.ExitError).Stderr)
+ os.Exit(2)
+ }
+ return strings.TrimSpace(string(out))
+}
+
+func cmdToRun(name string) []string {
+ execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec"
+ executor, err := exec.LookPath(execScript)
+ if err != nil {
+ return []string{name}
+ }
+ return []string{executor, name}
+}
+
+func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
+ cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+ defer func() {
+ os.Remove(libgoa)
+ os.Remove(libgoh)
+ }()
+
+ ccArgs := append(cc, "-o", exe, "main.c")
+ if GOOS == "windows" {
+ ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm")
+ } else {
+ ccArgs = append(ccArgs, "main_unix.c", libgoa)
+ }
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ t.Log(ccArgs)
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+ defer os.Remove(exe)
+
+ binArgs := append(cmdToRun(exe), "arg1", "arg2")
+ cmd = exec.Command(binArgs[0], binArgs[1:]...)
+ if runtime.Compiler == "gccgo" {
+ cmd.Env = append(os.Environ(), "GCCGO=1")
+ }
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+}
+
+func TestInstall(t *testing.T) {
+ defer os.RemoveAll("pkg")
+
+ libgoa := "libgo.a"
+ if runtime.Compiler == "gccgo" {
+ libgoa = "liblibgo.a"
+ }
+
+ testInstall(t, "./testp1"+exeSuffix,
+ filepath.Join("pkg", libgodir, libgoa),
+ filepath.Join("pkg", libgodir, "libgo.h"),
+ "go", "install", "-buildmode=c-archive", "libgo")
+
+ // Test building libgo other than installing it.
+ // Header files are now present.
+ testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h",
+ "go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go"))
+
+ testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h",
+ "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo")
+}
+
+func TestEarlySignalHandler(t *testing.T) {
+ switch GOOS {
+ case "darwin":
+ switch GOARCH {
+ case "arm", "arm64":
+ t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+ }
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+
+ defer func() {
+ os.Remove("libgo2.a")
+ os.Remove("libgo2.h")
+ os.Remove("testp")
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+}
+
+func TestSignalForwarding(t *testing.T) {
+ switch GOOS {
+ case "darwin":
+ switch GOARCH {
+ case "arm", "arm64":
+ t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+ }
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+
+ defer func() {
+ os.Remove("libgo2.a")
+ os.Remove("libgo2.h")
+ os.Remove("testp")
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ cmd = exec.Command(bin[0], append(bin[1:], "1")...)
+
+ out, err := cmd.CombinedOutput()
+
+ if err == nil {
+ t.Logf("%s", out)
+ t.Error("test program succeeded unexpectedly")
+ } else if ee, ok := err.(*exec.ExitError); !ok {
+ t.Logf("%s", out)
+ t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+ } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+ t.Logf("%s", out)
+ t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+ } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
+ t.Logf("%s", out)
+ t.Errorf("got %v; expected SIGSEGV", ee)
+ }
+}
+
+func TestSignalForwardingExternal(t *testing.T) {
+ switch GOOS {
+ case "darwin":
+ switch GOARCH {
+ case "arm", "arm64":
+ t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
+ }
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+
+ defer func() {
+ os.Remove("libgo2.a")
+ os.Remove("libgo2.h")
+ os.Remove("testp")
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ // We want to send the process a signal and see if it dies.
+ // Normally the signal goes to the C thread, the Go signal
+ // handler picks it up, sees that it is running in a C thread,
+ // and the program dies. Unfortunately, occasionally the
+ // signal is delivered to a Go thread, which winds up
+ // discarding it because it was sent by another program and
+ // there is no Go handler for it. To avoid this, run the
+ // program several times in the hopes that it will eventually
+ // fail.
+ const tries = 20
+ for i := 0; i < tries; i++ {
+ cmd = exec.Command(bin[0], append(bin[1:], "2")...)
+
+ stderr, err := cmd.StderrPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stderr.Close()
+
+ r := bufio.NewReader(stderr)
+
+ err = cmd.Start()
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Wait for trigger to ensure that the process is started.
+ ok, err := r.ReadString('\n')
+
+ // Verify trigger.
+ if err != nil || ok != "OK\n" {
+ t.Fatalf("Did not receive OK signal")
+ }
+
+ // Give the program a chance to enter the sleep function.
+ time.Sleep(time.Millisecond)
+
+ cmd.Process.Signal(syscall.SIGSEGV)
+
+ err = cmd.Wait()
+
+ if err == nil {
+ continue
+ }
+
+ if ee, ok := err.(*exec.ExitError); !ok {
+ t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+ } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+ t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+ } else if !ws.Signaled() || ws.Signal() != syscall.SIGSEGV {
+ t.Errorf("got %v; expected SIGSEGV", ee)
+ } else {
+ // We got the error we expected.
+ return
+ }
+ }
+
+ t.Errorf("program succeeded unexpectedly %d times", tries)
+}
+
+func TestOsSignal(t *testing.T) {
+ switch GOOS {
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+
+ defer func() {
+ os.Remove("libgo3.a")
+ os.Remove("libgo3.h")
+ os.Remove("testp")
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "libgo3")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+}
+
+func TestSigaltstack(t *testing.T) {
+ switch GOOS {
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+
+ defer func() {
+ os.Remove("libgo4.a")
+ os.Remove("libgo4.h")
+ os.Remove("testp")
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "libgo4")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+}
+
+const testar = `#!/usr/bin/env bash
+while expr $1 : '[-]' >/dev/null; do
+ shift
+done
+echo "testar" > $1
+echo "testar" > PWD/testar.ran
+`
+
+func TestExtar(t *testing.T) {
+ switch GOOS {
+ case "windows":
+ t.Skip("skipping signal test on Windows")
+ }
+ if runtime.Compiler == "gccgo" {
+ t.Skip("skipping -extar test when using gccgo")
+ }
+
+ defer func() {
+ os.Remove("libgo4.a")
+ os.Remove("libgo4.h")
+ os.Remove("testar")
+ os.Remove("testar.ran")
+ os.RemoveAll("pkg")
+ }()
+
+ os.Remove("testar")
+ dir, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ s := strings.Replace(testar, "PWD", dir, 1)
+ if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil {
+ t.Fatal(err)
+ }
+
+ cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "libgo4")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ if _, err := os.Stat("testar.ran"); err != nil {
+ if os.IsNotExist(err) {
+ t.Error("testar does not exist after go build")
+ } else {
+ t.Errorf("error checking testar: %v", err)
+ }
+ }
+}
+
+func TestPIE(t *testing.T) {
+ switch GOOS {
+ case "windows", "darwin", "plan9":
+ t.Skipf("skipping PIE test on %s", GOOS)
+ }
+
+ defer func() {
+ os.Remove("testp" + exeSuffix)
+ os.RemoveAll("pkg")
+ }()
+
+ cmd := exec.Command("go", "install", "-buildmode=c-archive", "libgo")
+ cmd.Env = gopathEnv
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ libgoa := "libgo.a"
+ if runtime.Compiler == "gccgo" {
+ libgoa = "liblibgo.a"
+ }
+
+ ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, libgoa))
+ if runtime.Compiler == "gccgo" {
+ ccArgs = append(ccArgs, "-lgo")
+ }
+ if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ binArgs := append(bin, "arg1", "arg2")
+ cmd = exec.Command(binArgs[0], binArgs[1:]...)
+ if runtime.Compiler == "gccgo" {
+ cmd.Env = append(os.Environ(), "GCCGO=1")
+ }
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+
+ f, err := elf.Open("testp" + exeSuffix)
+ if err != nil {
+ t.Fatal("elf.Open failed: ", err)
+ }
+ defer f.Close()
+ if hasDynTag(t, f, elf.DT_TEXTREL) {
+ t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
+ }
+}
+
+func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
+ ds := f.SectionByType(elf.SHT_DYNAMIC)
+ if ds == nil {
+ t.Error("no SHT_DYNAMIC section")
+ return false
+ }
+ d, err := ds.Data()
+ if err != nil {
+ t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
+ return false
+ }
+ for len(d) > 0 {
+ var t elf.DynTag
+ switch f.Class {
+ case elf.ELFCLASS32:
+ t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
+ d = d[8:]
+ case elf.ELFCLASS64:
+ t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
+ d = d[16:]
+ }
+ if t == tag {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libgo/misc/cgo/testcarchive/main.c b/libgo/misc/cgo/testcarchive/main.c
new file mode 100644
index 00000000000..163b5398e5e
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main.c
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "p.h"
+#include "libgo.h"
+
+extern int install_handler();
+extern int check_handler();
+
+int main(void) {
+ int32_t res;
+
+ int r1 = install_handler();
+ if (r1!=0) {
+ return r1;
+ }
+
+ if (!DidInitRun()) {
+ fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
+ return 2;
+ }
+
+ if (DidMainRun()) {
+ fprintf(stderr, "ERROR: buildmode=c-archive should not run main\n");
+ return 2;
+ }
+
+ int r2 = check_handler();
+ if (r2!=0) {
+ return r2;
+ }
+
+ res = FromPkg();
+ if (res != 1024) {
+ fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);
+ return 2;
+ }
+
+ CheckArgs();
+
+ fprintf(stderr, "PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main2.c b/libgo/misc/cgo/testcarchive/main2.c
new file mode 100644
index 00000000000..774e014a162
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main2.c
@@ -0,0 +1,199 @@
+// Copyright 2015 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.
+
+// Test installing a signal handler before the Go code starts.
+// This is a lot like misc/cgo/testcshared/main4.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+
+#include "libgo2.h"
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+ char a[1024];
+
+ *p = '\0';
+ if (i > 0) {
+ recur(i - 1, a);
+ }
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+ char a[1024];
+
+ recur(4, a);
+ sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// An arbitrary function which requires proper stack alignment; see
+// http://golang.org/issue/17641.
+static void callWithVarargs(void* dummy, ...) {
+ va_list args;
+ va_start(args, dummy);
+ va_end(args);
+}
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigset_t mask;
+ int i;
+
+ // Call an arbitrary function that requires the stack to be properly aligned.
+ callWithVarargs("dummy arg", 3.1415);
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGSEGV) < 0) {
+ die("sigaddset");
+ }
+ i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ // Don't try this at home.
+ longjmp(jmp, signo);
+
+ // We should never get here.
+ abort();
+}
+
+// Set up the signal handlers in a high priority constructor,
+// so that they are installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ sa.sa_sigaction = segvHandler;
+ if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ sigset_t mask;
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 1;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Call setsid so that we can use kill(0, SIGIO) below.
+ // Don't check the return value so that this works both from
+ // a job control shell and from a shell script.
+ setsid();
+
+ if (verbose) {
+ printf("calling RunGoroutines\n");
+ }
+
+ RunGoroutines();
+
+ // Block SIGIO in this thread to make it more likely that it
+ // will be delivered to a goroutine.
+
+ if (verbose) {
+ printf("calling pthread_sigmask\n");
+ }
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGIO) < 0) {
+ die("sigaddset");
+ }
+ i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling kill\n");
+ }
+
+ if (kill(0, SIGIO) < 0) {
+ die("kill");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (verbose) {
+ printf("calling setjmp\n");
+ }
+
+ // Test that a SIGSEGV on this thread is delivered to us.
+ if (setjmp(jmp) == 0) {
+ if (verbose) {
+ printf("triggering SIGSEGV\n");
+ }
+
+ *nullPointer = '\0';
+
+ fprintf(stderr, "continued after address error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling TestSEGV\n");
+ }
+
+ TestSEGV();
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main3.c b/libgo/misc/cgo/testcarchive/main3.c
new file mode 100644
index 00000000000..0a6c0d3f74e
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main3.c
@@ -0,0 +1,155 @@
+// Copyright 2015 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.
+
+// Test os/signal.Notify and os/signal.Reset.
+// This is a lot like misc/cgo/testcshared/main5.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+
+#include "libgo3.h"
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ struct sigaction sa;
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 2;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (verbose) {
+ printf("calling sigaction\n");
+ }
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ // At this point there should not be a Go signal handler
+ // installed for SIGIO.
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ sigioSeen = 0;
+
+ // Tell the Go code to catch SIGIO.
+
+ if (verbose) {
+ printf("calling CatchSIGIO\n");
+ }
+
+ CatchSIGIO();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (!SawSIGIO()) {
+ fprintf(stderr, "Go handler did not see SIGIO\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (sigioSeen != 0) {
+ fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Tell the Go code to stop catching SIGIO.
+
+ if (verbose) {
+ printf("calling ResetSIGIO\n");
+ }
+
+ ResetSIGIO();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (SawSIGIO()) {
+ fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main4.c b/libgo/misc/cgo/testcarchive/main4.c
new file mode 100644
index 00000000000..4fd55e753d5
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main4.c
@@ -0,0 +1,197 @@
+// Copyright 2015 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.
+
+// Test a C thread that calls sigaltstack and then calls Go code.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <pthread.h>
+
+#include "libgo4.h"
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static int ok = 1;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+}
+
+// Set up the SIGIO signal handler in a high priority constructor, so
+// that it is installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+}
+
+// Test raising SIGIO on a C thread with an alternate signal stack
+// when there is a Go signal handler for SIGIO.
+static void* thread1(void* arg __attribute__ ((unused))) {
+ stack_t ss;
+ int i;
+ stack_t nss;
+ struct timespec ts;
+
+ // Set up an alternate signal stack for this thread.
+ memset(&ss, 0, sizeof ss);
+ ss.ss_sp = malloc(SIGSTKSZ);
+ if (ss.ss_sp == NULL) {
+ die("malloc");
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = SIGSTKSZ;
+ if (sigaltstack(&ss, NULL) < 0) {
+ die("sigaltstack");
+ }
+
+ // Send ourselves a SIGIO. This will be caught by the Go
+ // signal handler which should forward to the C signal
+ // handler.
+ i = pthread_kill(pthread_self(), SIGIO);
+ if (i != 0) {
+ fprintf(stderr, "pthread_kill: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (SIGIOCount() == 0) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // We should still be on the same signal stack.
+ if (sigaltstack(NULL, &nss) < 0) {
+ die("sigaltstack check");
+ }
+ if ((nss.ss_flags & SS_DISABLE) != 0) {
+ fprintf(stderr, "sigaltstack disabled on return from Go\n");
+ ok = 0;
+ } else if (nss.ss_sp != ss.ss_sp) {
+ fprintf(stderr, "sigalstack changed on return from Go\n");
+ ok = 0;
+ }
+
+ return NULL;
+}
+
+// Test calling a Go function to raise SIGIO on a C thread with an
+// alternate signal stack when there is a Go signal handler for SIGIO.
+static void* thread2(void* arg __attribute__ ((unused))) {
+ stack_t ss;
+ int i;
+ int oldcount;
+ pthread_t tid;
+ struct timespec ts;
+ stack_t nss;
+
+ // Set up an alternate signal stack for this thread.
+ memset(&ss, 0, sizeof ss);
+ ss.ss_sp = malloc(SIGSTKSZ);
+ if (ss.ss_sp == NULL) {
+ die("malloc");
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = SIGSTKSZ;
+ if (sigaltstack(&ss, NULL) < 0) {
+ die("sigaltstack");
+ }
+
+ oldcount = SIGIOCount();
+
+ // Call a Go function that will call a C function to send us a
+ // SIGIO.
+ tid = pthread_self();
+ GoRaiseSIGIO(&tid);
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (SIGIOCount() == oldcount) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // We should still be on the same signal stack.
+ if (sigaltstack(NULL, &nss) < 0) {
+ die("sigaltstack check");
+ }
+ if ((nss.ss_flags & SS_DISABLE) != 0) {
+ fprintf(stderr, "sigaltstack disabled on return from Go\n");
+ ok = 0;
+ } else if (nss.ss_sp != ss.ss_sp) {
+ fprintf(stderr, "sigalstack changed on return from Go\n");
+ ok = 0;
+ }
+
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+ pthread_t tid;
+ int i;
+
+ // Tell the Go library to start looking for SIGIO.
+ GoCatchSIGIO();
+
+ i = pthread_create(&tid, NULL, thread1, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_create: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ i = pthread_join(tid, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_join: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ i = pthread_create(&tid, NULL, thread2, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_create: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ i = pthread_join(tid, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_join: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ if (!ok) {
+ exit(EXIT_FAILURE);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main5.c b/libgo/misc/cgo/testcarchive/main5.c
new file mode 100644
index 00000000000..9fadf0801e1
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main5.c
@@ -0,0 +1,78 @@
+// Copyright 2015 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.
+
+// Test for verifying that the Go runtime properly forwards
+// signals when non-Go signals are raised.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+#include "libgo2.h"
+
+int main(int argc, char** argv) {
+ int verbose;
+ int test;
+
+ if (argc < 2) {
+ printf("Missing argument\n");
+ return 1;
+ }
+
+ test = atoi(argv[1]);
+
+ verbose = (argc > 2);
+
+ if (verbose) {
+ printf("calling RunGoroutines\n");
+ }
+
+ Noop();
+
+ switch (test) {
+ case 1: {
+ if (verbose) {
+ printf("attempting segfault\n");
+ }
+
+ volatile int crash = *(int *) 0;
+ break;
+ }
+
+ case 2: {
+ struct timeval tv;
+
+ if (verbose) {
+ printf("attempting external signal test\n");
+ }
+
+ fprintf(stderr, "OK\n");
+ fflush(stderr);
+
+ // The program should be interrupted before
+ // this sleep finishes. We use select rather
+ // than sleep because in older versions of
+ // glibc the sleep function does some signal
+ // fiddling to handle SIGCHLD. If this
+ // program is fiddling signals just when the
+ // test program sends the signal, the signal
+ // may be delivered to a Go thread which will
+ // break this test.
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ select(0, NULL, NULL, NULL, &tv);
+
+ break;
+ }
+ default:
+ printf("Unknown test: %d\n", test);
+ return 0;
+ }
+
+ printf("FAIL\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/main_unix.c b/libgo/misc/cgo/testcarchive/main_unix.c
new file mode 100644
index 00000000000..b23ac1c2428
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main_unix.c
@@ -0,0 +1,59 @@
+// Copyright 2015 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.
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct sigaction sa;
+struct sigaction osa;
+
+static void (*oldHandler)(int, siginfo_t*, void*);
+
+static void handler(int signo, siginfo_t* info, void* ctxt) {
+ if (oldHandler) {
+ oldHandler(signo, info, ctxt);
+ }
+}
+
+int install_handler() {
+ // Install our own signal handler.
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ memset(&osa, 0, sizeof osa);
+ sigemptyset(&osa.sa_mask);
+ if (sigaction(SIGSEGV, &sa, &osa) < 0) {
+ perror("sigaction");
+ return 2;
+ }
+ if (osa.sa_handler == SIG_DFL) {
+ fprintf(stderr, "Go runtime did not install signal handler\n");
+ return 2;
+ }
+ // gccgo does not set SA_ONSTACK for SIGSEGV.
+ if (getenv("GCCGO") == "" && (osa.sa_flags&SA_ONSTACK) == 0) {
+ fprintf(stderr, "Go runtime did not install signal handler\n");
+ return 2;
+ }
+ oldHandler = osa.sa_sigaction;
+
+ return 0;
+}
+
+int check_handler() {
+ if (sigaction(SIGSEGV, NULL, &sa) < 0) {
+ perror("sigaction check");
+ return 2;
+ }
+ if (sa.sa_sigaction != handler) {
+ fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler);
+ return 2;
+ }
+ return 0;
+}
+
diff --git a/libgo/misc/cgo/testcarchive/main_windows.c b/libgo/misc/cgo/testcarchive/main_windows.c
new file mode 100644
index 00000000000..eded8af1a2c
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/main_windows.c
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+/*
+ * Dummy implementations for Windows, because Windows doesn't
+ * support Unix-style signal handling.
+ */
+
+int install_handler() {
+ return 0;
+}
+
+
+int check_handler() {
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo/libgo.go b/libgo/misc/cgo/testcarchive/src/libgo/libgo.go
new file mode 100644
index 00000000000..45958a546cb
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/libgo/libgo.go
@@ -0,0 +1,53 @@
+// Copyright 2015 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.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+
+ _ "p"
+)
+
+import "C"
+
+var initCh = make(chan int, 1)
+var ranMain bool
+
+func init() {
+ // emulate an exceedingly slow package initialization function
+ time.Sleep(100 * time.Millisecond)
+ initCh <- 42
+}
+
+func main() { ranMain = true }
+
+//export DidInitRun
+func DidInitRun() bool {
+ select {
+ case x := <-initCh:
+ if x != 42 {
+ // Just in case initCh was not correctly made.
+ println("want init value of 42, got: ", x)
+ syscall.Exit(2)
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+//export DidMainRun
+func DidMainRun() bool { return ranMain }
+
+//export CheckArgs
+func CheckArgs() {
+ if len(os.Args) != 3 || os.Args[1] != "arg1" || os.Args[2] != "arg2" {
+ fmt.Printf("CheckArgs: want [_, arg1, arg2], got: %v\n", os.Args)
+ os.Exit(2)
+ }
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go b/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
new file mode 100644
index 00000000000..fbed493b93f
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+ for i := 0; i < 4; i++ {
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ }
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+ defer func() {
+ if recover() == nil {
+ fmt.Fprintln(os.Stderr, "no panic from segv")
+ os.Exit(1)
+ }
+ }()
+ *P = 0
+ fmt.Fprintln(os.Stderr, "continued after segv")
+ os.Exit(1)
+}
+
+// Noop ensures that the Go runtime is initialized.
+//export Noop
+func Noop() {
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go b/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
new file mode 100644
index 00000000000..94e5d21c14a
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+ sigioChan = make(chan os.Signal, 1)
+ signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+ signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+ select {
+ case <-sigioChan:
+ return 1
+ case <-time.After(100 * time.Millisecond):
+ return 0
+ }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go b/libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go
new file mode 100644
index 00000000000..8cc1895f99f
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/libgo4/libgo4.go
@@ -0,0 +1,52 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <signal.h>
+#include <pthread.h>
+
+// Raise SIGIO.
+static void CRaiseSIGIO(pthread_t* p) {
+ pthread_kill(*p, SIGIO);
+}
+*/
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "sync/atomic"
+ "syscall"
+)
+
+var sigioCount int32
+
+// Catch SIGIO.
+//export GoCatchSIGIO
+func GoCatchSIGIO() {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, syscall.SIGIO)
+ go func() {
+ for range c {
+ atomic.AddInt32(&sigioCount, 1)
+ }
+ }()
+}
+
+// Raise SIGIO.
+//export GoRaiseSIGIO
+func GoRaiseSIGIO(p *C.pthread_t) {
+ C.CRaiseSIGIO(p)
+}
+
+// Return the number of SIGIO signals seen.
+//export SIGIOCount
+func SIGIOCount() C.int {
+ return C.int(atomic.LoadInt32(&sigioCount))
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcarchive/src/p/p.go b/libgo/misc/cgo/testcarchive/src/p/p.go
new file mode 100644
index 00000000000..82b445c1210
--- /dev/null
+++ b/libgo/misc/cgo/testcarchive/src/p/p.go
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package p
+
+import "C"
+
+//export FromPkg
+func FromPkg() int32 { return 1024 }
diff --git a/libgo/misc/cgo/testcshared/main0.c b/libgo/misc/cgo/testcshared/main0.c
new file mode 100644
index 00000000000..1274b8950eb
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main0.c
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "p.h"
+#include "libgo.h"
+
+// Tests libgo.so to export the following functions.
+// int8_t DidInitRun();
+// int8_t DidMainRun();
+// int32_t FromPkg();
+int main(void) {
+ int8_t ran_init = DidInitRun();
+ if (!ran_init) {
+ fprintf(stderr, "ERROR: DidInitRun returned unexpected results: %d\n",
+ ran_init);
+ return 1;
+ }
+ int8_t ran_main = DidMainRun();
+ if (ran_main) {
+ fprintf(stderr, "ERROR: DidMainRun returned unexpected results: %d\n",
+ ran_main);
+ return 1;
+ }
+ int32_t from_pkg = FromPkg();
+ if (from_pkg != 1024) {
+ fprintf(stderr, "ERROR: FromPkg=%d, want %d\n", from_pkg, 1024);
+ return 1;
+ }
+ // test.bash looks for "PASS" to ensure this program has reached the end.
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main1.c b/libgo/misc/cgo/testcshared/main1.c
new file mode 100644
index 00000000000..420dd1ea974
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main1.c
@@ -0,0 +1,69 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+int check_int8(void* handle, const char* fname, int8_t want) {
+ int8_t (*fn)();
+ fn = (int8_t (*)())dlsym(handle, fname);
+ if (!fn) {
+ fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+ return 1;
+ }
+ signed char ret = fn();
+ if (ret != want) {
+ fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+ return 1;
+ }
+ return 0;
+}
+
+int check_int32(void* handle, const char* fname, int32_t want) {
+ int32_t (*fn)();
+ fn = (int32_t (*)())dlsym(handle, fname);
+ if (!fn) {
+ fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror());
+ return 1;
+ }
+ int32_t ret = fn();
+ if (ret != want) {
+ fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want);
+ return 1;
+ }
+ return 0;
+}
+
+// Tests libgo.so to export the following functions.
+// int8_t DidInitRun() // returns true
+// int8_t DidMainRun() // returns true
+// int32_t FromPkg() // returns 1024
+int main(int argc, char** argv) {
+ void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+ dlerror());
+ return 2;
+ }
+
+ int ret = 0;
+ ret = check_int8(handle, "DidInitRun", 1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = check_int8(handle, "DidMainRun", 0);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = check_int32(handle, "FromPkg", 1024);
+ if (ret != 0) {
+ return ret;
+ }
+ // test.bash looks for "PASS" to ensure this program has reached the end.
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main2.c b/libgo/misc/cgo/testcshared/main2.c
new file mode 100644
index 00000000000..6e8bf141caf
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main2.c
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define fd (100)
+
+// Tests libgo2.so, which does not export any functions.
+// Read a string from the file descriptor and print it.
+int main(void) {
+ int i;
+ ssize_t n;
+ char buf[20];
+ struct timespec ts;
+
+ // The descriptor will be initialized in a thread, so we have to
+ // give a chance to get opened.
+ for (i = 0; i < 1000; i++) {
+ n = read(fd, buf, sizeof buf);
+ if (n >= 0)
+ break;
+ if (errno != EBADF && errno != EINVAL) {
+ fprintf(stderr, "BUG: read: %s\n", strerror(errno));
+ return 2;
+ }
+
+ // An EBADF error means that the shared library has not opened the
+ // descriptor yet.
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ }
+
+ if (n < 0) {
+ fprintf(stderr, "BUG: failed to read any data from pipe\n");
+ return 2;
+ }
+
+ if (n == 0) {
+ fprintf(stderr, "BUG: unexpected EOF\n");
+ return 2;
+ }
+
+ if (n == sizeof buf) {
+ n--;
+ }
+ buf[n] = '\0';
+ printf("%s\n", buf);
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main3.c b/libgo/misc/cgo/testcshared/main3.c
new file mode 100644
index 00000000000..49cc0558a01
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main3.c
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+// Tests "main.main" is exported on android/arm,
+// which golang.org/x/mobile/app depends on.
+int main(int argc, char** argv) {
+ void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ fprintf(stderr, "ERROR: failed to open the shared library: %s\n",
+ dlerror());
+ return 2;
+ }
+
+ uintptr_t main_fn = (uintptr_t)dlsym(handle, "main.main");
+ if (!main_fn) {
+ fprintf(stderr, "ERROR: missing main.main: %s\n", dlerror());
+ return 2;
+ }
+
+ // TODO(hyangah): check that main.main can run.
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main4.c b/libgo/misc/cgo/testcshared/main4.c
new file mode 100644
index 00000000000..355cdefb017
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main4.c
@@ -0,0 +1,215 @@
+// Copyright 2015 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.
+
+// Test that a signal handler that uses up stack space does not crash
+// if the signal is delivered to a thread running a goroutine.
+// This is a lot like misc/cgo/testcarchive/main2.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+ char a[1024];
+
+ *p = '\0';
+ if (i > 0) {
+ recur(i - 1, a);
+ }
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+ char a[1024];
+
+ recur(4, a);
+ sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigset_t mask;
+ int i;
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGSEGV) < 0) {
+ die("sigaddset");
+ }
+ i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ // Don't try this at home.
+ longjmp(jmp, signo);
+
+ // We should never get here.
+ abort();
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ struct sigaction sa;
+ void* handle;
+ void (*fn)(void);
+ sigset_t mask;
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 2;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Call setsid so that we can use kill(0, SIGIO) below.
+ // Don't check the return value so that this works both from
+ // a job control shell and from a shell script.
+ setsid();
+
+ if (verbose) {
+ printf("calling sigaction\n");
+ }
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ sa.sa_sigaction = segvHandler;
+ if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ if (verbose) {
+ printf("calling dlopen\n");
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Start some goroutines.
+ fn = (void(*)(void))dlsym(handle, "RunGoroutines");
+ if (fn == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling RunGoroutines\n");
+ }
+
+ fn();
+
+ // Block SIGIO in this thread to make it more likely that it
+ // will be delivered to a goroutine.
+
+ if (verbose) {
+ printf("calling pthread_sigmask\n");
+ }
+
+ if (sigemptyset(&mask) < 0) {
+ die("sigemptyset");
+ }
+ if (sigaddset(&mask, SIGIO) < 0) {
+ die("sigaddset");
+ }
+ i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+ if (i != 0) {
+ fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling kill\n");
+ }
+
+ if (kill(0, SIGIO) < 0) {
+ die("kill");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (verbose) {
+ printf("calling setjmp\n");
+ }
+
+ // Test that a SIGSEGV on this thread is delivered to us.
+ if (setjmp(jmp) == 0) {
+ if (verbose) {
+ printf("triggering SIGSEGV\n");
+ }
+
+ *nullPointer = '\0';
+
+ fprintf(stderr, "continued after address error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Make sure that a SIGSEGV in Go causes a run-time panic.
+ fn = (void (*)(void))dlsym(handle, "TestSEGV");
+ if (fn == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling TestSEGV\n");
+ }
+
+ fn();
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/main5.c b/libgo/misc/cgo/testcshared/main5.c
new file mode 100644
index 00000000000..1bc99101d7a
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/main5.c
@@ -0,0 +1,199 @@
+// Copyright 2015 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.
+
+// Test that a signal handler works in non-Go code when using
+// os/signal.Notify.
+// This is a lot like misc/cgo/testcarchive/main3.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+ perror(msg);
+ exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+ sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+ int verbose;
+ struct sigaction sa;
+ void* handle;
+ void (*fn1)(void);
+ int (*sawSIGIO)(void);
+ int i;
+ struct timespec ts;
+
+ verbose = argc > 2;
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (verbose) {
+ printf("calling sigaction\n");
+ }
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_sigaction = ioHandler;
+ if (sigemptyset(&sa.sa_mask) < 0) {
+ die("sigemptyset");
+ }
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGIO, &sa, NULL) < 0) {
+ die("sigaction");
+ }
+
+ if (verbose) {
+ printf("calling dlopen\n");
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ // At this point there should not be a Go signal handler
+ // installed for SIGIO.
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ sigioSeen = 0;
+
+ // Tell the Go code to catch SIGIO.
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO");
+ if (fn1 == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling CatchSIGIO\n");
+ }
+
+ fn1();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ // Check that the Go code saw SIGIO.
+ sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO");
+ if (sawSIGIO == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (!sawSIGIO()) {
+ fprintf(stderr, "Go handler did not see SIGIO\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (sigioSeen != 0) {
+ fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Tell the Go code to stop catching SIGIO.
+
+ if (verbose) {
+ printf("calling dlsym\n");
+ }
+
+ fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO");
+ if (fn1 == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("calling ResetSIGIO\n");
+ }
+
+ fn1();
+
+ if (verbose) {
+ printf("raising SIGIO\n");
+ }
+
+ if (raise(SIGIO) < 0) {
+ die("raise");
+ }
+
+ if (verbose) {
+ printf("calling SawSIGIO\n");
+ }
+
+ if (sawSIGIO()) {
+ fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (verbose) {
+ printf("waiting for sigioSeen\n");
+ }
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000;
+ nanosleep(&ts, NULL);
+ i++;
+ if (i > 5000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo/libgo.go b/libgo/misc/cgo/testcshared/src/libgo/libgo.go
new file mode 100644
index 00000000000..8a4bf795e91
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo/libgo.go
@@ -0,0 +1,46 @@
+// Copyright 2015 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.
+
+package main
+
+import (
+ _ "p"
+ "syscall"
+ "time"
+)
+
+import "C"
+
+var initCh = make(chan int, 1)
+var ranMain bool
+
+func init() {
+ // emulate an exceedingly slow package initialization function
+ time.Sleep(100 * time.Millisecond)
+ initCh <- 42
+}
+
+func main() {
+ ranMain = true
+}
+
+//export DidInitRun
+func DidInitRun() bool {
+ select {
+ case x := <-initCh:
+ if x != 42 {
+ // Just in case initCh was not correctly made.
+ println("want init value of 42, got: ", x)
+ syscall.Exit(2)
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+//export DidMainRun
+func DidMainRun() bool {
+ return ranMain
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/dup2.go b/libgo/misc/cgo/testcshared/src/libgo2/dup2.go
new file mode 100644
index 00000000000..d18f0b130d3
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo2/dup2.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build darwin dragonfly freebsd linux,!arm64 netbsd openbsd
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup2(oldfd, newfd)
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/dup3.go b/libgo/misc/cgo/testcshared/src/libgo2/dup3.go
new file mode 100644
index 00000000000..c9c65a6e3c1
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo2/dup3.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build linux,arm64
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+ return syscall.Dup3(oldfd, newfd, 0)
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go b/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go
new file mode 100644
index 00000000000..1b69d8f09fa
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo2/libgo2.go
@@ -0,0 +1,52 @@
+// Copyright 2015 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main
+
+// Test a shared library created by -buildmode=c-shared that does not
+// export anything.
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+)
+
+// To test this we want to communicate between the main program and
+// the shared library without using any exported symbols. The init
+// function creates a pipe and Dups the read end to a known number
+// that the C code can also use.
+
+const (
+ fd = 100
+)
+
+func init() {
+ var p [2]int
+ if e := syscall.Pipe(p[0:]); e != nil {
+ fmt.Fprintf(os.Stderr, "pipe: %v\n", e)
+ os.Exit(2)
+ }
+
+ if e := dup2(p[0], fd); e != nil {
+ fmt.Fprintf(os.Stderr, "dup2: %v\n", e)
+ os.Exit(2)
+ }
+
+ const str = "PASS"
+ if n, e := syscall.Write(p[1], []byte(str)); e != nil || n != len(str) {
+ fmt.Fprintf(os.Stderr, "write: %d %v\n", n, e)
+ os.Exit(2)
+ }
+
+ if e := syscall.Close(p[1]); e != nil {
+ fmt.Fprintf(os.Stderr, "close: %v\n", e)
+ os.Exit(2)
+ }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo4/libgo4.go b/libgo/misc/cgo/testcshared/src/libgo4/libgo4.go
new file mode 100644
index 00000000000..ab40b75e78a
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo4/libgo4.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+ for i := 0; i < 4; i++ {
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ }
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+ defer func() {
+ if recover() == nil {
+ fmt.Fprintln(os.Stderr, "no panic from segv")
+ os.Exit(1)
+ }
+ }()
+ *P = 0
+ fmt.Fprintln(os.Stderr, "continued after segv")
+ os.Exit(1)
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/libgo5/libgo5.go b/libgo/misc/cgo/testcshared/src/libgo5/libgo5.go
new file mode 100644
index 00000000000..94e5d21c14a
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/libgo5/libgo5.go
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+import "C"
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+ sigioChan = make(chan os.Signal, 1)
+ signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+ signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+ select {
+ case <-sigioChan:
+ return 1
+ case <-time.After(100 * time.Millisecond):
+ return 0
+ }
+}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testcshared/src/p/p.go b/libgo/misc/cgo/testcshared/src/p/p.go
new file mode 100644
index 00000000000..82b445c1210
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/src/p/p.go
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+package p
+
+import "C"
+
+//export FromPkg
+func FromPkg() int32 { return 1024 }
diff --git a/libgo/misc/cgo/testcshared/test.bash b/libgo/misc/cgo/testcshared/test.bash
new file mode 100644
index 00000000000..0315fb07f57
--- /dev/null
+++ b/libgo/misc/cgo/testcshared/test.bash
@@ -0,0 +1,193 @@
+#!/usr/bin/env bash
+# Copyright 2015 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.
+
+# For testing Android, this script requires adb to push and run compiled
+# binaries on a target device.
+
+set -e
+
+if [ ! -f src/libgo/libgo.go ]; then
+ cwd=$(pwd)
+ echo "misc/cgo/testcshared/test.bash is running in $cwd" 1>&2
+ exit 1
+fi
+
+goos=$(go env GOOS)
+goarch=$(go env GOARCH)
+goroot=$(go env GOROOT)
+if [ ! -d "$goroot" ]; then
+ echo 'misc/cgo/testcshared/test.bash cannot find GOROOT' 1>&2
+ echo '$GOROOT:' "$GOROOT" 1>&2
+ echo 'go env GOROOT:' "$goroot" 1>&2
+ exit 1
+fi
+
+# Directory where cgo headers and outputs will be installed.
+# The installation directory format varies depending on the platform.
+installdir=pkg/${goos}_${goarch}_testcshared_shared
+if [ "${goos}" == "darwin" ]; then
+ installdir=pkg/${goos}_${goarch}_testcshared
+fi
+
+# Temporary directory on the android device.
+androidpath=/data/local/tmp/testcshared-$$
+
+function cleanup() {
+ rm -f libgo.$libext libgo2.$libext libgo4.$libext libgo5.$libext
+ rm -f libgo.h libgo4.h libgo5.h
+ rm -f testp testp2 testp3 testp4 testp5
+ rm -rf pkg "${goroot}/${installdir}"
+
+ if [ "$goos" == "android" ]; then
+ adb shell rm -rf "$androidpath"
+ fi
+}
+trap cleanup EXIT
+
+if [ "$goos" == "android" ]; then
+ adb shell mkdir -p "$androidpath"
+fi
+
+function run() {
+ case "$goos" in
+ "android")
+ local args=$@
+ output=$(adb shell "cd ${androidpath}; $@")
+ output=$(echo $output|tr -d '\r')
+ case $output in
+ *PASS) echo "PASS";;
+ *) echo "$output";;
+ esac
+ ;;
+ *)
+ echo $(env $@)
+ ;;
+ esac
+}
+
+function binpush() {
+ bin=${1}
+ if [ "$goos" == "android" ]; then
+ adb push "$bin" "${androidpath}/${bin}" 2>/dev/null
+ fi
+}
+
+rm -rf pkg
+
+suffix="-installsuffix testcshared"
+
+libext="so"
+if [ "$goos" == "darwin" ]; then
+ libext="dylib"
+fi
+
+# Create the header files.
+GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
+
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
+binpush libgo.$libext
+
+if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+ if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
+ echo "libgo.$libext has TEXTREL set"
+ exit 1
+ fi
+fi
+
+GOGCCFLAGS=$(go env GOGCCFLAGS)
+if [ "$goos" == "android" ]; then
+ GOGCCFLAGS="${GOGCCFLAGS} -pie"
+fi
+
+status=0
+
+# test0: exported symbols in shared lib are accessible.
+# TODO(iant): using _shared here shouldn't really be necessary.
+$(go env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c ./libgo.$libext
+binpush testp
+
+output=$(run LD_LIBRARY_PATH=. ./testp)
+if [ "$output" != "PASS" ]; then
+ echo "FAIL test0 got ${output}"
+ status=1
+fi
+
+# test1: shared library can be dynamically loaded and exported symbols are accessible.
+$(go env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
+binpush testp
+output=$(run ./testp ./libgo.$libext)
+if [ "$output" != "PASS" ]; then
+ echo "FAIL test1 got ${output}"
+ status=1
+fi
+
+# test2: tests libgo2 which does not export any functions.
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
+binpush libgo2.$libext
+linkflags="-Wl,--no-as-needed"
+if [ "$goos" == "darwin" ]; then
+ linkflags=""
+fi
+$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
+binpush testp2
+output=$(run LD_LIBRARY_PATH=. ./testp2)
+if [ "$output" != "PASS" ]; then
+ echo "FAIL test2 got ${output}"
+ status=1
+fi
+
+# test3: tests main.main is exported on android.
+if [ "$goos" == "android" ]; then
+ $(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
+ binpush testp3
+ output=$(run ./testp ./libgo.so)
+ if [ "$output" != "PASS" ]; then
+ echo "FAIL test3 got ${output}"
+ status=1
+ fi
+fi
+
+# test4: tests signal handlers
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
+binpush libgo4.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
+binpush testp4
+output=$(run ./testp4 ./libgo4.$libext 2>&1)
+if test "$output" != "PASS"; then
+ echo "FAIL test4 got ${output}"
+ if test "$goos" != "android"; then
+ echo "re-running test4 in verbose mode"
+ ./testp4 ./libgo4.$libext verbose
+ fi
+ status=1
+fi
+
+# test5: tests signal handlers with os/signal.Notify
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
+binpush libgo5.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
+binpush testp5
+output=$(run ./testp5 ./libgo5.$libext 2>&1)
+if test "$output" != "PASS"; then
+ echo "FAIL test5 got ${output}"
+ if test "$goos" != "android"; then
+ echo "re-running test5 in verbose mode"
+ ./testp5 ./libgo5.$libext verbose
+ fi
+ status=1
+fi
+
+if test "$libext" = "dylib"; then
+ # make sure dylibs are well-formed
+ if ! otool -l libgo*.dylib >/dev/null; then
+ status=1
+ fi
+fi
+
+if test $status = 0; then
+ echo "ok"
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/testgodefs/anonunion.go b/libgo/misc/cgo/testgodefs/anonunion.go
new file mode 100644
index 00000000000..18840f2577c
--- /dev/null
+++ b/libgo/misc/cgo/testgodefs/anonunion.go
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+//
+// +build ignore
+
+package main
+
+// This file tests that when cgo -godefs sees a struct with a field
+// that is an anonymous union, the first field in the union is
+// promoted to become a field of the struct. See issue 6677 for
+// background.
+
+/*
+typedef struct {
+ union {
+ long l;
+ int c;
+ };
+} t;
+*/
+import "C"
+
+// Input for cgo -godefs.
+
+type T C.t
diff --git a/libgo/misc/cgo/testgodefs/issue8478.go b/libgo/misc/cgo/testgodefs/issue8478.go
new file mode 100644
index 00000000000..23214461711
--- /dev/null
+++ b/libgo/misc/cgo/testgodefs/issue8478.go
@@ -0,0 +1,20 @@
+// Copyright 2014 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.
+//
+// +build ignore
+
+package main
+
+// Issue 8478. Test that void* is consistently mapped to *byte.
+
+/*
+typedef struct {
+ void *p;
+ void **q;
+ void ***r;
+} s;
+*/
+import "C"
+
+type Issue8478 C.s
diff --git a/libgo/misc/cgo/testgodefs/main.go b/libgo/misc/cgo/testgodefs/main.go
new file mode 100644
index 00000000000..1ce0fd0d1e1
--- /dev/null
+++ b/libgo/misc/cgo/testgodefs/main.go
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+package main
+
+// Test that the struct field in anonunion.go was promoted.
+var v1 T
+var v2 = v1.L
+
+// Test that P, Q, and R all point to byte.
+var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)}
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testgodefs/test.bash b/libgo/misc/cgo/testgodefs/test.bash
new file mode 100644
index 00000000000..a82ff9328fe
--- /dev/null
+++ b/libgo/misc/cgo/testgodefs/test.bash
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright 2014 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.
+
+# We are testing cgo -godefs, which translates Go files that use
+# import "C" into Go files with Go definitions of types defined in the
+# import "C" block. Add more tests here.
+FILE_PREFIXES="anonunion issue8478"
+
+RM=
+for FP in $FILE_PREFIXES
+do
+ go tool cgo -godefs -srcdir . ${FP}.go > ${FP}_defs.go
+ RM="${RM} ${FP}_defs.go"
+done
+
+go build . && ./testgodefs
+EXIT=$?
+rm -rf _obj testgodefs ${RM}
+exit $EXIT
diff --git a/libgo/misc/cgo/testplugin/altpath/src/common/common.go b/libgo/misc/cgo/testplugin/altpath/src/common/common.go
new file mode 100644
index 00000000000..505ba02b1f1
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/altpath/src/common/common.go
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+package common
+
+var X int
+
+func init() {
+ X = 4
+}
diff --git a/libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go b/libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go
new file mode 100644
index 00000000000..8aacafc4530
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/altpath/src/plugin-mismatch/main.go
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+// The common package imported here does not match the common package
+// imported by plugin1. A program that attempts to load plugin1 and
+// plugin-mismatch should produce an error.
+import "common"
+
+func ReadCommonX() int {
+ return common.X
+}
diff --git a/libgo/misc/cgo/testplugin/src/common/common.go b/libgo/misc/cgo/testplugin/src/common/common.go
new file mode 100644
index 00000000000..b064e6bccfe
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/common/common.go
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+package common
+
+var X int
+
+func init() {
+ X = 3
+}
diff --git a/libgo/misc/cgo/testplugin/src/host/host.go b/libgo/misc/cgo/testplugin/src/host/host.go
new file mode 100644
index 00000000000..898f44efa15
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/host/host.go
@@ -0,0 +1,148 @@
+// Copyright 2016 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.
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "path/filepath"
+ "plugin"
+ "strings"
+
+ "common"
+)
+
+func init() {
+ common.X *= 5
+}
+
+// testUnnamed tests that two plugins built with .go files passed on
+// the command line do not have overlapping symbols. That is,
+// unnamed1.so/FuncInt and unnamed2.so/FuncInt should be distinct functions.
+func testUnnamed() {
+ p, err := plugin.Open("unnamed1.so")
+ if err != nil {
+ log.Fatalf(`plugin.Open("unnamed1.so"): %v`, err)
+ }
+ fn, err := p.Lookup("FuncInt")
+ if err != nil {
+ log.Fatalf(`unnamed1.so: Lookup("FuncInt") failed: %v`, err)
+ }
+ if got, want := fn.(func() int)(), 1; got != want {
+ log.Fatalf("unnamed1.so: FuncInt()=%d, want %d", got, want)
+ }
+
+ p, err = plugin.Open("unnamed2.so")
+ if err != nil {
+ log.Fatalf(`plugin.Open("unnamed2.so"): %v`, err)
+ }
+ fn, err = p.Lookup("FuncInt")
+ if err != nil {
+ log.Fatalf(`unnamed2.so: Lookup("FuncInt") failed: %v`, err)
+ }
+ if got, want := fn.(func() int)(), 2; got != want {
+ log.Fatalf("unnamed2.so: FuncInt()=%d, want %d", got, want)
+ }
+}
+
+func main() {
+ if got, want := common.X, 3*5; got != want {
+ log.Fatalf("before plugin load common.X=%d, want %d", got, want)
+ }
+
+ p, err := plugin.Open("plugin1.so")
+ if err != nil {
+ log.Fatalf("plugin.Open failed: %v", err)
+ }
+
+ const wantX = 3 * 5 * 7
+ if got := common.X; got != wantX {
+ log.Fatalf("after plugin load common.X=%d, want %d", got, wantX)
+ }
+
+ seven, err := p.Lookup("Seven")
+ if err != nil {
+ log.Fatalf(`Lookup("Seven") failed: %v`, err)
+ }
+ if got, want := *seven.(*int), 7; got != want {
+ log.Fatalf("plugin1.Seven=%d, want %d", got, want)
+ }
+
+ readFunc, err := p.Lookup("ReadCommonX")
+ if err != nil {
+ log.Fatalf(`plugin1.Lookup("ReadCommonX") failed: %v`, err)
+ }
+ if got := readFunc.(func() int)(); got != wantX {
+ log.Fatalf("plugin1.ReadCommonX()=%d, want %d", got, wantX)
+ }
+
+ // sub/plugin1.so is a different plugin with the same name as
+ // the already loaded plugin. It also depends on common. Test
+ // that we can load the different plugin, it is actually
+ // different, and that it sees the same common package.
+ subpPath, err := filepath.Abs("sub/plugin1.so")
+ if err != nil {
+ log.Fatalf("filepath.Abs(%q) failed: %v", subpPath, err)
+ }
+ subp, err := plugin.Open(subpPath)
+ if err != nil {
+ log.Fatalf("plugin.Open(%q) failed: %v", subpPath, err)
+ }
+
+ funcVar, err := subp.Lookup("FuncVar")
+ if err != nil {
+ log.Fatalf(`sub/plugin1.Lookup("FuncVar") failed: %v`, err)
+ }
+ called := false
+ *funcVar.(*func()) = func() {
+ called = true
+ }
+
+ readFunc, err = subp.Lookup("ReadCommonX")
+ if err != nil {
+ log.Fatalf(`sub/plugin1.Lookup("ReadCommonX") failed: %v`, err)
+ }
+ if got := readFunc.(func() int)(); got != wantX {
+ log.Fatalf("sub/plugin1.ReadCommonX()=%d, want %d", got, wantX)
+ }
+ if !called {
+ log.Fatal("calling ReadCommonX did not call FuncVar")
+ }
+
+ subf, err := subp.Lookup("F")
+ if err != nil {
+ log.Fatalf(`sub/plugin1.Lookup("F") failed: %v`, err)
+ }
+ if gotf := subf.(func() int)(); gotf != 17 {
+ log.Fatalf(`sub/plugin1.F()=%d, want 17`, gotf)
+ }
+ f, err := p.Lookup("F")
+ if err != nil {
+ log.Fatalf(`plugin1.Lookup("F") failed: %v`, err)
+ }
+ if gotf := f.(func() int)(); gotf != 3 {
+ log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
+ }
+
+ // plugin2 has no exported symbols, only an init function.
+ if _, err := plugin.Open("plugin2.so"); err != nil {
+ log.Fatalf("plugin.Open failed: %v", err)
+ }
+ if got, want := common.X, 2; got != want {
+ log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
+ }
+
+ _, err = plugin.Open("plugin-mismatch.so")
+ if err == nil {
+ log.Fatal(`plugin.Open("plugin-mismatch.so"): should have failed`)
+ }
+ if s := err.Error(); !strings.Contains(s, "different version") {
+ log.Fatalf(`plugin.Open("plugin-mismatch.so"): error does not mention "different version": %v`, s)
+ }
+
+ testUnnamed()
+
+ fmt.Println("PASS")
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface/main.go b/libgo/misc/cgo/testplugin/src/iface/main.go
new file mode 100644
index 00000000000..5e7e4d8b480
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/iface/main.go
@@ -0,0 +1,46 @@
+// Copyright 2017 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.
+
+package main
+
+import (
+ "iface_i"
+ "log"
+ "plugin"
+)
+
+func main() {
+ a, err := plugin.Open("iface_a.so")
+ if err != nil {
+ log.Fatalf(`plugin.Open("iface_a.so"): %v`, err)
+ }
+ b, err := plugin.Open("iface_b.so")
+ if err != nil {
+ log.Fatalf(`plugin.Open("iface_b.so"): %v`, err)
+ }
+
+ af, err := a.Lookup("F")
+ if err != nil {
+ log.Fatalf(`a.Lookup("F") failed: %v`, err)
+ }
+ bf, err := b.Lookup("F")
+ if err != nil {
+ log.Fatalf(`b.Lookup("F") failed: %v`, err)
+ }
+ if af.(func() interface{})() != bf.(func() interface{})() {
+ panic("empty interfaces not equal")
+ }
+
+ ag, err := a.Lookup("G")
+ if err != nil {
+ log.Fatalf(`a.Lookup("G") failed: %v`, err)
+ }
+ bg, err := b.Lookup("G")
+ if err != nil {
+ log.Fatalf(`b.Lookup("G") failed: %v`, err)
+ }
+ if ag.(func() iface_i.I)() != bg.(func() iface_i.I)() {
+ panic("nonempty interfaces not equal")
+ }
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_a/a.go b/libgo/misc/cgo/testplugin/src/iface_a/a.go
new file mode 100644
index 00000000000..29d2e277640
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/iface_a/a.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package main
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+ return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+ return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_b/b.go b/libgo/misc/cgo/testplugin/src/iface_b/b.go
new file mode 100644
index 00000000000..29d2e277640
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/iface_b/b.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package main
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+ return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+ return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testplugin/src/iface_i/i.go b/libgo/misc/cgo/testplugin/src/iface_i/i.go
new file mode 100644
index 00000000000..31c80387c7e
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/iface_i/i.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package iface_i
+
+type I interface {
+ M()
+}
+
+type T struct {
+}
+
+func (t *T) M() {
+}
+
+// *T implements I
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go b/libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go
new file mode 100644
index 00000000000..70fd054d089
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/issue18676/dynamodbstreamsevt/definition.go
@@ -0,0 +1,13 @@
+// Copyright 2017 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.
+
+package dynamodbstreamsevt
+
+import "encoding/json"
+
+var foo json.RawMessage
+
+type Event struct{}
+
+func (e *Event) Dummy() {}
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/main.go b/libgo/misc/cgo/testplugin/src/issue18676/main.go
new file mode 100644
index 00000000000..c75409dafe7
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/issue18676/main.go
@@ -0,0 +1,31 @@
+// Copyright 2017 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.
+
+// The bug happened like this:
+// 1) The main binary adds an itab for *json.UnsupportedValueError / error
+// (concrete type / interface type). This itab goes in hash bucket 0x111.
+// 2) The plugin adds that same itab again. That makes a cycle in the itab
+// chain rooted at hash bucket 0x111.
+// 3) The main binary then asks for the itab for *dynamodbstreamsevt.Event /
+// json.Unmarshaler. This itab happens to also live in bucket 0x111.
+// The lookup code goes into an infinite loop searching for this itab.
+// The code is carefully crafted so that the two itabs are both from the
+// same bucket, and so that the second itab doesn't exist in
+// the itab hashmap yet (so the entire linked list must be searched).
+package main
+
+import (
+ "encoding/json"
+ "issue18676/dynamodbstreamsevt"
+ "plugin"
+)
+
+func main() {
+ plugin.Open("plugin.so")
+
+ var x interface{} = (*dynamodbstreamsevt.Event)(nil)
+ if _, ok := x.(json.Unmarshaler); !ok {
+ println("something")
+ }
+}
diff --git a/libgo/misc/cgo/testplugin/src/issue18676/plugin.go b/libgo/misc/cgo/testplugin/src/issue18676/plugin.go
new file mode 100644
index 00000000000..8a3b85a75cd
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/issue18676/plugin.go
@@ -0,0 +1,11 @@
+// Copyright 2017 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.
+
+package main
+
+import "C"
+
+import "issue18676/dynamodbstreamsevt"
+
+func F(evt *dynamodbstreamsevt.Event) {}
diff --git a/libgo/misc/cgo/testplugin/src/plugin1/plugin1.go b/libgo/misc/cgo/testplugin/src/plugin1/plugin1.go
new file mode 100644
index 00000000000..edcef2c77e9
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/plugin1/plugin1.go
@@ -0,0 +1,38 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+import "common"
+
+func F() int {
+ _ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190.
+ return 3
+}
+
+func ReadCommonX() int {
+ return common.X
+}
+
+var Seven int
+
+func call(fn func()) {
+ fn()
+}
+
+func g() {
+ common.X *= Seven
+}
+
+func init() {
+ Seven = 7
+ call(g)
+}
+
+func main() {
+ panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/src/plugin2/plugin2.go b/libgo/misc/cgo/testplugin/src/plugin2/plugin2.go
new file mode 100644
index 00000000000..9c507fc3658
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/plugin2/plugin2.go
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+package main
+
+//#include <errno.h>
+//#include <string.h>
+import "C"
+
+// #include
+// void cfunc() {} // uses cgo_topofstack
+
+import (
+ "common"
+ "strings"
+)
+
+func init() {
+ _ = strings.NewReplacer() // trigger stack unwind, Issue #18190.
+ C.strerror(C.EIO) // uses cgo_topofstack
+ common.X = 2
+}
+
+func main() {
+ panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go b/libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go
new file mode 100644
index 00000000000..cf9000c4a4e
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/src/sub/plugin1/plugin1.go
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+import "common"
+
+func F() int { return 17 }
+
+var FuncVar = func() {}
+
+func ReadCommonX() int {
+ FuncVar()
+ return common.X
+}
+
+func main() {
+ panic("plugin1.main called")
+}
diff --git a/libgo/misc/cgo/testplugin/test.bash b/libgo/misc/cgo/testplugin/test.bash
new file mode 100644
index 00000000000..ab7430acc37
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/test.bash
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# Copyright 2016 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.
+
+set -e
+
+if [ ! -f src/host/host.go ]; then
+ cwd=$(pwd)
+ echo "misc/cgo/testplugin/test.bash is running in $cwd" 1>&2
+ exit 1
+fi
+
+goos=$(go env GOOS)
+goarch=$(go env GOARCH)
+
+function cleanup() {
+ rm -f plugin*.so unnamed*.so iface*.so
+ rm -rf host pkg sub iface issue18676
+}
+trap cleanup EXIT
+
+rm -rf pkg sub
+mkdir sub
+
+GOPATH=$(pwd) go build -buildmode=plugin plugin1
+GOPATH=$(pwd) go build -buildmode=plugin plugin2
+GOPATH=$(pwd)/altpath go build -buildmode=plugin plugin-mismatch
+GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
+GOPATH=$(pwd) go build -buildmode=plugin unnamed1.go
+GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go
+GOPATH=$(pwd) go build host
+
+LD_LIBRARY_PATH=$(pwd) ./host
+
+# Test that types and itabs get properly uniqified.
+GOPATH=$(pwd) go build -buildmode=plugin iface_a
+GOPATH=$(pwd) go build -buildmode=plugin iface_b
+GOPATH=$(pwd) go build iface
+LD_LIBRARY_PATH=$(pwd) ./iface
+
+# Test for issue 18676 - make sure we don't add the same itab twice.
+# The buggy code hangs forever, so use a timeout to check for that.
+GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
+GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
+timeout 10s ./issue18676
diff --git a/libgo/misc/cgo/testplugin/unnamed1.go b/libgo/misc/cgo/testplugin/unnamed1.go
new file mode 100644
index 00000000000..102edaf3e29
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/unnamed1.go
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+func FuncInt() int { return 1 }
+
+func main() {}
diff --git a/libgo/misc/cgo/testplugin/unnamed2.go b/libgo/misc/cgo/testplugin/unnamed2.go
new file mode 100644
index 00000000000..55070d5e9f7
--- /dev/null
+++ b/libgo/misc/cgo/testplugin/unnamed2.go
@@ -0,0 +1,12 @@
+// Copyright 2016 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.
+
+package main
+
+// // No C code required.
+import "C"
+
+func FuncInt() int { return 2 }
+
+func main() {}
diff --git a/libgo/misc/cgo/testsanitizers/msan.go b/libgo/misc/cgo/testsanitizers/msan.go
new file mode 100644
index 00000000000..7915fa84f60
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <stdint.h>
+
+void f(int32_t *p, int n) {
+ int i;
+
+ for (i = 0; i < n; i++) {
+ p[i] = (int32_t)i;
+ }
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "unsafe"
+)
+
+func main() {
+ a := make([]int32, 10)
+ C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+ for i, v := range a {
+ if i != int(v) {
+ fmt.Println("bad %d: %v\n", i, a)
+ os.Exit(1)
+ }
+ }
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan2.go b/libgo/misc/cgo/testsanitizers/msan2.go
new file mode 100644
index 00000000000..6690cb034fc
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan2.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+ int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+ memcpy(p, q, n * sizeof(*p));
+ free(q);
+}
+
+void g(int32_t *p, int n) {
+ if (p[4] != 1) {
+ abort();
+ }
+}
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+func main() {
+ a := make([]int32, 10)
+ C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+ a[4] = 1
+ C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan3.go b/libgo/misc/cgo/testsanitizers/msan3.go
new file mode 100644
index 00000000000..61a9c29e1a9
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan3.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+extern int *GoFn(int *);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+int f(void) __attribute__ ((weak));
+
+int f() {
+ int i;
+ int *p = GoFn(&i);
+ if (*p != 12345)
+ return 0;
+ return 1;
+}
+*/
+import "C"
+
+//export GoFn
+func GoFn(p *C.int) *C.int {
+ *p = C.int(12345)
+ return p
+}
+
+func main() {
+ if r := C.f(); r != 1 {
+ panic(r)
+ }
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan4.go b/libgo/misc/cgo/testsanitizers/msan4.go
new file mode 100644
index 00000000000..6c91ff5f091
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan4.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+package main
+
+// The memory profiler can call copy from a slice on the system stack,
+// which msan used to think meant a reference to uninitialized memory.
+
+/*
+#include <time.h>
+#include <unistd.h>
+
+extern void Nop(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void poison() __attribute__ ((weak));
+
+// Poison the stack.
+void poison() {
+ char a[1024];
+ Nop(&a[0]);
+}
+
+*/
+import "C"
+
+import (
+ "runtime"
+)
+
+func main() {
+ runtime.MemProfileRate = 1
+ start(100)
+}
+
+func start(i int) {
+ if i == 0 {
+ return
+ }
+ C.poison()
+ // Tie up a thread.
+ // We won't actually wait for this sleep to complete.
+ go func() { C.sleep(1) }()
+ start(i - 1)
+}
+
+//export Nop
+func Nop(*C.char) {
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan5.go b/libgo/misc/cgo/testsanitizers/msan5.go
new file mode 100644
index 00000000000..f1479eb8a00
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan5.go
@@ -0,0 +1,57 @@
+// Copyright 2016 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.
+
+package main
+
+// Using reflect to set a value was not seen by msan.
+
+/*
+#include <stdlib.h>
+
+extern void Go1(int*);
+extern void Go2(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void C1() __attribute__ ((weak));
+void C2() __attribute__ ((weak));
+
+void C1() {
+ int i;
+ Go1(&i);
+ if (i != 42) {
+ abort();
+ }
+}
+
+void C2() {
+ char a[2];
+ a[1] = 42;
+ Go2(a);
+ if (a[0] != 42) {
+ abort();
+ }
+}
+*/
+import "C"
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+//export Go1
+func Go1(p *C.int) {
+ reflect.ValueOf(p).Elem().Set(reflect.ValueOf(C.int(42)))
+}
+
+//export Go2
+func Go2(p *C.char) {
+ a := (*[2]byte)(unsafe.Pointer(p))
+ reflect.Copy(reflect.ValueOf(a[:1]), reflect.ValueOf(a[1:]))
+}
+
+func main() {
+ C.C1()
+ C.C2()
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan_fail.go b/libgo/misc/cgo/testsanitizers/msan_fail.go
new file mode 100644
index 00000000000..4c8dab34f6e
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan_fail.go
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+package main
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+ int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+ memcpy(p, q, n * sizeof(*p));
+ free(q);
+}
+
+void g(int32_t *p, int n) {
+ if (p[4] != 1) {
+ // We shouldn't get here; msan should stop us first.
+ exit(0);
+ }
+}
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+func main() {
+ a := make([]int32, 10)
+ C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+ a[3] = 1
+ C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/libgo/misc/cgo/testsanitizers/msan_shared.go b/libgo/misc/cgo/testsanitizers/msan_shared.go
new file mode 100644
index 00000000000..966947cac35
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/msan_shared.go
@@ -0,0 +1,12 @@
+// Copyright 2017 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.
+
+// This program segfaulted during libpreinit when built with -msan:
+// http://golang.org/issue/18707
+
+package main
+
+import "C"
+
+func main() {}
diff --git a/libgo/misc/cgo/testsanitizers/test.bash b/libgo/misc/cgo/testsanitizers/test.bash
new file mode 100644
index 00000000000..4da85020d89
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/test.bash
@@ -0,0 +1,204 @@
+#!/usr/bin/env bash
+# Copyright 2015 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.
+
+# This directory is intended to test the use of Go with sanitizers
+# like msan, asan, etc. See https://github.com/google/sanitizers .
+
+set -e
+
+# The sanitizers were originally developed with clang, so prefer it.
+CC=cc
+if test -x "$(type -p clang)"; then
+ CC=clang
+fi
+export CC
+
+if [ "$(sysctl -n vm.overcommit_memory)" = 2 ]; then
+ echo "skipping msan/tsan tests: vm.overcommit_memory=2" >&2
+ exit 0
+fi
+
+msan=yes
+
+TMPDIR=${TMPDIR:-/tmp}
+echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
+if $CC -fsanitize=memory -o ${TMPDIR}/testsanitizers$$ ${TMPDIR}/testsanitizers$$.c 2>&1 | grep "unrecognized" >& /dev/null; then
+ echo "skipping msan tests: $CC -fsanitize=memory not supported"
+ msan=no
+elif ! test -x ${TMPDIR}/testsanitizers$$; then
+ echo "skipping msan tests: $CC -fsanitize-memory did not generate an executable"
+ msan=no
+elif ! ${TMPDIR}/testsanitizers$$ >/dev/null 2>&1; then
+ echo "skipping msan tests: $CC -fsanitize-memory generates broken executable"
+ msan=no
+fi
+rm -f ${TMPDIR}/testsanitizers$$.*
+
+tsan=yes
+
+# The memory and thread sanitizers in versions of clang before 3.6
+# don't work with Go.
+if test "$msan" = "yes" && $CC --version | grep clang >& /dev/null; then
+ ver=$($CC --version | sed -e 's/.* version \([0-9.-]*\).*/\1/')
+ major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
+ minor=$(echo $ver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+ if test "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 6; then
+ echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.6)"
+ msan=no
+ tsan=no
+ fi
+
+ # Clang before 3.8 does not work with Linux at or after 4.1.
+ # golang.org/issue/12898.
+ if test "$msan" = "yes" -a "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 8; then
+ if test "$(uname)" = Linux; then
+ linuxver=$(uname -r)
+ linuxmajor=$(echo $linuxver | sed -e 's/\([0-9]*\).*/\1/')
+ linuxminor=$(echo $linuxver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+ if test "$linuxmajor" -gt 4 || test "$linuxmajor" -eq 4 -a "$linuxminor" -ge 1; then
+ echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.8) incompatible with linux version $linuxmajor.$linuxminor (4.1 or newer)"
+ msan=no
+ tsan=no
+ fi
+ fi
+ fi
+fi
+
+status=0
+
+testmsanshared() {
+ goos=$(go env GOOS)
+ suffix="-installsuffix testsanitizers"
+ libext="so"
+ if [ "$goos" == "darwin" ]; then
+ libext="dylib"
+ fi
+ go build -msan -buildmode=c-shared $suffix -o ${TMPDIR}/libmsanshared.$libext msan_shared.go
+
+ echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
+ $CC $(go env GOGCCFLAGS) -fsanitize=memory -o ${TMPDIR}/testmsanshared ${TMPDIR}/testmsanshared.c ${TMPDIR}/libmsanshared.$libext
+
+ if ! LD_LIBRARY_PATH=. ${TMPDIR}/testmsanshared; then
+ echo "FAIL: msan_shared"
+ status=1
+ fi
+ rm -f ${TMPDIR}/{testmsanshared,testmsanshared.c,libmsanshared.$libext}
+}
+
+if test "$msan" = "yes"; then
+ if ! go build -msan std; then
+ echo "FAIL: build -msan std"
+ status=1
+ fi
+
+ if ! go run -msan msan.go; then
+ echo "FAIL: msan"
+ status=1
+ fi
+
+ if ! CGO_LDFLAGS="-fsanitize=memory" CGO_CPPFLAGS="-fsanitize=memory" go run -msan -a msan2.go; then
+ echo "FAIL: msan2 with -fsanitize=memory"
+ status=1
+ fi
+
+ if ! go run -msan -a msan2.go; then
+ echo "FAIL: msan2"
+ status=1
+ fi
+
+ if ! go run -msan msan3.go; then
+ echo "FAIL: msan3"
+ status=1
+ fi
+
+ if ! go run -msan msan4.go; then
+ echo "FAIL: msan4"
+ status=1
+ fi
+
+ if ! go run -msan msan5.go; then
+ echo "FAIL: msan5"
+ status=1
+ fi
+
+ if go run -msan msan_fail.go 2>/dev/null; then
+ echo "FAIL: msan_fail"
+ status=1
+ fi
+
+ testmsanshared
+fi
+
+if test "$tsan" = "yes"; then
+ echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
+ ok=yes
+ if ! $CC -fsanitize=thread ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$ &> ${TMPDIR}/testsanitizers$$.err; then
+ ok=no
+ fi
+ if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then
+ echo "skipping tsan tests: -fsanitize=thread not supported"
+ tsan=no
+ elif test "$ok" != "yes"; then
+ cat ${TMPDIR}/testsanitizers$$.err
+ echo "skipping tsan tests: -fsanitizer=thread build failed"
+ tsan=no
+ fi
+ rm -f ${TMPDIR}/testsanitizers$$*
+fi
+
+# Run a TSAN test.
+# $1 test name
+# $2 environment variables
+# $3 go run args
+testtsan() {
+ err=${TMPDIR}/tsanerr$$.out
+ if ! env $2 go run $3 $1 2>$err; then
+ cat $err
+ echo "FAIL: $1"
+ status=1
+ elif grep -i warning $err >/dev/null 2>&1; then
+ cat $err
+ echo "FAIL: $1"
+ status=1
+ fi
+ rm -f $err
+}
+
+if test "$tsan" = "yes"; then
+ testtsan tsan.go
+ testtsan tsan2.go
+ testtsan tsan3.go
+ testtsan tsan4.go
+ testtsan tsan8.go
+ testtsan tsan9.go
+
+ # These tests are only reliable using clang or GCC version 7 or later.
+ # Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
+ ok=false
+ if ${CC} --version | grep clang >/dev/null 2>&1; then
+ ok=true
+ else
+ ver=$($CC -dumpversion)
+ major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
+ if test "$major" -lt 7; then
+ echo "skipping remaining TSAN tests: GCC version $major (older than 7)"
+ else
+ ok=true
+ fi
+ fi
+
+ if test "$ok" = "true"; then
+ # This test requires rebuilding os/user with -fsanitize=thread.
+ testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+
+ # This test requires rebuilding runtime/cgo with -fsanitize=thread.
+ testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+
+ # This test requires rebuilding runtime/cgo with -fsanitize=thread.
+ testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
+ fi
+fi
+
+exit $status
diff --git a/libgo/misc/cgo/testsanitizers/tsan.go b/libgo/misc/cgo/testsanitizers/tsan.go
new file mode 100644
index 00000000000..6c377a701fb
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan.go
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+package main
+
+// This program produced false race reports when run under the C/C++
+// ThreadSanitizer, as it did not understand the synchronization in
+// the Go code.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+int val;
+
+int getVal() {
+ return val;
+}
+
+void setVal(int i) {
+ val = i;
+}
+*/
+import "C"
+
+import (
+ "runtime"
+)
+
+func main() {
+ runtime.LockOSThread()
+ C.setVal(1)
+ c := make(chan bool)
+ go func() {
+ runtime.LockOSThread()
+ C.setVal(2)
+ c <- true
+ }()
+ <-c
+ if v := C.getVal(); v != 2 {
+ panic(v)
+ }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan2.go b/libgo/misc/cgo/testsanitizers/tsan2.go
new file mode 100644
index 00000000000..5018a1987ca
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan2.go
@@ -0,0 +1,55 @@
+// Copyright 2015 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.
+
+package main
+
+// This program produced false race reports when run under the C/C++
+// ThreadSanitizer, as it did not understand the synchronization in
+// the Go code.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+extern void GoRun(void);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+
+int val __attribute__ ((weak));
+
+int run(void) __attribute__ ((weak));
+
+int run() {
+ val = 1;
+ GoRun();
+ return val;
+}
+
+void setVal(int) __attribute__ ((weak));
+
+void setVal(int i) {
+ val = i;
+}
+*/
+import "C"
+
+import "runtime"
+
+//export GoRun
+func GoRun() {
+ runtime.LockOSThread()
+ c := make(chan bool)
+ go func() {
+ runtime.LockOSThread()
+ C.setVal(2)
+ c <- true
+ }()
+ <-c
+}
+
+func main() {
+ if v := C.run(); v != 2 {
+ panic(v)
+ }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan3.go b/libgo/misc/cgo/testsanitizers/tsan3.go
new file mode 100644
index 00000000000..87f6c80f1b1
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan3.go
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+package main
+
+// The stubs for the C functions read and write the same slot on the
+// g0 stack when copying arguments in and out.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+int Func1() {
+ return 0;
+}
+
+void Func2(int x) {
+ (void)x;
+}
+*/
+import "C"
+
+func main() {
+ const N = 10000
+ done := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ go func() {
+ C.Func1()
+ done <- true
+ }()
+ go func() {
+ C.Func2(0)
+ done <- true
+ }()
+ }
+ for i := 0; i < 2*N; i++ {
+ <-done
+ }
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan4.go b/libgo/misc/cgo/testsanitizers/tsan4.go
new file mode 100644
index 00000000000..f0c76d84116
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan4.go
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that calls to C.malloc/C.free do not trigger TSAN false
+// positive reports.
+
+// #cgo CFLAGS: -fsanitize=thread
+// #cgo LDFLAGS: -fsanitize=thread
+// #include <stdlib.h>
+import "C"
+
+import (
+ "runtime"
+ "sync"
+)
+
+func main() {
+ var wg sync.WaitGroup
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 100; i++ {
+ p := C.malloc(C.size_t(i * 10))
+ runtime.Gosched()
+ C.free(p)
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan5.go b/libgo/misc/cgo/testsanitizers/tsan5.go
new file mode 100644
index 00000000000..1214a7743b6
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan5.go
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that calls to C.malloc/C.free do not collide with the calls
+// made by the os/user package.
+
+// #cgo CFLAGS: -fsanitize=thread
+// #cgo LDFLAGS: -fsanitize=thread
+// #include <stdlib.h>
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "os/user"
+ "runtime"
+ "sync"
+)
+
+func main() {
+ u, err := user.Current()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ // Let the test pass.
+ os.Exit(0)
+ }
+
+ var wg sync.WaitGroup
+ for i := 0; i < 20; i++ {
+ wg.Add(2)
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 1000; i++ {
+ user.Lookup(u.Username)
+ runtime.Gosched()
+ }
+ }()
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 1000; i++ {
+ p := C.malloc(C.size_t(len(u.Username) + 1))
+ runtime.Gosched()
+ C.free(p)
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan6.go b/libgo/misc/cgo/testsanitizers/tsan6.go
new file mode 100644
index 00000000000..c96f08d2f37
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan6.go
@@ -0,0 +1,49 @@
+// Copyright 2016 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.
+
+package main
+
+// Check that writes to Go allocated memory, with Go synchronization,
+// do not look like a race.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+void f(char *p) {
+ *p = 1;
+}
+*/
+import "C"
+
+import (
+ "runtime"
+ "sync"
+)
+
+func main() {
+ var wg sync.WaitGroup
+ var mu sync.Mutex
+ c := make(chan []C.char, 100)
+ for i := 0; i < 10; i++ {
+ wg.Add(2)
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 100; i++ {
+ c <- make([]C.char, 4096)
+ runtime.Gosched()
+ }
+ }()
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 100; i++ {
+ p := &(<-c)[0]
+ mu.Lock()
+ C.f(p)
+ mu.Unlock()
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan7.go b/libgo/misc/cgo/testsanitizers/tsan7.go
new file mode 100644
index 00000000000..2fb9e45ee2d
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan7.go
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+package main
+
+// Setting an environment variable in a cgo program changes the C
+// environment. Test that this does not confuse the race detector.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "sync"
+ "time"
+)
+
+func main() {
+ var wg sync.WaitGroup
+ var mu sync.Mutex
+ f := func() {
+ defer wg.Done()
+ for i := 0; i < 100; i++ {
+ time.Sleep(time.Microsecond)
+ mu.Lock()
+ s := fmt.Sprint(i)
+ os.Setenv("TSAN_TEST"+s, s)
+ mu.Unlock()
+ }
+ }
+ wg.Add(2)
+ go f()
+ go f()
+ wg.Wait()
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan8.go b/libgo/misc/cgo/testsanitizers/tsan8.go
new file mode 100644
index 00000000000..88d82a60789
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan8.go
@@ -0,0 +1,60 @@
+// Copyright 2016 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.
+
+package main
+
+// This program failed when run under the C/C++ ThreadSanitizer. The TSAN
+// sigaction function interceptor returned SIG_DFL instead of the Go runtime's
+// handler in registerSegvForwarder.
+
+/*
+#cgo CFLAGS: -fsanitize=thread
+#cgo LDFLAGS: -fsanitize=thread
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct sigaction prev_sa;
+
+void forwardSignal(int signo, siginfo_t *info, void *context) {
+ // One of sa_sigaction and/or sa_handler
+ if ((prev_sa.sa_flags&SA_SIGINFO) != 0) {
+ prev_sa.sa_sigaction(signo, info, context);
+ return;
+ }
+ if (prev_sa.sa_handler != SIG_IGN && prev_sa.sa_handler != SIG_DFL) {
+ prev_sa.sa_handler(signo);
+ return;
+ }
+
+ fprintf(stderr, "No Go handler to forward to!\n");
+ abort();
+}
+
+void registerSegvFowarder() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+ sa.sa_sigaction = forwardSignal;
+
+ if (sigaction(SIGSEGV, &sa, &prev_sa) != 0) {
+ perror("failed to register SEGV forwarder");
+ exit(EXIT_FAILURE);
+ }
+}
+*/
+import "C"
+
+func main() {
+ C.registerSegvFowarder()
+
+ defer func() {
+ recover()
+ }()
+ var nilp *int
+ *nilp = 42
+}
diff --git a/libgo/misc/cgo/testsanitizers/tsan9.go b/libgo/misc/cgo/testsanitizers/tsan9.go
new file mode 100644
index 00000000000..f166d8b495a
--- /dev/null
+++ b/libgo/misc/cgo/testsanitizers/tsan9.go
@@ -0,0 +1,67 @@
+// Copyright 2016 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.
+
+package main
+
+// This program failed when run under the C/C++ ThreadSanitizer. The
+// TSAN library was not keeping track of whether signals should be
+// delivered on the alternate signal stack, and the Go signal handler
+// was not preserving callee-saved registers from C callers.
+
+/*
+#cgo CFLAGS: -g -fsanitize=thread
+#cgo LDFLAGS: -g -fsanitize=thread
+
+#include <stdlib.h>
+#include <sys/time.h>
+
+void spin() {
+ size_t n;
+ struct timeval tvstart, tvnow;
+ int diff;
+ void *prev = NULL, *cur;
+
+ gettimeofday(&tvstart, NULL);
+ for (n = 0; n < 1<<20; n++) {
+ cur = malloc(n);
+ free(prev);
+ prev = cur;
+
+ gettimeofday(&tvnow, NULL);
+ diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec);
+
+ // Profile frequency is 100Hz so we should definitely
+ // get a signal in 50 milliseconds.
+ if (diff > 50 * 1000) {
+ break;
+ }
+ }
+
+ free(prev);
+}
+*/
+import "C"
+
+import (
+ "io/ioutil"
+ "runtime/pprof"
+ "time"
+)
+
+func goSpin() {
+ start := time.Now()
+ for n := 0; n < 1<<20; n++ {
+ _ = make([]byte, n)
+ if time.Since(start) > 50*time.Millisecond {
+ break
+ }
+ }
+}
+
+func main() {
+ pprof.StartCPUProfile(ioutil.Discard)
+ go C.spin()
+ goSpin()
+ pprof.StopCPUProfile()
+}
diff --git a/libgo/misc/cgo/testshared/shared_test.go b/libgo/misc/cgo/testshared/shared_test.go
new file mode 100644
index 00000000000..f0766e511ec
--- /dev/null
+++ b/libgo/misc/cgo/testshared/shared_test.go
@@ -0,0 +1,828 @@
+// Copyright 2015 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.
+
+package shared_test
+
+import (
+ "bufio"
+ "bytes"
+ "debug/elf"
+ "encoding/binary"
+ "errors"
+ "flag"
+ "fmt"
+ "go/build"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strings"
+ "testing"
+ "time"
+)
+
+var gopathInstallDir, gorootInstallDir, suffix string
+
+// This is the smallest set of packages we can link into a shared
+// library (runtime/cgo is built implicitly).
+var minpkgs = []string{"runtime", "sync/atomic"}
+var soname = "libruntime,sync-atomic.so"
+
+// run runs a command and calls t.Errorf if it fails.
+func run(t *testing.T, msg string, args ...string) {
+ c := exec.Command(args[0], args[1:]...)
+ if output, err := c.CombinedOutput(); err != nil {
+ t.Errorf("executing %s (%s) failed %s:\n%s", strings.Join(args, " "), msg, err, output)
+ }
+}
+
+// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls
+// t.Fatalf if the command fails.
+func goCmd(t *testing.T, args ...string) {
+ newargs := []string{args[0], "-installsuffix=" + suffix}
+ if testing.Verbose() {
+ newargs = append(newargs, "-v")
+ }
+ newargs = append(newargs, args[1:]...)
+ c := exec.Command("go", newargs...)
+ var output []byte
+ var err error
+ if testing.Verbose() {
+ fmt.Printf("+ go %s\n", strings.Join(newargs, " "))
+ c.Stdout = os.Stdout
+ c.Stderr = os.Stderr
+ err = c.Run()
+ } else {
+ output, err = c.CombinedOutput()
+ }
+ if err != nil {
+ if t != nil {
+ t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+ } else {
+ log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
+ }
+ }
+}
+
+// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
+func testMain(m *testing.M) (int, error) {
+ // Because go install -buildmode=shared $standard_library_package always
+ // installs into $GOROOT, here are some gymnastics to come up with a unique
+ // installsuffix to use in this test that we can clean up afterwards.
+ myContext := build.Default
+ runtimeP, err := myContext.Import("runtime", ".", build.ImportComment)
+ if err != nil {
+ return 0, fmt.Errorf("import failed: %v", err)
+ }
+ for i := 0; i < 10000; i++ {
+ try := fmt.Sprintf("%s_%d_dynlink", runtimeP.PkgTargetRoot, rand.Int63())
+ err = os.Mkdir(try, 0700)
+ if os.IsExist(err) {
+ continue
+ }
+ if err == nil {
+ gorootInstallDir = try
+ }
+ break
+ }
+ if err != nil {
+ return 0, fmt.Errorf("can't create temporary directory: %v", err)
+ }
+ if gorootInstallDir == "" {
+ return 0, errors.New("could not create temporary directory after 10000 tries")
+ }
+ if testing.Verbose() {
+ fmt.Printf("+ mkdir -p %s\n", gorootInstallDir)
+ }
+ defer os.RemoveAll(gorootInstallDir)
+
+ // Some tests need to edit the source in GOPATH, so copy this directory to a
+ // temporary directory and chdir to that.
+ scratchDir, err := ioutil.TempDir("", "testshared")
+ if err != nil {
+ return 0, fmt.Errorf("TempDir failed: %v", err)
+ }
+ if testing.Verbose() {
+ fmt.Printf("+ mkdir -p %s\n", scratchDir)
+ }
+ defer os.RemoveAll(scratchDir)
+ err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
+ scratchPath := filepath.Join(scratchDir, path)
+ if info.IsDir() {
+ if path == "." {
+ return nil
+ }
+ if testing.Verbose() {
+ fmt.Printf("+ mkdir -p %s\n", scratchPath)
+ }
+ return os.Mkdir(scratchPath, info.Mode())
+ } else {
+ fromBytes, err := ioutil.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ if testing.Verbose() {
+ fmt.Printf("+ cp %s %s\n", path, scratchPath)
+ }
+ return ioutil.WriteFile(scratchPath, fromBytes, info.Mode())
+ }
+ })
+ if err != nil {
+ return 0, fmt.Errorf("walk failed: %v", err)
+ }
+ os.Setenv("GOPATH", scratchDir)
+ if testing.Verbose() {
+ fmt.Printf("+ export GOPATH=%s\n", scratchDir)
+ }
+ myContext.GOPATH = scratchDir
+ if testing.Verbose() {
+ fmt.Printf("+ cd %s\n", scratchDir)
+ }
+ os.Chdir(scratchDir)
+
+ // All tests depend on runtime being built into a shared library. Because
+ // that takes a few seconds, do it here and have all tests use the version
+ // built here.
+ suffix = strings.Split(filepath.Base(gorootInstallDir), "_")[2]
+ goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...)
+
+ myContext.InstallSuffix = suffix + "_dynlink"
+ depP, err := myContext.Import("depBase", ".", build.ImportComment)
+ if err != nil {
+ return 0, fmt.Errorf("import failed: %v", err)
+ }
+ gopathInstallDir = depP.PkgTargetRoot
+ return m.Run(), nil
+}
+
+func TestMain(m *testing.M) {
+ // Some of the tests install binaries into a custom GOPATH.
+ // That won't work if GOBIN is set.
+ os.Unsetenv("GOBIN")
+
+ flag.Parse()
+ exitCode, err := testMain(m)
+ if err != nil {
+ log.Fatal(err)
+ }
+ os.Exit(exitCode)
+}
+
+// The shared library was built at the expected location.
+func TestSOBuilt(t *testing.T) {
+ _, err := os.Stat(filepath.Join(gorootInstallDir, soname))
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func hasDynTag(f *elf.File, tag elf.DynTag) bool {
+ ds := f.SectionByType(elf.SHT_DYNAMIC)
+ if ds == nil {
+ return false
+ }
+ d, err := ds.Data()
+ if err != nil {
+ return false
+ }
+ for len(d) > 0 {
+ var t elf.DynTag
+ switch f.Class {
+ case elf.ELFCLASS32:
+ t = elf.DynTag(f.ByteOrder.Uint32(d[0:4]))
+ d = d[8:]
+ case elf.ELFCLASS64:
+ t = elf.DynTag(f.ByteOrder.Uint64(d[0:8]))
+ d = d[16:]
+ }
+ if t == tag {
+ return true
+ }
+ }
+ return false
+}
+
+// The shared library does not have relocations against the text segment.
+func TestNoTextrel(t *testing.T) {
+ sopath := filepath.Join(gorootInstallDir, soname)
+ f, err := elf.Open(sopath)
+ if err != nil {
+ t.Fatal("elf.Open failed: ", err)
+ }
+ defer f.Close()
+ if hasDynTag(f, elf.DT_TEXTREL) {
+ t.Errorf("%s has DT_TEXTREL set", soname)
+ }
+}
+
+// The shared library does not contain symbols called ".dup"
+func TestNoDupSymbols(t *testing.T) {
+ sopath := filepath.Join(gorootInstallDir, soname)
+ f, err := elf.Open(sopath)
+ if err != nil {
+ t.Fatal("elf.Open failed: ", err)
+ }
+ defer f.Close()
+ syms, err := f.Symbols()
+ if err != nil {
+ t.Errorf("error reading symbols %v", err)
+ return
+ }
+ for _, s := range syms {
+ if s.Name == ".dup" {
+ t.Fatalf("%s contains symbol called .dup", sopath)
+ }
+ }
+}
+
+// The install command should have created a "shlibname" file for the
+// listed packages (and runtime/cgo, and math on arm) indicating the
+// name of the shared library containing it.
+func TestShlibnameFiles(t *testing.T) {
+ pkgs := append([]string{}, minpkgs...)
+ pkgs = append(pkgs, "runtime/cgo")
+ if runtime.GOARCH == "arm" {
+ pkgs = append(pkgs, "math")
+ }
+ for _, pkg := range pkgs {
+ shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
+ contentsb, err := ioutil.ReadFile(shlibnamefile)
+ if err != nil {
+ t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
+ continue
+ }
+ contents := strings.TrimSpace(string(contentsb))
+ if contents != soname {
+ t.Errorf("shlibnamefile for %s has wrong contents: %q", pkg, contents)
+ }
+ }
+}
+
+// Is a given offset into the file contained in a loaded segment?
+func isOffsetLoaded(f *elf.File, offset uint64) bool {
+ for _, prog := range f.Progs {
+ if prog.Type == elf.PT_LOAD {
+ if prog.Off <= offset && offset < prog.Off+prog.Filesz {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func rnd(v int32, r int32) int32 {
+ if r <= 0 {
+ return v
+ }
+ v += r - 1
+ c := v % r
+ if c < 0 {
+ c += r
+ }
+ v -= c
+ return v
+}
+
+func readwithpad(r io.Reader, sz int32) ([]byte, error) {
+ data := make([]byte, rnd(sz, 4))
+ _, err := io.ReadFull(r, data)
+ if err != nil {
+ return nil, err
+ }
+ data = data[:sz]
+ return data, nil
+}
+
+type note struct {
+ name string
+ tag int32
+ desc string
+ section *elf.Section
+}
+
+// Read all notes from f. As ELF section names are not supposed to be special, one
+// looks for a particular note by scanning all SHT_NOTE sections looking for a note
+// with a particular "name" and "tag".
+func readNotes(f *elf.File) ([]*note, error) {
+ var notes []*note
+ for _, sect := range f.Sections {
+ if sect.Type != elf.SHT_NOTE {
+ continue
+ }
+ r := sect.Open()
+ for {
+ var namesize, descsize, tag int32
+ err := binary.Read(r, f.ByteOrder, &namesize)
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, fmt.Errorf("read namesize failed: %v", err)
+ }
+ err = binary.Read(r, f.ByteOrder, &descsize)
+ if err != nil {
+ return nil, fmt.Errorf("read descsize failed: %v", err)
+ }
+ err = binary.Read(r, f.ByteOrder, &tag)
+ if err != nil {
+ return nil, fmt.Errorf("read type failed: %v", err)
+ }
+ name, err := readwithpad(r, namesize)
+ if err != nil {
+ return nil, fmt.Errorf("read name failed: %v", err)
+ }
+ desc, err := readwithpad(r, descsize)
+ if err != nil {
+ return nil, fmt.Errorf("read desc failed: %v", err)
+ }
+ notes = append(notes, &note{name: string(name), tag: tag, desc: string(desc), section: sect})
+ }
+ }
+ return notes, nil
+}
+
+func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
+ f, err := elf.Open(path)
+ defer f.Close()
+ if err != nil {
+ t.Fatalf("elf.Open(%q) failed: %v", path, err)
+ }
+ dynstrings, err := f.DynString(flag)
+ if err != nil {
+ t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err)
+ }
+ return dynstrings
+}
+
+func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) {
+ for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) {
+ if re.MatchString(dynstring) {
+ return
+ }
+ }
+ t.Errorf("%s is not linked to anything matching %v", path, re)
+}
+
+func AssertIsLinkedTo(t *testing.T, path, lib string) {
+ AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib)))
+}
+
+func AssertHasRPath(t *testing.T, path, dir string) {
+ for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} {
+ for _, dynstring := range dynStrings(t, path, tag) {
+ for _, rpath := range strings.Split(dynstring, ":") {
+ if filepath.Clean(rpath) == filepath.Clean(dir) {
+ return
+ }
+ }
+ }
+ }
+ t.Errorf("%s does not have rpath %s", path, dir)
+}
+
+// Build a trivial program that links against the shared runtime and check it runs.
+func TestTrivialExecutable(t *testing.T) {
+ goCmd(t, "install", "-linkshared", "trivial")
+ run(t, "trivial executable", "./bin/trivial")
+ AssertIsLinkedTo(t, "./bin/trivial", soname)
+ AssertHasRPath(t, "./bin/trivial", gorootInstallDir)
+}
+
+// Build a trivial program in PIE mode that links against the shared runtime and check it runs.
+func TestTrivialExecutablePIE(t *testing.T) {
+ goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "trivial")
+ run(t, "trivial executable", "./trivial.pie")
+ AssertIsLinkedTo(t, "./trivial.pie", soname)
+ AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
+}
+
+// Build an executable that uses cgo linked against the shared runtime and check it
+// runs.
+func TestCgoExecutable(t *testing.T) {
+ goCmd(t, "install", "-linkshared", "execgo")
+ run(t, "cgo executable", "./bin/execgo")
+}
+
+func checkPIE(t *testing.T, name string) {
+ f, err := elf.Open(name)
+ if err != nil {
+ t.Fatal("elf.Open failed: ", err)
+ }
+ defer f.Close()
+ if f.Type != elf.ET_DYN {
+ t.Errorf("%s has type %v, want ET_DYN", name, f.Type)
+ }
+ if hasDynTag(f, elf.DT_TEXTREL) {
+ t.Errorf("%s has DT_TEXTREL set", name)
+ }
+}
+
+func TestTrivialPIE(t *testing.T) {
+ name := "trivial_pie"
+ goCmd(t, "build", "-buildmode=pie", "-o="+name, "trivial")
+ defer os.Remove(name)
+ run(t, name, "./"+name)
+ checkPIE(t, name)
+}
+
+func TestCgoPIE(t *testing.T) {
+ name := "cgo_pie"
+ goCmd(t, "build", "-buildmode=pie", "-o="+name, "execgo")
+ defer os.Remove(name)
+ run(t, name, "./"+name)
+ checkPIE(t, name)
+}
+
+// Build a GOPATH package into a shared library that links against the goroot runtime
+// and an executable that links against both.
+func TestGopathShlib(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ AssertIsLinkedTo(t, filepath.Join(gopathInstallDir, "libdepBase.so"), soname)
+ goCmd(t, "install", "-linkshared", "exe")
+ AssertIsLinkedTo(t, "./bin/exe", soname)
+ AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
+ AssertHasRPath(t, "./bin/exe", gorootInstallDir)
+ AssertHasRPath(t, "./bin/exe", gopathInstallDir)
+ // And check it runs.
+ run(t, "executable linked to GOPATH library", "./bin/exe")
+}
+
+// The shared library contains a note listing the packages it contains in a section
+// that is not mapped into memory.
+func testPkgListNote(t *testing.T, f *elf.File, note *note) {
+ if note.section.Flags != 0 {
+ t.Errorf("package list section has flags %v", note.section.Flags)
+ }
+ if isOffsetLoaded(f, note.section.Offset) {
+ t.Errorf("package list section contained in PT_LOAD segment")
+ }
+ if note.desc != "depBase\n" {
+ t.Errorf("incorrect package list %q", note.desc)
+ }
+}
+
+// The shared library contains a note containing the ABI hash that is mapped into
+// memory and there is a local symbol called go.link.abihashbytes that points 16
+// bytes into it.
+func testABIHashNote(t *testing.T, f *elf.File, note *note) {
+ if note.section.Flags != elf.SHF_ALLOC {
+ t.Errorf("abi hash section has flags %v", note.section.Flags)
+ }
+ if !isOffsetLoaded(f, note.section.Offset) {
+ t.Errorf("abihash section not contained in PT_LOAD segment")
+ }
+ var hashbytes elf.Symbol
+ symbols, err := f.Symbols()
+ if err != nil {
+ t.Errorf("error reading symbols %v", err)
+ return
+ }
+ for _, sym := range symbols {
+ if sym.Name == "go.link.abihashbytes" {
+ hashbytes = sym
+ }
+ }
+ if hashbytes.Name == "" {
+ t.Errorf("no symbol called go.link.abihashbytes")
+ return
+ }
+ if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL {
+ t.Errorf("%s has incorrect binding %v", hashbytes.Name, elf.ST_BIND(hashbytes.Info))
+ }
+ if f.Sections[hashbytes.Section] != note.section {
+ t.Errorf("%s has incorrect section %v", hashbytes.Name, f.Sections[hashbytes.Section].Name)
+ }
+ if hashbytes.Value-note.section.Addr != 16 {
+ t.Errorf("%s has incorrect offset into section %d", hashbytes.Name, hashbytes.Value-note.section.Addr)
+ }
+}
+
+// A Go shared library contains a note indicating which other Go shared libraries it
+// was linked against in an unmapped section.
+func testDepsNote(t *testing.T, f *elf.File, note *note) {
+ if note.section.Flags != 0 {
+ t.Errorf("package list section has flags %v", note.section.Flags)
+ }
+ if isOffsetLoaded(f, note.section.Offset) {
+ t.Errorf("package list section contained in PT_LOAD segment")
+ }
+ // libdepBase.so just links against the lib containing the runtime.
+ if note.desc != soname {
+ t.Errorf("incorrect dependency list %q", note.desc)
+ }
+}
+
+// The shared library contains notes with defined contents; see above.
+func TestNotes(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ f, err := elf.Open(filepath.Join(gopathInstallDir, "libdepBase.so"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ notes, err := readNotes(f)
+ if err != nil {
+ t.Fatal(err)
+ }
+ pkgListNoteFound := false
+ abiHashNoteFound := false
+ depsNoteFound := false
+ for _, note := range notes {
+ if note.name != "Go\x00\x00" {
+ continue
+ }
+ switch note.tag {
+ case 1: // ELF_NOTE_GOPKGLIST_TAG
+ if pkgListNoteFound {
+ t.Error("multiple package list notes")
+ }
+ testPkgListNote(t, f, note)
+ pkgListNoteFound = true
+ case 2: // ELF_NOTE_GOABIHASH_TAG
+ if abiHashNoteFound {
+ t.Error("multiple abi hash notes")
+ }
+ testABIHashNote(t, f, note)
+ abiHashNoteFound = true
+ case 3: // ELF_NOTE_GODEPS_TAG
+ if depsNoteFound {
+ t.Error("multiple abi hash notes")
+ }
+ testDepsNote(t, f, note)
+ depsNoteFound = true
+ }
+ }
+ if !pkgListNoteFound {
+ t.Error("package list note not found")
+ }
+ if !abiHashNoteFound {
+ t.Error("abi hash note not found")
+ }
+ if !depsNoteFound {
+ t.Error("deps note not found")
+ }
+}
+
+// Build a GOPATH package (depBase) into a shared library that links against the goroot
+// runtime, another package (dep2) that links against the first, and and an
+// executable that links against dep2.
+func TestTwoGopathShlibs(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
+ goCmd(t, "install", "-linkshared", "exe2")
+ run(t, "executable linked to GOPATH library", "./bin/exe2")
+}
+
+func TestThreeGopathShlibs(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep2")
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep3")
+ goCmd(t, "install", "-linkshared", "exe3")
+ run(t, "executable linked to GOPATH library", "./bin/exe3")
+}
+
+// If gccgo is not available or not new enough call t.Skip. Otherwise,
+// return a build.Context that is set up for gccgo.
+func prepGccgo(t *testing.T) build.Context {
+ gccgoName := os.Getenv("GCCGO")
+ if gccgoName == "" {
+ gccgoName = "gccgo"
+ }
+ gccgoPath, err := exec.LookPath(gccgoName)
+ if err != nil {
+ t.Skip("gccgo not found")
+ }
+ cmd := exec.Command(gccgoPath, "-dumpversion")
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output)
+ }
+ if string(output) < "5" {
+ t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output)))
+ }
+ gccgoContext := build.Default
+ gccgoContext.InstallSuffix = suffix + "_fPIC"
+ gccgoContext.Compiler = "gccgo"
+ gccgoContext.GOPATH = os.Getenv("GOPATH")
+ return gccgoContext
+}
+
+// Build a GOPATH package into a shared library with gccgo and an executable that
+// links against it.
+func TestGoPathShlibGccgo(t *testing.T) {
+ gccgoContext := prepGccgo(t)
+
+ libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
+
+ depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
+ if err != nil {
+ t.Fatalf("import failed: %v", err)
+ }
+ gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
+ goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
+ AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
+ goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe")
+ AssertIsLinkedToRegexp(t, "./bin/exe", libgoRE)
+ AssertIsLinkedTo(t, "./bin/exe", "libdepBase.so")
+ AssertHasRPath(t, "./bin/exe", gccgoInstallDir)
+ // And check it runs.
+ run(t, "gccgo-built", "./bin/exe")
+}
+
+// The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared
+// library with gccgo, another GOPATH package that depends on the first and an
+// executable that links the second library.
+func TestTwoGopathShlibsGccgo(t *testing.T) {
+ gccgoContext := prepGccgo(t)
+
+ libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
+
+ depP, err := gccgoContext.Import("depBase", ".", build.ImportComment)
+ if err != nil {
+ t.Fatalf("import failed: %v", err)
+ }
+ gccgoInstallDir := filepath.Join(depP.PkgTargetRoot, "shlibs")
+ goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "depBase")
+ goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "dep2")
+ goCmd(t, "install", "-compiler=gccgo", "-linkshared", "exe2")
+
+ AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdepBase.so"), libgoRE)
+ AssertIsLinkedToRegexp(t, filepath.Join(gccgoInstallDir, "libdep2.so"), libgoRE)
+ AssertIsLinkedTo(t, filepath.Join(gccgoInstallDir, "libdep2.so"), "libdepBase.so")
+ AssertIsLinkedToRegexp(t, "./bin/exe2", libgoRE)
+ AssertIsLinkedTo(t, "./bin/exe2", "libdep2")
+ AssertIsLinkedTo(t, "./bin/exe2", "libdepBase.so")
+
+ // And check it runs.
+ run(t, "gccgo-built", "./bin/exe2")
+}
+
+// Testing rebuilding of shared libraries when they are stale is a bit more
+// complicated that it seems like it should be. First, we make everything "old": but
+// only a few seconds old, or it might be older than gc (or the runtime source) and
+// everything will get rebuilt. Then define a timestamp slightly newer than this
+// time, which is what we set the mtime to of a file to cause it to be seen as new,
+// and finally another slightly even newer one that we can compare files against to
+// see if they have been rebuilt.
+var oldTime = time.Now().Add(-9 * time.Second)
+var nearlyNew = time.Now().Add(-6 * time.Second)
+var stampTime = time.Now().Add(-3 * time.Second)
+
+// resetFileStamps makes "everything" (bin, src, pkg from GOPATH and the
+// test-specific parts of GOROOT) appear old.
+func resetFileStamps() {
+ chtime := func(path string, info os.FileInfo, err error) error {
+ return os.Chtimes(path, oldTime, oldTime)
+ }
+ reset := func(path string) {
+ if err := filepath.Walk(path, chtime); err != nil {
+ log.Fatalf("resetFileStamps failed: %v", err)
+ }
+
+ }
+ reset("bin")
+ reset("pkg")
+ reset("src")
+ reset(gorootInstallDir)
+}
+
+// touch makes path newer than the "old" time stamp used by resetFileStamps.
+func touch(path string) {
+ if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
+ log.Fatalf("os.Chtimes failed: %v", err)
+ }
+}
+
+// isNew returns if the path is newer than the time stamp used by touch.
+func isNew(path string) bool {
+ fi, err := os.Stat(path)
+ if err != nil {
+ log.Fatalf("os.Stat failed: %v", err)
+ }
+ return fi.ModTime().After(stampTime)
+}
+
+// Fail unless path has been rebuilt (i.e. is newer than the time stamp used by
+// isNew)
+func AssertRebuilt(t *testing.T, msg, path string) {
+ if !isNew(path) {
+ t.Errorf("%s was not rebuilt (%s)", msg, path)
+ }
+}
+
+// Fail if path has been rebuilt (i.e. is newer than the time stamp used by isNew)
+func AssertNotRebuilt(t *testing.T, msg, path string) {
+ if isNew(path) {
+ t.Errorf("%s was rebuilt (%s)", msg, path)
+ }
+}
+
+func TestRebuilding(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ goCmd(t, "install", "-linkshared", "exe")
+
+ // If the source is newer than both the .a file and the .so, both are rebuilt.
+ resetFileStamps()
+ touch("src/depBase/dep.go")
+ goCmd(t, "install", "-linkshared", "exe")
+ AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "depBase.a"))
+ AssertRebuilt(t, "new source", filepath.Join(gopathInstallDir, "libdepBase.so"))
+
+ // If the .a file is newer than the .so, the .so is rebuilt (but not the .a)
+ resetFileStamps()
+ touch(filepath.Join(gopathInstallDir, "depBase.a"))
+ goCmd(t, "install", "-linkshared", "exe")
+ AssertNotRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "depBase.a"))
+ AssertRebuilt(t, "new .a file", filepath.Join(gopathInstallDir, "libdepBase.so"))
+}
+
+func appendFile(path, content string) {
+ f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660)
+ if err != nil {
+ log.Fatalf("os.OpenFile failed: %v", err)
+ }
+ defer func() {
+ err := f.Close()
+ if err != nil {
+ log.Fatalf("f.Close failed: %v", err)
+ }
+ }()
+ _, err = f.WriteString(content)
+ if err != nil {
+ log.Fatalf("f.WriteString failed: %v", err)
+ }
+}
+
+func TestABIChecking(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ goCmd(t, "install", "-linkshared", "exe")
+
+ // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe,
+ // exe will abort with a complaint on startup.
+ // This assumes adding an exported function breaks ABI, which is not true in
+ // some senses but suffices for the narrow definition of ABI compatibility the
+ // toolchain uses today.
+ resetFileStamps()
+ appendFile("src/depBase/dep.go", "func ABIBreak() {}\n")
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ c := exec.Command("./bin/exe")
+ output, err := c.CombinedOutput()
+ if err == nil {
+ t.Fatal("executing exe did not fail after ABI break")
+ }
+ scanner := bufio.NewScanner(bytes.NewReader(output))
+ foundMsg := false
+ const wantLine = "abi mismatch detected between the executable and libdepBase.so"
+ for scanner.Scan() {
+ if scanner.Text() == wantLine {
+ foundMsg = true
+ break
+ }
+ }
+ if err = scanner.Err(); err != nil {
+ t.Errorf("scanner encountered error: %v", err)
+ }
+ if !foundMsg {
+ t.Fatalf("exe failed, but without line %q; got output:\n%s", wantLine, output)
+ }
+
+ // Rebuilding exe makes it work again.
+ goCmd(t, "install", "-linkshared", "exe")
+ run(t, "rebuilt exe", "./bin/exe")
+
+ // If we make a change which does not break ABI (such as adding an unexported
+ // function) and rebuild libdepBase.so, exe still works.
+ resetFileStamps()
+ appendFile("src/depBase/dep.go", "func noABIBreak() {}\n")
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
+ run(t, "after non-ABI breaking change", "./bin/exe")
+}
+
+// If a package 'explicit' imports a package 'implicit', building
+// 'explicit' into a shared library implicitly includes implicit in
+// the shared library. Building an executable that imports both
+// explicit and implicit builds the code from implicit into the
+// executable rather than fetching it from the shared library. The
+// link still succeeds and the executable still runs though.
+func TestImplicitInclusion(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "explicit")
+ goCmd(t, "install", "-linkshared", "implicitcmd")
+ run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
+}
+
+// Tests to make sure that the type fields of empty interfaces and itab
+// fields of nonempty interfaces are unique even across modules,
+// so that interface equality works correctly.
+func TestInterface(t *testing.T) {
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_a")
+ // Note: iface_i gets installed implicitly as a dependency of iface_a.
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_b")
+ goCmd(t, "install", "-linkshared", "iface")
+ run(t, "running type/itab uniqueness tester", "./bin/iface")
+}
diff --git a/libgo/misc/cgo/testshared/src/dep2/dep2.go b/libgo/misc/cgo/testshared/src/dep2/dep2.go
new file mode 100644
index 00000000000..c2c812adb9b
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/dep2/dep2.go
@@ -0,0 +1,15 @@
+package dep2
+
+import "depBase"
+
+var W int = 1
+
+var hasProg depBase.HasProg
+
+type Dep2 struct {
+ depBase.Dep
+}
+
+func G() int {
+ return depBase.F() + 1
+}
diff --git a/libgo/misc/cgo/testshared/src/dep3/dep3.go b/libgo/misc/cgo/testshared/src/dep3/dep3.go
new file mode 100644
index 00000000000..7b7c9dac1f9
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/dep3/dep3.go
@@ -0,0 +1,22 @@
+package dep3
+
+// The point of this test file is that it references a type from
+// depBase that is also referenced in dep2, but dep2 is loaded by the
+// linker before depBase (because it is earlier in the import list).
+// There was a bug in the linker where it would not correctly read out
+// the type data in this case and later crash.
+
+import (
+ "dep2"
+ "depBase"
+)
+
+type Dep3 struct {
+ dep depBase.Dep
+ dep2 dep2.Dep2
+}
+
+func D3() int {
+ var x Dep3
+ return x.dep.X + x.dep2.X
+}
diff --git a/libgo/misc/cgo/testshared/src/depBase/asm.s b/libgo/misc/cgo/testshared/src/depBase/asm.s
new file mode 100644
index 00000000000..f203f8b0301
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/depBase/asm.s
@@ -0,0 +1,10 @@
+// Copyright 2014 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.
+
+//+build !gccgo
+
+#include "textflag.h"
+
+TEXT ·ImplementedInAsm(SB),NOSPLIT,$0-0
+ RET
diff --git a/libgo/misc/cgo/testshared/src/depBase/dep.go b/libgo/misc/cgo/testshared/src/depBase/dep.go
new file mode 100644
index 00000000000..9f86710db01
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/depBase/dep.go
@@ -0,0 +1,33 @@
+package depBase
+
+import (
+ "os"
+ "reflect"
+)
+
+var SlicePtr interface{} = &[]int{}
+
+var V int = 1
+
+var HasMask []string = []string{"hi"}
+
+type HasProg struct {
+ array [1024]*byte
+}
+
+type Dep struct {
+ X int
+}
+
+func (d *Dep) Method() int {
+ // This code below causes various go.itab.* symbols to be generated in
+ // the shared library. Similar code in ../exe/exe.go results in
+ // exercising https://github.com/golang/go/issues/17594
+ reflect.TypeOf(os.Stdout).Elem()
+ return 10
+}
+
+func F() int {
+ defer func() {}()
+ return V
+}
diff --git a/libgo/misc/cgo/testshared/src/depBase/gccgo.go b/libgo/misc/cgo/testshared/src/depBase/gccgo.go
new file mode 100644
index 00000000000..3e2b69b50bc
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/depBase/gccgo.go
@@ -0,0 +1,5 @@
+//+build gccgo
+
+package depBase
+
+func ImplementedInAsm() {}
diff --git a/libgo/misc/cgo/testshared/src/depBase/stubs.go b/libgo/misc/cgo/testshared/src/depBase/stubs.go
new file mode 100644
index 00000000000..96573c12ece
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/depBase/stubs.go
@@ -0,0 +1,5 @@
+//+build !gccgo
+
+package depBase
+
+func ImplementedInAsm()
diff --git a/libgo/misc/cgo/testshared/src/exe/exe.go b/libgo/misc/cgo/testshared/src/exe/exe.go
new file mode 100644
index 00000000000..84302a811f0
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/exe/exe.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "depBase"
+ "os"
+ "reflect"
+ "runtime"
+)
+
+// Having a function declared in the main package triggered
+// golang.org/issue/18250
+func DeclaredInMain() {
+}
+
+type C struct {
+}
+
+func F() *C {
+ return nil
+}
+
+var slicePtr interface{} = &[]int{}
+
+func main() {
+ defer depBase.ImplementedInAsm()
+ // This code below causes various go.itab.* symbols to be generated in
+ // the executable. Similar code in ../depBase/dep.go results in
+ // exercising https://github.com/golang/go/issues/17594
+ reflect.TypeOf(os.Stdout).Elem()
+ runtime.GC()
+ depBase.V = depBase.F() + 1
+
+ var c *C
+ if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) {
+ panic("bad reflection results, see golang.org/issue/18252")
+ }
+
+ sp := reflect.New(reflect.TypeOf(slicePtr).Elem())
+ s := sp.Interface()
+
+ if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) {
+ panic("bad reflection results, see golang.org/issue/18729")
+ }
+}
diff --git a/libgo/misc/cgo/testshared/src/exe2/exe2.go b/libgo/misc/cgo/testshared/src/exe2/exe2.go
new file mode 100644
index 00000000000..675fd1f365c
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/exe2/exe2.go
@@ -0,0 +1,8 @@
+package main
+
+import "dep2"
+
+func main() {
+ d := &dep2.Dep2{}
+ dep2.W = dep2.G() + 1 + d.Method()
+}
diff --git a/libgo/misc/cgo/testshared/src/exe3/exe3.go b/libgo/misc/cgo/testshared/src/exe3/exe3.go
new file mode 100644
index 00000000000..643f2605f66
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/exe3/exe3.go
@@ -0,0 +1,7 @@
+package main
+
+import "dep3"
+
+func main() {
+ dep3.D3()
+}
diff --git a/libgo/misc/cgo/testshared/src/execgo/exe.go b/libgo/misc/cgo/testshared/src/execgo/exe.go
new file mode 100644
index 00000000000..0427be8bdfd
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/execgo/exe.go
@@ -0,0 +1,8 @@
+package main
+
+/*
+ */
+import "C"
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testshared/src/explicit/explicit.go b/libgo/misc/cgo/testshared/src/explicit/explicit.go
new file mode 100644
index 00000000000..6a4453f7758
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/explicit/explicit.go
@@ -0,0 +1,9 @@
+package explicit
+
+import (
+ "implicit"
+)
+
+func E() int {
+ return implicit.I()
+}
diff --git a/libgo/misc/cgo/testshared/src/iface/main.go b/libgo/misc/cgo/testshared/src/iface/main.go
new file mode 100644
index 00000000000..3d5b54e73b9
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/iface/main.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package main
+
+import "iface_a"
+import "iface_b"
+
+func main() {
+ if iface_a.F() != iface_b.F() {
+ panic("empty interfaces not equal")
+ }
+ if iface_a.G() != iface_b.G() {
+ panic("non-empty interfaces not equal")
+ }
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_a/a.go b/libgo/misc/cgo/testshared/src/iface_a/a.go
new file mode 100644
index 00000000000..e11047c166c
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/iface_a/a.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package iface_a
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+ return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+ return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_b/b.go b/libgo/misc/cgo/testshared/src/iface_b/b.go
new file mode 100644
index 00000000000..47aee2e77ee
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/iface_b/b.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package iface_b
+
+import "iface_i"
+
+//go:noinline
+func F() interface{} {
+ return (*iface_i.T)(nil)
+}
+
+//go:noinline
+func G() iface_i.I {
+ return (*iface_i.T)(nil)
+}
diff --git a/libgo/misc/cgo/testshared/src/iface_i/i.go b/libgo/misc/cgo/testshared/src/iface_i/i.go
new file mode 100644
index 00000000000..31c80387c7e
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/iface_i/i.go
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+package iface_i
+
+type I interface {
+ M()
+}
+
+type T struct {
+}
+
+func (t *T) M() {
+}
+
+// *T implements I
diff --git a/libgo/misc/cgo/testshared/src/implicit/implicit.go b/libgo/misc/cgo/testshared/src/implicit/implicit.go
new file mode 100644
index 00000000000..5360188c562
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/implicit/implicit.go
@@ -0,0 +1,5 @@
+package implicit
+
+func I() int {
+ return 42
+}
diff --git a/libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go b/libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go
new file mode 100644
index 00000000000..f6112933e56
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/implicitcmd/implicitcmd.go
@@ -0,0 +1,10 @@
+package main
+
+import (
+ "explicit"
+ "implicit"
+)
+
+func main() {
+ println(implicit.I() + explicit.E())
+}
diff --git a/libgo/misc/cgo/testshared/src/trivial/trivial.go b/libgo/misc/cgo/testshared/src/trivial/trivial.go
new file mode 100644
index 00000000000..da29a2cadf1
--- /dev/null
+++ b/libgo/misc/cgo/testshared/src/trivial/trivial.go
@@ -0,0 +1,4 @@
+package main
+
+func main() {
+}
diff --git a/libgo/misc/cgo/testsigfwd/main.go b/libgo/misc/cgo/testsigfwd/main.go
new file mode 100644
index 00000000000..61bd0da88a8
--- /dev/null
+++ b/libgo/misc/cgo/testsigfwd/main.go
@@ -0,0 +1,113 @@
+// Copyright 2015 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.
+
+package main
+
+import "fmt"
+
+/*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+int *p;
+static void sigsegv() {
+ *p = 1;
+ fprintf(stderr, "ERROR: C SIGSEGV not thrown on caught?.\n");
+ exit(2);
+}
+
+static void segvhandler(int signum) {
+ if (signum == SIGSEGV) {
+ exit(0); // success
+ }
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+ char a[1024];
+
+ *p = '\0';
+ if (i > 0) {
+ recur(i - 1, a);
+ }
+}
+
+static void iohandler(int signum) {
+ char a[1024];
+
+ recur(4, a);
+ sigioSeen = 1;
+}
+
+static void* sigioThread(void* arg __attribute__ ((unused))) {
+ raise(SIGIO);
+ return NULL;
+}
+
+static void sigioOnThread() {
+ pthread_t tid;
+ int i;
+
+ pthread_create(&tid, NULL, sigioThread, NULL);
+ pthread_join(tid, NULL);
+
+ // Wait until the signal has been delivered.
+ i = 0;
+ while (!sigioSeen) {
+ if (sched_yield() < 0) {
+ perror("sched_yield");
+ }
+ i++;
+ if (i > 10000) {
+ fprintf(stderr, "looping too long waiting for signal\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+static void __attribute__ ((constructor)) sigsetup(void) {
+ struct sigaction act;
+
+ memset(&act, 0, sizeof act);
+ act.sa_handler = segvhandler;
+ sigaction(SIGSEGV, &act, NULL);
+
+ act.sa_handler = iohandler;
+ sigaction(SIGIO, &act, NULL);
+}
+*/
+import "C"
+
+var p *byte
+
+func f() (ret bool) {
+ defer func() {
+ if recover() == nil {
+ fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.")
+ C.exit(2)
+ }
+ ret = true
+ }()
+ *p = 1
+ return false
+}
+
+func main() {
+ // Test that the signal originating in Go is handled (and recovered) by Go.
+ if !f() {
+ fmt.Errorf("couldn't recover from SIGSEGV in Go.")
+ C.exit(2)
+ }
+
+ // Test that the signal originating in C is handled by C.
+ C.sigsegv()
+}
diff --git a/libgo/misc/cgo/testso/cgoso.c b/libgo/misc/cgo/testso/cgoso.c
new file mode 100644
index 00000000000..917f472d368
--- /dev/null
+++ b/libgo/misc/cgo/testso/cgoso.c
@@ -0,0 +1,14 @@
+// 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.
+
+#include "_cgo_export.h"
+
+#ifdef WIN32
+extern void setCallback(void *);
+void init() {
+ setCallback(goCallback);
+}
+#else
+void init() {}
+#endif
diff --git a/libgo/misc/cgo/testso/cgoso.go b/libgo/misc/cgo/testso/cgoso.go
new file mode 100644
index 00000000000..29814fa43ae
--- /dev/null
+++ b/libgo/misc/cgo/testso/cgoso.go
@@ -0,0 +1,31 @@
+// Copyright 2011 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.
+
+package cgosotest
+
+/*
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo dragonfly LDFLAGS: -L. -l cgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo solaris LDFLAGS: -L. -lcgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
+void init(void);
+void sofunc(void);
+*/
+import "C"
+
+func Test() {
+ C.init()
+ C.sofunc()
+}
+
+//export goCallback
+func goCallback() {
+}
diff --git a/libgo/misc/cgo/testso/cgoso_c.c b/libgo/misc/cgo/testso/cgoso_c.c
new file mode 100644
index 00000000000..7a38022b547
--- /dev/null
+++ b/libgo/misc/cgo/testso/cgoso_c.c
@@ -0,0 +1,30 @@
+// Copyright 2011 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.
+
+// +build ignore
+
+#ifdef WIN32
+// A Windows DLL is unable to call an arbitrary function in
+// the main executable. Work around that by making the main
+// executable pass the callback function pointer to us.
+void (*goCallback)(void);
+__declspec(dllexport) void setCallback(void *f)
+{
+ goCallback = (void (*)())f;
+}
+__declspec(dllexport) void sofunc(void);
+#else
+extern void goCallback(void);
+void setCallback(void *f) { (void)f; }
+#endif
+
+// OpenBSD and older Darwin lack TLS support
+#if !defined(__OpenBSD__) && !defined(__APPLE__)
+__thread int tlsvar = 12345;
+#endif
+
+void sofunc(void)
+{
+ goCallback();
+}
diff --git a/libgo/misc/cgo/testso/cgoso_unix.go b/libgo/misc/cgo/testso/cgoso_unix.go
new file mode 100644
index 00000000000..49cdeaa2f59
--- /dev/null
+++ b/libgo/misc/cgo/testso/cgoso_unix.go
@@ -0,0 +1,20 @@
+// Copyright 2014 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.
+
+// +build dragonfly freebsd linux netbsd solaris
+
+package cgosotest
+
+/*
+extern int __thread tlsvar;
+int *getTLS() { return &tlsvar; }
+*/
+import "C"
+
+func init() {
+ if v := *C.getTLS(); v != 12345 {
+ println("got", v)
+ panic("BAD TLS value")
+ }
+}
diff --git a/libgo/misc/cgo/testso/main.go b/libgo/misc/cgo/testso/main.go
new file mode 100644
index 00000000000..88aa4322d24
--- /dev/null
+++ b/libgo/misc/cgo/testso/main.go
@@ -0,0 +1,13 @@
+// Copyright 2011 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.
+
+// +build ignore
+
+package main
+
+import "."
+
+func main() {
+ cgosotest.Test()
+}
diff --git a/libgo/misc/cgo/testsovar/cgoso.go b/libgo/misc/cgo/testsovar/cgoso.go
new file mode 100644
index 00000000000..88d44c2c6ee
--- /dev/null
+++ b/libgo/misc/cgo/testsovar/cgoso.go
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+package cgosotest
+
+// This test verifies that Go can access C variables
+// in shared object file via cgo.
+
+/*
+// intentionally write the same LDFLAGS differently
+// to test correct handling of LDFLAGS.
+#cgo windows CFLAGS: -DIMPORT_DLL
+#cgo linux LDFLAGS: -L. -lcgosotest
+#cgo dragonfly LDFLAGS: -L. -l cgosotest
+#cgo freebsd LDFLAGS: -L. -l cgosotest
+#cgo openbsd LDFLAGS: -L. -l cgosotest
+#cgo solaris LDFLAGS: -L. -lcgosotest
+#cgo netbsd LDFLAGS: -L. libcgosotest.so
+#cgo darwin LDFLAGS: -L. libcgosotest.dylib
+#cgo windows LDFLAGS: -L. libcgosotest.dll
+
+#include "cgoso_c.h"
+
+const char* getVar() {
+ return exported_var;
+}
+*/
+import "C"
+
+import "fmt"
+
+func Test() {
+ const want = "Hello world"
+ got := C.GoString(C.getVar())
+ if got != want {
+ panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want))
+ }
+ got = C.GoString(C.exported_var)
+ if got != want {
+ panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want))
+ }
+}
diff --git a/libgo/misc/cgo/testsovar/cgoso_c.c b/libgo/misc/cgo/testsovar/cgoso_c.c
new file mode 100644
index 00000000000..a448c013428
--- /dev/null
+++ b/libgo/misc/cgo/testsovar/cgoso_c.c
@@ -0,0 +1,7 @@
+// Copyright 2015 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.
+
+// +build ignore
+
+const char *exported_var = "Hello world";
diff --git a/libgo/misc/cgo/testsovar/cgoso_c.h b/libgo/misc/cgo/testsovar/cgoso_c.h
new file mode 100644
index 00000000000..640db7b396a
--- /dev/null
+++ b/libgo/misc/cgo/testsovar/cgoso_c.h
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// +build ignore
+
+#ifdef WIN32
+#if defined(EXPORT_DLL)
+# define VAR __declspec(dllexport)
+#elif defined(IMPORT_DLL)
+# define VAR __declspec(dllimport)
+#endif
+#else
+# define VAR extern
+#endif
+
+VAR const char *exported_var;
diff --git a/libgo/misc/cgo/testsovar/main.go b/libgo/misc/cgo/testsovar/main.go
new file mode 100644
index 00000000000..9c8a1c4e66e
--- /dev/null
+++ b/libgo/misc/cgo/testsovar/main.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build ignore
+
+package main
+
+import "."
+
+func main() {
+ cgosotest.Test()
+}
diff --git a/libgo/misc/cgo/testtls/tls.go b/libgo/misc/cgo/testtls/tls.go
new file mode 100644
index 00000000000..e634220be7c
--- /dev/null
+++ b/libgo/misc/cgo/testtls/tls.go
@@ -0,0 +1,30 @@
+// 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.
+
+package cgotlstest
+
+// #include <pthread.h>
+// extern void setTLS(int);
+// extern int getTLS();
+import "C"
+
+import (
+ "runtime"
+ "testing"
+)
+
+func testTLS(t *testing.T) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if val := C.getTLS(); val != 0 {
+ t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+ }
+
+ const keyVal = 0x1234
+ C.setTLS(keyVal)
+ if val := C.getTLS(); val != keyVal {
+ t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
+ }
+}
diff --git a/libgo/misc/cgo/testtls/tls_test.go b/libgo/misc/cgo/testtls/tls_test.go
new file mode 100644
index 00000000000..3076c2d5943
--- /dev/null
+++ b/libgo/misc/cgo/testtls/tls_test.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build !windows
+
+package cgotlstest
+
+import "testing"
+
+func TestTLS(t *testing.T) {
+ testTLS(t)
+}
diff --git a/libgo/misc/cgo/testtls/tls_unix.c b/libgo/misc/cgo/testtls/tls_unix.c
new file mode 100644
index 00000000000..957afce90d4
--- /dev/null
+++ b/libgo/misc/cgo/testtls/tls_unix.c
@@ -0,0 +1,19 @@
+// 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.
+
+#include <pthread.h>
+
+static __thread int tls;
+
+void
+setTLS(int v)
+{
+ tls = v;
+}
+
+int
+getTLS()
+{
+ return tls;
+}
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 8fd8eadefc6..fe0bb545605 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -310,17 +310,8 @@ upcase_fields () {
# _user_regs_struct.
regs=`grep '^type _user_regs_struct struct' gen-sysinfo.go || true`
if test "$regs" = ""; then
- # s390
- regs=`grep '^type __user_regs_struct struct' gen-sysinfo.go || true`
- if test "$regs" != ""; then
- # Substructures of __user_regs_struct on s390
- upcase_fields "__user_psw_struct" "PtracePsw" >> ${OUT} || true
- upcase_fields "__user_fpregs_struct" "PtraceFpregs" >> ${OUT} || true
- upcase_fields "__user_per_struct" "PtracePer" >> ${OUT} || true
- else
- # mips*
- regs=`grep '^type _pt_regs struct' gen-sysinfo.go || true`
- fi
+ # mips*
+ regs=`grep '^type _pt_regs struct' gen-sysinfo.go || true`
fi
if test "$regs" != ""; then
regs=`echo $regs | sed -e 's/type _pt_regs struct//'`
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c
index a35d8d73f44..360bae69594 100644
--- a/libgo/runtime/go-caller.c
+++ b/libgo/runtime/go-caller.c
@@ -74,7 +74,7 @@ static void *back_state;
/* A lock to control creating back_state. */
-static Lock back_state_lock;
+static uint32 back_state_lock;
/* The program arguments. */
@@ -85,7 +85,15 @@ extern Slice runtime_get_args(void);
struct backtrace_state *
__go_get_backtrace_state ()
{
- runtime_lock (&back_state_lock);
+ uint32 set;
+
+ /* We may not have a g here, so we can't use runtime_lock. */
+ set = 0;
+ while (!__atomic_compare_exchange_n (&back_state_lock, &set, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
+ {
+ runtime_osyield ();
+ set = 0;
+ }
if (back_state == NULL)
{
Slice args;
@@ -113,7 +121,7 @@ __go_get_backtrace_state ()
back_state = backtrace_create_state (filename, 1, error_callback, NULL);
}
- runtime_unlock (&back_state_lock);
+ __atomic_store_n (&back_state_lock, 0, __ATOMIC_RELEASE);
return back_state;
}
diff --git a/libgo/runtime/go-libmain.c b/libgo/runtime/go-libmain.c
index 06f6bd32f35..5e3b8d9e48a 100644
--- a/libgo/runtime/go-libmain.c
+++ b/libgo/runtime/go-libmain.c
@@ -105,7 +105,8 @@ gostart (void *arg)
runtime_check ();
runtime_args (a->argc, (byte **) a->argv);
- runtime_osinit ();
+ setncpu (getproccount ());
+ setpagesize (getpagesize ());
runtime_sched = runtime_getsched();
runtime_schedinit ();
__go_go (runtime_main, NULL);
diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c
index 26354ce69b0..1048161786c 100644
--- a/libgo/runtime/go-main.c
+++ b/libgo/runtime/go-main.c
@@ -51,7 +51,8 @@ main (int argc, char **argv)
runtime_cpuinit ();
runtime_check ();
runtime_args (argc, (byte **) argv);
- runtime_osinit ();
+ setncpu (getproccount ());
+ setpagesize (getpagesize ());
runtime_sched = runtime_getsched();
runtime_schedinit ();
__go_go (runtime_main, NULL);
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index ad29662d0fd..8c7ecbae3b5 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -215,6 +215,16 @@ getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP];
#endif
#endif
+#ifdef __alpha__
+ #ifdef __linux__
+ ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc;
+ #endif
+#endif
+#ifdef __PPC__
+ #ifdef __linux__
+ ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.regs->nip;
+ #endif
+#endif
if (ret.sigpc == 0) {
// Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 1272669a8bd..3e3437e6a47 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -370,7 +370,6 @@ extern G* allocg(void)
__asm__ (GOSYM_PREFIX "runtime.allocg");
Sched* runtime_sched;
-int32 runtime_ncpu;
bool runtime_isarchive;
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 9f84f523f5e..3324038a57d 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -217,7 +217,6 @@ extern M* runtime_getallm(void)
extern Sched* runtime_sched;
extern uint32 runtime_panicking(void)
__asm__ (GOSYM_PREFIX "runtime.getPanicking");
-extern int32 runtime_ncpu;
extern struct debugVars runtime_debug;
extern bool runtime_isstarted;
@@ -237,7 +236,6 @@ void runtime_gogo(G*)
struct __go_func_type;
void runtime_args(int32, byte**)
__asm__ (GOSYM_PREFIX "runtime.args");
-void runtime_osinit();
void runtime_alginit(void)
__asm__ (GOSYM_PREFIX "runtime.alginit");
void runtime_goargs(void)
diff --git a/libgo/runtime/runtime_c.c b/libgo/runtime/runtime_c.c
index 336b2611324..6da35210440 100644
--- a/libgo/runtime/runtime_c.c
+++ b/libgo/runtime/runtime_c.c
@@ -139,6 +139,10 @@ uintptr getEnd(void)
uintptr
getEnd()
{
+#ifdef _AIX
+ // mmap adresses range start at 0x30000000 on AIX for 32 bits processes
+ uintptr end = 0x30000000U;
+#else
uintptr end = 0;
uintptr *pend;
@@ -146,6 +150,8 @@ getEnd()
if (pend != nil) {
end = *pend;
}
+#endif
+
return end;
}
diff --git a/libgo/runtime/thread-linux.c b/libgo/runtime/thread-linux.c
deleted file mode 100644
index f6d8be90caa..00000000000
--- a/libgo/runtime/thread-linux.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 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.
-
-#include "runtime.h"
-#include "defs.h"
-
-// Linux futex.
-
-#include <unistd.h>
-#include <syscall.h>
-#include <linux/futex.h>
-
-void
-runtime_osinit(void)
-{
- runtime_ncpu = getproccount();
- setncpu(runtime_ncpu);
- setpagesize(getpagesize());
-}
diff --git a/libgo/runtime/thread-sema.c b/libgo/runtime/thread-sema.c
deleted file mode 100644
index 77d53c41684..00000000000
--- a/libgo/runtime/thread-sema.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 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.
-
-#include "config.h"
-#include "runtime.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-#include <semaphore.h>
-
-void
-runtime_osinit (void)
-{
- runtime_ncpu = getproccount();
- setncpu(runtime_ncpu);
- setpagesize(getpagesize());
-}
diff --git a/libgo/sysinfo.c b/libgo/sysinfo.c
index a1afc7d119c..884d01716b8 100644
--- a/libgo/sysinfo.c
+++ b/libgo/sysinfo.c
@@ -103,7 +103,16 @@
#include <linux/netlink.h>
#endif
#if defined(HAVE_LINUX_PTRACE_H)
+/* Avoid https://sourceware.org/bugzilla/show_bug.cgi?id=762 . */
+#define ia64_fpreg pt_ia64_fpreg
+#define pt_all_user_regs pt_ia64_all_user_regs
+/* Avoid redefinition of ptrace_peeksiginfo from <sys/ptrace.h>.
+ https://gcc.gnu.org/PR81324 . */
+#define ptrace_peeksiginfo_args ignore_ptrace_peeksiginfo_args
#include <linux/ptrace.h>
+#undef ia64_fpreg
+#undef pt_all_user_regs
+#undef ptrace_peeksiginfo_args
#endif
#if defined(HAVE_LINUX_RTNETLINK_H)
#include <linux/rtnetlink.h>
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index da9946fed94..0e6258ff87a 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,34 @@
+2017-07-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/45784
+ * testsuite/libgomp.c/pr45784.c: New test.
+ * testsuite/libgomp.c++/pr45784.C: New test.
+
+2017-07-19 Tom de Vries <tom@codesourcery.com>
+
+ * testsuite/libgomp.oacc-c/vec.c: New test.
+
+2017-07-03 Tom de Vries <tom@codesourcery.com>
+
+ * plugin/plugin-hsa.c: Fix secure_getenv.h include.
+
+2017-06-27 Tom de Vries <tom@codesourcery.com>
+
+ * plugin/plugin-nvptx.c (notify_var): New function.
+ (nvptx_exec): Use notify_var for GOMP_OPENACC_DIM.
+
+2017-06-27 Tom de Vries <tom@codesourcery.com>
+
+ * env.c (parse_unsigned_long_1): Factor out of ...
+ (parse_unsigned_long): ... here.
+ (parse_int_1): Factor out of ...
+ (parse_int): ... here.
+ (parse_int_secure): New function.
+ (initialize_env): Use parse_int_secure for GOMP_DEBUG.
+ * secure_getenv.h: Factor out of ...
+ * plugin/plugin-hsa.c: ... here.
+ * testsuite/libgomp.oacc-c-c++-common/gomp-debug-env.c: New test.
+
2017-06-21 Jakub Jelinek <jakub@redhat.com>
PR c++/81130
diff --git a/libgomp/env.c b/libgomp/env.c
index ced752d18e4..802c73bb464 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -26,6 +26,7 @@
/* This file defines the OpenMP internal control variables and arranges
for them to be initialized from environment variables at startup. */
+#define _GNU_SOURCE
#include "libgomp.h"
#include "gomp-constants.h"
#include <limits.h>
@@ -58,6 +59,8 @@
#endif
#endif /* LIBGOMP_OFFLOADED_ONLY */
+#include "secure_getenv.h"
+
struct gomp_task_icv gomp_global_icv = {
.nthreads_var = 1,
.thread_limit_var = UINT_MAX,
@@ -171,15 +174,17 @@ parse_schedule (void)
}
/* Parse an unsigned long environment variable. Return true if one was
- present and it was successfully parsed. */
+ present and it was successfully parsed. If SECURE, use secure_getenv to the
+ environment variable. */
static bool
-parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
+parse_unsigned_long_1 (const char *name, unsigned long *pvalue, bool allow_zero,
+ bool secure)
{
char *env, *end;
unsigned long value;
- env = getenv (name);
+ env = (secure ? secure_getenv (name) : getenv (name));
if (env == NULL)
return false;
@@ -206,14 +211,23 @@ parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
return false;
}
+/* As parse_unsigned_long_1, but always use getenv. */
+
+static bool
+parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
+{
+ return parse_unsigned_long_1 (name, pvalue, allow_zero, false);
+}
+
/* Parse a positive int environment variable. Return true if one was
- present and it was successfully parsed. */
+ present and it was successfully parsed. If SECURE, use secure_getenv to the
+ environment variable. */
static bool
-parse_int (const char *name, int *pvalue, bool allow_zero)
+parse_int_1 (const char *name, int *pvalue, bool allow_zero, bool secure)
{
unsigned long value;
- if (!parse_unsigned_long (name, &value, allow_zero))
+ if (!parse_unsigned_long_1 (name, &value, allow_zero, secure))
return false;
if (value > INT_MAX)
{
@@ -224,6 +238,22 @@ parse_int (const char *name, int *pvalue, bool allow_zero)
return true;
}
+/* As parse_int_1, but use getenv. */
+
+static bool
+parse_int (const char *name, int *pvalue, bool allow_zero)
+{
+ return parse_int_1 (name, pvalue, allow_zero, false);
+}
+
+/* As parse_int_1, but use getenv_secure. */
+
+static bool
+parse_int_secure (const char *name, int *pvalue, bool allow_zero)
+{
+ return parse_int_1 (name, pvalue, allow_zero, true);
+}
+
/* Parse an unsigned long list environment variable. Return true if one was
present and it was successfully parsed. */
@@ -1207,7 +1237,7 @@ initialize_env (void)
gomp_global_icv.thread_limit_var
= thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
}
- parse_int ("GOMP_DEBUG", &gomp_debug_var, true);
+ parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
#ifndef HAVE_SYNC_BUILTINS
gomp_mutex_init (&gomp_managed_threads_lock);
#endif
diff --git a/libgomp/plugin/plugin-hsa.c b/libgomp/plugin/plugin-hsa.c
index 90ca24719d0..fc08f5df058 100644
--- a/libgomp/plugin/plugin-hsa.c
+++ b/libgomp/plugin/plugin-hsa.c
@@ -39,32 +39,7 @@
#include <dlfcn.h>
#include "libgomp-plugin.h"
#include "gomp-constants.h"
-
-/* Secure getenv() which returns NULL if running as SUID/SGID. */
-#ifndef HAVE_SECURE_GETENV
-#ifdef HAVE___SECURE_GETENV
-#define secure_getenv __secure_getenv
-#elif defined (HAVE_UNISTD_H) && defined(HAVE_GETUID) && defined(HAVE_GETEUID) \
- && defined(HAVE_GETGID) && defined(HAVE_GETEGID)
-
-#include <unistd.h>
-
-/* Implementation of secure_getenv() for targets where it is not provided but
- we have at least means to test real and effective IDs. */
-
-static char *
-secure_getenv (const char *name)
-{
- if ((getuid () == geteuid ()) && (getgid () == getegid ()))
- return getenv (name);
- else
- return NULL;
-}
-
-#else
-#define secure_getenv getenv
-#endif
-#endif
+#include "secure_getenv.h"
/* As an HSA runtime is dlopened, following structure defines function
pointers utilized by the HSA plug-in. */
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index 0e1b3e2d4f3..71630b57355 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -867,6 +867,14 @@ nvptx_get_num_devices (void)
return n;
}
+static void
+notify_var (const char *var_name, const char *env_var)
+{
+ if (env_var == NULL)
+ GOMP_PLUGIN_debug (0, "%s: <Not defined>\n", var_name);
+ else
+ GOMP_PLUGIN_debug (0, "%s: '%s'\n", var_name, env_var);
+}
static bool
link_ptx (CUmodule *module, const struct targ_ptx_obj *ptx_objs,
@@ -1089,10 +1097,12 @@ nvptx_exec (void (*fn), size_t mapnum, void **hostaddrs, void **devaddrs,
pthread_mutex_lock (&ptx_dev_lock);
if (!default_dims[0])
{
+ const char *var_name = "GOMP_OPENACC_DIM";
/* We only read the environment variable once. You can't
change it in the middle of execution. The syntax is
the same as for the -fopenacc-dim compilation option. */
- const char *env_var = getenv ("GOMP_OPENACC_DIM");
+ const char *env_var = getenv (var_name);
+ notify_var (var_name, env_var);
if (env_var)
{
const char *pos = env_var;
diff --git a/libgomp/secure_getenv.h b/libgomp/secure_getenv.h
new file mode 100644
index 00000000000..0d3ec5f6868
--- /dev/null
+++ b/libgomp/secure_getenv.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2017 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.
+
+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 _SECURE_GETENV_H
+#define _SECURE_GETENV_H 1
+
+/* Secure getenv() which returns NULL if running as SUID/SGID. */
+#ifndef HAVE_SECURE_GETENV
+#if defined (HAVE_UNISTD_H) && defined (HAVE_GETUID) \
+ && defined (HAVE_GETEUID) && defined (HAVE_GETGID) \
+ && defined (HAVE_GETEGID)
+
+#include <unistd.h>
+
+#if SUPPORTS_WEAKREF && defined (HAVE___SECURE_GETENV)
+static char* weak_secure_getenv (const char*)
+ __attribute__((__weakref__("__secure_getenv")));
+#endif
+
+/* Implementation of secure_getenv() for targets where it is not provided but
+ we have at least means to test real and effective IDs. */
+
+static inline char *
+secure_getenv (const char *name)
+{
+#if SUPPORTS_WEAKREF && defined (HAVE___SECURE_GETENV)
+ if (weak_secure_getenv)
+ return weak_secure_getenv (name);
+#endif
+
+ if ((getuid () == geteuid ()) && (getgid () == getegid ()))
+ return getenv (name);
+ else
+ return NULL;
+}
+#else
+#define secure_getenv getenv
+#endif
+#endif
+
+#endif /* _SECURE_GETENV_H. */
diff --git a/libgomp/testsuite/libgomp.c++/pr45784.C b/libgomp/testsuite/libgomp.c++/pr45784.C
new file mode 100644
index 00000000000..306246c754a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr45784.C
@@ -0,0 +1,5 @@
+// PR c/45784
+// { dg-do run }
+
+#include "../libgomp.c/pr45784.c"
+
diff --git a/libgomp/testsuite/libgomp.c/pr45784.c b/libgomp/testsuite/libgomp.c/pr45784.c
new file mode 100644
index 00000000000..78612108bf6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr45784.c
@@ -0,0 +1,41 @@
+/* PR c/45784 */
+/* { dg-do run } */
+
+void
+foo (int n)
+{
+ char *p, vla[2 * n];
+ int i;
+ #pragma omp parallel for
+ for (p = vla; p < vla + (sizeof (vla) / sizeof (vla[0])); p++)
+ *p = ' ';
+ #pragma omp parallel for
+ for (i = 0; i < 2 * n; i++)
+ if (vla[i] != ' ')
+ __builtin_abort ();
+}
+
+void
+bar (int n)
+{
+ char *p, vla1[n], vla2[n * 2], vla3[n * 3], vla4[n * 4];
+ int i;
+ __builtin_memset (vla4, ' ', n * 4);
+ #pragma omp parallel for
+ for (p = vla4 + sizeof (vla1); p < vla4 + sizeof (vla3) - sizeof (vla2) + sizeof (vla1); p += sizeof (vla4) / sizeof (vla4))
+ p[0] = '!';
+ #pragma omp parallel for
+ for (i = 0; i < n * 4; i++)
+ if (vla4[i] != ((i >= n && i < 2 * n) ? '!' : ' '))
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ volatile int n;
+ n = 128;
+ foo (n);
+ bar (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/gomp-debug-env.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/gomp-debug-env.c
new file mode 100644
index 00000000000..3fc3503c3aa
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/gomp-debug-env.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var GOMP_DEBUG "1" } */
+
+/* Check that GOMP_DEBUG=1 triggers some output. */
+
+int
+main (void)
+{
+#pragma acc parallel
+ ;
+}
+
+/* { dg-output "GOACC_parallel_keyed" } */
diff --git a/libgomp/testsuite/libgomp.oacc-c/vec.c b/libgomp/testsuite/libgomp.oacc-c/vec.c
new file mode 100644
index 00000000000..79c1c175fe6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c/vec.c
@@ -0,0 +1,48 @@
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-DACC_MEM_SHARED=0" } } */
+/* { dg-additional-options "-std=c99 -ftree-slp-vectorize -foffload=-ftree-slp-vectorize -foffload=-fdump-tree-slp1 -foffload=-save-temps -save-temps" } */
+
+#include <stdio.h>
+#include <sys/time.h>
+
+long long int p[32 *1000] __attribute__((aligned(16)));
+long long int p2[32 *1000] __attribute__((aligned(16)));
+
+int
+main (void)
+{
+#pragma acc parallel num_gangs(1) num_workers(1) vector_length(32)
+ {
+ if (((unsigned long int)p & (0xfULL)) != 0)
+ __builtin_abort ();
+ if (((unsigned long int)p2 & (0xfULL)) != 0)
+ __builtin_abort ();
+
+ for (unsigned int k = 0; k < 10000; k += 1)
+ {
+#pragma acc loop vector
+ for (unsigned long long int j = 0; j < 32; j += 1)
+ {
+ unsigned long long a, b;
+ unsigned long long *p3, *p4;
+ p3 = (unsigned long long *)((unsigned long long int)p & (~0xfULL));
+ p4 = (unsigned long long *)((unsigned long long int)p2 & (~0xfULL));
+
+ for (unsigned int i = 0; i < 1000; i += 2)
+ {
+ a = p3[j * 1000 + i];
+ b = p3[j * 1000 + i + 1];
+
+ p4[j * 1000 + i] = a;
+ p4[j * 1000 + i + 1] = b;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Todo: make a scan-tree-dump variant that scans vec.o instead. */
+/* { dg-final { file copy -force [glob vec.o.*] [regsub \.o\. [glob vec.o.*] \.c\.] } } */
+/* { dg-final { scan-tree-dump "vector\\(2\\) long long unsigned int" "slp1" } } */
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 6e9ff713de1..027aa56c88d 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * dwarfnames.c (DW_FIRST_IDX, DW_END_IDX, DW_IDX, DW_IDX_DUP): New.
+
2017-06-07 Tony Reix <tony.reix@atos.net>
Matthieu Sarter <matthieu.sarter.external@atos.net>
David Edelsohn <dje.gcc@gmail.com>
diff --git a/libiberty/dwarfnames.c b/libiberty/dwarfnames.c
index 62563b75c8f..e58d03c3a3d 100644
--- a/libiberty/dwarfnames.c
+++ b/libiberty/dwarfnames.c
@@ -59,6 +59,11 @@ Boston, MA 02110-1301, USA. */
switch (opc) { \
DW_CFA (name, value)
#define DW_END_CFA } return 0; }
+#define DW_FIRST_IDX(name, value) \
+ const char *get_DW_IDX_name (unsigned int idx) { \
+ switch (idx) { \
+ DW_IDX (name, value)
+#define DW_END_IDX } return 0; }
#define DW_TAG(name, value) case name: return # name ;
#define DW_TAG_DUP(name, value)
@@ -70,6 +75,8 @@ Boston, MA 02110-1301, USA. */
#define DW_ATE(name, value) case name: return # name ;
#define DW_ATE_DUP(name, value)
#define DW_CFA(name, value) case name: return # name ;
+#define DW_IDX(name, value) case name: return # name ;
+#define DW_IDX_DUP(name, value)
#include "dwarf2.def"
@@ -85,6 +92,8 @@ Boston, MA 02110-1301, USA. */
#undef DW_END_ATE
#undef DW_FIRST_CFA
#undef DW_END_CFA
+#undef DW_FIRST_IDX
+#undef DW_END_IDX
#undef DW_TAG
#undef DW_TAG_DUP
@@ -96,3 +105,5 @@ Boston, MA 02110-1301, USA. */
#undef DW_ATE
#undef DW_ATE_DUP
#undef DW_CFA
+#undef DW_IDX
+#undef DW_IDX_DUP
diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog
index 4bd166b0ff9..bc37c3f66ba 100644
--- a/libquadmath/ChangeLog
+++ b/libquadmath/ChangeLog
@@ -1,3 +1,57 @@
+2017-07-19 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * math/powq.c (powq): Use uint32_t instead of u_int32_t.
+
+2017-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR libquadmath/65757
+ * quadmath-imp.h (math_opt_barrier, math_force_eval,
+ math_narrow_eval, math_check_force_underflow,
+ math_check_force_underflow_nonneg): Define.
+ * math/ceilq.c: Backport changes from upstream glibc
+ between 2012-11-01 and 2017-07-13.
+ * math/remquoq.c: Likewise.
+ * math/expq.c: Likewise.
+ * math/llroundq.c: Likewise.
+ * math/logq.c: Likewise.
+ * math/atanq.c: Likewise.
+ * math/nearbyintq.c: Likewise.
+ * math/scalblnq.c: Likewise.
+ * math/finiteq.c: Likewise.
+ * math/atanhq.c: Likewise.
+ * math/expm1q.c: Likewise.
+ * math/sinhq.c: Likewise.
+ * math/log10q.c: Likewise.
+ * math/rintq.c: Likewise.
+ * math/roundq.c: Likewise.
+ * math/fmaq.c: Likewise.
+ * math/erfq.c: Likewise.
+ * math/log2q.c: Likewise.
+ * math/lroundq.c: Likewise.
+ * math/j1q.c: Likewise.
+ * math/scalbnq.c: Likewise.
+ * math/truncq.c: Likewise.
+ * math/frexpq.c: Likewise.
+ * math/sincosq.c: Likewise.
+ * math/tanhq.c: Likewise.
+ * math/asinq.c: Likewise.
+ * math/coshq.c: Likewise.
+ * math/j0q.c: Likewise.
+ * math/asinhq.c: Likewise.
+ * math/floorq.c: Likewise.
+ * math/sinq_kernel.c: Likewise.
+ * math/powq.c: Likewise.
+ * math/hypotq.c: Likewise.
+ * math/sincos_table.c: Likewise.
+ * math/rem_pio2q.c: Likewise.
+ * math/nextafterq.c: Likewise.
+ * math/log1pq.c: Likewise.
+ * math/sincosq_kernel.c: Likewise.
+ * math/tanq.c: Likewise.
+ * math/acosq.c: Likewise.
+ * math/lrintq.c: Likewise.
+ * math/llrintq.c: Likewise.
+
2017-02-09 Gerald Pfeifer <gerald@pfeifer.com>
* configure.ac (ACX_BUGURL): Update.
diff --git a/libquadmath/math/acosq.c b/libquadmath/math/acosq.c
index 7ef79474651..7f2ed2725d1 100644
--- a/libquadmath/math/acosq.c
+++ b/libquadmath/math/acosq.c
@@ -172,7 +172,7 @@ acosq (__float128 x)
}
else if (ix < 0x3ffe0000) /* |x| < 0.5 */
{
- if (ix < 0x3fc60000) /* |x| < 2**-57 */
+ if (ix < 0x3f8e0000) /* |x| < 2**-113 */
return pio2_hi + pio2_lo;
if (ix < 0x3ffde000) /* |x| < .4375 */
{
diff --git a/libquadmath/math/asinhq.c b/libquadmath/math/asinhq.c
index 9be0aa1f053..f3644939b3a 100644
--- a/libquadmath/math/asinhq.c
+++ b/libquadmath/math/asinhq.c
@@ -46,6 +46,7 @@ asinhq (__float128 x)
return x + x; /* x is inf or NaN */
if (ix < 0x3fc70000)
{ /* |x| < 2^ -56 */
+ math_check_force_underflow (x);
if (huge + x > one)
return x; /* return x inexact except 0 */
}
diff --git a/libquadmath/math/asinq.c b/libquadmath/math/asinq.c
index 7bd4d768c97..5dff2817694 100644
--- a/libquadmath/math/asinq.c
+++ b/libquadmath/math/asinq.c
@@ -151,8 +151,10 @@ asinq (__float128 x)
{
if (ix < 0x3fc60000) /* |x| < 2**-57 */
{
- if (huge + x > one)
- return x; /* return x with inexact if x!=0 */
+ math_check_force_underflow (x);
+ __float128 force_inexact = huge + x;
+ math_force_eval (force_inexact);
+ return x; /* return x with inexact if x!=0 */
}
else
{
diff --git a/libquadmath/math/atanhq.c b/libquadmath/math/atanhq.c
index b34036715d7..652138d495c 100644
--- a/libquadmath/math/atanhq.c
+++ b/libquadmath/math/atanhq.c
@@ -55,7 +55,11 @@ atanhq (__float128 x)
else
return (x-x)/(x-x);
}
- if(ix<0x3fc60000 && (huge+x)>zero) return x; /* x < 2^-57 */
+ if(ix<0x3fc60000 && (huge+x)>zero) /* x < 2^-57 */
+ {
+ math_check_force_underflow (x);
+ return x;
+ }
if(ix<0x3ffe0000) { /* x < 0.5 */
t = u.value+u.value;
diff --git a/libquadmath/math/atanq.c b/libquadmath/math/atanq.c
index 8eccdc3317d..01fd9d69e57 100644
--- a/libquadmath/math/atanq.c
+++ b/libquadmath/math/atanq.c
@@ -42,7 +42,7 @@
*
*/
-/* Copyright 2001 by Stephen L. Moshier <moshier@na-net.ornl.gov>
+/* Copyright 2001 by Stephen L. Moshier <moshier@na-net.ornl.gov>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -167,7 +167,7 @@ static const __float128
q4 = 2.173623741810414221251136181221172551416E1Q;
/* q5 = 1.000000000000000000000000000000000000000E0 */
-static const long double huge = 1.0e4930Q;
+static const __float128 huge = 1.0e4930Q;
__float128
atanq (__float128 x)
@@ -200,6 +200,7 @@ atanq (__float128 x)
if (k <= 0x3fc50000) /* |x| < 2**-58 */
{
+ math_check_force_underflow (x);
/* Raise inexact. */
if (huge + x > 0.0)
return x;
diff --git a/libquadmath/math/ceilq.c b/libquadmath/math/ceilq.c
index 0d9bb8b87f3..1adc1e1b9f0 100644
--- a/libquadmath/math/ceilq.c
+++ b/libquadmath/math/ceilq.c
@@ -15,8 +15,6 @@
#include "quadmath-imp.h"
-static const __float128 huge = 1.0e4930Q;
-
__float128
ceilq (__float128 x)
{
@@ -25,18 +23,15 @@ ceilq (__float128 x)
GET_FLT128_WORDS64(i0,i1,x);
j0 = ((i0>>48)&0x7fff)-0x3fff;
if(j0<48) {
- if(j0<0) { /* raise inexact if x != 0 */
- if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
- if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
- else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
- }
+ if(j0<0) {
+ /* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
} else {
i = (0x0000ffffffffffffULL)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
- if(huge+x>0.0) { /* raise inexact flag */
- if(i0>0) i0 += (0x0001000000000000LL)>>j0;
- i0 &= (~i); i1=0;
- }
+ if(i0>0) i0 += (0x0001000000000000LL)>>j0;
+ i0 &= (~i); i1=0;
}
} else if (j0>111) {
if(j0==0x4000) return x+x; /* inf or NaN */
@@ -44,17 +39,15 @@ ceilq (__float128 x)
} else {
i = -1ULL>>(j0-48);
if((i1&i)==0) return x; /* x is integral */
- if(huge+x>0.0) { /* raise inexact flag */
- if(i0>0) {
- if(j0==48) i0+=1;
- else {
- j = i1+(1LL<<(112-j0));
- if(j<i1) i0 +=1 ; /* got a carry */
- i1=j;
- }
+ if(i0>0) {
+ if(j0==48) i0+=1;
+ else {
+ j = i1+(1LL<<(112-j0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
}
- i1 &= (~i);
}
+ i1 &= (~i);
}
SET_FLT128_WORDS64(x,i0,i1);
return x;
diff --git a/libquadmath/math/coshq.c b/libquadmath/math/coshq.c
index 77f4b98338b..61397509527 100644
--- a/libquadmath/math/coshq.c
+++ b/libquadmath/math/coshq.c
@@ -76,10 +76,10 @@ coshq (__float128 x)
/* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expq(|x|)) */
if (ex < 0x3ffd62e4) /* 0.3465728759765625 */
{
+ if (ex < 0x3fb80000) /* |x| < 2^-116 */
+ return one; /* cosh(tiny) = 1 */
t = expm1q (u.value);
w = one + t;
- if (ex < 0x3fb80000) /* |x| < 2^-116 */
- return w; /* cosh(tiny) = 1 */
return one + (t * t) / (w + w);
}
diff --git a/libquadmath/math/erfq.c b/libquadmath/math/erfq.c
index 8d383e9ca70..45a8c014e5c 100644
--- a/libquadmath/math/erfq.c
+++ b/libquadmath/math/erfq.c
@@ -11,9 +11,9 @@
/* Modifications and expansions for 128-bit long double are
Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
- and are incorporated herein by permission of the author. The author
+ and are incorporated herein by permission of the author. The author
reserves the right to distribute this material elsewhere under different
- copying permissions. These modifications are distributed here under
+ copying permissions. These modifications are distributed here under
the following terms:
This library is free software; you can redistribute it and/or
@@ -96,6 +96,7 @@
* erfc/erf(NaN) is NaN
*/
+#include <errno.h>
#include "quadmath-imp.h"
@@ -142,13 +143,10 @@ deval (__float128 x, const __float128 *p, int n)
static const __float128
tiny = 1e-4931Q,
- half = 0.5Q,
one = 1.0Q,
two = 2.0Q,
/* 2/sqrt(pi) - 1 */
- efx = 1.2837916709551257389615890312154517168810E-1Q,
- /* 8 * (2/sqrt(pi) - 1) */
- efx8 = 1.0270333367641005911692712249723613735048E0Q;
+ efx = 1.2837916709551257389615890312154517168810E-1Q;
/* erf(x) = x + x R(x^2)
@@ -773,6 +771,8 @@ erfq (__float128 x)
if (ix >= 0x3fff0000) /* |x| >= 1.0 */
{
+ if (ix >= 0x40030000 && sign > 0)
+ return one; /* x >= 16, avoid spurious underflow from erfc. */
y = erfcq (x);
return (one - y);
/* return (one - erfcq (x)); */
@@ -785,7 +785,12 @@ erfq (__float128 x)
if (ix < 0x3fc60000) /* |x|<2**-57 */
{
if (ix < 0x00080000)
- return 0.125 * (8.0 * x + efx8 * x); /*avoid underflow */
+ {
+ /* Avoid spurious underflow. */
+ __float128 ret = 0.0625 * (16.0 * x + (16.0 * efx) * x);
+ math_check_force_underflow (ret);
+ return ret;
+ }
return x + efx * x;
}
y = a + a * neval (z, TN1, NTN1) / deval (z, TD1, NTD1);
@@ -867,7 +872,7 @@ erfcq (__float128 x)
y = C19b + z * neval (z, RNr19, NRNr19) / deval (z, RDr19, NRDr19);
y += C19a;
break;
- case 9:
+ default: /* i == 9. */
z = x - 1.125Q;
y = C20b + z * neval (z, RNr20, NRNr20) / deval (z, RDr20, NRDr20);
y += C20a;
@@ -921,14 +926,22 @@ erfcq (__float128 x)
z = u.value;
r = expq (-z * z - 0.5625) * expq ((z - x) * (z + x) + p);
if ((sign & 0x80000000) == 0)
- return r / x;
+ {
+ __float128 ret = r / x;
+ if (ret == 0)
+ errno = ERANGE;
+ return ret;
+ }
else
return two - r / x;
}
else
{
if ((sign & 0x80000000) == 0)
- return tiny * tiny;
+ {
+ errno = ERANGE;
+ return tiny * tiny;
+ }
else
return two - tiny;
}
diff --git a/libquadmath/math/expm1q.c b/libquadmath/math/expm1q.c
index 8cfdd8eec94..9060d480858 100644
--- a/libquadmath/math/expm1q.c
+++ b/libquadmath/math/expm1q.c
@@ -35,7 +35,7 @@
*
*/
-/* Copyright 2001 by Stephen L. Moshier
+/* Copyright 2001 by Stephen L. Moshier
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -82,8 +82,6 @@ static const __float128
C1 = 6.93145751953125E-1Q,
C2 = 1.428606820309417232121458176568075500134E-6Q,
-/* ln (2^16384 * (1 - 2^-113)) */
- maxlog = 1.1356523406294143949491931077970764891253E4Q,
/* ln 2^-114 */
minarg = -7.9018778583833765273564461846232128760607E1Q;
@@ -108,33 +106,30 @@ expm1q (__float128 x)
}
if (ix >= 0x7fff0000)
{
- /* Infinity. */
+ /* Infinity (which must be negative infinity). */
if (((ix & 0xffff) | u.words32.w1 | u.words32.w2 | u.words32.w3) == 0)
- {
- if (sign)
- return -1.0Q;
- else
- return x;
- }
- /* NaN. No invalid exception. */
- return x;
+ return -1.0Q;
+ /* NaN. Invalid exception if signaling. */
+ return x + x;
}
/* expm1(+- 0) = +- 0. */
if ((ix == 0) && (u.words32.w1 | u.words32.w2 | u.words32.w3) == 0)
return x;
- /* Overflow. */
- if (x > maxlog)
- {
- errno = ERANGE;
- return (HUGE_VALQ * HUGE_VALQ);
- }
-
/* Minimum value. */
if (x < minarg)
return (4.0/HUGE_VALQ - 1.0Q);
+ /* Avoid internal underflow when result does not underflow, while
+ ensuring underflow (without returning a zero of the wrong sign)
+ when the result does underflow. */
+ if (fabsq (x) < 0x1p-113Q)
+ {
+ math_check_force_underflow (x);
+ return x;
+ }
+
/* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
xx = C1 + C2; /* ln 2. */
px = floorq (0.5 + x / xx);
diff --git a/libquadmath/math/expq.c b/libquadmath/math/expq.c
index 70c638d7a08..5df6cd8e192 100644
--- a/libquadmath/math/expq.c
+++ b/libquadmath/math/expq.c
@@ -1,5 +1,5 @@
/* Quad-precision floating point e^x.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jj@ultra.linux.cz>
Partly based on double-precision code
@@ -1075,7 +1075,7 @@ static const __float128 C[] = {
#define TWO15 C[11]
32768.0Q,
-/* Chebyshev polynom coeficients for (exp(x)-1)/x */
+/* Chebyshev polynom coefficients for (exp(x)-1)/x */
#define P1 C[12]
#define P2 C[13]
#define P3 C[14]
@@ -1142,7 +1142,7 @@ expq (__float128 x)
* __expq_table[T_EXPL_RES2 + tval2];
n_i = (int)n;
/* 'unsafe' is 1 iff n_1 != 0. */
- unsafe = abs(n_i) >= -FLT128_MIN_EXP - 1;
+ unsafe = abs(n_i) >= 15000;
ex2_u.ieee.exponent += n_i >> unsafe;
/* Compute scale = 2^n_1. */
@@ -1179,7 +1179,7 @@ expq (__float128 x)
ex3_u.d = (result - ex2_u.d) - x22 * ex2_u.d;
ex2_u.d = result;
ex3_u.ieee.exponent += LDBL_MANT_DIG + 15 + IEEE854_LONG_DOUBLE_BIAS
- - ex2_u.ieee.exponent;
+ - ex2_u.ieee.exponent;
n_i = abs (ex3_u.d);
n_i = (n_i + 1) / 2;
#ifdef USE_FENV_H
@@ -1196,7 +1196,11 @@ expq (__float128 x)
if (!unsafe)
return result;
else
- return result * scale_u.value;
+ {
+ result *= scale_u.value;
+ math_check_force_underflow_nonneg (result);
+ return result;
+ }
}
/* Exceptional cases: */
else if (__builtin_isless (x, himark))
diff --git a/libquadmath/math/finiteq.c b/libquadmath/math/finiteq.c
index c5326d2194b..e6703fb2261 100644
--- a/libquadmath/math/finiteq.c
+++ b/libquadmath/math/finiteq.c
@@ -25,6 +25,6 @@ finiteq (const __float128 x)
{
int64_t hx;
GET_FLT128_MSW64(hx,x);
- return (int)((uint64_t)((hx&0x7fffffffffffffffLL)
+ return (int)((uint64_t)((hx&0x7fff000000000000LL)
-0x7fff000000000000LL)>>63);
}
diff --git a/libquadmath/math/floorq.c b/libquadmath/math/floorq.c
index 0d74f94e27d..41b993fa7a0 100644
--- a/libquadmath/math/floorq.c
+++ b/libquadmath/math/floorq.c
@@ -15,8 +15,6 @@
#include "quadmath-imp.h"
-static const __float128 huge = 1.0e4930Q;
-
__float128
floorq (__float128 x)
{
@@ -25,19 +23,16 @@ floorq (__float128 x)
GET_FLT128_WORDS64(i0,i1,x);
j0 = ((i0>>48)&0x7fff)-0x3fff;
if(j0<48) {
- if(j0<0) { /* raise inexact if x != 0 */
- if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
- if(i0>=0) {i0=i1=0;}
- else if(((i0&0x7fffffffffffffffLL)|i1)!=0)
- { i0=0xbfff000000000000ULL;i1=0;}
- }
+ if(j0<0) {
+ /* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=i1=0;}
+ else if(((i0&0x7fffffffffffffffLL)|i1)!=0)
+ { i0=0xbfff000000000000ULL;i1=0;}
} else {
i = (0x0000ffffffffffffULL)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
- if(huge+x>0.0) { /* raise inexact flag */
- if(i0<0) i0 += (0x0001000000000000LL)>>j0;
- i0 &= (~i); i1=0;
- }
+ if(i0<0) i0 += (0x0001000000000000LL)>>j0;
+ i0 &= (~i); i1=0;
}
} else if (j0>111) {
if(j0==0x4000) return x+x; /* inf or NaN */
@@ -45,17 +40,15 @@ floorq (__float128 x)
} else {
i = -1ULL>>(j0-48);
if((i1&i)==0) return x; /* x is integral */
- if(huge+x>0.0) { /* raise inexact flag */
- if(i0<0) {
- if(j0==48) i0+=1;
- else {
- j = i1+(1LL<<(112-j0));
- if(j<i1) i0 +=1 ; /* got a carry */
- i1=j;
- }
+ if(i0<0) {
+ if(j0==48) i0+=1;
+ else {
+ j = i1+(1LL<<(112-j0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
}
- i1 &= (~i);
}
+ i1 &= (~i);
}
SET_FLT128_WORDS64(x,i0,i1);
return x;
diff --git a/libquadmath/math/fmaq.c b/libquadmath/math/fmaq.c
index d3c5fb3901a..68a63cf8fd6 100644
--- a/libquadmath/math/fmaq.c
+++ b/libquadmath/math/fmaq.c
@@ -1,5 +1,5 @@
/* Compute x * y + z as ternary operation.
- Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2010.
@@ -97,8 +97,8 @@ fmaq (__float128 x, __float128 y, __float128 z)
&& w.ieee.mant_low == 0
&& w.ieee.mant_high == 0)))
{
- volatile __float128 force_underflow = x * y;
- (void) force_underflow;
+ __float128 force_underflow = x * y;
+ math_force_eval (force_underflow);
}
return v.value * 0x1p-114Q;
}
@@ -161,15 +161,15 @@ fmaq (__float128 x, __float128 y, __float128 z)
<= IEEE854_FLOAT128_BIAS + FLT128_MANT_DIG) */
{
if (u.ieee.exponent > v.ieee.exponent)
- u.ieee.exponent += 2 * FLT128_MANT_DIG;
+ u.ieee.exponent += 2 * FLT128_MANT_DIG + 2;
else
- v.ieee.exponent += 2 * FLT128_MANT_DIG;
- if (w.ieee.exponent <= 4 * FLT128_MANT_DIG + 4)
+ v.ieee.exponent += 2 * FLT128_MANT_DIG + 2;
+ if (w.ieee.exponent <= 4 * FLT128_MANT_DIG + 6)
{
if (w.ieee.exponent)
- w.ieee.exponent += 2 * FLT128_MANT_DIG;
+ w.ieee.exponent += 2 * FLT128_MANT_DIG + 2;
else
- w.value *= 0x1p226Q;
+ w.value *= 0x1p228Q;
adjust = -1;
}
/* Otherwise x * y should just affect inexact
@@ -182,7 +182,10 @@ fmaq (__float128 x, __float128 y, __float128 z)
/* Ensure correct sign of exact 0 + 0. */
if (__builtin_expect ((x == 0 || y == 0) && z == 0, 0))
- return x * y + z;
+ {
+ x = math_opt_barrier (x);
+ return x * y + z;
+ }
#ifdef USE_FENV_H
fenv_t env;
@@ -208,24 +211,24 @@ fmaq (__float128 x, __float128 y, __float128 z)
t1 = m1 - t1;
t2 = z - t2;
__float128 a2 = t1 + t2;
+ /* Ensure the arithmetic is not scheduled after feclearexcept call. */
+ math_force_eval (m2);
+ math_force_eval (a2);
#ifdef USE_FENV_H
feclearexcept (FE_INEXACT);
#endif
- /* If the result is an exact zero, ensure it has the correct
- sign. */
+ /* If the result is an exact zero, ensure it has the correct sign. */
if (a1 == 0 && m2 == 0)
{
#ifdef USE_FENV_H
feupdateenv (&env);
#endif
- /* Ensure that round-to-nearest value of z + m1 is not
- reused. */
- asm volatile ("" : "=m" (z) : "m" (z));
+ /* Ensure that round-to-nearest value of z + m1 is not reused. */
+ z = math_opt_barrier (z);
return z + m1;
}
-
#ifdef USE_FENV_H
fesetround (FE_TOWARDZERO);
#endif
@@ -273,19 +276,19 @@ fmaq (__float128 x, __float128 y, __float128 z)
/* If a1 + u.value is exact, the only rounding happens during
scaling down. */
if (j == 0)
- return v.value * 0x1p-226Q;
+ return v.value * 0x1p-228Q;
/* If result rounded to zero is not subnormal, no double
rounding will occur. */
- if (v.ieee.exponent > 226)
- return (a1 + u.value) * 0x1p-226Q;
- /* If v.value * 0x1p-226Q with round to zero is a subnormal above
- or equal to FLT128_MIN / 2, then v.value * 0x1p-226Q shifts mantissa
+ if (v.ieee.exponent > 228)
+ return (a1 + u.value) * 0x1p-228Q;
+ /* If v.value * 0x1p-228Q with round to zero is a subnormal above
+ or equal to FLT128_MIN / 2, then v.value * 0x1p-228Q shifts mantissa
down just by 1 bit, which means v.ieee.mant_low |= j would
change the round bit, not sticky or guard bit.
- v.value * 0x1p-226Q never normalizes by shifting up,
+ v.value * 0x1p-228Q never normalizes by shifting up,
so round bit plus sticky bit should be already enough
for proper rounding. */
- if (v.ieee.exponent == 226)
+ if (v.ieee.exponent == 228)
{
/* If the exponent would be in the normal range when
rounding to normal precision with unbounded exponent
@@ -295,8 +298,8 @@ fmaq (__float128 x, __float128 y, __float128 z)
if (TININESS_AFTER_ROUNDING)
{
w.value = a1 + u.value;
- if (w.ieee.exponent == 227)
- return w.value * 0x1p-226Q;
+ if (w.ieee.exponent == 229)
+ return w.value * 0x1p-228Q;
}
/* v.ieee.mant_low & 2 is LSB bit of the result before rounding,
v.ieee.mant_low & 1 is the round bit and j is our sticky
@@ -305,11 +308,11 @@ fmaq (__float128 x, __float128 y, __float128 z)
w.ieee.mant_low = ((v.ieee.mant_low & 3) << 1) | j;
w.ieee.negative = v.ieee.negative;
v.ieee.mant_low &= ~3U;
- v.value *= 0x1p-226Q;
+ v.value *= 0x1p-228Q;
w.value *= 0x1p-2Q;
return v.value + w.value;
}
v.ieee.mant_low |= j;
- return v.value * 0x1p-226Q;
+ return v.value * 0x1p-228Q;
}
}
diff --git a/libquadmath/math/frexpq.c b/libquadmath/math/frexpq.c
index b0b305af574..2bd77829bf2 100644
--- a/libquadmath/math/frexpq.c
+++ b/libquadmath/math/frexpq.c
@@ -35,7 +35,7 @@ frexpq (__float128 x, int *eptr)
GET_FLT128_WORDS64(hx,lx,x);
ix = 0x7fffffffffffffffULL&hx;
*eptr = 0;
- if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x; /* 0,inf,nan */
+ if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x + x;/* 0,inf,nan */
if (ix<0x0001000000000000ULL) { /* subnormal */
x *= two114;
GET_FLT128_MSW64(hx,x);
diff --git a/libquadmath/math/hypotq.c b/libquadmath/math/hypotq.c
index 2df317f3681..057901073dc 100644
--- a/libquadmath/math/hypotq.c
+++ b/libquadmath/math/hypotq.c
@@ -89,6 +89,17 @@ hypotq (__float128 x, __float128 y)
b *= t1;
a *= t1;
k -= 16382;
+ GET_FLT128_MSW64 (ha, a);
+ GET_FLT128_MSW64 (hb, b);
+ if (hb > ha)
+ {
+ t1 = a;
+ a = b;
+ b = t1;
+ j = ha;
+ ha = hb;
+ hb = j;
+ }
} else { /* scale a and b by 2^9600 */
ha += 0x2580000000000000LL; /* a *= 2^9600 */
hb += 0x2580000000000000LL; /* b *= 2^9600 */
@@ -119,6 +130,8 @@ hypotq (__float128 x, __float128 y)
t1 = 1.0Q;
GET_FLT128_MSW64(high,t1);
SET_FLT128_MSW64(t1,high+(k<<48));
- return t1*w;
+ w *= t1;
+ math_check_force_underflow_nonneg (w);
+ return w;
} else return w;
}
diff --git a/libquadmath/math/j0q.c b/libquadmath/math/j0q.c
index 8c6f811125e..c6e482b1c51 100644
--- a/libquadmath/math/j0q.c
+++ b/libquadmath/math/j0q.c
@@ -681,7 +681,7 @@ j0q (__float128 x)
if (! finiteq (x))
{
if (x != x)
- return x;
+ return x + x;
else
return 0.0Q;
}
@@ -691,6 +691,8 @@ j0q (__float128 x)
xx = fabsq (x);
if (xx <= 2.0Q)
{
+ if (xx < 0x1p-57Q)
+ return 1.0Q;
/* 0 <= x <= 2 */
z = xx * xx;
p = z * z * neval (z, J0_2N, NJ0_2N) / deval (z, J0_2D, NJ0_2D);
@@ -699,6 +701,28 @@ j0q (__float128 x)
return p;
}
+ /* X = x - pi/4
+ cos(X) = cos(x) cos(pi/4) + sin(x) sin(pi/4)
+ = 1/sqrt(2) * (cos(x) + sin(x))
+ sin(X) = sin(x) cos(pi/4) - cos(x) sin(pi/4)
+ = 1/sqrt(2) * (sin(x) - cos(x))
+ sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ cf. Fdlibm. */
+ sincosq (xx, &s, &c);
+ ss = s - c;
+ cc = s + c;
+ if (xx <= FLT128_MAX / 2.0Q)
+ {
+ z = -cosq (xx + xx);
+ if ((s * c) < 0)
+ cc = z / ss;
+ else
+ ss = z / cc;
+ }
+
+ if (xx > 0x1p256Q)
+ return ONEOSQPI * cc / sqrtq (xx);
+
xinv = 1.0Q / xx;
z = xinv * xinv;
if (xinv <= 0.25)
@@ -760,21 +784,6 @@ j0q (__float128 x)
p = 1.0Q + z * p;
q = z * xinv * q;
q = q - 0.125Q * xinv;
- /* X = x - pi/4
- cos(X) = cos(x) cos(pi/4) + sin(x) sin(pi/4)
- = 1/sqrt(2) * (cos(x) + sin(x))
- sin(X) = sin(x) cos(pi/4) - cos(x) sin(pi/4)
- = 1/sqrt(2) * (sin(x) - cos(x))
- sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
- cf. Fdlibm. */
- sincosq (xx, &s, &c);
- ss = s - c;
- cc = s + c;
- z = - cosq (xx + xx);
- if ((s * c) < 0)
- cc = z / ss;
- else
- ss = z / cc;
z = ONEOSQPI * (p * cc - q * ss) / sqrtq (xx);
return z;
}
@@ -817,17 +826,12 @@ y0q (__float128 x)
__float128 xx, xinv, z, p, q, c, s, cc, ss;
if (! finiteq (x))
- {
- if (x != x)
- return x;
- else
- return 0.0Q;
- }
+ return 1 / (x + x * x);
if (x <= 0.0Q)
{
if (x < 0.0Q)
return (zero / (zero * x));
- return -HUGE_VALQ + x;
+ return -1 / zero; /* -inf and divide by zero exception. */
}
xx = fabsq (x);
if (xx <= 0x1p-57)
@@ -841,6 +845,28 @@ y0q (__float128 x)
return p;
}
+ /* X = x - pi/4
+ cos(X) = cos(x) cos(pi/4) + sin(x) sin(pi/4)
+ = 1/sqrt(2) * (cos(x) + sin(x))
+ sin(X) = sin(x) cos(pi/4) - cos(x) sin(pi/4)
+ = 1/sqrt(2) * (sin(x) - cos(x))
+ sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ cf. Fdlibm. */
+ sincosq (x, &s, &c);
+ ss = s - c;
+ cc = s + c;
+ if (xx <= FLT128_MAX / 2.0Q)
+ {
+ z = -cosq (x + x);
+ if ((s * c) < 0)
+ cc = z / ss;
+ else
+ ss = z / cc;
+ }
+
+ if (xx > 0x1p256Q)
+ return ONEOSQPI * ss / sqrtq (x);
+
xinv = 1.0Q / xx;
z = xinv * xinv;
if (xinv <= 0.25)
@@ -902,21 +928,6 @@ y0q (__float128 x)
p = 1.0Q + z * p;
q = z * xinv * q;
q = q - 0.125Q * xinv;
- /* X = x - pi/4
- cos(X) = cos(x) cos(pi/4) + sin(x) sin(pi/4)
- = 1/sqrt(2) * (cos(x) + sin(x))
- sin(X) = sin(x) cos(pi/4) - cos(x) sin(pi/4)
- = 1/sqrt(2) * (sin(x) - cos(x))
- sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
- cf. Fdlibm. */
- sincosq (x, &s, &c);
- ss = s - c;
- cc = s + c;
- z = - cosq (x + x);
- if ((s * c) < 0)
- cc = z / ss;
- else
- ss = z / cc;
z = ONEOSQPI * (p * ss + q * cc) / sqrtq (x);
return z;
}
diff --git a/libquadmath/math/j1q.c b/libquadmath/math/j1q.c
index eb599c949a9..5eb705084e2 100644
--- a/libquadmath/math/j1q.c
+++ b/libquadmath/math/j1q.c
@@ -95,6 +95,7 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <errno.h>
#include "quadmath-imp.h"
/* 1 / sqrt(pi) */
@@ -687,13 +688,21 @@ j1q (__float128 x)
if (! finiteq (x))
{
if (x != x)
- return x;
+ return x + x;
else
return 0.0Q;
}
if (x == 0.0Q)
return x;
xx = fabsq (x);
+ if (xx <= 0x1p-58Q)
+ {
+ __float128 ret = x * 0.5Q;
+ math_check_force_underflow (ret);
+ if (ret == 0)
+ errno = ERANGE;
+ return ret;
+ }
if (xx <= 2.0Q)
{
/* 0 <= x <= 2 */
@@ -705,6 +714,32 @@ j1q (__float128 x)
return p;
}
+ /* X = x - 3 pi/4
+ cos(X) = cos(x) cos(3 pi/4) + sin(x) sin(3 pi/4)
+ = 1/sqrt(2) * (-cos(x) + sin(x))
+ sin(X) = sin(x) cos(3 pi/4) - cos(x) sin(3 pi/4)
+ = -1/sqrt(2) * (sin(x) + cos(x))
+ cf. Fdlibm. */
+ sincosq (xx, &s, &c);
+ ss = -s - c;
+ cc = s - c;
+ if (xx <= FLT128_MAX / 2.0Q)
+ {
+ z = cosq (xx + xx);
+ if ((s * c) > 0)
+ cc = z / ss;
+ else
+ ss = z / cc;
+ }
+
+ if (xx > 0x1p256Q)
+ {
+ z = ONEOSQPI * cc / sqrtq (xx);
+ if (x < 0)
+ z = -z;
+ return z;
+ }
+
xinv = 1.0Q / xx;
z = xinv * xinv;
if (xinv <= 0.25)
@@ -766,20 +801,6 @@ j1q (__float128 x)
p = 1.0Q + z * p;
q = z * q;
q = q * xinv + 0.375Q * xinv;
- /* X = x - 3 pi/4
- cos(X) = cos(x) cos(3 pi/4) + sin(x) sin(3 pi/4)
- = 1/sqrt(2) * (-cos(x) + sin(x))
- sin(X) = sin(x) cos(3 pi/4) - cos(x) sin(3 pi/4)
- = -1/sqrt(2) * (sin(x) + cos(x))
- cf. Fdlibm. */
- sincosq (xx, &s, &c);
- ss = -s - c;
- cc = s - c;
- z = cosq (xx + xx);
- if ((s * c) > 0)
- cc = z / ss;
- else
- ss = z / cc;
z = ONEOSQPI * (p * cc - q * ss) / sqrtq (xx);
if (x < 0)
z = -z;
@@ -823,24 +844,25 @@ y1q (__float128 x)
__float128 xx, xinv, z, p, q, c, s, cc, ss;
if (! finiteq (x))
- {
- if (x != x)
- return x;
- else
- return 0.0Q;
- }
+ return 1 / (x + x * x);
if (x <= 0.0Q)
{
if (x < 0.0Q)
return (zero / (zero * x));
- return -HUGE_VALQ + x;
+ return -1 / zero; /* -inf and divide by zero exception. */
}
xx = fabsq (x);
if (xx <= 0x1p-114)
- return -TWOOPI / x;
+ {
+ z = -TWOOPI / x;
+ if (isinfq (z))
+ errno = ERANGE;
+ return z;
+ }
if (xx <= 2.0Q)
{
/* 0 <= x <= 2 */
+ /* FIXME: SET_RESTORE_ROUNDL (FE_TONEAREST); */
z = xx * xx;
p = xx * neval (z, Y0_2N, NY0_2N) / deval (z, Y0_2D, NY0_2D);
p = -TWOOPI / xx + p;
@@ -848,6 +870,27 @@ y1q (__float128 x)
return p;
}
+ /* X = x - 3 pi/4
+ cos(X) = cos(x) cos(3 pi/4) + sin(x) sin(3 pi/4)
+ = 1/sqrt(2) * (-cos(x) + sin(x))
+ sin(X) = sin(x) cos(3 pi/4) - cos(x) sin(3 pi/4)
+ = -1/sqrt(2) * (sin(x) + cos(x))
+ cf. Fdlibm. */
+ sincosq (xx, &s, &c);
+ ss = -s - c;
+ cc = s - c;
+ if (xx <= FLT128_MAX / 2.0Q)
+ {
+ z = cosq (xx + xx);
+ if ((s * c) > 0)
+ cc = z / ss;
+ else
+ ss = z / cc;
+ }
+
+ if (xx > 0x1p256Q)
+ return ONEOSQPI * ss / sqrtq (xx);
+
xinv = 1.0Q / xx;
z = xinv * xinv;
if (xinv <= 0.25)
@@ -909,20 +952,6 @@ y1q (__float128 x)
p = 1.0Q + z * p;
q = z * q;
q = q * xinv + 0.375Q * xinv;
- /* X = x - 3 pi/4
- cos(X) = cos(x) cos(3 pi/4) + sin(x) sin(3 pi/4)
- = 1/sqrt(2) * (-cos(x) + sin(x))
- sin(X) = sin(x) cos(3 pi/4) - cos(x) sin(3 pi/4)
- = -1/sqrt(2) * (sin(x) + cos(x))
- cf. Fdlibm. */
- sincosq (xx, &s, &c);
- ss = -s - c;
- cc = s - c;
- z = cosq (xx + xx);
- if ((s * c) > 0)
- cc = z / ss;
- else
- ss = z / cc;
z = ONEOSQPI * (p * ss + q * cc) / sqrtq (xx);
return z;
}
diff --git a/libquadmath/math/llrintq.c b/libquadmath/math/llrintq.c
index eef31d823b6..a6a0ae64bd3 100644
--- a/libquadmath/math/llrintq.c
+++ b/libquadmath/math/llrintq.c
@@ -1,9 +1,9 @@
/* Round argument to nearest integral value according to current rounding
direction.
- Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
- Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+ Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -33,7 +33,7 @@ llrintq (__float128 x)
{
int32_t j0;
uint64_t i0,i1;
- volatile __float128 w;
+ __float128 w;
__float128 t;
long long int result;
int sx;
@@ -46,8 +46,23 @@ llrintq (__float128 x)
if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
{
- w = two112[sx] + x;
- t = w - two112[sx];
+#if defined FE_INVALID || defined FE_INEXACT
+ /* X < LLONG_MAX + 1 implied by J0 < 63. */
+ if (x > (__float128) LLONG_MAX)
+ {
+ /* In the event of overflow we must raise the "invalid"
+ exception, but not "inexact". */
+ t = nearbyintq (x);
+#ifdef USE_FENV_H
+ feraiseexcept (t == LLONG_MAX ? FE_INEXACT : FE_INVALID);
+#endif
+ }
+ else
+#endif
+ {
+ w = two112[sx] + x;
+ t = w - two112[sx];
+ }
GET_FLT128_WORDS64 (i0, i1, t);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
i0 &= 0x0000ffffffffffffLL;
@@ -62,6 +77,24 @@ llrintq (__float128 x)
}
else
{
+ /* The number is too large. Unless it rounds to LLONG_MIN,
+ FE_INVALID must be raised and the return value is
+ unspecified. */
+#if defined FE_INVALID || defined FE_INEXACT
+ if (x < (__float128) LLONG_MIN
+ && x > (__float128) LLONG_MIN - 1.0Q)
+ {
+ /* If truncation produces LLONG_MIN, the cast will not raise
+ the exception, but may raise "inexact". */
+ t = nearbyintq (x);
+#ifdef USE_FENV_H
+ feraiseexcept (t == LLONG_MIN ? FE_INEXACT : FE_INVALID);
+#endif
+ return LLONG_MIN;
+ }
+
+#endif
+
/* The number is too large. It is left implementation defined
what happens. */
return (long long int) x;
diff --git a/libquadmath/math/llroundq.c b/libquadmath/math/llroundq.c
index d22180d6bba..098fb9ef72b 100644
--- a/libquadmath/math/llroundq.c
+++ b/libquadmath/math/llroundq.c
@@ -1,8 +1,8 @@
/* Round __float128 value to long long int.
- Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
- Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+ Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -59,13 +59,32 @@ llroundq (__float128 x)
if (j0 == 48)
result = (long long int) i0;
else
- result = ((long long int) i0 << (j0 - 48)) | (j >> (112 - j0));
+ {
+ result = ((long long int) i0 << (j0 - 48)) | (j >> (112 - j0));
+#if defined FE_INVALID && defined USE_FENV_H
+ if (sign == 1 && result == LLONG_MIN)
+ /* Rounding brought the value out of range. */
+ feraiseexcept (FE_INVALID);
+#endif
+ }
}
}
else
{
- /* The number is too large. It is left implementation defined
- what happens. */
+ /* The number is too large. Unless it rounds to LLONG_MIN,
+ FE_INVALID must be raised and the return value is
+ unspecified. */
+#ifdef FE_INVALID
+ if (x <= (__float128) LLONG_MIN - 0.5Q)
+ {
+ /* If truncation produces LLONG_MIN, the cast will not raise
+ the exception, but may raise "inexact". */
+#ifdef USE_FENV_H
+ feraiseexcept (FE_INVALID);
+#endif
+ return LLONG_MIN;
+ }
+#endif
return (long long int) x;
}
diff --git a/libquadmath/math/log10q.c b/libquadmath/math/log10q.c
index 9eeb9ae3fc4..3afb1121267 100644
--- a/libquadmath/math/log10q.c
+++ b/libquadmath/math/log10q.c
@@ -188,12 +188,15 @@ log10q (__float128 x)
/* Test for domain */
GET_FLT128_WORDS64 (hx, lx, x);
if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
- return (-1.0Q / (x - x));
+ return (-1.0Q / fabsq (x)); /* log10l(+-0)=-inf */
if (hx < 0)
return (x - x) / (x - x);
if (hx >= 0x7fff000000000000LL)
return (x + x);
+ if (x == 1.0Q)
+ return 0.0Q;
+
/* separate mantissa from exponent */
/* Note, frexp is used so that denormal numbers
diff --git a/libquadmath/math/log1pq.c b/libquadmath/math/log1pq.c
index d8bff405dff..c59ceef5c9e 100644
--- a/libquadmath/math/log1pq.c
+++ b/libquadmath/math/log1pq.c
@@ -36,7 +36,7 @@
* IEEE -1, 8 100000 1.9e-34 4.3e-35
*/
-/* Copyright 2001 by Stephen L. Moshier
+/* Copyright 2001 by Stephen L. Moshier
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -128,8 +128,8 @@ log1pq (__float128 xm1)
/* Test for NaN or infinity input. */
u.value = xm1;
hx = u.words32.w0;
- if (hx >= 0x7fff0000)
- return xm1;
+ if ((hx & 0x7fffffff) >= 0x7fff0000)
+ return xm1 + fabsq (xm1);
/* log1p(+- 0) = +- 0. */
if (((hx & 0x7fffffff) == 0)
@@ -138,17 +138,21 @@ log1pq (__float128 xm1)
if ((hx & 0x7fffffff) < 0x3f8e0000)
{
+ math_check_force_underflow (xm1);
if ((int) xm1 == 0)
return xm1;
}
- x = xm1 + 1.0Q;
+ if (xm1 >= 0x1p113Q)
+ x = xm1;
+ else
+ x = xm1 + 1.0Q;
/* log1p(-1) = -inf */
if (x <= 0.0Q)
{
if (x == 0.0Q)
- return (-1.0Q / (x - x));
+ return (-1.0Q / zero); /* log1p(-1) = -inf */
else
return (zero / (x - x));
}
diff --git a/libquadmath/math/log2q.c b/libquadmath/math/log2q.c
index f8275369b37..865f341f03d 100644
--- a/libquadmath/math/log2q.c
+++ b/libquadmath/math/log2q.c
@@ -181,12 +181,15 @@ log2q (__float128 x)
/* Test for domain */
GET_FLT128_WORDS64 (hx, lx, x);
if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
- return (-1.0Q / (x - x));
+ return (-1.0Q / fabsq (x)); /* log2l(+-0)=-inf */
if (hx < 0)
return (x - x) / (x - x);
if (hx >= 0x7fff000000000000LL)
return (x + x);
+ if (x == 1.0Q)
+ return 0.0Q;
+
/* separate mantissa from exponent */
/* Note, frexp is used so that denormal numbers
diff --git a/libquadmath/math/logq.c b/libquadmath/math/logq.c
index 7aae9b101ad..43249bb498a 100644
--- a/libquadmath/math/logq.c
+++ b/libquadmath/math/logq.c
@@ -212,9 +212,8 @@ logq (__float128 x)
}
/* Extract exponent and reduce domain to 0.703125 <= u < 1.40625 */
- e = (int) (m >> 16) - (int) 0x3ffe;
- m &= 0xffff;
- u.words32.w0 = m | 0x3ffe0000;
+ u.value = frexpq (x, &e);
+ m = u.words32.w0 & 0xffff;
m |= 0x10000;
/* Find lookup table index k from high order bits of the significand. */
if (m < 0x16800)
@@ -241,6 +240,8 @@ logq (__float128 x)
/* On this interval the table is not used due to cancellation error. */
if ((x <= 1.0078125Q) && (x >= 0.9921875Q))
{
+ if (x == 1.0Q)
+ return 0.0Q;
z = x - 1.0Q;
k = 64;
t.value = 1.0Q;
diff --git a/libquadmath/math/lrintq.c b/libquadmath/math/lrintq.c
index d1497ae3882..50a300554b9 100644
--- a/libquadmath/math/lrintq.c
+++ b/libquadmath/math/lrintq.c
@@ -1,9 +1,9 @@
/* Round argument to nearest integral value according to current rounding
direction.
- Copyright (C) 1997, 1999, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
- Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+ Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -33,7 +33,7 @@ lrintq (__float128 x)
{
int32_t j0;
uint64_t i0,i1;
- volatile __float128 w;
+ __float128 w;
__float128 t;
long int result;
int sx;
@@ -44,25 +44,57 @@ lrintq (__float128 x)
i0 &= 0x0000ffffffffffffLL;
i0 |= 0x0001000000000000LL;
- if (j0 < 48)
+ if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
{
- w = two112[sx] + x;
- t = w - two112[sx];
- GET_FLT128_WORDS64 (i0, i1, t);
- j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
- i0 &= 0x0000ffffffffffffLL;
- i0 |= 0x0001000000000000LL;
+ if (j0 < 48)
+ {
+#if defined FE_INVALID || defined FE_INEXACT
+ /* X < LONG_MAX + 1 implied by J0 < 31. */
+ if (sizeof (long int) == 4
+ && x > (__float128) LONG_MAX)
+ {
+ /* In the event of overflow we must raise the "invalid"
+ exception, but not "inexact". */
+ t = nearbyintq (x);
+#ifdef USE_FENV_H
+ feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
+#endif
+ }
+ else
+#endif
+ {
+ w = two112[sx] + x;
+ t = w - two112[sx];
+ }
+ GET_FLT128_WORDS64 (i0, i1, t);
+ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
+ i0 &= 0x0000ffffffffffffLL;
+ i0 |= 0x0001000000000000LL;
- result = (j0 < 0 ? 0 : i0 >> (48 - j0));
- }
- else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
- {
- if (j0 >= 112)
+ result = (j0 < 0 ? 0 : i0 >> (48 - j0));
+ }
+ else if (j0 >= 112)
result = ((long int) i0 << (j0 - 48)) | (i1 << (j0 - 112));
else
{
- w = two112[sx] + x;
- t = w - two112[sx];
+#if defined FE_INVALID || defined FE_INEXACT
+ /* X < LONG_MAX + 1 implied by J0 < 63. */
+ if (sizeof (long int) == 8
+ && x > (__float128) LONG_MAX)
+ {
+ /* In the event of overflow we must raise the "invalid"
+ exception, but not "inexact". */
+ t = nearbyintq (x);
+#ifdef USE_FENV_H
+ feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
+#endif
+ }
+ else
+#endif
+ {
+ w = two112[sx] + x;
+ t = w - two112[sx];
+ }
GET_FLT128_WORDS64 (i0, i1, t);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
i0 &= 0x0000ffffffffffffLL;
@@ -76,8 +108,22 @@ lrintq (__float128 x)
}
else
{
- /* The number is too large. It is left implementation defined
- what happens. */
+ /* The number is too large. Unless it rounds to LONG_MIN,
+ FE_INVALID must be raised and the return value is
+ unspecified. */
+#if defined FE_INVALID || defined FE_INEXACT
+ if (x < (__float128) LONG_MIN
+ && x > (__float128) LONG_MIN - 1.0Q)
+ {
+ /* If truncation produces LONG_MIN, the cast will not raise
+ the exception, but may raise "inexact". */
+ t = nearbyintq (x);
+#ifdef USE_FENV_H
+ feraiseexcept (t == LONG_MIN ? FE_INEXACT : FE_INVALID);
+#endif
+ return LONG_MIN;
+ }
+#endif
return (long int) x;
}
diff --git a/libquadmath/math/lroundq.c b/libquadmath/math/lroundq.c
index 59c883a1464..55285034cec 100644
--- a/libquadmath/math/lroundq.c
+++ b/libquadmath/math/lroundq.c
@@ -1,8 +1,8 @@
/* Round __float128 value to long int.
- Copyright (C) 1997, 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
- Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+ Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -36,19 +36,26 @@ lroundq (__float128 x)
i0 &= 0x0000ffffffffffffLL;
i0 |= 0x0001000000000000LL;
- if (j0 < 48)
+ if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
{
- if (j0 < 0)
- return j0 < -1 ? 0 : sign;
- else
+ if (j0 < 48)
{
- i0 += 0x0000800000000000LL >> j0;
- result = i0 >> (48 - j0);
+ if (j0 < 0)
+ return j0 < -1 ? 0 : sign;
+ else
+ {
+ i0 += 0x0000800000000000LL >> j0;
+ result = i0 >> (48 - j0);
+#if defined FE_INVALID && defined USE_FENV_H
+ if (sizeof (long int) == 4
+ && sign == 1
+ && result == LONG_MIN)
+ /* Rounding brought the value out of range. */
+ feraiseexcept (FE_INVALID);
+#endif
+ }
}
- }
- else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
- {
- if (j0 >= 112)
+ else if (j0 >= 112)
result = ((long int) i0 << (j0 - 48)) | (i1 << (j0 - 112));
else
{
@@ -59,13 +66,34 @@ lroundq (__float128 x)
if (j0 == 48)
result = (long int) i0;
else
- result = ((long int) i0 << (j0 - 48)) | (j >> (112 - j0));
+ {
+ result = ((long int) i0 << (j0 - 48)) | (j >> (112 - j0));
+#if defined FE_INVALID && defined USE_FENV_H
+ if (sizeof (long int) == 8
+ && sign == 1
+ && result == LONG_MIN)
+ /* Rounding brought the value out of range. */
+ feraiseexcept (FE_INVALID);
+#endif
+ }
}
}
else
{
- /* The number is too large. It is left implementation defined
- what happens. */
+ /* The number is too large. Unless it rounds to LONG_MIN,
+ FE_INVALID must be raised and the return value is
+ unspecified. */
+#ifdef FE_INVALID
+ if (x <= (__float128) LONG_MIN - 0.5Q)
+ {
+ /* If truncation produces LONG_MIN, the cast will not raise
+ the exception, but may raise "inexact". */
+#ifdef USE_FENV_H
+ feraiseexcept (FE_INVALID);
+#endif
+ return LONG_MIN;
+ }
+#endif
return (long int) x;
}
diff --git a/libquadmath/math/nearbyintq.c b/libquadmath/math/nearbyintq.c
index 207124808e7..b250927ea2a 100644
--- a/libquadmath/math/nearbyintq.c
+++ b/libquadmath/math/nearbyintq.c
@@ -44,7 +44,7 @@ nearbyintq(__float128 x)
fenv_t env;
#endif
int64_t i0,j0,sx;
- uint64_t i1;
+ uint64_t i1 __attribute__ ((unused));
__float128 w,t;
GET_FLT128_WORDS64(i0,i1,x);
sx = (((uint64_t)i0)>>63);
@@ -56,6 +56,7 @@ nearbyintq(__float128 x)
#endif
w = TWO112[sx]+x;
t = w-TWO112[sx];
+ math_force_eval (t);
#ifdef USE_FENV_H
fesetenv (&env);
#endif
@@ -72,6 +73,7 @@ nearbyintq(__float128 x)
#endif
w = TWO112[sx]+x;
t = w-TWO112[sx];
+ math_force_eval (t);
#ifdef USE_FENV_H
fesetenv (&env);
#endif
diff --git a/libquadmath/math/nextafterq.c b/libquadmath/math/nextafterq.c
index 04d63deb8e2..a030e9c6444 100644
--- a/libquadmath/math/nextafterq.c
+++ b/libquadmath/math/nextafterq.c
@@ -13,6 +13,7 @@
* ====================================================
*/
+#include <errno.h>
#include "quadmath-imp.h"
__float128
@@ -54,9 +55,15 @@ nextafterq (__float128 x, __float128 y)
}
}
hy = hx&0x7fff000000000000LL;
- if(hy==0x7fff000000000000LL) return x+x;/* overflow */
+ if(hy==0x7fff000000000000LL) {
+ __float128 u = x + x; /* overflow */
+ math_force_eval (u);
+ errno = ERANGE;
+ }
if(hy==0) {
- /* here we should raise an underflow flag */
+ __float128 u = x*x; /* underflow */
+ math_force_eval (u); /* raise underflow flag */
+ errno = ERANGE;
}
SET_FLT128_WORDS64(x,hx,lx);
return x;
diff --git a/libquadmath/math/powq.c b/libquadmath/math/powq.c
index dd44b7c175a..4d586d6534a 100644
--- a/libquadmath/math/powq.c
+++ b/libquadmath/math/powq.c
@@ -147,7 +147,7 @@ __float128
powq (__float128 x, __float128 y)
{
__float128 z, ax, z_h, z_l, p_h, p_l;
- __float128 y1, t1, t2, r, s, t, u, v, w;
+ __float128 y1, t1, t2, r, s, sgn, t, u, v, w;
__float128 s2, s_h, s_l, t_h, t_l, ay;
int32_t i, j, k, yisint, n;
uint32_t ix, iy;
@@ -261,6 +261,11 @@ powq (__float128 x, __float128 y)
if (((((uint32_t) hx >> 31) - 1) | yisint) == 0)
return (x - x) / (x - x);
+ /* sgn (sign of result -ve**odd) = -1 else = 1 */
+ sgn = one;
+ if (((((uint32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
+ sgn = -one; /* (-ve)**(odd int) */
+
/* |y| is huge.
2^-16495 = 1/2 of smallest representable value.
If (1 - 1/131072)^y underflows, y > 1.4986e9 */
@@ -276,9 +281,9 @@ powq (__float128 x, __float128 y)
}
/* over/underflow if x is not close to one */
if (ix < 0x3ffeffff)
- return (hy < 0) ? huge * huge : tiny * tiny;
+ return (hy < 0) ? sgn * huge * huge : sgn * tiny * tiny;
if (ix > 0x3fff0000)
- return (hy > 0) ? huge * huge : tiny * tiny;
+ return (hy > 0) ? sgn * huge * huge : sgn * tiny * tiny;
}
ay = y > 0 ? y : -y;
@@ -365,11 +370,6 @@ powq (__float128 x, __float128 y)
t1 = o.value;
t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
- /* s (sign of result -ve**odd) = -1 else = 1 */
- s = one;
- if (((((uint32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
- s = -one; /* (-ve)**(odd int) */
-
/* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
y1 = y;
o.value = y1;
@@ -385,11 +385,11 @@ powq (__float128 x, __float128 y)
{
/* if z > 16384 */
if (((j - 0x400d0000) | o.words32.w1 | o.words32.w2 | o.words32.w3) != 0)
- return s * huge * huge; /* overflow */
+ return sgn * huge * huge; /* overflow */
else
{
if (p_l + ovt > z - p_h)
- return s * huge * huge; /* overflow */
+ return sgn * huge * huge; /* overflow */
}
}
else if ((j & 0x7fffffff) >= 0x400d01b9) /* z <= -16495 */
@@ -397,11 +397,11 @@ powq (__float128 x, __float128 y)
/* z < -16495 */
if (((j - 0xc00d01bc) | o.words32.w1 | o.words32.w2 | o.words32.w3)
!= 0)
- return s * tiny * tiny; /* underflow */
+ return sgn * tiny * tiny; /* underflow */
else
{
if (p_l <= z - p_h)
- return s * tiny * tiny; /* underflow */
+ return sgn * tiny * tiny; /* underflow */
}
}
/* compute 2**(p_h+p_l) */
@@ -434,11 +434,15 @@ powq (__float128 x, __float128 y)
j = o.words32.w0;
j += (n << 16);
if ((j >> 16) <= 0)
- z = scalbnq (z, n); /* subnormal output */
+ {
+ z = scalbnq (z, n); /* subnormal output */
+ __float128 force_underflow = z * z;
+ math_force_eval (force_underflow);
+ }
else
{
o.words32.w0 = j;
z = o.value;
}
- return s * z;
+ return sgn * z;
}
diff --git a/libquadmath/math/rem_pio2q.c b/libquadmath/math/rem_pio2q.c
index 60653c8d1d3..3308b218473 100644
--- a/libquadmath/math/rem_pio2q.c
+++ b/libquadmath/math/rem_pio2q.c
@@ -312,7 +312,7 @@ recompute:
/* Quad-precision floating point argument reduction.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jj@ultra.linux.cz>
@@ -332,176 +332,176 @@ recompute:
02111-1307 USA. */
/*
- * Table of constants for 2/pi, 5628 hexadecimal digits of 2/pi
+ * Table of constants for 2/pi, 5628 hexadecimal digits of 2/pi
*/
static const int32_t two_over_pi[] = {
-0xa2f983, 0x6e4e44, 0x1529fc, 0x2757d1, 0xf534dd, 0xc0db62,
-0x95993c, 0x439041, 0xfe5163, 0xabdebb, 0xc561b7, 0x246e3a,
-0x424dd2, 0xe00649, 0x2eea09, 0xd1921c, 0xfe1deb, 0x1cb129,
-0xa73ee8, 0x8235f5, 0x2ebb44, 0x84e99c, 0x7026b4, 0x5f7e41,
-0x3991d6, 0x398353, 0x39f49c, 0x845f8b, 0xbdf928, 0x3b1ff8,
-0x97ffde, 0x05980f, 0xef2f11, 0x8b5a0a, 0x6d1f6d, 0x367ecf,
-0x27cb09, 0xb74f46, 0x3f669e, 0x5fea2d, 0x7527ba, 0xc7ebe5,
-0xf17b3d, 0x0739f7, 0x8a5292, 0xea6bfb, 0x5fb11f, 0x8d5d08,
-0x560330, 0x46fc7b, 0x6babf0, 0xcfbc20, 0x9af436, 0x1da9e3,
-0x91615e, 0xe61b08, 0x659985, 0x5f14a0, 0x68408d, 0xffd880,
-0x4d7327, 0x310606, 0x1556ca, 0x73a8c9, 0x60e27b, 0xc08c6b,
-0x47c419, 0xc367cd, 0xdce809, 0x2a8359, 0xc4768b, 0x961ca6,
-0xddaf44, 0xd15719, 0x053ea5, 0xff0705, 0x3f7e33, 0xe832c2,
-0xde4f98, 0x327dbb, 0xc33d26, 0xef6b1e, 0x5ef89f, 0x3a1f35,
-0xcaf27f, 0x1d87f1, 0x21907c, 0x7c246a, 0xfa6ed5, 0x772d30,
-0x433b15, 0xc614b5, 0x9d19c3, 0xc2c4ad, 0x414d2c, 0x5d000c,
-0x467d86, 0x2d71e3, 0x9ac69b, 0x006233, 0x7cd2b4, 0x97a7b4,
-0xd55537, 0xf63ed7, 0x1810a3, 0xfc764d, 0x2a9d64, 0xabd770,
-0xf87c63, 0x57b07a, 0xe71517, 0x5649c0, 0xd9d63b, 0x3884a7,
-0xcb2324, 0x778ad6, 0x23545a, 0xb91f00, 0x1b0af1, 0xdfce19,
-0xff319f, 0x6a1e66, 0x615799, 0x47fbac, 0xd87f7e, 0xb76522,
-0x89e832, 0x60bfe6, 0xcdc4ef, 0x09366c, 0xd43f5d, 0xd7de16,
-0xde3b58, 0x929bde, 0x2822d2, 0xe88628, 0x4d58e2, 0x32cac6,
-0x16e308, 0xcb7de0, 0x50c017, 0xa71df3, 0x5be018, 0x34132e,
-0x621283, 0x014883, 0x5b8ef5, 0x7fb0ad, 0xf2e91e, 0x434a48,
-0xd36710, 0xd8ddaa, 0x425fae, 0xce616a, 0xa4280a, 0xb499d3,
-0xf2a606, 0x7f775c, 0x83c2a3, 0x883c61, 0x78738a, 0x5a8caf,
-0xbdd76f, 0x63a62d, 0xcbbff4, 0xef818d, 0x67c126, 0x45ca55,
-0x36d9ca, 0xd2a828, 0x8d61c2, 0x77c912, 0x142604, 0x9b4612,
-0xc459c4, 0x44c5c8, 0x91b24d, 0xf31700, 0xad43d4, 0xe54929,
-0x10d5fd, 0xfcbe00, 0xcc941e, 0xeece70, 0xf53e13, 0x80f1ec,
-0xc3e7b3, 0x28f8c7, 0x940593, 0x3e71c1, 0xb3092e, 0xf3450b,
-0x9c1288, 0x7b20ab, 0x9fb52e, 0xc29247, 0x2f327b, 0x6d550c,
-0x90a772, 0x1fe76b, 0x96cb31, 0x4a1679, 0xe27941, 0x89dff4,
-0x9794e8, 0x84e6e2, 0x973199, 0x6bed88, 0x365f5f, 0x0efdbb,
-0xb49a48, 0x6ca467, 0x427271, 0x325d8d, 0xb8159f, 0x09e5bc,
-0x25318d, 0x3974f7, 0x1c0530, 0x010c0d, 0x68084b, 0x58ee2c,
-0x90aa47, 0x02e774, 0x24d6bd, 0xa67df7, 0x72486e, 0xef169f,
-0xa6948e, 0xf691b4, 0x5153d1, 0xf20acf, 0x339820, 0x7e4bf5,
-0x6863b2, 0x5f3edd, 0x035d40, 0x7f8985, 0x295255, 0xc06437,
-0x10d86d, 0x324832, 0x754c5b, 0xd4714e, 0x6e5445, 0xc1090b,
-0x69f52a, 0xd56614, 0x9d0727, 0x50045d, 0xdb3bb4, 0xc576ea,
-0x17f987, 0x7d6b49, 0xba271d, 0x296996, 0xacccc6, 0x5414ad,
-0x6ae290, 0x89d988, 0x50722c, 0xbea404, 0x940777, 0x7030f3,
-0x27fc00, 0xa871ea, 0x49c266, 0x3de064, 0x83dd97, 0x973fa3,
-0xfd9443, 0x8c860d, 0xde4131, 0x9d3992, 0x8c70dd, 0xe7b717,
-0x3bdf08, 0x2b3715, 0xa0805c, 0x93805a, 0x921110, 0xd8e80f,
-0xaf806c, 0x4bffdb, 0x0f9038, 0x761859, 0x15a562, 0xbbcb61,
-0xb989c7, 0xbd4010, 0x04f2d2, 0x277549, 0xf6b6eb, 0xbb22db,
-0xaa140a, 0x2f2689, 0x768364, 0x333b09, 0x1a940e, 0xaa3a51,
-0xc2a31d, 0xaeedaf, 0x12265c, 0x4dc26d, 0x9c7a2d, 0x9756c0,
-0x833f03, 0xf6f009, 0x8c402b, 0x99316d, 0x07b439, 0x15200c,
-0x5bc3d8, 0xc492f5, 0x4badc6, 0xa5ca4e, 0xcd37a7, 0x36a9e6,
-0x9492ab, 0x6842dd, 0xde6319, 0xef8c76, 0x528b68, 0x37dbfc,
-0xaba1ae, 0x3115df, 0xa1ae00, 0xdafb0c, 0x664d64, 0xb705ed,
-0x306529, 0xbf5657, 0x3aff47, 0xb9f96a, 0xf3be75, 0xdf9328,
-0x3080ab, 0xf68c66, 0x15cb04, 0x0622fa, 0x1de4d9, 0xa4b33d,
-0x8f1b57, 0x09cd36, 0xe9424e, 0xa4be13, 0xb52333, 0x1aaaf0,
-0xa8654f, 0xa5c1d2, 0x0f3f0b, 0xcd785b, 0x76f923, 0x048b7b,
-0x721789, 0x53a6c6, 0xe26e6f, 0x00ebef, 0x584a9b, 0xb7dac4,
-0xba66aa, 0xcfcf76, 0x1d02d1, 0x2df1b1, 0xc1998c, 0x77adc3,
-0xda4886, 0xa05df7, 0xf480c6, 0x2ff0ac, 0x9aecdd, 0xbc5c3f,
-0x6dded0, 0x1fc790, 0xb6db2a, 0x3a25a3, 0x9aaf00, 0x9353ad,
-0x0457b6, 0xb42d29, 0x7e804b, 0xa707da, 0x0eaa76, 0xa1597b,
-0x2a1216, 0x2db7dc, 0xfde5fa, 0xfedb89, 0xfdbe89, 0x6c76e4,
-0xfca906, 0x70803e, 0x156e85, 0xff87fd, 0x073e28, 0x336761,
-0x86182a, 0xeabd4d, 0xafe7b3, 0x6e6d8f, 0x396795, 0x5bbf31,
-0x48d784, 0x16df30, 0x432dc7, 0x356125, 0xce70c9, 0xb8cb30,
-0xfd6cbf, 0xa200a4, 0xe46c05, 0xa0dd5a, 0x476f21, 0xd21262,
-0x845cb9, 0x496170, 0xe0566b, 0x015299, 0x375550, 0xb7d51e,
-0xc4f133, 0x5f6e13, 0xe4305d, 0xa92e85, 0xc3b21d, 0x3632a1,
-0xa4b708, 0xd4b1ea, 0x21f716, 0xe4698f, 0x77ff27, 0x80030c,
-0x2d408d, 0xa0cd4f, 0x99a520, 0xd3a2b3, 0x0a5d2f, 0x42f9b4,
-0xcbda11, 0xd0be7d, 0xc1db9b, 0xbd17ab, 0x81a2ca, 0x5c6a08,
-0x17552e, 0x550027, 0xf0147f, 0x8607e1, 0x640b14, 0x8d4196,
-0xdebe87, 0x2afdda, 0xb6256b, 0x34897b, 0xfef305, 0x9ebfb9,
-0x4f6a68, 0xa82a4a, 0x5ac44f, 0xbcf82d, 0x985ad7, 0x95c7f4,
-0x8d4d0d, 0xa63a20, 0x5f57a4, 0xb13f14, 0x953880, 0x0120cc,
-0x86dd71, 0xb6dec9, 0xf560bf, 0x11654d, 0x6b0701, 0xacb08c,
-0xd0c0b2, 0x485551, 0x0efb1e, 0xc37295, 0x3b06a3, 0x3540c0,
-0x7bdc06, 0xcc45e0, 0xfa294e, 0xc8cad6, 0x41f3e8, 0xde647c,
-0xd8649b, 0x31bed9, 0xc397a4, 0xd45877, 0xc5e369, 0x13daf0,
-0x3c3aba, 0x461846, 0x5f7555, 0xf5bdd2, 0xc6926e, 0x5d2eac,
-0xed440e, 0x423e1c, 0x87c461, 0xe9fd29, 0xf3d6e7, 0xca7c22,
-0x35916f, 0xc5e008, 0x8dd7ff, 0xe26a6e, 0xc6fdb0, 0xc10893,
-0x745d7c, 0xb2ad6b, 0x9d6ecd, 0x7b723e, 0x6a11c6, 0xa9cff7,
-0xdf7329, 0xbac9b5, 0x5100b7, 0x0db2e2, 0x24ba74, 0x607de5,
-0x8ad874, 0x2c150d, 0x0c1881, 0x94667e, 0x162901, 0x767a9f,
-0xbefdfd, 0xef4556, 0x367ed9, 0x13d9ec, 0xb9ba8b, 0xfc97c4,
-0x27a831, 0xc36ef1, 0x36c594, 0x56a8d8, 0xb5a8b4, 0x0ecccf,
-0x2d8912, 0x34576f, 0x89562c, 0xe3ce99, 0xb920d6, 0xaa5e6b,
-0x9c2a3e, 0xcc5f11, 0x4a0bfd, 0xfbf4e1, 0x6d3b8e, 0x2c86e2,
-0x84d4e9, 0xa9b4fc, 0xd1eeef, 0xc9352e, 0x61392f, 0x442138,
-0xc8d91b, 0x0afc81, 0x6a4afb, 0xd81c2f, 0x84b453, 0x8c994e,
-0xcc2254, 0xdc552a, 0xd6c6c0, 0x96190b, 0xb8701a, 0x649569,
-0x605a26, 0xee523f, 0x0f117f, 0x11b5f4, 0xf5cbfc, 0x2dbc34,
-0xeebc34, 0xcc5de8, 0x605edd, 0x9b8e67, 0xef3392, 0xb817c9,
-0x9b5861, 0xbc57e1, 0xc68351, 0x103ed8, 0x4871dd, 0xdd1c2d,
-0xa118af, 0x462c21, 0xd7f359, 0x987ad9, 0xc0549e, 0xfa864f,
-0xfc0656, 0xae79e5, 0x362289, 0x22ad38, 0xdc9367, 0xaae855,
-0x382682, 0x9be7ca, 0xa40d51, 0xb13399, 0x0ed7a9, 0x480569,
-0xf0b265, 0xa7887f, 0x974c88, 0x36d1f9, 0xb39221, 0x4a827b,
-0x21cf98, 0xdc9f40, 0x5547dc, 0x3a74e1, 0x42eb67, 0xdf9dfe,
-0x5fd45e, 0xa4677b, 0x7aacba, 0xa2f655, 0x23882b, 0x55ba41,
-0x086e59, 0x862a21, 0x834739, 0xe6e389, 0xd49ee5, 0x40fb49,
-0xe956ff, 0xca0f1c, 0x8a59c5, 0x2bfa94, 0xc5c1d3, 0xcfc50f,
-0xae5adb, 0x86c547, 0x624385, 0x3b8621, 0x94792c, 0x876110,
-0x7b4c2a, 0x1a2c80, 0x12bf43, 0x902688, 0x893c78, 0xe4c4a8,
-0x7bdbe5, 0xc23ac4, 0xeaf426, 0x8a67f7, 0xbf920d, 0x2ba365,
-0xb1933d, 0x0b7cbd, 0xdc51a4, 0x63dd27, 0xdde169, 0x19949a,
-0x9529a8, 0x28ce68, 0xb4ed09, 0x209f44, 0xca984e, 0x638270,
-0x237c7e, 0x32b90f, 0x8ef5a7, 0xe75614, 0x08f121, 0x2a9db5,
-0x4d7e6f, 0x5119a5, 0xabf9b5, 0xd6df82, 0x61dd96, 0x023616,
-0x9f3ac4, 0xa1a283, 0x6ded72, 0x7a8d39, 0xa9b882, 0x5c326b,
-0x5b2746, 0xed3400, 0x7700d2, 0x55f4fc, 0x4d5901, 0x8071e0,
-0xe13f89, 0xb295f3, 0x64a8f1, 0xaea74b, 0x38fc4c, 0xeab2bb,
-0x47270b, 0xabc3a7, 0x34ba60, 0x52dd34, 0xf8563a, 0xeb7e8a,
-0x31bb36, 0x5895b7, 0x47f7a9, 0x94c3aa, 0xd39225, 0x1e7f3e,
-0xd8974e, 0xbba94f, 0xd8ae01, 0xe661b4, 0x393d8e, 0xa523aa,
-0x33068e, 0x1633b5, 0x3bb188, 0x1d3a9d, 0x4013d0, 0xcc1be5,
-0xf862e7, 0x3bf28f, 0x39b5bf, 0x0bc235, 0x22747e, 0xa247c0,
-0xd52d1f, 0x19add3, 0x9094df, 0x9311d0, 0xb42b25, 0x496db2,
-0xe264b2, 0x5ef135, 0x3bc6a4, 0x1a4ad0, 0xaac92e, 0x64e886,
-0x573091, 0x982cfb, 0x311b1a, 0x08728b, 0xbdcee1, 0x60e142,
-0xeb641d, 0xd0bba3, 0xe559d4, 0x597b8c, 0x2a4483, 0xf332ba,
-0xf84867, 0x2c8d1b, 0x2fa9b0, 0x50f3dd, 0xf9f573, 0xdb61b4,
-0xfe233e, 0x6c41a6, 0xeea318, 0x775a26, 0xbc5e5c, 0xcea708,
-0x94dc57, 0xe20196, 0xf1e839, 0xbe4851, 0x5d2d2f, 0x4e9555,
-0xd96ec2, 0xe7d755, 0x6304e0, 0xc02e0e, 0xfc40a0, 0xbbf9b3,
-0x7125a7, 0x222dfb, 0xf619d8, 0x838c1c, 0x6619e6, 0xb20d55,
-0xbb5137, 0x79e809, 0xaf9149, 0x0d73de, 0x0b0da5, 0xce7f58,
-0xac1934, 0x724667, 0x7a1a13, 0x9e26bc, 0x4555e7, 0x585cb5,
-0x711d14, 0x486991, 0x480d60, 0x56adab, 0xd62f64, 0x96ee0c,
-0x212ff3, 0x5d6d88, 0xa67684, 0x95651e, 0xab9e0a, 0x4ddefe,
-0x571010, 0x836a39, 0xf8ea31, 0x9e381d, 0xeac8b1, 0xcac96b,
-0x37f21e, 0xd505e9, 0x984743, 0x9fc56c, 0x0331b7, 0x3b8bf8,
-0x86e56a, 0x8dc343, 0x6230e7, 0x93cfd5, 0x6a8f2d, 0x733005,
-0x1af021, 0xa09fcb, 0x7415a1, 0xd56b23, 0x6ff725, 0x2f4bc7,
-0xb8a591, 0x7fac59, 0x5c55de, 0x212c38, 0xb13296, 0x5cff50,
-0x366262, 0xfa7b16, 0xf4d9a6, 0x2acfe7, 0xf07403, 0xd4d604,
-0x6fd916, 0x31b1bf, 0xcbb450, 0x5bd7c8, 0x0ce194, 0x6bd643,
-0x4fd91c, 0xdf4543, 0x5f3453, 0xe2b5aa, 0xc9aec8, 0x131485,
-0xf9d2bf, 0xbadb9e, 0x76f5b9, 0xaf15cf, 0xca3182, 0x14b56d,
-0xe9fe4d, 0x50fc35, 0xf5aed5, 0xa2d0c1, 0xc96057, 0x192eb6,
-0xe91d92, 0x07d144, 0xaea3c6, 0x343566, 0x26d5b4, 0x3161e2,
-0x37f1a2, 0x209eff, 0x958e23, 0x493798, 0x35f4a6, 0x4bdc02,
-0xc2be13, 0xbe80a0, 0x0b72a3, 0x115c5f, 0x1e1bd1, 0x0db4d3,
-0x869e85, 0x96976b, 0x2ac91f, 0x8a26c2, 0x3070f0, 0x041412,
-0xfc9fa5, 0xf72a38, 0x9c6878, 0xe2aa76, 0x50cfe1, 0x559274,
-0x934e38, 0x0a92f7, 0x5533f0, 0xa63db4, 0x399971, 0xe2b755,
-0xa98a7c, 0x008f19, 0xac54d2, 0x2ea0b4, 0xf5f3e0, 0x60c849,
-0xffd269, 0xae52ce, 0x7a5fdd, 0xe9ce06, 0xfb0ae8, 0xa50cce,
-0xea9d3e, 0x3766dd, 0xb834f5, 0x0da090, 0x846f88, 0x4ae3d5,
-0x099a03, 0x2eae2d, 0xfcb40a, 0xfb9b33, 0xe281dd, 0x1b16ba,
-0xd8c0af, 0xd96b97, 0xb52dc9, 0x9c277f, 0x5951d5, 0x21ccd6,
-0xb6496b, 0x584562, 0xb3baf2, 0xa1a5c4, 0x7ca2cf, 0xa9b93d,
-0x7b7b89, 0x483d38,
+0xa2f983, 0x6e4e44, 0x1529fc, 0x2757d1, 0xf534dd, 0xc0db62,
+0x95993c, 0x439041, 0xfe5163, 0xabdebb, 0xc561b7, 0x246e3a,
+0x424dd2, 0xe00649, 0x2eea09, 0xd1921c, 0xfe1deb, 0x1cb129,
+0xa73ee8, 0x8235f5, 0x2ebb44, 0x84e99c, 0x7026b4, 0x5f7e41,
+0x3991d6, 0x398353, 0x39f49c, 0x845f8b, 0xbdf928, 0x3b1ff8,
+0x97ffde, 0x05980f, 0xef2f11, 0x8b5a0a, 0x6d1f6d, 0x367ecf,
+0x27cb09, 0xb74f46, 0x3f669e, 0x5fea2d, 0x7527ba, 0xc7ebe5,
+0xf17b3d, 0x0739f7, 0x8a5292, 0xea6bfb, 0x5fb11f, 0x8d5d08,
+0x560330, 0x46fc7b, 0x6babf0, 0xcfbc20, 0x9af436, 0x1da9e3,
+0x91615e, 0xe61b08, 0x659985, 0x5f14a0, 0x68408d, 0xffd880,
+0x4d7327, 0x310606, 0x1556ca, 0x73a8c9, 0x60e27b, 0xc08c6b,
+0x47c419, 0xc367cd, 0xdce809, 0x2a8359, 0xc4768b, 0x961ca6,
+0xddaf44, 0xd15719, 0x053ea5, 0xff0705, 0x3f7e33, 0xe832c2,
+0xde4f98, 0x327dbb, 0xc33d26, 0xef6b1e, 0x5ef89f, 0x3a1f35,
+0xcaf27f, 0x1d87f1, 0x21907c, 0x7c246a, 0xfa6ed5, 0x772d30,
+0x433b15, 0xc614b5, 0x9d19c3, 0xc2c4ad, 0x414d2c, 0x5d000c,
+0x467d86, 0x2d71e3, 0x9ac69b, 0x006233, 0x7cd2b4, 0x97a7b4,
+0xd55537, 0xf63ed7, 0x1810a3, 0xfc764d, 0x2a9d64, 0xabd770,
+0xf87c63, 0x57b07a, 0xe71517, 0x5649c0, 0xd9d63b, 0x3884a7,
+0xcb2324, 0x778ad6, 0x23545a, 0xb91f00, 0x1b0af1, 0xdfce19,
+0xff319f, 0x6a1e66, 0x615799, 0x47fbac, 0xd87f7e, 0xb76522,
+0x89e832, 0x60bfe6, 0xcdc4ef, 0x09366c, 0xd43f5d, 0xd7de16,
+0xde3b58, 0x929bde, 0x2822d2, 0xe88628, 0x4d58e2, 0x32cac6,
+0x16e308, 0xcb7de0, 0x50c017, 0xa71df3, 0x5be018, 0x34132e,
+0x621283, 0x014883, 0x5b8ef5, 0x7fb0ad, 0xf2e91e, 0x434a48,
+0xd36710, 0xd8ddaa, 0x425fae, 0xce616a, 0xa4280a, 0xb499d3,
+0xf2a606, 0x7f775c, 0x83c2a3, 0x883c61, 0x78738a, 0x5a8caf,
+0xbdd76f, 0x63a62d, 0xcbbff4, 0xef818d, 0x67c126, 0x45ca55,
+0x36d9ca, 0xd2a828, 0x8d61c2, 0x77c912, 0x142604, 0x9b4612,
+0xc459c4, 0x44c5c8, 0x91b24d, 0xf31700, 0xad43d4, 0xe54929,
+0x10d5fd, 0xfcbe00, 0xcc941e, 0xeece70, 0xf53e13, 0x80f1ec,
+0xc3e7b3, 0x28f8c7, 0x940593, 0x3e71c1, 0xb3092e, 0xf3450b,
+0x9c1288, 0x7b20ab, 0x9fb52e, 0xc29247, 0x2f327b, 0x6d550c,
+0x90a772, 0x1fe76b, 0x96cb31, 0x4a1679, 0xe27941, 0x89dff4,
+0x9794e8, 0x84e6e2, 0x973199, 0x6bed88, 0x365f5f, 0x0efdbb,
+0xb49a48, 0x6ca467, 0x427271, 0x325d8d, 0xb8159f, 0x09e5bc,
+0x25318d, 0x3974f7, 0x1c0530, 0x010c0d, 0x68084b, 0x58ee2c,
+0x90aa47, 0x02e774, 0x24d6bd, 0xa67df7, 0x72486e, 0xef169f,
+0xa6948e, 0xf691b4, 0x5153d1, 0xf20acf, 0x339820, 0x7e4bf5,
+0x6863b2, 0x5f3edd, 0x035d40, 0x7f8985, 0x295255, 0xc06437,
+0x10d86d, 0x324832, 0x754c5b, 0xd4714e, 0x6e5445, 0xc1090b,
+0x69f52a, 0xd56614, 0x9d0727, 0x50045d, 0xdb3bb4, 0xc576ea,
+0x17f987, 0x7d6b49, 0xba271d, 0x296996, 0xacccc6, 0x5414ad,
+0x6ae290, 0x89d988, 0x50722c, 0xbea404, 0x940777, 0x7030f3,
+0x27fc00, 0xa871ea, 0x49c266, 0x3de064, 0x83dd97, 0x973fa3,
+0xfd9443, 0x8c860d, 0xde4131, 0x9d3992, 0x8c70dd, 0xe7b717,
+0x3bdf08, 0x2b3715, 0xa0805c, 0x93805a, 0x921110, 0xd8e80f,
+0xaf806c, 0x4bffdb, 0x0f9038, 0x761859, 0x15a562, 0xbbcb61,
+0xb989c7, 0xbd4010, 0x04f2d2, 0x277549, 0xf6b6eb, 0xbb22db,
+0xaa140a, 0x2f2689, 0x768364, 0x333b09, 0x1a940e, 0xaa3a51,
+0xc2a31d, 0xaeedaf, 0x12265c, 0x4dc26d, 0x9c7a2d, 0x9756c0,
+0x833f03, 0xf6f009, 0x8c402b, 0x99316d, 0x07b439, 0x15200c,
+0x5bc3d8, 0xc492f5, 0x4badc6, 0xa5ca4e, 0xcd37a7, 0x36a9e6,
+0x9492ab, 0x6842dd, 0xde6319, 0xef8c76, 0x528b68, 0x37dbfc,
+0xaba1ae, 0x3115df, 0xa1ae00, 0xdafb0c, 0x664d64, 0xb705ed,
+0x306529, 0xbf5657, 0x3aff47, 0xb9f96a, 0xf3be75, 0xdf9328,
+0x3080ab, 0xf68c66, 0x15cb04, 0x0622fa, 0x1de4d9, 0xa4b33d,
+0x8f1b57, 0x09cd36, 0xe9424e, 0xa4be13, 0xb52333, 0x1aaaf0,
+0xa8654f, 0xa5c1d2, 0x0f3f0b, 0xcd785b, 0x76f923, 0x048b7b,
+0x721789, 0x53a6c6, 0xe26e6f, 0x00ebef, 0x584a9b, 0xb7dac4,
+0xba66aa, 0xcfcf76, 0x1d02d1, 0x2df1b1, 0xc1998c, 0x77adc3,
+0xda4886, 0xa05df7, 0xf480c6, 0x2ff0ac, 0x9aecdd, 0xbc5c3f,
+0x6dded0, 0x1fc790, 0xb6db2a, 0x3a25a3, 0x9aaf00, 0x9353ad,
+0x0457b6, 0xb42d29, 0x7e804b, 0xa707da, 0x0eaa76, 0xa1597b,
+0x2a1216, 0x2db7dc, 0xfde5fa, 0xfedb89, 0xfdbe89, 0x6c76e4,
+0xfca906, 0x70803e, 0x156e85, 0xff87fd, 0x073e28, 0x336761,
+0x86182a, 0xeabd4d, 0xafe7b3, 0x6e6d8f, 0x396795, 0x5bbf31,
+0x48d784, 0x16df30, 0x432dc7, 0x356125, 0xce70c9, 0xb8cb30,
+0xfd6cbf, 0xa200a4, 0xe46c05, 0xa0dd5a, 0x476f21, 0xd21262,
+0x845cb9, 0x496170, 0xe0566b, 0x015299, 0x375550, 0xb7d51e,
+0xc4f133, 0x5f6e13, 0xe4305d, 0xa92e85, 0xc3b21d, 0x3632a1,
+0xa4b708, 0xd4b1ea, 0x21f716, 0xe4698f, 0x77ff27, 0x80030c,
+0x2d408d, 0xa0cd4f, 0x99a520, 0xd3a2b3, 0x0a5d2f, 0x42f9b4,
+0xcbda11, 0xd0be7d, 0xc1db9b, 0xbd17ab, 0x81a2ca, 0x5c6a08,
+0x17552e, 0x550027, 0xf0147f, 0x8607e1, 0x640b14, 0x8d4196,
+0xdebe87, 0x2afdda, 0xb6256b, 0x34897b, 0xfef305, 0x9ebfb9,
+0x4f6a68, 0xa82a4a, 0x5ac44f, 0xbcf82d, 0x985ad7, 0x95c7f4,
+0x8d4d0d, 0xa63a20, 0x5f57a4, 0xb13f14, 0x953880, 0x0120cc,
+0x86dd71, 0xb6dec9, 0xf560bf, 0x11654d, 0x6b0701, 0xacb08c,
+0xd0c0b2, 0x485551, 0x0efb1e, 0xc37295, 0x3b06a3, 0x3540c0,
+0x7bdc06, 0xcc45e0, 0xfa294e, 0xc8cad6, 0x41f3e8, 0xde647c,
+0xd8649b, 0x31bed9, 0xc397a4, 0xd45877, 0xc5e369, 0x13daf0,
+0x3c3aba, 0x461846, 0x5f7555, 0xf5bdd2, 0xc6926e, 0x5d2eac,
+0xed440e, 0x423e1c, 0x87c461, 0xe9fd29, 0xf3d6e7, 0xca7c22,
+0x35916f, 0xc5e008, 0x8dd7ff, 0xe26a6e, 0xc6fdb0, 0xc10893,
+0x745d7c, 0xb2ad6b, 0x9d6ecd, 0x7b723e, 0x6a11c6, 0xa9cff7,
+0xdf7329, 0xbac9b5, 0x5100b7, 0x0db2e2, 0x24ba74, 0x607de5,
+0x8ad874, 0x2c150d, 0x0c1881, 0x94667e, 0x162901, 0x767a9f,
+0xbefdfd, 0xef4556, 0x367ed9, 0x13d9ec, 0xb9ba8b, 0xfc97c4,
+0x27a831, 0xc36ef1, 0x36c594, 0x56a8d8, 0xb5a8b4, 0x0ecccf,
+0x2d8912, 0x34576f, 0x89562c, 0xe3ce99, 0xb920d6, 0xaa5e6b,
+0x9c2a3e, 0xcc5f11, 0x4a0bfd, 0xfbf4e1, 0x6d3b8e, 0x2c86e2,
+0x84d4e9, 0xa9b4fc, 0xd1eeef, 0xc9352e, 0x61392f, 0x442138,
+0xc8d91b, 0x0afc81, 0x6a4afb, 0xd81c2f, 0x84b453, 0x8c994e,
+0xcc2254, 0xdc552a, 0xd6c6c0, 0x96190b, 0xb8701a, 0x649569,
+0x605a26, 0xee523f, 0x0f117f, 0x11b5f4, 0xf5cbfc, 0x2dbc34,
+0xeebc34, 0xcc5de8, 0x605edd, 0x9b8e67, 0xef3392, 0xb817c9,
+0x9b5861, 0xbc57e1, 0xc68351, 0x103ed8, 0x4871dd, 0xdd1c2d,
+0xa118af, 0x462c21, 0xd7f359, 0x987ad9, 0xc0549e, 0xfa864f,
+0xfc0656, 0xae79e5, 0x362289, 0x22ad38, 0xdc9367, 0xaae855,
+0x382682, 0x9be7ca, 0xa40d51, 0xb13399, 0x0ed7a9, 0x480569,
+0xf0b265, 0xa7887f, 0x974c88, 0x36d1f9, 0xb39221, 0x4a827b,
+0x21cf98, 0xdc9f40, 0x5547dc, 0x3a74e1, 0x42eb67, 0xdf9dfe,
+0x5fd45e, 0xa4677b, 0x7aacba, 0xa2f655, 0x23882b, 0x55ba41,
+0x086e59, 0x862a21, 0x834739, 0xe6e389, 0xd49ee5, 0x40fb49,
+0xe956ff, 0xca0f1c, 0x8a59c5, 0x2bfa94, 0xc5c1d3, 0xcfc50f,
+0xae5adb, 0x86c547, 0x624385, 0x3b8621, 0x94792c, 0x876110,
+0x7b4c2a, 0x1a2c80, 0x12bf43, 0x902688, 0x893c78, 0xe4c4a8,
+0x7bdbe5, 0xc23ac4, 0xeaf426, 0x8a67f7, 0xbf920d, 0x2ba365,
+0xb1933d, 0x0b7cbd, 0xdc51a4, 0x63dd27, 0xdde169, 0x19949a,
+0x9529a8, 0x28ce68, 0xb4ed09, 0x209f44, 0xca984e, 0x638270,
+0x237c7e, 0x32b90f, 0x8ef5a7, 0xe75614, 0x08f121, 0x2a9db5,
+0x4d7e6f, 0x5119a5, 0xabf9b5, 0xd6df82, 0x61dd96, 0x023616,
+0x9f3ac4, 0xa1a283, 0x6ded72, 0x7a8d39, 0xa9b882, 0x5c326b,
+0x5b2746, 0xed3400, 0x7700d2, 0x55f4fc, 0x4d5901, 0x8071e0,
+0xe13f89, 0xb295f3, 0x64a8f1, 0xaea74b, 0x38fc4c, 0xeab2bb,
+0x47270b, 0xabc3a7, 0x34ba60, 0x52dd34, 0xf8563a, 0xeb7e8a,
+0x31bb36, 0x5895b7, 0x47f7a9, 0x94c3aa, 0xd39225, 0x1e7f3e,
+0xd8974e, 0xbba94f, 0xd8ae01, 0xe661b4, 0x393d8e, 0xa523aa,
+0x33068e, 0x1633b5, 0x3bb188, 0x1d3a9d, 0x4013d0, 0xcc1be5,
+0xf862e7, 0x3bf28f, 0x39b5bf, 0x0bc235, 0x22747e, 0xa247c0,
+0xd52d1f, 0x19add3, 0x9094df, 0x9311d0, 0xb42b25, 0x496db2,
+0xe264b2, 0x5ef135, 0x3bc6a4, 0x1a4ad0, 0xaac92e, 0x64e886,
+0x573091, 0x982cfb, 0x311b1a, 0x08728b, 0xbdcee1, 0x60e142,
+0xeb641d, 0xd0bba3, 0xe559d4, 0x597b8c, 0x2a4483, 0xf332ba,
+0xf84867, 0x2c8d1b, 0x2fa9b0, 0x50f3dd, 0xf9f573, 0xdb61b4,
+0xfe233e, 0x6c41a6, 0xeea318, 0x775a26, 0xbc5e5c, 0xcea708,
+0x94dc57, 0xe20196, 0xf1e839, 0xbe4851, 0x5d2d2f, 0x4e9555,
+0xd96ec2, 0xe7d755, 0x6304e0, 0xc02e0e, 0xfc40a0, 0xbbf9b3,
+0x7125a7, 0x222dfb, 0xf619d8, 0x838c1c, 0x6619e6, 0xb20d55,
+0xbb5137, 0x79e809, 0xaf9149, 0x0d73de, 0x0b0da5, 0xce7f58,
+0xac1934, 0x724667, 0x7a1a13, 0x9e26bc, 0x4555e7, 0x585cb5,
+0x711d14, 0x486991, 0x480d60, 0x56adab, 0xd62f64, 0x96ee0c,
+0x212ff3, 0x5d6d88, 0xa67684, 0x95651e, 0xab9e0a, 0x4ddefe,
+0x571010, 0x836a39, 0xf8ea31, 0x9e381d, 0xeac8b1, 0xcac96b,
+0x37f21e, 0xd505e9, 0x984743, 0x9fc56c, 0x0331b7, 0x3b8bf8,
+0x86e56a, 0x8dc343, 0x6230e7, 0x93cfd5, 0x6a8f2d, 0x733005,
+0x1af021, 0xa09fcb, 0x7415a1, 0xd56b23, 0x6ff725, 0x2f4bc7,
+0xb8a591, 0x7fac59, 0x5c55de, 0x212c38, 0xb13296, 0x5cff50,
+0x366262, 0xfa7b16, 0xf4d9a6, 0x2acfe7, 0xf07403, 0xd4d604,
+0x6fd916, 0x31b1bf, 0xcbb450, 0x5bd7c8, 0x0ce194, 0x6bd643,
+0x4fd91c, 0xdf4543, 0x5f3453, 0xe2b5aa, 0xc9aec8, 0x131485,
+0xf9d2bf, 0xbadb9e, 0x76f5b9, 0xaf15cf, 0xca3182, 0x14b56d,
+0xe9fe4d, 0x50fc35, 0xf5aed5, 0xa2d0c1, 0xc96057, 0x192eb6,
+0xe91d92, 0x07d144, 0xaea3c6, 0x343566, 0x26d5b4, 0x3161e2,
+0x37f1a2, 0x209eff, 0x958e23, 0x493798, 0x35f4a6, 0x4bdc02,
+0xc2be13, 0xbe80a0, 0x0b72a3, 0x115c5f, 0x1e1bd1, 0x0db4d3,
+0x869e85, 0x96976b, 0x2ac91f, 0x8a26c2, 0x3070f0, 0x041412,
+0xfc9fa5, 0xf72a38, 0x9c6878, 0xe2aa76, 0x50cfe1, 0x559274,
+0x934e38, 0x0a92f7, 0x5533f0, 0xa63db4, 0x399971, 0xe2b755,
+0xa98a7c, 0x008f19, 0xac54d2, 0x2ea0b4, 0xf5f3e0, 0x60c849,
+0xffd269, 0xae52ce, 0x7a5fdd, 0xe9ce06, 0xfb0ae8, 0xa50cce,
+0xea9d3e, 0x3766dd, 0xb834f5, 0x0da090, 0x846f88, 0x4ae3d5,
+0x099a03, 0x2eae2d, 0xfcb40a, 0xfb9b33, 0xe281dd, 0x1b16ba,
+0xd8c0af, 0xd96b97, 0xb52dc9, 0x9c277f, 0x5951d5, 0x21ccd6,
+0xb6496b, 0x584562, 0xb3baf2, 0xa1a5c4, 0x7ca2cf, 0xa9b93d,
+0x7b7b89, 0x483d38,
};
static const __float128 c[] = {
-/* 93 bits of pi/2 */
+/* 113 bits of pi/2 */
#define PI_2_1 c[0]
- 1.57079632679489661923132169155131424e+00Q, /* 3fff921fb54442d18469898cc5100000 */
+ 0x1.921fb54442d18469898cc51701b8p+0Q,
/* pi/2 - PI_2_1 */
#define PI_2_1t c[1]
- 8.84372056613570112025531863263659260e-29Q, /* 3fa1c06e0e68948127044533e63a0106 */
+ 0x3.9a252049c1114cf98e804177d4c8p-116Q,
};
@@ -525,8 +525,8 @@ __quadmath_rem_pio2q (__float128 x, __float128 *y)
if (ix < 0x40002d97c7f3321dLL) /* |x| in <pi/4, 3pi/4) */
{
if (hx > 0)
- {
- /* 113 + 93 bit PI is ok */
+ {
+ /* 113 + 113 bit PI is ok */
z = x - PI_2_1;
y[0] = z - PI_2_1t;
y[1] = (z - y[0]) - PI_2_1t;
@@ -534,7 +534,7 @@ __quadmath_rem_pio2q (__float128 x, __float128 *y)
}
else
{
- /* 113 + 93 bit PI is ok */
+ /* 113 + 113 bit PI is ok */
z = x + PI_2_1;
y[0] = z + PI_2_1t;
y[1] = (z - y[0]) + PI_2_1t;
diff --git a/libquadmath/math/remquoq.c b/libquadmath/math/remquoq.c
index f7001afc3e5..fa85c5b2d50 100644
--- a/libquadmath/math/remquoq.c
+++ b/libquadmath/math/remquoq.c
@@ -1,5 +1,5 @@
/* Compute remainder and a congruent to the quotient.
- Copyright (C) 1997, 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
Jakub Jelinek <jj@ultra.linux.cz>, 1999.
@@ -49,7 +49,7 @@ remquoq (__float128 x, __float128 y, int *quo)
if (hy <= 0x7ffbffffffffffffLL)
x = fmodq (x, 8 * y); /* now x < 8y */
-
+
if (((hx - hy) | (lx - ly)) == 0)
{
*quo = qs ? -1 : 1;
@@ -60,12 +60,12 @@ remquoq (__float128 x, __float128 y, int *quo)
y = fabsq (y);
cquo = 0;
- if (x >= 4 * y)
+ if (hy <= 0x7ffcffffffffffffLL && x >= 4 * y)
{
x -= 4 * y;
cquo += 4;
}
- if (x >= 2 * y)
+ if (hy <= 0x7ffdffffffffffffLL && x >= 2 * y)
{
x -= 2 * y;
cquo += 2;
@@ -101,6 +101,9 @@ remquoq (__float128 x, __float128 y, int *quo)
*quo = qs ? -cquo : cquo;
+ /* Ensure correct sign of zero result in round-downward mode. */
+ if (x == 0.0Q)
+ x = 0.0Q;
if (sx)
x = -x;
return x;
diff --git a/libquadmath/math/rintq.c b/libquadmath/math/rintq.c
index 15d4c781ba4..7bc9684e5ea 100644
--- a/libquadmath/math/rintq.c
+++ b/libquadmath/math/rintq.c
@@ -35,7 +35,7 @@ __float128
rintq (__float128 x)
{
int64_t i0,j0,sx;
- uint64_t i1;
+ uint64_t i1 __attribute__ ((unused));
__float128 w,t;
GET_FLT128_WORDS64(i0,i1,x);
sx = (((uint64_t)i0)>>63);
diff --git a/libquadmath/math/roundq.c b/libquadmath/math/roundq.c
index 7c9d640e933..b48366315f4 100644
--- a/libquadmath/math/roundq.c
+++ b/libquadmath/math/roundq.c
@@ -1,5 +1,5 @@
/* Round __float128 to integer away from zero.
- Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
Jakub Jelinek <jj@ultra.linux.cz>, 1999.
@@ -21,9 +21,6 @@
#include "quadmath-imp.h"
-static const __float128 huge = 1.0E4930Q;
-
-
__float128
roundq (__float128 x)
{
@@ -32,17 +29,14 @@ roundq (__float128 x)
GET_FLT128_WORDS64 (i0, i1, x);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
- if (j0 < 31)
+ if (j0 < 48)
{
if (j0 < 0)
{
- if (huge + x > 0.0)
- {
- i0 &= 0x8000000000000000ULL;
- if (j0 == -1)
- i0 |= 0x3fff000000000000LL;
- i1 = 0;
- }
+ i0 &= 0x8000000000000000ULL;
+ if (j0 == -1)
+ i0 |= 0x3fff000000000000LL;
+ i1 = 0;
}
else
{
@@ -50,13 +44,9 @@ roundq (__float128 x)
if (((i0 & i) | i1) == 0)
/* X is integral. */
return x;
- if (huge + x > 0.0)
- {
- /* Raise inexact if x != 0. */
- i0 += 0x0000800000000000LL >> j0;
- i0 &= ~i;
- i1 = 0;
- }
+ i0 += 0x0000800000000000LL >> j0;
+ i0 &= ~i;
+ i1 = 0;
}
}
else if (j0 > 111)
@@ -74,14 +64,10 @@ roundq (__float128 x)
/* X is integral. */
return x;
- if (huge + x > 0.0)
- {
- /* Raise inexact if x != 0. */
- uint64_t j = i1 + (1LL << (111 - j0));
- if (j < i1)
- i0 += 1;
- i1 = j;
- }
+ uint64_t j = i1 + (1LL << (111 - j0));
+ if (j < i1)
+ i0 += 1;
+ i1 = j;
i1 &= ~i;
}
diff --git a/libquadmath/math/scalblnq.c b/libquadmath/math/scalblnq.c
index a414045b51f..6aac21125f8 100644
--- a/libquadmath/math/scalblnq.c
+++ b/libquadmath/math/scalblnq.c
@@ -1,7 +1,7 @@
/* scalblnq.c -- __float128 version of s_scalbn.c.
* Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
*/
-
+
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
diff --git a/libquadmath/math/scalbnq.c b/libquadmath/math/scalbnq.c
index 9975a47154c..9ed5fe61799 100644
--- a/libquadmath/math/scalbnq.c
+++ b/libquadmath/math/scalbnq.c
@@ -1,7 +1,7 @@
/* scalbnq.c -- __float128 version of s_scalbn.c.
* Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
*/
-
+
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
diff --git a/libquadmath/math/sincos_table.c b/libquadmath/math/sincos_table.c
index b7e7c750314..362f517a6ef 100644
--- a/libquadmath/math/sincos_table.c
+++ b/libquadmath/math/sincos_table.c
@@ -1,5 +1,5 @@
/* Quad-precision floating point sine and cosine tables.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jj@ultra.linux.cz>
@@ -37,7 +37,7 @@ const __float128 __sincosq_table[] = {
/* sin(x) = 0.25dc50bc95711d0d9787d108fd438cf5959ee0bfb7a1e36e8b1a112968f356657420e9cc9ea */
1.47892995873409608580026675734609314e-01Q, /* 3ffc2ee285e4ab88e86cbc3e8847ea1c */
9.74950446464233268291647449768590886e-36Q, /* 3f8a9eb2b3dc17f6f43c6dd16342252d */
-
+
/* x = 1.56250000000000000000000000000000000e-01 3ffc4000000000000000000000000000 */
/* cos(x) = 0.fce1a053e621438b6d60c76e8c45bf0a9dc71aa16f922acc10e95144ec796a249813c9cb649 */
9.87817783816471944100503034363211317e-01Q, /* 3ffef9c340a7cc428716dac18edd188b */
diff --git a/libquadmath/math/sincosq.c b/libquadmath/math/sincosq.c
index b7c221486d7..d83b1a6b757 100644
--- a/libquadmath/math/sincosq.c
+++ b/libquadmath/math/sincosq.c
@@ -1,5 +1,5 @@
/* Compute sine and cosine of argument.
- Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
Jakub Jelinek <jj@ultra.linux.cz>.
@@ -19,6 +19,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <errno.h>
#include "quadmath-imp.h"
void
@@ -37,6 +38,8 @@ sincosq (__float128 x, __float128 *sinx, __float128 *cosx)
{
/* sin(Inf or NaN) is NaN */
*sinx = *cosx = x - x;
+ if (isinfq (x))
+ errno = EDOM;
}
else
{
diff --git a/libquadmath/math/sincosq_kernel.c b/libquadmath/math/sincosq_kernel.c
index f6341a4d948..171ed6fc117 100644
--- a/libquadmath/math/sincosq_kernel.c
+++ b/libquadmath/math/sincosq_kernel.c
@@ -1,5 +1,5 @@
/* Quad-precision floating point sine and cosine on <-pi/4,pi/4>.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jj@ultra.linux.cz>
@@ -110,12 +110,15 @@ __quadmath_kernel_sincosq(__float128 x, __float128 y, __float128 *sinx,
/* Argument is small enough to approximate it by a Chebyshev
polynomial of degree 16(17). */
if (tix < 0x3fc60000) /* |x| < 2^-57 */
- if (!((int)x)) /* generate inexact */
- {
- *sinx = x;
- *cosx = ONE;
- return;
- }
+ {
+ math_check_force_underflow (x);
+ if (!((int)x)) /* generate inexact */
+ {
+ *sinx = x;
+ *cosx = ONE;
+ return;
+ }
+ }
z = x * x;
*sinx = x + (x * (z*(SIN1+z*(SIN2+z*(SIN3+z*(SIN4+
z*(SIN5+z*(SIN6+z*(SIN7+z*SIN8)))))))));
diff --git a/libquadmath/math/sinhq.c b/libquadmath/math/sinhq.c
index eff8149b515..a4191c0fd3d 100644
--- a/libquadmath/math/sinhq.c
+++ b/libquadmath/math/sinhq.c
@@ -85,8 +85,11 @@ sinhq (__float128 x)
if (ix <= 0x40044000)
{
if (ix < 0x3fc60000) /* |x| < 2^-57 */
- if (shuge + x > one)
- return x; /* sinh(tiny) = tiny with inexact */
+ {
+ math_check_force_underflow (x);
+ if (shuge + x > one)
+ return x; /* sinh(tiny) = tiny with inexact */
+ }
t = expm1q (u.value);
if (ix < 0x3fff0000)
return h * (2.0Q * t - t * t / (t + one));
diff --git a/libquadmath/math/sinq_kernel.c b/libquadmath/math/sinq_kernel.c
index 86034551d43..873341a7617 100644
--- a/libquadmath/math/sinq_kernel.c
+++ b/libquadmath/math/sinq_kernel.c
@@ -90,7 +90,10 @@ __quadmath_kernel_sinq (__float128 x, __float128 y, int iy)
/* Argument is small enough to approximate it by a Chebyshev
polynomial of degree 17. */
if (tix < 0x3fc60000) /* |x| < 2^-57 */
- if (!((int)x)) return x; /* generate inexact */
+ {
+ math_check_force_underflow (x);
+ if (!((int)x)) return x; /* generate inexact */
+ }
z = x * x;
return x + (x * (z*(SIN1+z*(SIN2+z*(SIN3+z*(SIN4+
z*(SIN5+z*(SIN6+z*(SIN7+z*SIN8)))))))));
diff --git a/libquadmath/math/tanhq.c b/libquadmath/math/tanhq.c
index 4ef4fd02143..6b60dbf1b2f 100644
--- a/libquadmath/math/tanhq.c
+++ b/libquadmath/math/tanhq.c
@@ -72,7 +72,10 @@ tanhq (__float128 x)
if (u.value == 0)
return x; /* x == +- 0 */
if (ix < 0x3fc60000) /* |x| < 2^-57 */
- return x * (one + tiny); /* tanh(small) = small */
+ {
+ math_check_force_underflow (x);
+ return x * (one + tiny); /* tanh(small) = small */
+ }
u.words32.w0 = ix; /* Absolute value of x. */
if (ix >= 0x3fff0000)
{ /* |x| >= 1 */
diff --git a/libquadmath/math/tanq.c b/libquadmath/math/tanq.c
index 690d94b782c..d2864f61c7d 100644
--- a/libquadmath/math/tanq.c
+++ b/libquadmath/math/tanq.c
@@ -12,9 +12,9 @@
/*
Long double expansions are
Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
- and are incorporated herein by permission of the author. The author
+ and are incorporated herein by permission of the author. The author
reserves the right to distribute this material elsewhere under different
- copying permissions. These modifications are distributed here under
+ copying permissions. These modifications are distributed here under
the following terms:
This library is free software; you can redistribute it and/or
@@ -99,8 +99,13 @@ __quadmath_kernel_tanq (__float128 x, __float128 y, int iy)
if ((ix | u.words32.w1 | u.words32.w2 | u.words32.w3
| (iy + 1)) == 0)
return one / fabsq (x);
+ else if (iy == 1)
+ {
+ math_check_force_underflow (x);
+ return x;
+ }
else
- return (iy == 1) ? x : -one / x;
+ return -one / x;
}
}
if (ix >= 0x3ffe5942) /* |x| >= 0.6743316650390625 */
@@ -163,7 +168,7 @@ __quadmath_kernel_tanq (__float128 x, __float128 y, int iy)
/* tanq.c -- __float128 version of s_tan.c.
* Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
*/
-
+
/* @(#)s_tan.c 5.1 93/09/24 */
/*
* ====================================================
diff --git a/libquadmath/math/truncq.c b/libquadmath/math/truncq.c
index 608871785d1..607c24985e3 100644
--- a/libquadmath/math/truncq.c
+++ b/libquadmath/math/truncq.c
@@ -1,8 +1,8 @@
/* Truncate argument to nearest integral value not larger than the argument.
- Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
- Jakub Jelinek <jj@ultra.linux.cz>, 1999.
+ Jakub Jelinek <jj@ultra.linux.cz>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
diff --git a/libquadmath/quadmath-imp.h b/libquadmath/quadmath-imp.h
index 40b346b6ff2..ed186144e75 100644
--- a/libquadmath/quadmath-imp.h
+++ b/libquadmath/quadmath-imp.h
@@ -186,4 +186,45 @@ do { \
__builtin_fpclassify (QUADFP_NAN, QUADFP_INFINITE, QUADFP_NORMAL, \
QUADFP_SUBNORMAL, QUADFP_ZERO, x)
+#ifndef math_opt_barrier
+# define math_opt_barrier(x) \
+({ __typeof (x) __x = (x); __asm ("" : "+m" (__x)); __x; })
+# define math_force_eval(x) \
+({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "m" (__x)); })
+#endif
+
+/* math_narrow_eval reduces its floating-point argument to the range
+ and precision of its semantic type. (The original evaluation may
+ still occur with excess range and precision, so the result may be
+ affected by double rounding.) */
+#define math_narrow_eval(x) (x)
+
+/* If X (which is not a NaN) is subnormal, force an underflow
+ exception. */
+#define math_check_force_underflow(x) \
+ do \
+ { \
+ __float128 force_underflow_tmp = (x); \
+ if (fabsq (force_underflow_tmp) < FLT128_MIN) \
+ { \
+ __float128 force_underflow_tmp2 \
+ = force_underflow_tmp * force_underflow_tmp; \
+ math_force_eval (force_underflow_tmp2); \
+ } \
+ } \
+ while (0)
+/* Likewise, but X is also known to be nonnegative. */
+#define math_check_force_underflow_nonneg(x) \
+ do \
+ { \
+ __float128 force_underflow_tmp = (x); \
+ if (force_underflow_tmp < FLT128_MIN) \
+ { \
+ __float128 force_underflow_tmp2 \
+ = force_underflow_tmp * force_underflow_tmp; \
+ math_force_eval (force_underflow_tmp2); \
+ } \
+ } \
+ while (0)
+
#endif
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 106e168007c..75c9f0cecd0 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,18 @@
+2017-07-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/80998
+ * ubsan/ubsan_handlers.cc: Cherry-pick upstream r304461.
+ * ubsan/ubsan_checks.inc: Likewise.
+ * ubsan/ubsan_handlers.h: Likewise.
+
+2017-07-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/81066
+ * sanitizer_common/sanitizer_linux.h: Cherry-pick upstream r307969.
+ * sanitizer_common/sanitizer_linux.cc: Likewise.
+ * sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc: Likewise.
+ * tsan/tsan_platform_linux.cc: Likewise.
+
2017-04-06 Martin Liska <mliska@suse.cz>
PR sanitizer/80166
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
index 806fcd5e284..5b6f18602e7 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
@@ -605,8 +605,7 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
}
#endif
-uptr internal_sigaltstack(const struct sigaltstack *ss,
- struct sigaltstack *oss) {
+uptr internal_sigaltstack(const void *ss, void *oss) {
return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h b/libsanitizer/sanitizer_common/sanitizer_linux.h
index 895bfc18195..a42df576405 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.h
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.h
@@ -19,7 +19,6 @@
#include "sanitizer_platform_limits_posix.h"
struct link_map; // Opaque type returned by dlopen().
-struct sigaltstack;
namespace __sanitizer {
// Dirent structure for getdents(). Note that this structure is different from
@@ -28,8 +27,7 @@ struct linux_dirent;
// Syscall wrappers.
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
-uptr internal_sigaltstack(const struct sigaltstack* ss,
- struct sigaltstack* oss);
+uptr internal_sigaltstack(const void* ss, void* oss);
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset);
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index 891386dc0ba..234e8c652c6 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -273,7 +273,7 @@ static int TracerThread(void* argument) {
// Alternate stack for signal handling.
InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize);
- struct sigaltstack handler_stack;
+ stack_t handler_stack;
internal_memset(&handler_stack, 0, sizeof(handler_stack));
handler_stack.ss_sp = handler_stack_memory.data();
handler_stack.ss_size = kHandlerStackSize;
diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc
index 2ed5718a12e..6f972ab0dd6 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cc
+++ b/libsanitizer/tsan/tsan_platform_linux.cc
@@ -287,7 +287,7 @@ void InitializePlatform() {
int ExtractResolvFDs(void *state, int *fds, int nfd) {
#if SANITIZER_LINUX && !SANITIZER_ANDROID
int cnt = 0;
- __res_state *statp = (__res_state*)state;
+ struct __res_state *statp = (struct __res_state*)state;
for (int i = 0; i < MAXNS && cnt < nfd; i++) {
if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1)
fds[cnt++] = statp->_u._ext.nssocks[i];
diff --git a/libsanitizer/ubsan/ubsan_checks.inc b/libsanitizer/ubsan/ubsan_checks.inc
index ea85877198a..31e9495e301 100644
--- a/libsanitizer/ubsan/ubsan_checks.inc
+++ b/libsanitizer/ubsan/ubsan_checks.inc
@@ -17,6 +17,7 @@
UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
+UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow")
UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment")
UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size")
UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow",
diff --git a/libsanitizer/ubsan/ubsan_handlers.cc b/libsanitizer/ubsan/ubsan_handlers.cc
index 5631e457a1c..761ccef63f3 100644
--- a/libsanitizer/ubsan/ubsan_handlers.cc
+++ b/libsanitizer/ubsan/ubsan_handlers.cc
@@ -521,6 +521,37 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
Die();
}
+static void handlePointerOverflowImpl(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::PointerOverflow;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, "pointer index expression with base %0 overflowed to %1")
+ << (void *)Base << (void*)Result;
+}
+
+void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result) {
+ GET_REPORT_OPTIONS(false);
+ handlePointerOverflowImpl(Data, Base, Result, Opts);
+}
+
+void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result) {
+ GET_REPORT_OPTIONS(true);
+ handlePointerOverflowImpl(Data, Base, Result, Opts);
+ Die();
+}
+
static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
ReportOptions Opts) {
if (Data->CheckKind != CFITCK_ICall)
diff --git a/libsanitizer/ubsan/ubsan_handlers.h b/libsanitizer/ubsan/ubsan_handlers.h
index 394c9eac298..d04554acee3 100644
--- a/libsanitizer/ubsan/ubsan_handlers.h
+++ b/libsanitizer/ubsan/ubsan_handlers.h
@@ -146,6 +146,13 @@ struct NonNullArgData {
/// \brief Handle passing null pointer to function with nonnull attribute.
RECOVERABLE(nonnull_arg, NonNullArgData *Data)
+struct PointerOverflowData {
+ SourceLocation Loc;
+};
+
+RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base,
+ ValueHandle Result)
+
/// \brief Known CFI check kinds.
/// Keep in sync with the enum of the same name in CodeGenFunction.h
enum CFITypeCheckKind : unsigned char {
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6be91fedcc5..c723b94875b 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,359 @@
+2017-07-26 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/27_io/basic_fstream/53984.cc: Fix test.
+
+2017-07-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/27_io/basic_fstream/53984.cc: Fix typo in dg-require
+ directive.
+
+2017-07-25 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/53984
+ * include/bits/basic_ios.h (basic_ios::_M_setstate): Adjust comment.
+ * include/bits/istream.tcc (basic_istream::sentry): Handle exceptions
+ during construction.
+ * include/std/istream: Adjust comments for formatted input functions
+ and unformatted input functions.
+ * testsuite/27_io/basic_fstream/53984.cc: New.
+ * testsuite/27_io/basic_istream/sentry/char/53984.cc: New.
+
+ * include/bits/ios_base.h (ios_base::io_state, ios_base::open_mode)
+ (ios_base::seek_dir): Remove for C++17.
+ * include/std/streambuf (basic_streambuf::stossc): Remove for C++17.
+ Add deprecated attribute for C++11 and C++14.
+ * testsuite/27_io/types/1.cc: Don't run for C++17 and later.
+ * testsuite/27_io/types/4.cc: New.
+
+2017-07-23 Michael Collison <michael.collison@arm.com>
+
+ Add optimized implementation of mersenne twister for aarch64
+ * config/cpu/aarch64/opt/ext/opt_random.h: New file.
+ (__arch64_recursion): New function.
+ (__aarch64_lsr_128): New function.
+ (__aarch64_lsl_128): New function.
+ (operator==): New function.
+ (simd_fast_mersenne_twister_engine): Implement
+ method _M_gen_rand.
+ * config/cpu/aarch64/opt/bits/opt_random.h: New file.
+ * include/ext/random: (simd_fast_mersenne_twister_engine):
+ add _M_state private array.
+
+2017-07-23 François Dumont <fdumont@gcc.gnu.org>
+
+ PR libstdc++/81064
+ * include/bits/algorithmfwd.h: Reorganize versioned namespace.
+ * include/bits/basic_string.h: Likewise.
+ * include/bits/c++config: Likewise.
+ * include/bits/deque.tcc: Likewise.
+ * include/bits/forward_list.h: Likewise.
+ * include/bits/forward_list.tcc: Likewise.
+ * include/bits/hashtable_policy.h: Likewise.
+ * include/bits/list.tcc: Likewise.
+ * include/bits/move.h: Likewise.
+ * include/bits/quoted_string.h: Likewise.
+ * include/bits/random.h: Likewise.
+ * include/bits/random.tcc: Likewise.
+ * include/bits/regex.h: Likewise.
+ * include/bits/regex.tcc: Likewise.
+ * include/bits/regex_automaton.h: Likewise.
+ * include/bits/regex_automaton.tcc: Likewise.
+ * include/bits/regex_compiler.h: Likewise.
+ * include/bits/regex_compiler.tcc: Likewise.
+ * include/bits/regex_constants.h: Likewise.
+ * include/bits/regex_error.h: Likewise.
+ * include/bits/regex_executor.h: Likewise.
+ * include/bits/regex_executor.tcc: Likewise.
+ * include/bits/regex_scanner.h: Likewise.
+ * include/bits/regex_scanner.tcc: Likewise.
+ * include/bits/specfun.h: Likewise.
+ * include/bits/stl_algo.h: Likewise.
+ * include/bits/stl_algobase.h: Likewise.
+ * include/bits/stl_bvector.h: Likewise.
+ * include/bits/stl_deque.h: Likewise.
+ * include/bits/stl_iterator.h: Likewise.
+ * include/bits/stl_iterator_base_funcs.h: Likewise.
+ * include/bits/stl_list.h: Likewise.
+ * include/bits/stl_map.h: Likewise.
+ * include/bits/stl_multimap.h: Likewise.
+ * include/bits/stl_multiset.h: Likewise.
+ * include/bits/stl_relops.h: Likewise.
+ * include/bits/stl_set.h: Likewise.
+ * include/bits/stl_vector.h: Likewise.
+ * include/bits/uniform_int_dist.h: Likewise.
+ * include/bits/unordered_map.h: Likewise.
+ * include/bits/unordered_set.h: Likewise.
+ * include/bits/vector.tcc: Likewise.
+ * include/c_global/cmath: Likewise.
+ * include/c_std/cmath: Likewise.
+ * include/decimal/decimal: Likewise.
+ * include/decimal/decimal.h: Likewise.
+ * include/experimental/algorithm: Likewise.
+ * include/experimental/any: Likewise.
+ * include/experimental/array: Likewise.
+ * include/experimental/bits/erase_if.h: Likewise.
+ * include/experimental/bits/fs_dir.h: Likewise.
+ * include/experimental/bits/fs_fwd.h: Likewise.
+ * include/experimental/bits/fs_ops.h: Likewise.
+ * include/experimental/bits/fs_path.h: Likewise.
+ * include/experimental/bits/lfts_config.h: Likewise.
+ * include/experimental/bits/shared_ptr.h: Likewise.
+ * include/experimental/bits/string_view.tcc: Likewise.
+ * include/experimental/chrono: Likewise.
+ * include/experimental/deque: Likewise.
+ * include/experimental/filesystem: Likewise.
+ * include/experimental/forward_list: Likewise.
+ * include/experimental/functional: Likewise.
+ * include/experimental/iterator: Likewise.
+ * include/experimental/list: Likewise.
+ * include/experimental/map: Likewise.
+ * include/experimental/memory: Likewise.
+ * include/experimental/memory_resource: Likewise.
+ * include/experimental/numeric: Likewise.
+ * include/experimental/optional: Likewise.
+ * include/experimental/propagate_const: Likewise.
+ * include/experimental/random: Likewise.
+ * include/experimental/ratio: Likewise.
+ * include/experimental/regex: Likewise.
+ * include/experimental/set: Likewise.
+ * include/experimental/source_location: Likewise.
+ * include/experimental/string: Likewise.
+ * include/experimental/string_view: Likewise.
+ * include/experimental/system_error: Likewise.
+ * include/experimental/tuple: Likewise.
+ * include/experimental/type_traits: Likewise.
+ * include/experimental/unordered_map: Likewise.
+ * include/experimental/unordered_set: Likewise.
+ * include/experimental/utility: Likewise.
+ * include/experimental/vector: Likewise.
+ * include/ext/bitmap_allocator.h: Likewise.
+ * include/ext/codecvt_specializations.h: Likewise.
+ * include/ext/rope: Likewise.
+ * include/ext/typelist.h: Likewise.
+ * include/std/chrono: Likewise.
+ * include/std/complex: Likewise.
+ * include/std/functional: Likewise.
+ * include/std/numeric: Likewise.
+ * include/std/string_view: Likewise.
+ * include/std/thread: Likewise.
+ * include/std/variant: Likewise.
+ * include/tr1/array: Likewise.
+ * include/tr1/bessel_function.tcc: Likewise.
+ * include/tr1/beta_function.tcc: Likewise.
+ * include/tr1/cmath: Likewise.
+ * include/tr1/complex: Likewise.
+ * include/tr1/ell_integral.tcc: Likewise.
+ * include/tr1/exp_integral.tcc: Likewise.
+ * include/tr1/functional: Likewise.
+ * include/tr1/functional_hash.h: Likewise.
+ * include/tr1/gamma.tcc: Likewise.
+ * include/tr1/hashtable.h: Likewise.
+ * include/tr1/hashtable_policy.h: Likewise.
+ * include/tr1/hypergeometric.tcc: Likewise.
+ * include/tr1/legendre_function.tcc: Likewise.
+ * include/tr1/modified_bessel_func.tcc: Likewise.
+ * include/tr1/poly_hermite.tcc: Likewise.
+ * include/tr1/poly_laguerre.tcc: Likewise.
+ * include/tr1/random.h: Likewise.
+ * include/tr1/random.tcc: Likewise.
+ * include/tr1/regex: Likewise.
+ * include/tr1/riemann_zeta.tcc: Likewise.
+ * include/tr1/shared_ptr.h: Likewise.
+ * include/tr1/special_function_util.h: Likewise.
+ * include/tr1/tuple: Likewise.
+ * include/tr1/type_traits: Likewise.
+ * include/tr1/unordered_map.h: Likewise.
+ * include/tr1/unordered_set.h: Likewise.
+ * include/tr1/utility: Likewise.
+ * include/tr2/bool_set: Likewise.
+ * include/tr2/bool_set.tcc: Likewise.
+ * include/tr2/dynamic_bitset: Likewise.
+ * include/tr2/dynamic_bitset.tcc: Likewise.
+ * include/tr2/ratio: Likewise.
+ * include/tr2/type_traits: Likewise.
+ * src/c++11/chrono.cc: Likewise.
+ * src/c++11/compatibility-c++0x.cc: Likewise.
+ * src/c++11/compatibility-chrono.cc: Likewise.
+ * src/c++11/cxx11-shim_facets.cc: Likewise.
+ * src/c++11/hashtable_c++0x.cc: Likewise.
+ * src/c++11/placeholders.cc: Likewise.
+ * src/c++11/thread.cc: Likewise.
+ * src/c++98/bitmap_allocator.cc: Likewise.
+ * src/c++98/hashtable_tr1.cc: Likewise.
+ * src/c++98/list.cc: Likewise.
+ * src/shared/hashtable-aux.cc: Likewise.
+ * testsuite/20_util/duration/literals/range.cc: Adapt line number.
+ * testsuite/20_util/duration/requirements/typedefs_neg1.cc: Likewise.
+ * testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
+ * testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.
+ * testsuite/20_util/forward/c_neg.cc: Likewise.
+ * testsuite/20_util/forward/f_neg.cc: Likewise.
+ * testsuite/26_numerics/gcd/gcd_neg.cc: Likewise.
+ * testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
+ * testsuite/26_numerics/random/pr60037-neg.cc: Likewise.
+ * python/libstdcxx/v6/printers.py: Adapt.
+
+2017-07-20 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/allocator/malloc_allocator_base.h [__SANITIZE_ADDRESS__]
+ (_GLIBCXX_SANITIZE_STD_ALLOCATOR): Define.
+ * config/allocator/new_allocator_base.h [__SANITIZE_ADDRESS__]
+ (_GLIBCXX_SANITIZE_STD_ALLOCATOR): Define.
+ * doc/xml/manual/using.xml (_GLIBCXX_SANITIZE_VECTOR): Document macro.
+ * include/bits/stl_vector.h [_GLIBCXX_SANITIZE_VECTOR]
+ (_Vector_impl::_Asan, _Vector_impl::_Asan::_Reinit)
+ (_Vector_impl::_Asan::_Grow, _GLIBCXX_ASAN_ANNOTATE_REINIT)
+ (_GLIBCXX_ASAN_ANNOTATE_GROW, _GLIBCXX_ASAN_ANNOTATE_GREW)
+ (_GLIBCXX_ASAN_ANNOTATE_SHRINK, _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC):
+ Define annotation helper types and macros.
+ (vector::~vector, vector::push_back, vector::pop_back)
+ (vector::_M_erase_at_end): Add annotations.
+ * include/bits/vector.tcc (vector::reserve, vector::emplace_back)
+ (vector::insert, vector::_M_erase, vector::operator=)
+ (vector::_M_fill_assign, vector::_M_assign_aux)
+ (vector::_M_insert_rval, vector::_M_emplace_aux)
+ (vector::_M_insert_aux, vector::_M_realloc_insert)
+ (vector::_M_fill_insert, vector::_M_default_append)
+ (vector::_M_shrink_to_fit, vector::_M_range_insert): Annotate.
+
+2017-07-19 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81476
+ * include/bits/vector.tcc (vector::_M_range_insert<_InputIterator>):
+ Only insert elements one-by-one when inserting at the end.
+ * testsuite/performance/23_containers/insert/81476.cc: New.
+
+2017-07-19 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * libsupc++/new (bad_array_new_length): Remove redundant
+ semicolon after in-class member function definition.
+ * include/bits/locale_facets.h (ctype_byname, num_put): Likewise.
+ * include/bits/locale_facets_nonio.h (time_put_byname): Likewise.
+ * include/bits/random.h (mersenne_twister_engine): Likewise.
+ * include/tr1/random.h (mersenne_twister): Likewise
+ * include/ext/random (simd_fast_mersenne_twister_engine): Likewise.
+ * include/ext/rope (char_producer, _Rope_char_consumer,
+ _Rope_self_destruct_ptr, _Rope_const_iterator, _Rope_iterator):
+ Likewise.
+ * include/ext/ropeimpl.h (_Rope_flatten_char_consumer,
+ _Rope_insert_char_consumer): Likewise.
+
+2017-07-19 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/fstream.tcc (basic_filebuf::xsgetn)
+ (basic_filebuf::xsputn, basic_filebuf::seekoff): Fix indentation.
+
+ * testsuite/util/testsuite_iterators.h: Fix indentation.
+
+ * testsuite/27_io/basic_filebuf/sgetn/char/81395.cc: Add dg-require.
+
+2017-07-18 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81395
+ * include/bits/fstream.tcc (basic_filebuf::xsgetn): Don't set buffer
+ pointers for write mode after reading.
+ * testsuite/27_io/basic_filebuf/sgetn/char/81395.cc: New.
+
+2017-07-18 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_list.h
+ (struct _List_node_header): New.
+ (_List_impl()): Fix noexcept qualification.
+ (_List_impl(_List_impl&&)): New, default.
+ (_List_base()): Default.
+ (_List_base(_List_base&&)): Default.
+ (_List_base::_M_move_nodes): Adapt to use
+ _List_node_header._M_move_nodes.
+ (_List_base::_M_init): Likewise.
+ (list<>()): Default.
+ (list<>(list&&)): Default.
+ (list<>::_M_move_assign(list&&, true_type)): Use _M_move_nodes.
+ (__distance(_List_const_iterator<>, _List_const_iterator<>,
+ input_iterator_tag)): Adapt.
+ * testsuite/23_containers/list/allocator/default_init.cc: New.
+
+2017-07-15 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/mutex (scoped_lock): Reorder std::adopt_lock_t parameter
+ as per P0739R0.
+ * testsuite/30_threads/scoped_lock/cons/1.cc: Reorder arguments.
+ * testsuite/30_threads/scoped_lock/cons/deduction.cc: Test deduction
+ with std::adopt_lock_t.
+ * testsuite/30_threads/scoped_lock/requirements/typedefs.cc: Check
+ feature-test macro.
+
+2017-07-14 Jason Merrill <jason@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/variant (variant::variant(_Tp&&)): Constrain to remove
+ the constructor for empty variants from the candidate functions
+ during class template argument deduction.
+ * testsuite/20_util/variant/deduction.cc: New.
+
+2017-07-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/xml/faq.xml: Update several old entries. Improve
+ cross-references.
+ * doc/xml/manual/intro.xml: Add anchors to each DR.
+ * doc/html/*: Regenerate.
+
+2017-07-10 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/abi/pr42230.cc: Add header for std::free.
+
+ PR libstdc++/81381
+ * include/bits/sstream.tcc (basic_stringbuf::overflow)
+ (basic_stringbuf::basic_stringbuf(const __string_type&, ios::mode))
+ (basic_stringbuf::str()): Construct new strings with an allocator.
+ * testsuite/27_io/basic_stringbuf/cons/81381.cc: New.
+
+ PR libstdc++/81338
+ * include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI] (basic_string):
+ Declare basic_stringbuf to be a friend.
+ * include/bits/sstream.tcc (basic_stringbuf::overflow)
+ [_GLIBCXX_USE_CXX11_ABI]: Use unused capacity before reallocating.
+ * include/std/sstream (basic_stringbuf::__xfer_bufptrs): Update string
+ length to buffer length.
+ * testsuite/27_io/basic_stringstream/assign/81338.cc: New.
+
+2017-07-06 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/20_util/specialized_algorithms/memory_management_tools/
+ 1.cc: Free memory.
+ * testsuite/22_locale/locale/cons/5.cc: Remove redundant restoration
+ of original environment and free memory.
+
+ * testsuite/abi/pr42230.cc: Free memory.
+ * testsuite/util/testsuite_abi.cc (demangle): Return std::string
+ instead of pointer that might need freeing.
+ * testsuite/util/testsuite_abi.h (demangle): Likewise.
+ * testsuite/util/testsuite_hooks.cc (verify_demangle): Free memory.
+
+ * include/bits/uses_allocator.h (__use_alloc(const _Alloc&&)): Add
+ deleted overload to prevent dangling references to rvalues.
+ * include/experimental/memory_resource
+ (polymorphic_allocator::construct): Do not call __use_alloc with
+ rvalue arguments.
+
+2017-06-27 Tim Shen <timshen@google.com>
+
+ PR libstdc++/80187
+ * include/std/variant (variant::variant, variant::~variant,
+ variant::operator=): Implement triviality forwarding for four
+ special member functions.
+ * testsuite/20_util/variant/compile.cc: Tests.
+
+2017-06-27 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81221
+ * testsuite/25_algorithms/sample/81221.cc: Disable except for
+ check-parallel.
+
+ PR libstdc++/81221
+ * include/bits/stl_algo.h (sample): Qualify with _GLIBCXX_STD_A not
+ std.
+ * testsuite/25_algorithms/sample/81221.cc: New.
+
2017-06-22 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/81173
diff --git a/libstdc++-v3/config/allocator/malloc_allocator_base.h b/libstdc++-v3/config/allocator/malloc_allocator_base.h
index b091bbca863..54e0837f01f 100644
--- a/libstdc++-v3/config/allocator/malloc_allocator_base.h
+++ b/libstdc++-v3/config/allocator/malloc_allocator_base.h
@@ -52,4 +52,8 @@ namespace std
# define __allocator_base __gnu_cxx::malloc_allocator
#endif
+#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR)
+# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
+#endif
+
#endif
diff --git a/libstdc++-v3/config/allocator/new_allocator_base.h b/libstdc++-v3/config/allocator/new_allocator_base.h
index 3d2bb67887f..e776ed31864 100644
--- a/libstdc++-v3/config/allocator/new_allocator_base.h
+++ b/libstdc++-v3/config/allocator/new_allocator_base.h
@@ -52,4 +52,8 @@ namespace std
# define __allocator_base __gnu_cxx::new_allocator
#endif
+#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR)
+# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1
+#endif
+
#endif
diff --git a/libstdc++-v3/config/cpu/aarch64/opt/bits/opt_random.h b/libstdc++-v3/config/cpu/aarch64/opt/bits/opt_random.h
new file mode 100644
index 00000000000..fba7ea812ad
--- /dev/null
+++ b/libstdc++-v3/config/cpu/aarch64/opt/bits/opt_random.h
@@ -0,0 +1,47 @@
+// Optimizations for random number functions, aarch64 version -*- C++ -*-
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/opt_random.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{random}
+ */
+
+#ifndef _BITS_OPT_RANDOM_H
+#define _BITS_OPT_RANDOM_H 1
+
+#pragma GCC system_header
+
+
+namespace std _GLIBCXX_VISIBILITY (default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+
+
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+
+#endif // _BITS_OPT_RANDOM_H
diff --git a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
new file mode 100644
index 00000000000..330050fc7f7
--- /dev/null
+++ b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
@@ -0,0 +1,180 @@
+// Optimizations for random number extensions, aarch64 version -*- C++ -*-
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ext/random.tcc
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{ext/random}
+ */
+
+#ifndef _EXT_OPT_RANDOM_H
+#define _EXT_OPT_RANDOM_H 1
+
+#pragma GCC system_header
+
+#ifdef __ARM_NEON
+
+#ifdef __AARCH64EB__
+# define __VEXT(_A,_B,_C) __builtin_shuffle (_A, _B, (__Uint8x16_t) \
+ {16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \
+ 24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C})
+#else
+# define __VEXT(_A,_B,_C) __builtin_shuffle (_B, _A, (__Uint8x16_t) \
+ {_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \
+ _C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15})
+#endif
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY (default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ namespace {
+ // Logical Shift right 128-bits by c * 8 bits
+
+ __extension__ extern __inline __Uint32x4_t
+ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+ __aarch64_lsr_128 (__Uint8x16_t __a, __const int __c)
+ {
+ const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+ return (__Uint32x4_t) __VEXT (__zero, __a, __c);
+ }
+
+ // Logical Shift left 128-bits by c * 8 bits
+
+ __extension__ extern __inline __Uint32x4_t
+ __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+ __aarch64_lsl_128 (__Uint8x16_t __a, __const int __c)
+ {
+ const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+ return (__Uint32x4_t) __VEXT (__a, __zero, 16 - __c);
+ }
+
+ template<size_t __sl1, size_t __sl2, size_t __sr1, size_t __sr2>
+ inline __Uint32x4_t __aarch64_recursion (__Uint32x4_t __a,
+ __Uint32x4_t __b,
+ __Uint32x4_t __c,
+ __Uint32x4_t __d,
+ __Uint32x4_t __e)
+ {
+ __Uint32x4_t __y = (__b >> __sr1);
+ __Uint32x4_t __z = __aarch64_lsr_128 ((__Uint8x16_t) __c, __sr2);
+
+ __Uint32x4_t __v = __d << __sl1;
+
+ __z = __z ^ __a;
+ __z = __z ^ __v;
+
+ __Uint32x4_t __x = __aarch64_lsl_128 ((__Uint8x16_t) __a, __sl2);
+
+ __y = __y & __e;
+ __z = __z ^ __x;
+ return __z ^ __y;
+ }
+}
+
+#define _GLIBCXX_OPT_HAVE_RANDOM_SFMT_GEN_READ 1
+ template<typename _UIntType, size_t __m,
+ size_t __pos1, size_t __sl1, size_t __sl2,
+ size_t __sr1, size_t __sr2,
+ uint32_t __msk1, uint32_t __msk2,
+ uint32_t __msk3, uint32_t __msk4,
+ uint32_t __parity1, uint32_t __parity2,
+ uint32_t __parity3, uint32_t __parity4>
+ void simd_fast_mersenne_twister_engine<_UIntType, __m,
+ __pos1, __sl1, __sl2, __sr1, __sr2,
+ __msk1, __msk2, __msk3, __msk4,
+ __parity1, __parity2, __parity3,
+ __parity4>::
+ _M_gen_rand (void)
+ {
+ __Uint32x4_t __r1 = _M_state[_M_nstate - 2];
+ __Uint32x4_t __r2 = _M_state[_M_nstate - 1];
+
+ __Uint32x4_t __aData = {__msk1, __msk2, __msk3, __msk4};
+
+ size_t __i;
+ for (__i = 0; __i < _M_nstate - __pos1; ++__i)
+ {
+ __Uint32x4_t __r = __aarch64_recursion<__sl1, __sl2, __sr1, __sr2>
+ (_M_state[__i], _M_state[__i + __pos1], __r1, __r2, __aData);
+
+ _M_state[__i] = __r;
+
+ __r1 = __r2;
+ __r2 = __r;
+ }
+ for (; __i < _M_nstate; ++__i)
+ {
+ __Uint32x4_t __r = __aarch64_recursion<__sl1, __sl2, __sr1, __sr2>
+ (_M_state[__i], _M_state[__i + __pos1 - _M_nstate], __r1, __r2,
+ __aData);
+
+ _M_state[__i] = __r;
+
+ __r1 = __r2;
+ __r2 = __r;
+ }
+
+ _M_pos = 0;
+ }
+
+
+#define _GLIBCXX_OPT_HAVE_RANDOM_SFMT_OPERATOREQUAL 1
+ template<typename _UIntType, size_t __m,
+ size_t __pos1, size_t __sl1, size_t __sl2,
+ size_t __sr1, size_t __sr2,
+ uint32_t __msk1, uint32_t __msk2,
+ uint32_t __msk3, uint32_t __msk4,
+ uint32_t __parity1, uint32_t __parity2,
+ uint32_t __parity3, uint32_t __parity4>
+ bool
+ operator==(const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType,
+ __m, __pos1, __sl1, __sl2, __sr1, __sr2,
+ __msk1, __msk2, __msk3, __msk4,
+ __parity1, __parity2, __parity3, __parity4>& __lhs,
+ const __gnu_cxx::simd_fast_mersenne_twister_engine<_UIntType,
+ __m, __pos1, __sl1, __sl2, __sr1, __sr2,
+ __msk1, __msk2, __msk3, __msk4,
+ __parity1, __parity2, __parity3, __parity4>& __rhs)
+ {
+ if (__lhs._M_pos != __rhs._M_pos)
+ return false;
+
+ __Uint32x4_t __res = __lhs._M_state[0] ^ __rhs._M_state[0];
+
+ for (size_t __i = 1; __i < __lhs._M_nstate; ++__i)
+ __res |= __lhs._M_state[__i] ^ __rhs._M_state[__i];
+
+ return (__int128) __res == 0;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+ } // namespace
+
+#endif // __ARM_NEON
+
+#endif // _EXT_OPT_RANDOM_H
diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html
index 95386554471..34a9b2bce60 100644
--- a/libstdc++-v3/doc/html/faq.html
+++ b/libstdc++-v3/doc/html/faq.html
@@ -76,7 +76,8 @@
</a></dt><dt>6.9. <a href="faq.html#faq.easy_to_fix">
Aw, that's easy to fix!
</a></dt></dl></dd><dt></dt><dd><dl><dt>7.1. <a href="faq.html#faq.iterator_as_pod">
- string::iterator is not char*; vector&lt;T&gt;::iterator is not T*
+ string::iterator is not char*;
+ vector&lt;T&gt;::iterator is not T*
</a></dt><dt>7.2. <a href="faq.html#faq.what_is_next">
What's next after libstdc++?
</a></dt><dt>7.3. <a href="faq.html#faq.sgi_stl">
@@ -133,10 +134,10 @@
<a class="link" href="https://gcc.gnu.org/buildstat.html" target="_top">portability</a>
that are the hallmarks of an open-source project are applied to libstdc++.
</p><p>
- All of the standard classes and functions from C++98/C++03
+ All of the standard classes and functions from C++98/C++03, C++11 and C++14
(such as <code class="classname">string</code>,
<code class="classname">vector&lt;&gt;</code>, iostreams, algorithms etc.)
- are freely available and atempt to be fully compliant.
+ are freely available and attempt to be fully compliant.
Work is ongoing to complete support for the current revision of the
ISO C++ Standard.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.who"></a><a id="q-who"></a><p><strong>1.3.</strong></p></td><td align="left" valign="top"><p>
@@ -431,7 +432,7 @@
C++ compiler.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.solaris_long_long"></a><a id="q-solaris_long_long"></a><p><strong>4.2.</strong></p></td><td align="left" valign="top"><p>
No '<span class="type">long long</span>' type on Solaris?
- </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-solaris_long_long"></a></td><td align="left" valign="top"><p>
+ </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-solaris_long_long"></a></td><td align="left" valign="top"><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This answer is old and probably no longer be relevant.</p></div><p>
By default we try to support the C99 <span class="type">long long</span> type.
This requires that certain functions from your C library be present.
</p><p>
@@ -509,7 +510,7 @@
more recent the C library. (This is also documented in the main
GCC installation instructions.)
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.freebsd_wchar"></a><a id="q-freebsd_wchar"></a><p><strong>4.8.</strong></p></td><td align="left" valign="top"><p>
- Can't use wchar_t/wstring on FreeBSD
+ Can't use <span class="type">wchar_t</span>/<code class="classname">wstring</code> on FreeBSD
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-freebsd_wchar"></a></td><td align="left" valign="top"><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This answer is old and probably no longer be relevant.</p></div><p>
Older versions of FreeBSD's C library do not have sufficient
support for wide character functions, and as a result the
@@ -552,7 +553,8 @@
place), a public list of the library defects is occasionally
published on <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/" target="_top">the WG21
website</a>.
- Many of these issues have resulted in code changes in libstdc++.
+ Many of these issues have resulted in
+ <a class="link" href="manual/bugs.html#manual.intro.status.bugs.iso" title="Standard Bugs">code changes in libstdc++</a>.
</p><p>
If you think you've discovered a new bug that is not listed,
please post a message describing your problem to the author of
@@ -570,8 +572,8 @@
these lists with terms describing your issue.
</p><p>
Before reporting a bug, please examine the
- <a class="link" href="http://gcc.gnu.org/bugs/" target="_top">bugs database</a> with the
- category set to <span class="quote">“<span class="quote">g++</span>”</span>.
+ <a class="link" href="https://gcc.gnu.org/bugs/" target="_top">bugs database</a>, with the
+ component set to <span class="quote">“<span class="quote">c++</span>”</span>.
</p></td></tr><tr class="toc"><td align="left" valign="top" colspan="2"><dl><dt>6.1. <a href="faq.html#faq.stream_reopening_fails">
Reopening a stream fails
</a></dt><dt>6.2. <a href="faq.html#faq.wefcxx_verbose">
@@ -594,8 +596,9 @@
Aw, that's easy to fix!
</a></dt></dl></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.stream_reopening_fails"></a><a id="q-stream_reopening_fails"></a><p><strong>6.1.</strong></p></td><td align="left" valign="top"><p>
Reopening a stream fails
- </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-stream_reopening_fails"></a></td><td align="left" valign="top"><p>
- One of the most-reported non-bug reports. Executing a sequence like:
+ </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-stream_reopening_fails"></a></td><td align="left" valign="top"><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This answer is old and probably no longer be relevant.</p></div><p>
+ Prior to GCC 4.0 this was one of the most-reported non-bug reports.
+ Executing a sequence like this would fail:
</p><pre class="programlisting">
#include &lt;fstream&gt;
...
@@ -606,19 +609,20 @@
fs.close();
fs.open("a_new_file");
</pre><p>
- All operations on the re-opened <code class="varname">fs</code> will fail, or at
- least act very strangely. Yes, they often will, especially if
- <code class="varname">fs</code> reached the EOF state on the previous file. The
- reason is that the state flags are <span class="emphasis"><em>not</em></span> cleared
- on a successful call to open(). The standard unfortunately did
- not specify behavior in this case, and to everybody's great sorrow,
- the <a class="link" href="manual/bugs.html" title="Bugs">proposed LWG resolution in
- DR #22</a> is to leave the flags unchanged. You must insert a call
- to <code class="function">fs.clear()</code> between the calls to close() and open(),
- and then everything will work like we all expect it to work.
- <span class="emphasis"><em>Update:</em></span> for GCC 4.0 we implemented the resolution
- of <a class="link" href="manual/bugs.html" title="Bugs">DR #409</a> and open()
- now calls <code class="function">clear()</code> on success!
+ All operations on the re-opened <code class="varname">fs</code> would fail, or at
+ least act very strangely, especially if <code class="varname">fs</code> reached the
+ EOF state on the previous file.
+ The original C++98 standard did not specify behavior in this case, and
+ the <a class="link" href="manual/bugs.html#manual.bugs.dr22">resolution of DR #22</a> was to
+ leave the state flags unchanged on a successful call to
+ <code class="function">open()</code>.
+ You had to insert a call to <code class="function">fs.clear()</code> between the
+ calls to <code class="function">close()</code> and <code class="function">open()</code>,
+ and then everything will work as expected.
+ <span class="emphasis"><em>Update:</em></span> For GCC 4.0 we implemented the resolution
+ of <a class="link" href="manual/bugs.html#manual.bugs.dr409">DR #409</a> and
+ <code class="function">open()</code>
+ now calls <code class="function">clear()</code> on success.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.wefcxx_verbose"></a><a id="q-wefcxx_verbose"></a><p><strong>6.2.</strong></p></td><td align="left" valign="top"><p>
-Weffc++ complains too much
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-wefcxx_verbose"></a></td><td align="left" valign="top"><p>
@@ -626,7 +630,9 @@
libstdc++ <code class="option">-Weffc++</code>-clean is not a goal of the project,
for a few reasons. Mainly, that option tries to enforce
object-oriented programming, while the Standard Library isn't
- necessarily trying to be OO.
+ necessarily trying to be OO. The option also enforces outdated guidelines
+ from old editions of the books, and the advice isn't all relevant to
+ modern C++ (especially C++11 and later).
</p><p>
We do, however, try to have libstdc++ sources as clean as possible. If
you see some simple changes that pacify <code class="option">-Weffc++</code>
@@ -637,15 +643,16 @@
Another problem is the <code class="literal">rel_ops</code> namespace and the template
comparison operator functions contained therein. If they become
visible in the same namespace as other comparison functions
- (e.g., <span class="quote">“<span class="quote">using</span>”</span> them and the &lt;iterator&gt; header),
+ (e.g., <span class="quote">“<span class="quote">using</span>”</span> them and the
+ <code class="filename">&lt;iterator&gt;</code> header),
then you will suddenly be faced with huge numbers of ambiguity
- errors. This was discussed on the -v3 list; Nathan Myers
+ errors. This was discussed on the mailing list; Nathan Myers
<a class="link" href="http://gcc.gnu.org/ml/libstdc++/2001-01/msg00247.html" target="_top">sums
things up here</a>. The collisions with vector/string iterator
types have been fixed for 3.1.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.v2_headers"></a><a id="q-v2_headers"></a><p><strong>6.4.</strong></p></td><td align="left" valign="top"><p>
The g++-3 headers are <span class="emphasis"><em>not ours</em></span>
- </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-v2_headers"></a></td><td align="left" valign="top"><p>
+ </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-v2_headers"></a></td><td align="left" valign="top"><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This answer is old and probably no longer be relevant.</p></div><p>
If you are using headers in
<code class="filename">${prefix}/include/g++-3</code>, or if
the installed library's name looks like
@@ -698,11 +705,12 @@
    <span class="command"><strong>g++ -fPIC -rdynamic -o foo ... -L. -lfoo -ldl</strong></span><br />
    </p></div></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.memory_leaks"></a><a id="q-memory_leaks"></a><p><strong>6.7.</strong></p></td><td align="left" valign="top"><p>
<span class="quote">“<span class="quote">Memory leaks</span>”</span> in containers
- </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-memory_leaks"></a></td><td align="left" valign="top"><p>
+ </p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-memory_leaks"></a></td><td align="left" valign="top"><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>This answer is old and probably no longer be relevant.</p></div><p>
A few people have reported that the standard containers appear
to leak memory when tested with memory checkers such as
<a class="link" href="http://valgrind.org/" target="_top"><span class="command"><strong>valgrind</strong></span></a>.
- Under some configurations the library's allocators keep free memory in a
+ Under some (non-default) configurations the library's allocators keep
+ free memory in a
pool for later reuse, rather than returning it to the OS. Although
this memory is always reachable by the library and is never
lost, memory debugging tools can report it as a leak. If you
@@ -710,7 +718,7 @@
<a class="link" href="manual/debug.html#debug.memory" title="Memory Leak Hunting">Tips for memory leak hunting</a>
first.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.list_size_on"></a><a id="q-list_size_on"></a><p><strong>6.8.</strong></p></td><td align="left" valign="top"><p>
- list::size() is O(n)!
+ <code class="code">list::size()</code> is O(n)!
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-list_size_on"></a></td><td align="left" valign="top"><p>
See
the <a class="link" href="manual/containers.html" title="Chapter 9.  Containers">Containers</a>
@@ -734,7 +742,8 @@
creeps back in, it will be caught immediately by the testsuite -
but only if such a test exists.
</p></td></tr><tr class="toc"><td align="left" valign="top" colspan="2"><dl><dt>7.1. <a href="faq.html#faq.iterator_as_pod">
- string::iterator is not char*; vector&lt;T&gt;::iterator is not T*
+ string::iterator is not char*;
+ vector&lt;T&gt;::iterator is not T*
</a></dt><dt>7.2. <a href="faq.html#faq.what_is_next">
What's next after libstdc++?
</a></dt><dt>7.3. <a href="faq.html#faq.sgi_stl">
@@ -749,7 +758,8 @@
</a></dt><dt>7.8. <a href="faq.html#faq.size_equals_capacity">
How do I make std::vector&lt;T&gt;::capacity() == std::vector&lt;T&gt;::size?
</a></dt></dl></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.iterator_as_pod"></a><a id="faq.iterator_as_pod_q"></a><p><strong>7.1.</strong></p></td><td align="left" valign="top"><p>
- string::iterator is not char*; vector&lt;T&gt;::iterator is not T*
+ <code class="classname">string::iterator</code> is not <code class="code">char*</code>;
+ <code class="classname">vector&lt;T&gt;::iterator</code> is not <code class="code">T*</code>
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="faq.iterator_as_pod_a"></a></td><td align="left" valign="top"><p>
If you have code that depends on container&lt;T&gt; iterators
being implemented as pointer-to-T, your code is broken. It's
@@ -762,38 +772,38 @@
than a typedef for <span class="type">T*</span> outweighs nearly all opposing
arguments.
</p><p>
- Code which does assume that a vector iterator <code class="varname">i</code>
+ Code which does assume that a vector/string iterator <code class="varname">i</code>
is a pointer can often be fixed by changing <code class="varname">i</code> in
- certain expressions to <code class="varname">&amp;*i</code>. Future revisions
- of the Standard are expected to bless this usage for
- vector&lt;&gt; (but not for basic_string&lt;&gt;).
+ certain expressions to <code class="varname">&amp;*i</code>.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.what_is_next"></a><a id="q-what_is_next"></a><p><strong>7.2.</strong></p></td><td align="left" valign="top"><p>
What's next after libstdc++?
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-what_is_next"></a></td><td align="left" valign="top"><p>
- Hopefully, not much. The goal of libstdc++ is to produce a
- fully-compliant, fully-portable Standard Library. After that,
- we're mostly done: there won't <span class="emphasis"><em>be</em></span> any
- more compliance work to do.
- </p><p>
- There is an effort underway to add significant extensions to
- the standard library specification. The latest version of
- this effort is described in
- <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf" target="_top">
- The C++ Library Technical Report 1</a>.
+ The goal of libstdc++ is to produce a
+ fully-compliant, fully-portable Standard Library.
+ While the C++ Standard continues to evolve the libstdc++ will
+ continue to track it.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.sgi_stl"></a><a id="q-sgi_stl"></a><p><strong>7.3.</strong></p></td><td align="left" valign="top"><p>
What about the STL from SGI?
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-sgi_stl"></a></td><td align="left" valign="top"><p>
- The <a class="link" href="http://www.sgi.com/tech/stl/" target="_top">STL from SGI</a>,
- version 3.3, was the final merge of the STL codebase. The
- code in libstdc++ contains many fixes and changes, and
- the SGI code is no longer under active
- development. We expect that no future merges will take place.
+ The STL (Standard Template Library) was the inspiration for large chunks
+ of the C++ Standard Library, but the terms are not interchangeable and
+ they don't mean the same thing. The C++ Standard Library includes lots of
+ things that didn't come from the STL, and some of them aren't even
+ templates, such as <code class="classname">std::locale</code> and
+ <code class="classname">std::thread</code>.
+ </p><p>
+ Libstdc++-v3 incorporates a lot of code from
+ <a class="link" href="http://www.sgi.com/tech/stl/" target="_top">the SGI STL</a>
+ (the final merge was from
+ <a class="link" href="http://www.sgi.com/tech/stl/whats_new.html" target="_top">release 3.3</a>).
+ The code in libstdc++ contains many fixes and changes compared to the
+ original SGI code.
</p><p>
In particular, <code class="classname">string</code> is not from SGI and makes no
- use of their "rope" class (which is included as an
- optional extension), nor is <code class="classname">valarray</code> and some others.
- Classes like <code class="classname">vector&lt;&gt;</code> are, but have been
- extensively modified.
+ use of their "rope" class (although that is included as an optional
+ extension), neither is <code class="classname">valarray</code> nor some others.
+ Classes like <code class="classname">vector&lt;&gt;</code> were from SGI, but have
+ been extensively modified.
</p><p>
More information on the evolution of libstdc++ can be found at the
<a class="link" href="manual/api.html" title="API Evolution and Deprecation History">API
@@ -812,13 +822,17 @@
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-tr1_support"></a></td><td align="left" valign="top"><p>
Yes.
</p><p>
- The C++ Standard Library Technical Report adds many new features to
- the library. The latest version of this effort is described in
+ The C++ Standard Library
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf" target="_top">
- Technical Report 1</a>.
+ Technical Report 1</a> added many new features to the library.
</p><p>
- The implementation status of TR1 in libstdc++ can be tracked <a class="link" href="manual/status.html#status.iso.tr1" title="C++ TR1">on the TR1 status
- page</a>.
+ The implementation status of TR1 in libstdc++ can be tracked
+ <a class="link" href="manual/status.html#status.iso.tr1" title="C++ TR1">on the TR1 status page</a>.
+ </p><p>
+ New code should probably not use TR1, because almost everything in it has
+ been added to the main C++ Standard Library (usually with significant
+ improvements).
+ The TR1 implementation in libstdc++ is no longer actively maintained.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.get_iso_cxx"></a><a id="q-get_iso_cxx"></a><p><strong>7.6.</strong></p></td><td align="left" valign="top"><p>How do I get a copy of the ISO C++ Standard?
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-get_iso_cxx"></a></td><td align="left" valign="top"><p>
Please refer to the <a class="link" href="manual/appendix_contributing.html" title="Appendix A.  Contributing">Contributing</a>
@@ -878,10 +892,14 @@
the decisions, must happen before you can reasonably document a
candidate C++ ABI that encompasses the standard library.
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.size_equals_capacity"></a><a id="q-size_equals_capacity"></a><p><strong>7.8.</strong></p></td><td align="left" valign="top"><p>
- How do I make std::vector&lt;T&gt;::capacity() == std::vector&lt;T&gt;::size?
+ How do I make <code class="code">std::vector&lt;T&gt;::capacity() == std::vector&lt;T&gt;::size</code>?
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-size_equals_capacity"></a></td><td align="left" valign="top"><p>
- The standard idiom for deallocating a <code class="classname">vector&lt;T&gt;</code>'s
- unused memory is to create a temporary copy of the vector and swap their
+ Since C++11 just call the <code class="function">shrink_to_fit()</code> member
+ function.
+ </p><p>
+ Before C++11, the standard idiom for deallocating a
+ <code class="classname">vector&lt;T&gt;</code>'s
+ unused memory was to create a temporary copy of the vector and swap their
contents, e.g. for <code class="classname">vector&lt;T&gt; v</code>
</p><div class="literallayout"><p><br />
     std::vector&lt;T&gt;(v).swap(v);<br />
diff --git a/libstdc++-v3/doc/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html
index 1cdbf398dce..1ed199e432e 100644
--- a/libstdc++-v3/doc/html/manual/bugs.html
+++ b/libstdc++-v3/doc/html/manual/bugs.html
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Bugs</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.78.1" /><meta name="keywords" content="ISO C++, library" /><meta name="keywords" content="ISO C++, runtime, library" /><link rel="home" href="../index.html" title="The GNU C++ Library" /><link rel="up" href="status.html" title="Chapter 1. Status" /><link rel="prev" href="license.html" title="License" /><link rel="next" href="setup.html" title="Chapter 2. Setup" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Bugs</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="license.html">Prev</a> </td><th width="60%" align="center">Chapter 1. Status</th><td width="20%" align="right"> <a accesskey="n" href="setup.html">Next</a></td></tr></table><hr /></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="manual.intro.status.bugs"></a>Bugs</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="manual.intro.status.bugs.impl"></a>Implementation Bugs</h3></div></div></div><p>
Information on known bugs, details on efforts to fix them, and
- fixed bugs are all available as part of the <a class="link" href="http://gcc.gnu.org/bugs/" target="_top">GCC bug tracking system</a>,
- with the category set to <code class="literal">libstdc++</code>.
+ fixed bugs are all available as part of the <a class="link" href="https://gcc.gnu.org/bugs/" target="_top">GCC bug tracking system</a>,
+ under the component <span class="quote">“<span class="quote">libstdc++</span>”</span>.
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="manual.intro.status.bugs.iso"></a>Standard Bugs</h3></div></div></div><p>
Everybody's got issues. Even the C++ Standard Library.
</p><p>
@@ -12,219 +12,221 @@
a consensus on proposed solutions, we often incorporate the solution.
</p><p>
Here are the issues which have resulted in code changes to the library.
- The links are to the specific defect reports from a <span class="emphasis"><em>partial
- copy</em></span> of the Issues List. You can read the full version online
+ The links are to the full version of the Issues List.
+ You can read the full version online
at the <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/" target="_top">ISO C++
Committee homepage</a>.
</p><p>
If a DR is not listed here, we may simply not have gotten to
- it yet; feel free to submit a patch. Search the include/bits
- and src directories for appearances of
+ it yet; feel free to submit a patch. Search the
+ <code class="filename">include</code> and
+ <code class="filename">src</code>
+ directories for appearances of
<code class="constant">_GLIBCXX_RESOLVE_LIB_DEFECTS</code> for examples
of style. Note that we usually do not make changes to the
code until an issue has reached <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#DR" target="_top">DR</a> status.
- </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#5" target="_top">5</a>:
+ </p><div class="variablelist"><dl class="variablelist"><dt><a id="manual.bugs.dr5"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#5" target="_top">5</a>:
<span class="emphasis"><em>string::compare specification questionable</em></span>
</span></dt><dd><p>This should be two overloaded functions rather than a single function.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#17" target="_top">17</a>:
+ </p></dd><dt><a id="manual.bugs.dr17"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#17" target="_top">17</a>:
<span class="emphasis"><em>Bad bool parsing</em></span>
</span></dt><dd><p>Apparently extracting Boolean values was messed up...
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#19" target="_top">19</a>:
+ </p></dd><dt><a id="manual.bugs.dr19"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#19" target="_top">19</a>:
<span class="emphasis"><em>"Noconv" definition too vague</em></span>
</span></dt><dd><p>If <code class="code">codecvt::do_in</code> returns <code class="code">noconv</code> there are
no changes to the values in <code class="code">[to, to_limit)</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#22" target="_top">22</a>:
+ </p></dd><dt><a id="manual.bugs.dr22"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#22" target="_top">22</a>:
<span class="emphasis"><em>Member open vs flags</em></span>
</span></dt><dd><p>Re-opening a file stream does <span class="emphasis"><em>not</em></span> clear the state flags.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#23" target="_top">23</a>:
+ </p></dd><dt><a id="manual.bugs.dr23"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#23" target="_top">23</a>:
<span class="emphasis"><em>Num_get overflow result</em></span>
</span></dt><dd><p>Implement the proposed resolution.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#25" target="_top">25</a>:
+ </p></dd><dt><a id="manual.bugs.dr25"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#25" target="_top">25</a>:
<span class="emphasis"><em>String operator&lt;&lt; uses width() value wrong</em></span>
</span></dt><dd><p>Padding issues.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#48" target="_top">48</a>:
+ </p></dd><dt><a id="manual.bugs.dr48"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#48" target="_top">48</a>:
<span class="emphasis"><em>Use of non-existent exception constructor</em></span>
</span></dt><dd><p>An instance of <code class="code">ios_base::failure</code> is constructed instead.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#49" target="_top">49</a>:
+ </p></dd><dt><a id="manual.bugs.dr49"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#49" target="_top">49</a>:
<span class="emphasis"><em>Underspecification of ios_base::sync_with_stdio</em></span>
</span></dt><dd><p>The return type is the <span class="emphasis"><em>previous</em></span> state of synchronization.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#50" target="_top">50</a>:
+ </p></dd><dt><a id="manual.bugs.dr50"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#50" target="_top">50</a>:
<span class="emphasis"><em>Copy constructor and assignment operator of ios_base</em></span>
</span></dt><dd><p>These members functions are declared <code class="code">private</code> and are
thus inaccessible. Specifying the correct semantics of
"copying stream state" was deemed too complicated.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#60" target="_top">60</a>:
+ </p></dd><dt><a id="manual.bugs.dr60"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#60" target="_top">60</a>:
<span class="emphasis"><em>What is a formatted input function?</em></span>
</span></dt><dd><p>This DR made many widespread changes to <code class="code">basic_istream</code>
and <code class="code">basic_ostream</code> all of which have been implemented.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#63" target="_top">63</a>:
+ </p></dd><dt><a id="manual.bugs.dr63"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#63" target="_top">63</a>:
<span class="emphasis"><em>Exception-handling policy for unformatted output</em></span>
</span></dt><dd><p>Make the policy consistent with that of formatted input, unformatted
input, and formatted output.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#68" target="_top">68</a>:
+ </p></dd><dt><a id="manual.bugs.dr68"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#68" target="_top">68</a>:
<span class="emphasis"><em>Extractors for char* should store null at end</em></span>
</span></dt><dd><p>And they do now. An editing glitch in the last item in the list of
[27.6.1.2.3]/7.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#74" target="_top">74</a>:
+ </p></dd><dt><a id="manual.bugs.dr74"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#74" target="_top">74</a>:
<span class="emphasis"><em>Garbled text for codecvt::do_max_length</em></span>
</span></dt><dd><p>The text of the standard was gibberish. Typos gone rampant.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#75" target="_top">75</a>:
+ </p></dd><dt><a id="manual.bugs.dr75"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#75" target="_top">75</a>:
<span class="emphasis"><em>Contradiction in codecvt::length's argument types</em></span>
</span></dt><dd><p>Change the first parameter to <code class="code">stateT&amp;</code> and implement
the new effects paragraph.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#83" target="_top">83</a>:
+ </p></dd><dt><a id="manual.bugs.dr83"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#83" target="_top">83</a>:
<span class="emphasis"><em>string::npos vs. string::max_size()</em></span>
</span></dt><dd><p>Safety checks on the size of the string should test against
<code class="code">max_size()</code> rather than <code class="code">npos</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#90" target="_top">90</a>:
+ </p></dd><dt><a id="manual.bugs.dr90"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#90" target="_top">90</a>:
<span class="emphasis"><em>Incorrect description of operator&gt;&gt; for strings</em></span>
</span></dt><dd><p>The effect contain <code class="code">isspace(c,getloc())</code> which must be
replaced by <code class="code">isspace(c,is.getloc())</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#91" target="_top">91</a>:
+ </p></dd><dt><a id="manual.bugs.dr91"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#91" target="_top">91</a>:
<span class="emphasis"><em>Description of operator&gt;&gt; and getline() for string&lt;&gt;
might cause endless loop</em></span>
</span></dt><dd><p>They behave as a formatted input function and as an unformatted
input function, respectively (except that <code class="code">getline</code> is
not required to set <code class="code">gcount</code>).
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103" target="_top">103</a>:
+ </p></dd><dt><a id="manual.bugs.dr103"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103" target="_top">103</a>:
<span class="emphasis"><em>set::iterator is required to be modifiable, but this allows
modification of keys.</em></span>
</span></dt><dd><p>For associative containers where the value type is the same as
the key type, both <code class="code">iterator</code> and <code class="code">const_iterator
</code> are constant iterators.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109" target="_top">109</a>:
+ </p></dd><dt><a id="manual.bugs.dr109"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109" target="_top">109</a>:
<span class="emphasis"><em>Missing binders for non-const sequence elements</em></span>
</span></dt><dd><p>The <code class="code">binder1st</code> and <code class="code">binder2nd</code> didn't have an
<code class="code">operator()</code> taking a non-const parameter.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#110" target="_top">110</a>:
+ </p></dd><dt><a id="manual.bugs.dr110"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#110" target="_top">110</a>:
<span class="emphasis"><em>istreambuf_iterator::equal not const</em></span>
</span></dt><dd><p>This was not a const member function. Note that the DR says to
replace the function with a const one; we have instead provided an
overloaded version with identical contents.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#117" target="_top">117</a>:
+ </p></dd><dt><a id="manual.bugs.dr117"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#117" target="_top">117</a>:
<span class="emphasis"><em>basic_ostream uses nonexistent num_put member functions</em></span>
</span></dt><dd><p><code class="code">num_put::put()</code> was overloaded on the wrong types.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#118" target="_top">118</a>:
+ </p></dd><dt><a id="manual.bugs.dr118"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#118" target="_top">118</a>:
<span class="emphasis"><em>basic_istream uses nonexistent num_get member functions</em></span>
</span></dt><dd><p>Same as 117, but for <code class="code">num_get::get()</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#129" target="_top">129</a>:
+ </p></dd><dt><a id="manual.bugs.dr129"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#129" target="_top">129</a>:
<span class="emphasis"><em>Need error indication from seekp() and seekg()</em></span>
</span></dt><dd><p>These functions set <code class="code">failbit</code> on error now.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130" target="_top">130</a>:
+ </p></dd><dt><a id="manual.bugs.dr130"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130" target="_top">130</a>:
<span class="emphasis"><em>Return type of container::erase(iterator) differs for associative containers</em></span>
</span></dt><dd><p>Make member <code class="code">erase</code> return iterator for <code class="code">set</code>, <code class="code">multiset</code>, <code class="code">map</code>, <code class="code">multimap</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136" target="_top">136</a>:
+ </p></dd><dt><a id="manual.bugs.dr136"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136" target="_top">136</a>:
<span class="emphasis"><em>seekp, seekg setting wrong streams?</em></span>
</span></dt><dd><p><code class="code">seekp</code> should only set the output stream, and
<code class="code">seekg</code> should only set the input stream.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#167" target="_top">167</a>:
+ </p></dd><dt><a id="manual.bugs.dr167"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#167" target="_top">167</a>:
<span class="emphasis"><em>Improper use of traits_type::length()</em></span>
</span></dt><dd><p><code class="code">op&lt;&lt;</code> with a <code class="code">const char*</code> was
calculating an incorrect number of characters to write.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#169" target="_top">169</a>:
+ </p></dd><dt><a id="manual.bugs.dr169"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#169" target="_top">169</a>:
<span class="emphasis"><em>Bad efficiency of overflow() mandated</em></span>
</span></dt><dd><p>Grow efficiently the internal array object.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#171" target="_top">171</a>:
+ </p></dd><dt><a id="manual.bugs.dr171"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#171" target="_top">171</a>:
<span class="emphasis"><em>Strange seekpos() semantics due to joint position</em></span>
</span></dt><dd><p>Quite complex to summarize...
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181" target="_top">181</a>:
+ </p></dd><dt><a id="manual.bugs.dr181"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181" target="_top">181</a>:
<span class="emphasis"><em>make_pair() unintended behavior</em></span>
</span></dt><dd><p>This function used to take its arguments as reference-to-const, now
it copies them (pass by value).
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195" target="_top">195</a>:
+ </p></dd><dt><a id="manual.bugs.dr195"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195" target="_top">195</a>:
<span class="emphasis"><em>Should basic_istream::sentry's constructor ever set eofbit?</em></span>
</span></dt><dd><p>Yes, it can, specifically if EOF is reached while skipping whitespace.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#211" target="_top">211</a>:
+ </p></dd><dt><a id="manual.bugs.dr211"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#211" target="_top">211</a>:
<span class="emphasis"><em>operator&gt;&gt;(istream&amp;, string&amp;) doesn't set failbit</em></span>
</span></dt><dd><p>If nothing is extracted into the string, <code class="code">op&gt;&gt;</code> now
sets <code class="code">failbit</code> (which can cause an exception, etc., etc.).
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#214" target="_top">214</a>:
+ </p></dd><dt><a id="manual.bugs.dr214"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#214" target="_top">214</a>:
<span class="emphasis"><em>set::find() missing const overload</em></span>
</span></dt><dd><p>Both <code class="code">set</code> and <code class="code">multiset</code> were missing
overloaded find, lower_bound, upper_bound, and equal_range functions
for const instances.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#231" target="_top">231</a>:
+ </p></dd><dt><a id="manual.bugs.dr231"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#231" target="_top">231</a>:
<span class="emphasis"><em>Precision in iostream?</em></span>
</span></dt><dd><p>For conversion from a floating-point type, <code class="code">str.precision()</code>
is specified in the conversion specification.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233" target="_top">233</a>:
+ </p></dd><dt><a id="manual.bugs.dr233"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233" target="_top">233</a>:
<span class="emphasis"><em>Insertion hints in associative containers</em></span>
</span></dt><dd><p>Implement N1780, first check before then check after, insert as close
to hint as possible.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235" target="_top">235</a>:
+ </p></dd><dt><a id="manual.bugs.dr235"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235" target="_top">235</a>:
<span class="emphasis"><em>No specification of default ctor for reverse_iterator</em></span>
</span></dt><dd><p>The declaration of <code class="code">reverse_iterator</code> lists a default constructor.
However, no specification is given what this constructor should do.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241" target="_top">241</a>:
+ </p></dd><dt><a id="manual.bugs.dr241"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241" target="_top">241</a>:
<span class="emphasis"><em>Does unique_copy() require CopyConstructible and Assignable?</em></span>
</span></dt><dd><p>Add a helper for forward_iterator/output_iterator, fix the existing
one for input_iterator/output_iterator to not rely on Assignability.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#243" target="_top">243</a>:
+ </p></dd><dt><a id="manual.bugs.dr243"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#243" target="_top">243</a>:
<span class="emphasis"><em>get and getline when sentry reports failure</em></span>
</span></dt><dd><p>Store a null character only if the character array has a non-zero size.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#251" target="_top">251</a>:
+ </p></dd><dt><a id="manual.bugs.dr251"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#251" target="_top">251</a>:
<span class="emphasis"><em>basic_stringbuf missing allocator_type</em></span>
</span></dt><dd><p>This nested typedef was originally not specified.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#253" target="_top">253</a>:
+ </p></dd><dt><a id="manual.bugs.dr253"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#253" target="_top">253</a>:
<span class="emphasis"><em>valarray helper functions are almost entirely useless</em></span>
</span></dt><dd><p>Make the copy constructor and copy-assignment operator declarations
public in gslice_array, indirect_array, mask_array, slice_array; provide
definitions.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265" target="_top">265</a>:
+ </p></dd><dt><a id="manual.bugs.dr265"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265" target="_top">265</a>:
<span class="emphasis"><em>std::pair::pair() effects overly restrictive</em></span>
</span></dt><dd><p>The default ctor would build its members from copies of temporaries;
now it simply uses their respective default ctors.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#266" target="_top">266</a>:
+ </p></dd><dt><a id="manual.bugs.dr266"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#266" target="_top">266</a>:
<span class="emphasis"><em>bad_exception::~bad_exception() missing Effects clause</em></span>
</span></dt><dd><p>The <code class="code">bad_</code>* classes no longer have destructors (they
are trivial), since no description of them was ever given.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#271" target="_top">271</a>:
+ </p></dd><dt><a id="manual.bugs.dr271"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#271" target="_top">271</a>:
<span class="emphasis"><em>basic_iostream missing typedefs</em></span>
</span></dt><dd><p>The typedefs it inherits from its base classes can't be used, since
(for example) <code class="code">basic_iostream&lt;T&gt;::traits_type</code> is ambiguous.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#275" target="_top">275</a>:
+ </p></dd><dt><a id="manual.bugs.dr275"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#275" target="_top">275</a>:
<span class="emphasis"><em>Wrong type in num_get::get() overloads</em></span>
</span></dt><dd><p>Similar to 118.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#280" target="_top">280</a>:
+ </p></dd><dt><a id="manual.bugs.dr280"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#280" target="_top">280</a>:
<span class="emphasis"><em>Comparison of reverse_iterator to const reverse_iterator</em></span>
</span></dt><dd><p>Add global functions with two template parameters.
(NB: not added for now a templated assignment operator)
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#292" target="_top">292</a>:
+ </p></dd><dt><a id="manual.bugs.dr292"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#292" target="_top">292</a>:
<span class="emphasis"><em>Effects of a.copyfmt (a)</em></span>
</span></dt><dd><p>If <code class="code">(this == &amp;rhs)</code> do nothing.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#300" target="_top">300</a>:
+ </p></dd><dt><a id="manual.bugs.dr300"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#300" target="_top">300</a>:
<span class="emphasis"><em>List::merge() specification incomplete</em></span>
</span></dt><dd><p>If <code class="code">(this == &amp;x)</code> do nothing.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303" target="_top">303</a>:
+ </p></dd><dt><a id="manual.bugs.dr303"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303" target="_top">303</a>:
<span class="emphasis"><em>Bitset input operator underspecified</em></span>
</span></dt><dd><p>Basically, compare the input character to
<code class="code">is.widen(0)</code> and <code class="code">is.widen(1)</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#305" target="_top">305</a>:
+ </p></dd><dt><a id="manual.bugs.dr305"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#305" target="_top">305</a>:
<span class="emphasis"><em>Default behavior of codecvt&lt;wchar_t, char,
mbstate_t&gt;::length()</em></span>
</span></dt><dd><p>Do not specify what <code class="code">codecvt&lt;wchar_t, char,
mbstate_t&gt;::do_length</code> must return.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#328" target="_top">328</a>:
+ </p></dd><dt><a id="manual.bugs.dr328"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#328" target="_top">328</a>:
<span class="emphasis"><em>Bad sprintf format modifier in
money_put&lt;&gt;::do_put()</em></span>
</span></dt><dd><p>Change the format string to "%.0Lf".
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#365" target="_top">365</a>:
+ </p></dd><dt><a id="manual.bugs.dr365"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#365" target="_top">365</a>:
<span class="emphasis"><em>Lack of const-qualification in clause 27</em></span>
</span></dt><dd><p>Add const overloads of <code class="code">is_open</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#387" target="_top">387</a>:
+ </p></dd><dt><a id="manual.bugs.dr387"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#387" target="_top">387</a>:
<span class="emphasis"><em>std::complex over-encapsulated</em></span>
</span></dt><dd><p>Add the <code class="code">real(T)</code> and <code class="code">imag(T)</code>
members; in C++11 mode, also adjust the existing
<code class="code">real()</code> and <code class="code">imag()</code> members and
free functions.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#389" target="_top">389</a>:
+ </p></dd><dt><a id="manual.bugs.dr389"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#389" target="_top">389</a>:
<span class="emphasis"><em>Const overload of valarray::operator[] returns
by value</em></span>
</span></dt><dd><p>Change it to return a <code class="code">const T&amp;</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#396" target="_top">396</a>:
+ </p></dd><dt><a id="manual.bugs.dr396"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#396" target="_top">396</a>:
<span class="emphasis"><em>what are characters zero and one</em></span>
</span></dt><dd><p>Implement the proposed resolution.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#402" target="_top">402</a>:
+ </p></dd><dt><a id="manual.bugs.dr402"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#402" target="_top">402</a>:
<span class="emphasis"><em>Wrong new expression in [some_]allocator::construct</em></span>
</span></dt><dd><p>Replace "new" with "::new".
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#408" target="_top">408</a>:
@@ -232,39 +234,39 @@
Is vector&lt;reverse_iterator&lt;char*&gt; &gt; forbidden?
</em></span>
</span></dt><dd><p>Tweak the debug-mode checks in _Safe_iterator.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#409" target="_top">409</a>:
+ </p></dd><dt><a id="manual.bugs.dr409"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#409" target="_top">409</a>:
<span class="emphasis"><em>Closing an fstream should clear the error state</em></span>
</span></dt><dd><p>Have <code class="code">open</code> clear the error flags.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#431" target="_top">431</a>:
<span class="emphasis"><em>Swapping containers with unequal allocators</em></span>
</span></dt><dd><p>Implement Option 3, as per N1599.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#432" target="_top">432</a>:
+ </p></dd><dt><a id="manual.bugs.dr432"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#432" target="_top">432</a>:
<span class="emphasis"><em>stringbuf::overflow() makes only one write position
available</em></span>
</span></dt><dd><p>Implement the resolution, beyond DR 169.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#434" target="_top">434</a>:
+ </p></dd><dt><a id="manual.bugs.dr434"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#434" target="_top">434</a>:
<span class="emphasis"><em>bitset::to_string() hard to use</em></span>
</span></dt><dd><p>Add three overloads, taking fewer template arguments.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438" target="_top">438</a>:
+ </p></dd><dt><a id="manual.bugs.dr438"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438" target="_top">438</a>:
<span class="emphasis"><em>Ambiguity in the "do the right thing" clause</em></span>
</span></dt><dd><p>Implement the resolution, basically cast less.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#445" target="_top">445</a>:
+ </p></dd><dt><a id="manual.bugs.dr445"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#445" target="_top">445</a>:
<span class="emphasis"><em>iterator_traits::reference unspecified for some iterator categories</em></span>
</span></dt><dd><p>Change <code class="code">istreambuf_iterator::reference</code> in C++11 mode.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#453" target="_top">453</a>:
+ </p></dd><dt><a id="manual.bugs.dr453"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#453" target="_top">453</a>:
<span class="emphasis"><em>basic_stringbuf::seekoff need not always fail for an empty stream</em></span>
</span></dt><dd><p>Don't fail if the next pointer is null and newoff is zero.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#455" target="_top">455</a>:
+ </p></dd><dt><a id="manual.bugs.dr455"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#455" target="_top">455</a>:
<span class="emphasis"><em>cerr::tie() and wcerr::tie() are overspecified</em></span>
</span></dt><dd><p>Initialize cerr tied to cout and wcerr tied to wcout.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464" target="_top">464</a>:
+ </p></dd><dt><a id="manual.bugs.dr464"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464" target="_top">464</a>:
<span class="emphasis"><em>Suggestion for new member functions in standard containers</em></span>
</span></dt><dd><p>Add <code class="code">data()</code> to <code class="code">std::vector</code> and
<code class="code">at(const key_type&amp;)</code> to <code class="code">std::map</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#467" target="_top">467</a>:
+ </p></dd><dt><a id="manual.bugs.dr467"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#467" target="_top">467</a>:
<span class="emphasis"><em>char_traits::lt(), compare(), and memcmp()</em></span>
</span></dt><dd><p>Change <code class="code">lt</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#508" target="_top">508</a>:
+ </p></dd><dt><a id="manual.bugs.dr508"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#508" target="_top">508</a>:
<span class="emphasis"><em>Bad parameters for ranlux64_base_01</em></span>
</span></dt><dd><p>Fix the parameters.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#512" target="_top">512</a>:
@@ -274,246 +276,246 @@
<span class="emphasis"><em>Is it undefined if a function in the standard changes in
parameters?</em></span>
</span></dt><dd><p>Use &amp;value.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#538" target="_top">538</a>:
+ </p></dd><dt><a id="manual.bugs.dr538"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#538" target="_top">538</a>:
<span class="emphasis"><em>241 again: Does unique_copy() require CopyConstructible
and Assignable?</em></span>
</span></dt><dd><p>In case of input_iterator/output_iterator rely on Assignability of
input_iterator' value_type.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#539" target="_top">539</a>:
+ </p></dd><dt><a id="manual.bugs.dr539"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#539" target="_top">539</a>:
<span class="emphasis"><em>partial_sum and adjacent_difference should mention
requirements</em></span>
</span></dt><dd><p>We were almost doing the right thing, just use std::move
in adjacent_difference.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#541" target="_top">541</a>:
+ </p></dd><dt><a id="manual.bugs.dr541"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#541" target="_top">541</a>:
<span class="emphasis"><em>shared_ptr template assignment and void</em></span>
</span></dt><dd><p>Add an auto_ptr&lt;void&gt; specialization.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#543" target="_top">543</a>:
+ </p></dd><dt><a id="manual.bugs.dr543"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#543" target="_top">543</a>:
<span class="emphasis"><em>valarray slice default constructor</em></span>
</span></dt><dd><p>Follow the straightforward proposed resolution.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#550" target="_top">550</a>:
+ </p></dd><dt><a id="manual.bugs.dr550"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#550" target="_top">550</a>:
<span class="emphasis"><em>What should the return type of pow(float,int) be?</em></span>
</span></dt><dd><p>In C++11 mode, remove the pow(float,int), etc., signatures.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#586" target="_top">586</a>:
+ </p></dd><dt><a id="manual.bugs.dr586"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#586" target="_top">586</a>:
<span class="emphasis"><em>string inserter not a formatted function</em></span>
</span></dt><dd><p>Change it to be a formatted output function (i.e. catch exceptions).
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#596" target="_top">596</a>:
+ </p></dd><dt><a id="manual.bugs.dr596"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#596" target="_top">596</a>:
<span class="emphasis"><em>27.8.1.3 Table 112 omits "a+" and "a+b" modes</em></span>
</span></dt><dd><p>Add the missing modes to fopen_mode.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#630" target="_top">630</a>:
+ </p></dd><dt><a id="manual.bugs.dr630"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#630" target="_top">630</a>:
<span class="emphasis"><em>arrays of valarray</em></span>
</span></dt><dd><p>Implement the simple resolution.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#660" target="_top">660</a>:
+ </p></dd><dt><a id="manual.bugs.dr660"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#660" target="_top">660</a>:
<span class="emphasis"><em>Missing bitwise operations</em></span>
</span></dt><dd><p>Add the missing operations.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#691" target="_top">691</a>:
+ </p></dd><dt><a id="manual.bugs.dr691"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#691" target="_top">691</a>:
<span class="emphasis"><em>const_local_iterator cbegin, cend missing from TR1</em></span>
</span></dt><dd><p>In C++11 mode add cbegin(size_type) and cend(size_type)
to the unordered containers.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#693" target="_top">693</a>:
+ </p></dd><dt><a id="manual.bugs.dr693"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#693" target="_top">693</a>:
<span class="emphasis"><em>std::bitset::all() missing</em></span>
</span></dt><dd><p>Add it, consistently with the discussion.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#695" target="_top">695</a>:
+ </p></dd><dt><a id="manual.bugs.dr695"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#695" target="_top">695</a>:
<span class="emphasis"><em>ctype&lt;char&gt;::classic_table() not accessible</em></span>
</span></dt><dd><p>Make the member functions table and classic_table public.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#696" target="_top">696</a>:
+ </p></dd><dt><a id="manual.bugs.dr696"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#696" target="_top">696</a>:
<span class="emphasis"><em>istream::operator&gt;&gt;(int&amp;) broken</em></span>
</span></dt><dd><p>Implement the straightforward resolution.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#761" target="_top">761</a>:
+ </p></dd><dt><a id="manual.bugs.dr761"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#761" target="_top">761</a>:
<span class="emphasis"><em>unordered_map needs an at() member function</em></span>
</span></dt><dd><p>In C++11 mode, add at() and at() const.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#775" target="_top">775</a>:
+ </p></dd><dt><a id="manual.bugs.dr775"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#775" target="_top">775</a>:
<span class="emphasis"><em>Tuple indexing should be unsigned?</em></span>
</span></dt><dd><p>Implement the int -&gt; size_t replacements.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776" target="_top">776</a>:
+ </p></dd><dt><a id="manual.bugs.dr776"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776" target="_top">776</a>:
<span class="emphasis"><em>Undescribed assign function of std::array</em></span>
</span></dt><dd><p>In C++11 mode, remove assign, add fill.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#781" target="_top">781</a>:
+ </p></dd><dt><a id="manual.bugs.dr781"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#781" target="_top">781</a>:
<span class="emphasis"><em>std::complex should add missing C99 functions</em></span>
</span></dt><dd><p>In C++11 mode, add std::proj.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809" target="_top">809</a>:
+ </p></dd><dt><a id="manual.bugs.dr809"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809" target="_top">809</a>:
<span class="emphasis"><em>std::swap should be overloaded for array types</em></span>
</span></dt><dd><p>Add the overload.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#853" target="_top">853</a>:
+ </p></dd><dt><a id="manual.bugs.dr853"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#853" target="_top">853</a>:
<span class="emphasis"><em>to_string needs updating with zero and one</em></span>
</span></dt><dd><p>Update / add the signatures.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#865" target="_top">865</a>:
+ </p></dd><dt><a id="manual.bugs.dr865"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#865" target="_top">865</a>:
<span class="emphasis"><em>More algorithms that throw away information</em></span>
</span></dt><dd><p>The traditional HP / SGI return type and value is blessed
by the resolution of the DR.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1339" target="_top">1339</a>:
+ </p></dd><dt><a id="manual.bugs.dr1339"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1339" target="_top">1339</a>:
<span class="emphasis"><em>uninitialized_fill_n should return the end of its range</em></span>
</span></dt><dd><p>Return the end of the filled range.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2021" target="_top">2021</a>:
+ </p></dd><dt><a id="manual.bugs.dr2021"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2021" target="_top">2021</a>:
<span class="emphasis"><em>Further incorrect uses of <code class="code">result_of</code></em></span>
</span></dt><dd><p>Correctly decay types in signature of <code class="code">std::async</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2049" target="_top">2049</a>:
+ </p></dd><dt><a id="manual.bugs.dr2049"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2049" target="_top">2049</a>:
<span class="emphasis"><em><code class="code">is_destructible</code> underspecified</em></span>
</span></dt><dd><p>Handle non-object types.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2056" target="_top">2056</a>:
+ </p></dd><dt><a id="manual.bugs.dr2056"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2056" target="_top">2056</a>:
<span class="emphasis"><em>future_errc enums start with value 0 (invalid value for broken_promise)</em></span>
</span></dt><dd><p>Reorder enumerators.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2059" target="_top">2059</a>:
+ </p></dd><dt><a id="manual.bugs.dr2059"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2059" target="_top">2059</a>:
<span class="emphasis"><em>C++0x ambiguity problem with map::erase</em></span>
</span></dt><dd><p>Add additional overloads.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2062" target="_top">2062</a>:
+ </p></dd><dt><a id="manual.bugs.dr2062"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2062" target="_top">2062</a>:
<span class="emphasis"><em>2062. Effect contradictions w/o no-throw guarantee of <code class="code">std::function</code> swaps</em></span>
</span></dt><dd><p>Add <code class="code">noexcept</code> to swap functions.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2063" target="_top">2063</a>:
+ </p></dd><dt><a id="manual.bugs.dr2063"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2063" target="_top">2063</a>:
<span class="emphasis"><em>Contradictory requirements for string move assignment</em></span>
</span></dt><dd><p>Respect propagation trait for move assignment.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2064" target="_top">2064</a>:
+ </p></dd><dt><a id="manual.bugs.dr2064"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2064" target="_top">2064</a>:
<span class="emphasis"><em>More noexcept issues in basic_string</em></span>
</span></dt><dd><p>Add noexcept to the comparison operators.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2067" target="_top">2067</a>:
+ </p></dd><dt><a id="manual.bugs.dr2067"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2067" target="_top">2067</a>:
<span class="emphasis"><em>packaged_task should have deleted copy c'tor with const parameter</em></span>
</span></dt><dd><p>Fix signatures.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2101" target="_top">2101</a>:
+ </p></dd><dt><a id="manual.bugs.dr2101"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2101" target="_top">2101</a>:
<span class="emphasis"><em>Some transformation types can produce impossible types</em></span>
</span></dt><dd><p>Use the referenceable type concept.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2106" target="_top">2106</a>:
+ </p></dd><dt><a id="manual.bugs.dr2106"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2106" target="_top">2106</a>:
<span class="emphasis"><em>move_iterator wrapping iterators returning prvalues</em></span>
</span></dt><dd><p>Change the <code class="code">reference</code> type.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2108" target="_top">2108</a>:
+ </p></dd><dt><a id="manual.bugs.dr2108"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2108" target="_top">2108</a>:
<span class="emphasis"><em>No way to identify allocator types that always compare equal</em></span>
</span></dt><dd><p>Define and use <code class="code">is_always_equal</code> even for C++11.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2118" target="_top">2118</a>:
+ </p></dd><dt><a id="manual.bugs.dr2118"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2118" target="_top">2118</a>:
<span class="emphasis"><em><code class="code">unique_ptr</code> for array does not support cv qualification conversion of actual argument</em></span>
</span></dt><dd><p>Adjust constraints to allow safe conversions.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2127" target="_top">2127</a>:
+ </p></dd><dt><a id="manual.bugs.dr2127"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2127" target="_top">2127</a>:
<span class="emphasis"><em>Move-construction with <code class="code">raw_storage_iterator</code></em></span>
</span></dt><dd><p>Add assignment operator taking an rvalue.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2132" target="_top">2132</a>:
+ </p></dd><dt><a id="manual.bugs.dr2132"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2132" target="_top">2132</a>:
<span class="emphasis"><em><code class="code">std::function</code> ambiguity</em></span>
</span></dt><dd><p>Constrain the constructor to only accept callable types.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2141" target="_top">2141</a>:
+ </p></dd><dt><a id="manual.bugs.dr2141"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2141" target="_top">2141</a>:
<span class="emphasis"><em><code class="code">common_type</code> trait produces reference types</em></span>
</span></dt><dd><p>Use <code class="code">decay</code> for the result type.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2144" target="_top">2144</a>:
+ </p></dd><dt><a id="manual.bugs.dr2144"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2144" target="_top">2144</a>:
<span class="emphasis"><em>Missing <code class="code">noexcept</code> specification in <code class="code">type_index</code></em></span>
</span></dt><dd><p>Add <code class="code">noexcept</code>
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2145" target="_top">2145</a>:
+ </p></dd><dt><a id="manual.bugs.dr2145"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2145" target="_top">2145</a>:
<span class="emphasis"><em><code class="code">error_category</code> default constructor</em></span>
</span></dt><dd><p>Declare a public constexpr constructor.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2162" target="_top">2162</a>:
+ </p></dd><dt><a id="manual.bugs.dr2162"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2162" target="_top">2162</a>:
<span class="emphasis"><em><code class="code">allocator_traits::max_size</code> missing <code class="code">noexcept</code></em></span>
</span></dt><dd><p>Add <code class="code">noexcept</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2187" target="_top">2187</a>:
+ </p></dd><dt><a id="manual.bugs.dr2187"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2187" target="_top">2187</a>:
<span class="emphasis"><em><code class="code">vector&lt;bool&gt;</code> is missing <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions</em></span>
</span></dt><dd><p>Add <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2192" target="_top">2192</a>:
+ </p></dd><dt><a id="manual.bugs.dr2192"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2192" target="_top">2192</a>:
<span class="emphasis"><em>Validity and return type of <code class="code">std::abs(0u)</code> is unclear</em></span>
</span></dt><dd><p>Move all declarations to a common header and remove the
generic <code class="code">abs</code> which accepted unsigned arguments.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2196" target="_top">2196</a>:
+ </p></dd><dt><a id="manual.bugs.dr2196"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2196" target="_top">2196</a>:
<span class="emphasis"><em>Specification of <code class="code">is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</em></span>
</span></dt><dd><p>Use the referenceable type concept.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2212" target="_top">2212</a>:
+ </p></dd><dt><a id="manual.bugs.dr2212"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2212" target="_top">2212</a>:
<span class="emphasis"><em><code class="code">tuple_size</code> for <code class="code">const pair</code> request <code class="code">&lt;tuple&gt;</code> header</em></span>
</span></dt><dd><p>The <code class="code">tuple_size</code> and <code class="code">tuple_element</code>
partial specializations are defined in <code class="code">&lt;utility&gt;</code> which
is included by <code class="code">&lt;array&gt;</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2296" target="_top">2296</a>:
+ </p></dd><dt><a id="manual.bugs.dr2296"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2296" target="_top">2296</a>:
<span class="emphasis"><em><code class="code">std::addressof</code> should be constexpr</em></span>
</span></dt><dd><p>Use <code class="code">__builtin_addressof</code> and add
<code class="code">constexpr</code> to <code class="code">addressof</code> for C++17 and later.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2313" target="_top">2313</a>:
+ </p></dd><dt><a id="manual.bugs.dr2313"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2313" target="_top">2313</a>:
<span class="emphasis"><em><code class="code">tuple_size</code> should always derive from <code class="code">integral_constant&lt;size_t, N&gt;</code></em></span>
</span></dt><dd><p>Update definitions of the partial specializations for const and volatile types.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2328" target="_top">2328</a>:
+ </p></dd><dt><a id="manual.bugs.dr2328"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2328" target="_top">2328</a>:
<span class="emphasis"><em>Rvalue stream extraction should use perfect forwarding</em></span>
</span></dt><dd><p>Use perfect forwarding for right operand.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2329" target="_top">2329</a>:
+ </p></dd><dt><a id="manual.bugs.dr2329"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2329" target="_top">2329</a>:
<span class="emphasis"><em><code class="code">regex_match()/regex_search()</code> with <code class="code">match_results</code> should forbid temporary strings</em></span>
</span></dt><dd><p>Add deleted overloads for rvalue strings.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2332" target="_top">2332</a>:
+ </p></dd><dt><a id="manual.bugs.dr2332"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2332" target="_top">2332</a>:
<span class="emphasis"><em><code class="code">regex_iterator/regex_token_iterator</code> should forbid temporary regexes</em></span>
</span></dt><dd><p>Add deleted constructors.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2399" target="_top">2399</a>:
+ </p></dd><dt><a id="manual.bugs.dr2399"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2399" target="_top">2399</a>:
<span class="emphasis"><em><code class="code">shared_ptr</code>'s constructor from <code class="code">unique_ptr</code> should be constrained</em></span>
</span></dt><dd><p>Constrain the constructor to require convertibility.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2400" target="_top">2400</a>:
+ </p></dd><dt><a id="manual.bugs.dr2400"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2400" target="_top">2400</a>:
<span class="emphasis"><em><code class="code">shared_ptr</code>'s <code class="code">get_deleter()</code> should use <code class="code">addressof()</code></em></span>
</span></dt><dd><p>Use <code class="code">addressof</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2401" target="_top">2401</a>:
+ </p></dd><dt><a id="manual.bugs.dr2401"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2401" target="_top">2401</a>:
<span class="emphasis"><em><code class="code">std::function</code> needs more <code class="code">noexcept</code></em></span>
</span></dt><dd><p>Add <code class="code">noexcept</code> to the assignment and comparisons.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2407" target="_top">2407</a>:
+ </p></dd><dt><a id="manual.bugs.dr2407"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2407" target="_top">2407</a>:
<span class="emphasis"><em><code class="code">packaged_task(allocator_arg_t, const Allocator&amp;, F&amp;&amp;)</code>
should neither be constrained nor <code class="code">explicit</code>
</em></span>
</span></dt><dd><p>Remove <code class="code">explicit</code> from the constructor.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2415" target="_top">2415</a>:
+ </p></dd><dt><a id="manual.bugs.dr2415"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2415" target="_top">2415</a>:
<span class="emphasis"><em>Inconsistency between <code class="code">unique_ptr</code> and <code class="code">shared_ptr</code></em></span>
</span></dt><dd><p>Create empty an <code class="code">shared_ptr</code> from an empty
<code class="code">unique_ptr</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2418" target="_top">2418</a>:
+ </p></dd><dt><a id="manual.bugs.dr2418"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2418" target="_top">2418</a>:
<span class="emphasis"><em><code class="code">apply</code> does not work with member pointers</em></span>
</span></dt><dd><p>Use <code class="code">mem_fn</code> for member pointers.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2440" target="_top">2440</a>:
+ </p></dd><dt><a id="manual.bugs.dr2440"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2440" target="_top">2440</a>:
<span class="emphasis"><em><code class="code">seed_seq::size()</code> should be <code class="code">noexcept</code></em></span>
</span></dt><dd><p>Add <code class="code">noexcept</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2441" target="_top">2441</a>:
+ </p></dd><dt><a id="manual.bugs.dr2441"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2441" target="_top">2441</a>:
<span class="emphasis"><em>Exact-width atomic typedefs should be provided</em></span>
</span></dt><dd><p>Define the typedefs.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442" target="_top">2442</a>:
+ </p></dd><dt><a id="manual.bugs.dr2442"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442" target="_top">2442</a>:
<span class="emphasis"><em><code class="code">call_once()</code> shouldn't <code class="code">DECAY_COPY()</code></em></span>
</span></dt><dd><p>Remove indirection through call wrapper that made copies
of arguments and forward arguments straight to <code class="code">std::invoke</code>.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2454" target="_top">2454</a>:
+ </p></dd><dt><a id="manual.bugs.dr2454"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2454" target="_top">2454</a>:
<span class="emphasis"><em>Add <code class="code">raw_storage_iterator::base()</code> member
</em></span>
</span></dt><dd><p>Add the <code class="code">base()</code> member function.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2455" target="_top">2455</a>:
+ </p></dd><dt><a id="manual.bugs.dr2455"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2455" target="_top">2455</a>:
<span class="emphasis"><em>Allocator default construction should be allowed to throw
</em></span>
</span></dt><dd><p>Make <code class="code">noexcept</code> specifications conditional.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2458" target="_top">2458</a>:
+ </p></dd><dt><a id="manual.bugs.dr2458"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2458" target="_top">2458</a>:
<span class="emphasis"><em>N3778 and new library deallocation signatures
</em></span>
</span></dt><dd><p>Remove unused overloads.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2459" target="_top">2459</a>:
+ </p></dd><dt><a id="manual.bugs.dr2459"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2459" target="_top">2459</a>:
<span class="emphasis"><em><code class="code">std::polar</code> should require a non-negative rho
</em></span>
</span></dt><dd><p>Add debug mode assertion.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2466" target="_top">2466</a>:
+ </p></dd><dt><a id="manual.bugs.dr2466"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2466" target="_top">2466</a>:
<span class="emphasis"><em><code class="code">allocator_traits::max_size()</code> default behavior is incorrect
</em></span>
</span></dt><dd><p>Divide by the object type.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2484" target="_top">2484</a>:
+ </p></dd><dt><a id="manual.bugs.dr2484"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2484" target="_top">2484</a>:
<span class="emphasis"><em><code class="code">rethrow_if_nested()</code> is doubly unimplementable
</em></span>
</span></dt><dd><p>Avoid using <code class="code">dynamic_cast</code> when it would be
ill-formed.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2583" target="_top">2583</a>:
+ </p></dd><dt><a id="manual.bugs.dr2583"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2583" target="_top">2583</a>:
<span class="emphasis"><em>There is no way to supply an allocator for <code class="code">basic_string(str, pos)</code>
</em></span>
</span></dt><dd><p>Add new constructor
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2684" target="_top">2684</a>:
+ </p></dd><dt><a id="manual.bugs.dr2684"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2684" target="_top">2684</a>:
<span class="emphasis"><em><code class="code">priority_queue</code> lacking comparator typedef
</em></span>
</span></dt><dd><p>Define the <code class="code">value_compare</code> typedef.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2770" target="_top">2770</a>:
+ </p></dd><dt><a id="manual.bugs.dr2770"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2770" target="_top">2770</a>:
<span class="emphasis"><em><code class="code">tuple_size&lt;const T&gt;</code> specialization is not
SFINAE compatible and breaks decomposition declarations
</em></span>
</span></dt><dd><p>Safely detect <code class="code">tuple_size&lt;T&gt;::value</code> and
only use it if valid.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2781" target="_top">2781</a>:
+ </p></dd><dt><a id="manual.bugs.dr2781"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2781" target="_top">2781</a>:
<span class="emphasis"><em>Contradictory requirements for <code class="code">std::function</code>
and <code class="code">std::reference_wrapper</code>
</em></span>
</span></dt><dd><p>Remove special handling for <code class="code">reference_wrapper</code>
arguments and store them directly as the target object.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2802" target="_top">2802</a>:
+ </p></dd><dt><a id="manual.bugs.dr2802"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2802" target="_top">2802</a>:
<span class="emphasis"><em>Add noexcept to several <code class="code">shared_ptr</code> related
functions
</em></span>
</span></dt><dd><p>Add noexcept.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2873" target="_top">2873</a>:
+ </p></dd><dt><a id="manual.bugs.dr2873"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2873" target="_top">2873</a>:
<span class="emphasis"><em><code class="code">shared_ptr</code> constructor requirements for a deleter
</em></span>
</span></dt><dd><p>Use rvalues for deleters.
- </p></dd><dt><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2942" target="_top">2942</a>:
+ </p></dd><dt><a id="manual.bugs.dr2942"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2942" target="_top">2942</a>:
<span class="emphasis"><em>LWG 2873's resolution missed
<code class="code">weak_ptr::owner_before</code>
</em></span>
diff --git a/libstdc++-v3/doc/html/manual/test.html b/libstdc++-v3/doc/html/manual/test.html
index 70341779ca7..f19a8e82a2c 100644
--- a/libstdc++-v3/doc/html/manual/test.html
+++ b/libstdc++-v3/doc/html/manual/test.html
@@ -327,13 +327,13 @@ cat 27_io/objects/char/3_xin.in | a.out</pre></dd><dt><span class="term"><code c
For example, to run the tests with
<code class="option">-O1 -D_GLIBCXX_ASSERTIONS</code>
you could use:
-</p><pre class="programlisting"> make RUNTESTFLAGS=--target_board=unix/-O1/-D_GLIBCXX_ASSERTIONS</pre><p>
+</p><pre class="programlisting"> make check RUNTESTFLAGS=--target_board=unix/-O1/-D_GLIBCXX_ASSERTIONS</pre><p>
</p><p>
The <code class="option">--target_board</code> option can also be used to run the
tests multiple times in different variations. For example, to run the
entire testsuite three times using <code class="option">-O3</code> but with
different <code class="option">-std</code> options:
-</p><pre class="programlisting"> make 'RUNTESTFLAGS=--target_board=unix/-O3\"{-std=gnu++98,-std=gnu++11,-std=gnu++14}\"'</pre><p>
+</p><pre class="programlisting"> make check 'RUNTESTFLAGS=--target_board=unix/-O3\"{-std=gnu++98,-std=gnu++11,-std=gnu++14}\"'</pre><p>
N.B. that set of variations could also be written as
<code class="literal">unix/-O3\"{-std=gnu++98,-std=gnu++11,}\"</code> so that
the third variation would use the default for <code class="option">-std</code>
diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml
index 8041c1428e6..703ade5b20d 100644
--- a/libstdc++-v3/doc/xml/faq.xml
+++ b/libstdc++-v3/doc/xml/faq.xml
@@ -66,10 +66,10 @@
that are the hallmarks of an open-source project are applied to libstdc++.
</para>
<para>
- All of the standard classes and functions from C++98/C++03
+ All of the standard classes and functions from C++98/C++03, C++11 and C++14
(such as <classname>string</classname>,
<classname>vector&lt;&gt;</classname>, iostreams, algorithms etc.)
- are freely available and atempt to be fully compliant.
+ are freely available and attempt to be fully compliant.
Work is ongoing to complete support for the current revision of the
ISO C++ Standard.
</para>
@@ -539,6 +539,9 @@
</para>
</question>
<answer xml:id="a-solaris_long_long">
+ <note>
+ <para>This answer is old and probably no longer be relevant.</para>
+ </note>
<para>
By default we try to support the C99 <type>long long</type> type.
This requires that certain functions from your C library be present.
@@ -692,7 +695,7 @@
<qandaentry xml:id="faq.freebsd_wchar">
<question xml:id="q-freebsd_wchar">
<para>
- Can't use wchar_t/wstring on FreeBSD
+ Can't use <type>wchar_t</type>/<classname>wstring</classname> on FreeBSD
</para>
</question>
<answer xml:id="a-freebsd_wchar">
@@ -764,7 +767,8 @@
published on <link xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">the WG21
website</link>.
- Many of these issues have resulted in code changes in libstdc++.
+ Many of these issues have resulted in
+ <link linkend="manual.intro.status.bugs.iso">code changes in libstdc++</link>.
</para>
<para>
If you think you've discovered a new bug that is not listed,
@@ -794,8 +798,8 @@
</para>
<para>
Before reporting a bug, please examine the
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/bugs/">bugs database</link> with the
- category set to <quote>g++</quote>.
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/bugs/">bugs database</link>, with the
+ component set to <quote>c++</quote>.
</para>
</answer>
</qandaentry>
@@ -813,8 +817,12 @@
</para>
</question>
<answer xml:id="a-stream_reopening_fails">
+ <note>
+ <para>This answer is old and probably no longer be relevant.</para>
+ </note>
<para>
- One of the most-reported non-bug reports. Executing a sequence like:
+ Prior to GCC 4.0 this was one of the most-reported non-bug reports.
+ Executing a sequence like this would fail:
</para>
<programlisting>
@@ -829,19 +837,20 @@
</programlisting>
<para>
- All operations on the re-opened <varname>fs</varname> will fail, or at
- least act very strangely. Yes, they often will, especially if
- <varname>fs</varname> reached the EOF state on the previous file. The
- reason is that the state flags are <emphasis>not</emphasis> cleared
- on a successful call to open(). The standard unfortunately did
- not specify behavior in this case, and to everybody's great sorrow,
- the <link linkend="manual.intro.status.bugs">proposed LWG resolution in
- DR #22</link> is to leave the flags unchanged. You must insert a call
- to <function>fs.clear()</function> between the calls to close() and open(),
- and then everything will work like we all expect it to work.
- <emphasis>Update:</emphasis> for GCC 4.0 we implemented the resolution
- of <link linkend="manual.intro.status.bugs">DR #409</link> and open()
- now calls <function>clear()</function> on success!
+ All operations on the re-opened <varname>fs</varname> would fail, or at
+ least act very strangely, especially if <varname>fs</varname> reached the
+ EOF state on the previous file.
+ The original C++98 standard did not specify behavior in this case, and
+ the <link linkend="manual.bugs.dr22">resolution of DR #22</link> was to
+ leave the state flags unchanged on a successful call to
+ <function>open()</function>.
+ You had to insert a call to <function>fs.clear()</function> between the
+ calls to <function>close()</function> and <function>open()</function>,
+ and then everything will work as expected.
+ <emphasis>Update:</emphasis> For GCC 4.0 we implemented the resolution
+ of <link linkend="manual.bugs.dr409">DR #409</link> and
+ <function>open()</function>
+ now calls <function>clear()</function> on success.
</para>
</answer>
</qandaentry>
@@ -858,7 +867,9 @@
libstdc++ <option>-Weffc++</option>-clean is not a goal of the project,
for a few reasons. Mainly, that option tries to enforce
object-oriented programming, while the Standard Library isn't
- necessarily trying to be OO.
+ necessarily trying to be OO. The option also enforces outdated guidelines
+ from old editions of the books, and the advice isn't all relevant to
+ modern C++ (especially C++11 and later).
</para>
<para>
We do, however, try to have libstdc++ sources as clean as possible. If
@@ -879,9 +890,10 @@
Another problem is the <literal>rel_ops</literal> namespace and the template
comparison operator functions contained therein. If they become
visible in the same namespace as other comparison functions
- (e.g., <quote>using</quote> them and the &lt;iterator&gt; header),
+ (e.g., <quote>using</quote> them and the
+ <filename class="headerfile">&lt;iterator&gt;</filename> header),
then you will suddenly be faced with huge numbers of ambiguity
- errors. This was discussed on the -v3 list; Nathan Myers
+ errors. This was discussed on the mailing list; Nathan Myers
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/ml/libstdc++/2001-01/msg00247.html">sums
things up here</link>. The collisions with vector/string iterator
types have been fixed for 3.1.
@@ -896,6 +908,9 @@
</para>
</question>
<answer xml:id="a-v2_headers">
+ <note>
+ <para>This answer is old and probably no longer be relevant.</para>
+ </note>
<para>
If you are using headers in
<filename class="directory">${prefix}/include/g++-3</filename>, or if
@@ -981,11 +996,15 @@
</para>
</question>
<answer xml:id="a-memory_leaks">
+ <note>
+ <para>This answer is old and probably no longer be relevant.</para>
+ </note>
<para>
A few people have reported that the standard containers appear
to leak memory when tested with memory checkers such as
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://valgrind.org/"><command>valgrind</command></link>.
- Under some configurations the library's allocators keep free memory in a
+ Under some (non-default) configurations the library's allocators keep
+ free memory in a
pool for later reuse, rather than returning it to the OS. Although
this memory is always reachable by the library and is never
lost, memory debugging tools can report it as a leak. If you
@@ -999,7 +1018,7 @@
<qandaentry xml:id="faq.list_size_on">
<question xml:id="q-list_size_on">
<para>
- list::size() is O(n)!
+ <code>list::size()</code> is O(n)!
</para>
</question>
<answer xml:id="a-list_size_on">
@@ -1049,7 +1068,8 @@
<qandaentry xml:id="faq.iterator_as_pod">
<question xml:id="faq.iterator_as_pod_q">
<para>
- string::iterator is not char*; vector&lt;T&gt;::iterator is not T*
+ <classname>string::iterator</classname> is not <code>char*</code>;
+ <classname>vector&lt;T&gt;::iterator</classname> is not <code>T*</code>
</para>
</question>
<answer xml:id="faq.iterator_as_pod_a">
@@ -1067,11 +1087,9 @@
arguments.
</para>
<para>
- Code which does assume that a vector iterator <varname>i</varname>
+ Code which does assume that a vector/string iterator <varname>i</varname>
is a pointer can often be fixed by changing <varname>i</varname> in
- certain expressions to <varname>&amp;*i</varname>. Future revisions
- of the Standard are expected to bless this usage for
- vector&lt;&gt; (but not for basic_string&lt;&gt;).
+ certain expressions to <varname>&amp;*i</varname>.
</para>
</answer>
</qandaentry>
@@ -1084,17 +1102,10 @@
</question>
<answer xml:id="a-what_is_next">
<para>
- Hopefully, not much. The goal of libstdc++ is to produce a
- fully-compliant, fully-portable Standard Library. After that,
- we're mostly done: there won't <emphasis>be</emphasis> any
- more compliance work to do.
- </para>
- <para>
- There is an effort underway to add significant extensions to
- the standard library specification. The latest version of
- this effort is described in
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">
- The C++ Library Technical Report 1</link>.
+ The goal of libstdc++ is to produce a
+ fully-compliant, fully-portable Standard Library.
+ While the C++ Standard continues to evolve the libstdc++ will
+ continue to track it.
</para>
</answer>
</qandaentry>
@@ -1107,18 +1118,27 @@
</question>
<answer xml:id="a-sgi_stl">
<para>
- The <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/">STL from SGI</link>,
- version 3.3, was the final merge of the STL codebase. The
- code in libstdc++ contains many fixes and changes, and
- the SGI code is no longer under active
- development. We expect that no future merges will take place.
+ The STL (Standard Template Library) was the inspiration for large chunks
+ of the C++ Standard Library, but the terms are not interchangeable and
+ they don't mean the same thing. The C++ Standard Library includes lots of
+ things that didn't come from the STL, and some of them aren't even
+ templates, such as <classname>std::locale</classname> and
+ <classname>std::thread</classname>.
+ </para>
+ <para>
+ Libstdc++-v3 incorporates a lot of code from
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/">the SGI STL</link>
+ (the final merge was from
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/whats_new.html">release 3.3</link>).
+ The code in libstdc++ contains many fixes and changes compared to the
+ original SGI code.
</para>
<para>
In particular, <classname>string</classname> is not from SGI and makes no
- use of their "rope" class (which is included as an
- optional extension), nor is <classname>valarray</classname> and some others.
- Classes like <classname>vector&lt;&gt;</classname> are, but have been
- extensively modified.
+ use of their "rope" class (although that is included as an optional
+ extension), neither is <classname>valarray</classname> nor some others.
+ Classes like <classname>vector&lt;&gt;</classname> were from SGI, but have
+ been extensively modified.
</para>
<para>
More information on the evolution of libstdc++ can be found at the
@@ -1158,14 +1178,19 @@
Yes.
</para>
<para>
- The C++ Standard Library Technical Report adds many new features to
- the library. The latest version of this effort is described in
+ The C++ Standard Library
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">
- Technical Report 1</link>.
+ Technical Report 1</link> added many new features to the library.
</para>
<para>
- The implementation status of TR1 in libstdc++ can be tracked <link linkend="status.iso.tr1">on the TR1 status
- page</link>.
+ The implementation status of TR1 in libstdc++ can be tracked
+ <link linkend="status.iso.tr1">on the TR1 status page</link>.
+ </para>
+ <para>
+ New code should probably not use TR1, because almost everything in it has
+ been added to the main C++ Standard Library (usually with significant
+ improvements).
+ The TR1 implementation in libstdc++ is no longer actively maintained.
</para>
</answer>
</qandaentry>
@@ -1252,13 +1277,18 @@
<qandaentry xml:id="faq.size_equals_capacity">
<question xml:id="q-size_equals_capacity">
<para>
- How do I make std::vector&lt;T&gt;::capacity() == std::vector&lt;T&gt;::size?
+ How do I make <code>std::vector&lt;T&gt;::capacity() == std::vector&lt;T&gt;::size</code>?
</para>
</question>
<answer xml:id="a-size_equals_capacity">
<para>
- The standard idiom for deallocating a <classname>vector&lt;T&gt;</classname>'s
- unused memory is to create a temporary copy of the vector and swap their
+ Since C++11 just call the <function>shrink_to_fit()</function> member
+ function.
+ </para>
+ <para>
+ Before C++11, the standard idiom for deallocating a
+ <classname>vector&lt;T&gt;</classname>'s
+ unused memory was to create a temporary copy of the vector and swap their
contents, e.g. for <classname>vector&lt;T&gt; v</classname>
</para>
<literallayout class="normal">
diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml
index 4ec74949bfb..782817e0698 100644
--- a/libstdc++-v3/doc/xml/manual/intro.xml
+++ b/libstdc++-v3/doc/xml/manual/intro.xml
@@ -193,8 +193,8 @@ requirements of the license of GCC.
<para>
Information on known bugs, details on efforts to fix them, and
- fixed bugs are all available as part of the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/bugs/">GCC bug tracking system</link>,
- with the category set to <literal>libstdc++</literal>.
+ fixed bugs are all available as part of the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/bugs/">GCC bug tracking system</link>,
+ under the component <quote>libstdc++</quote>.
</para>
</section>
@@ -211,71 +211,73 @@ requirements of the license of GCC.
</para>
<para>
Here are the issues which have resulted in code changes to the library.
- The links are to the specific defect reports from a <emphasis>partial
- copy</emphasis> of the Issues List. You can read the full version online
+ The links are to the full version of the Issues List.
+ You can read the full version online
at the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">ISO C++
Committee homepage</link>.
</para>
<para>
If a DR is not listed here, we may simply not have gotten to
- it yet; feel free to submit a patch. Search the include/bits
- and src directories for appearances of
+ it yet; feel free to submit a patch. Search the
+ <filename class="directory">include</filename> and
+ <filename class="directory">src</filename>
+ directories for appearances of
<constant>_GLIBCXX_RESOLVE_LIB_DEFECTS</constant> for examples
of style. Note that we usually do not make changes to the
code until an issue has reached <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#DR">DR</link> status.
</para>
<variablelist>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#5">5</link>:
+ <varlistentry xml:id="manual.bugs.dr5"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#5">5</link>:
<emphasis>string::compare specification questionable</emphasis>
</term>
<listitem><para>This should be two overloaded functions rather than a single function.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#17">17</link>:
+ <varlistentry xml:id="manual.bugs.dr17"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#17">17</link>:
<emphasis>Bad bool parsing</emphasis>
</term>
<listitem><para>Apparently extracting Boolean values was messed up...
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#19">19</link>:
+ <varlistentry xml:id="manual.bugs.dr19"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#19">19</link>:
<emphasis>"Noconv" definition too vague</emphasis>
</term>
<listitem><para>If <code>codecvt::do_in</code> returns <code>noconv</code> there are
no changes to the values in <code>[to, to_limit)</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#22">22</link>:
+ <varlistentry xml:id="manual.bugs.dr22"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#22">22</link>:
<emphasis>Member open vs flags</emphasis>
</term>
<listitem><para>Re-opening a file stream does <emphasis>not</emphasis> clear the state flags.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#23">23</link>:
+ <varlistentry xml:id="manual.bugs.dr23"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#23">23</link>:
<emphasis>Num_get overflow result</emphasis>
</term>
<listitem><para>Implement the proposed resolution.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#25">25</link>:
+ <varlistentry xml:id="manual.bugs.dr25"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#25">25</link>:
<emphasis>String operator&lt;&lt; uses width() value wrong</emphasis>
</term>
<listitem><para>Padding issues.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#48">48</link>:
+ <varlistentry xml:id="manual.bugs.dr48"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#48">48</link>:
<emphasis>Use of non-existent exception constructor</emphasis>
</term>
<listitem><para>An instance of <code>ios_base::failure</code> is constructed instead.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#49">49</link>:
+ <varlistentry xml:id="manual.bugs.dr49"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#49">49</link>:
<emphasis>Underspecification of ios_base::sync_with_stdio</emphasis>
</term>
<listitem><para>The return type is the <emphasis>previous</emphasis> state of synchronization.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#50">50</link>:
+ <varlistentry xml:id="manual.bugs.dr50"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#50">50</link>:
<emphasis>Copy constructor and assignment operator of ios_base</emphasis>
</term>
<listitem><para>These members functions are declared <code>private</code> and are
@@ -283,55 +285,55 @@ requirements of the license of GCC.
"copying stream state" was deemed too complicated.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#60">60</link>:
+ <varlistentry xml:id="manual.bugs.dr60"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#60">60</link>:
<emphasis>What is a formatted input function?</emphasis>
</term>
<listitem><para>This DR made many widespread changes to <code>basic_istream</code>
and <code>basic_ostream</code> all of which have been implemented.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#63">63</link>:
+ <varlistentry xml:id="manual.bugs.dr63"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#63">63</link>:
<emphasis>Exception-handling policy for unformatted output</emphasis>
</term>
<listitem><para>Make the policy consistent with that of formatted input, unformatted
input, and formatted output.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#68">68</link>:
+ <varlistentry xml:id="manual.bugs.dr68"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#68">68</link>:
<emphasis>Extractors for char* should store null at end</emphasis>
</term>
<listitem><para>And they do now. An editing glitch in the last item in the list of
[27.6.1.2.3]/7.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#74">74</link>:
+ <varlistentry xml:id="manual.bugs.dr74"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#74">74</link>:
<emphasis>Garbled text for codecvt::do_max_length</emphasis>
</term>
<listitem><para>The text of the standard was gibberish. Typos gone rampant.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#75">75</link>:
+ <varlistentry xml:id="manual.bugs.dr75"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#75">75</link>:
<emphasis>Contradiction in codecvt::length's argument types</emphasis>
</term>
<listitem><para>Change the first parameter to <code>stateT&amp;</code> and implement
the new effects paragraph.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#83">83</link>:
+ <varlistentry xml:id="manual.bugs.dr83"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#83">83</link>:
<emphasis>string::npos vs. string::max_size()</emphasis>
</term>
<listitem><para>Safety checks on the size of the string should test against
<code>max_size()</code> rather than <code>npos</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#90">90</link>:
+ <varlistentry xml:id="manual.bugs.dr90"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#90">90</link>:
<emphasis>Incorrect description of operator&gt;&gt; for strings</emphasis>
</term>
<listitem><para>The effect contain <code>isspace(c,getloc())</code> which must be
replaced by <code>isspace(c,is.getloc())</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#91">91</link>:
+ <varlistentry xml:id="manual.bugs.dr91"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#91">91</link>:
<emphasis>Description of operator&gt;&gt; and getline() for string&lt;&gt;
might cause endless loop</emphasis>
</term>
@@ -340,7 +342,7 @@ requirements of the license of GCC.
not required to set <code>gcount</code>).
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#103">103</link>:
+ <varlistentry xml:id="manual.bugs.dr103"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#103">103</link>:
<emphasis>set::iterator is required to be modifiable, but this allows
modification of keys.</emphasis>
</term>
@@ -349,14 +351,14 @@ requirements of the license of GCC.
</code> are constant iterators.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#109">109</link>:
+ <varlistentry xml:id="manual.bugs.dr109"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#109">109</link>:
<emphasis>Missing binders for non-const sequence elements</emphasis>
</term>
<listitem><para>The <code>binder1st</code> and <code>binder2nd</code> didn't have an
<code>operator()</code> taking a non-const parameter.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#110">110</link>:
+ <varlistentry xml:id="manual.bugs.dr110"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#110">110</link>:
<emphasis>istreambuf_iterator::equal not const</emphasis>
</term>
<listitem><para>This was not a const member function. Note that the DR says to
@@ -364,31 +366,31 @@ requirements of the license of GCC.
overloaded version with identical contents.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#117">117</link>:
+ <varlistentry xml:id="manual.bugs.dr117"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#117">117</link>:
<emphasis>basic_ostream uses nonexistent num_put member functions</emphasis>
</term>
<listitem><para><code>num_put::put()</code> was overloaded on the wrong types.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#118">118</link>:
+ <varlistentry xml:id="manual.bugs.dr118"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#118">118</link>:
<emphasis>basic_istream uses nonexistent num_get member functions</emphasis>
</term>
<listitem><para>Same as 117, but for <code>num_get::get()</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#129">129</link>:
+ <varlistentry xml:id="manual.bugs.dr129"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#129">129</link>:
<emphasis>Need error indication from seekp() and seekg()</emphasis>
</term>
<listitem><para>These functions set <code>failbit</code> on error now.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#130">130</link>:
+ <varlistentry xml:id="manual.bugs.dr130"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#130">130</link>:
<emphasis>Return type of container::erase(iterator) differs for associative containers</emphasis>
</term>
<listitem><para>Make member <code>erase</code> return iterator for <code>set</code>, <code>multiset</code>, <code>map</code>, <code>multimap</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#136">136</link>:
+ <varlistentry xml:id="manual.bugs.dr136"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#136">136</link>:
<emphasis>seekp, seekg setting wrong streams?</emphasis>
</term>
<listitem><para><code>seekp</code> should only set the output stream, and
@@ -402,46 +404,46 @@ requirements of the license of GCC.
should probably not be calling <code>underflow()</code>.
</para></listitem></varlistentry> -->
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#167">167</link>:
+ <varlistentry xml:id="manual.bugs.dr167"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#167">167</link>:
<emphasis>Improper use of traits_type::length()</emphasis>
</term>
<listitem><para><code>op&lt;&lt;</code> with a <code>const char*</code> was
calculating an incorrect number of characters to write.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#169">169</link>:
+ <varlistentry xml:id="manual.bugs.dr169"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#169">169</link>:
<emphasis>Bad efficiency of overflow() mandated</emphasis>
</term>
<listitem><para>Grow efficiently the internal array object.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#171">171</link>:
+ <varlistentry xml:id="manual.bugs.dr171"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#171">171</link>:
<emphasis>Strange seekpos() semantics due to joint position</emphasis>
</term>
<listitem><para>Quite complex to summarize...
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#181">181</link>:
+ <varlistentry xml:id="manual.bugs.dr181"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#181">181</link>:
<emphasis>make_pair() unintended behavior</emphasis>
</term>
<listitem><para>This function used to take its arguments as reference-to-const, now
it copies them (pass by value).
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#195">195</link>:
+ <varlistentry xml:id="manual.bugs.dr195"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#195">195</link>:
<emphasis>Should basic_istream::sentry's constructor ever set eofbit?</emphasis>
</term>
<listitem><para>Yes, it can, specifically if EOF is reached while skipping whitespace.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#211">211</link>:
+ <varlistentry xml:id="manual.bugs.dr211"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#211">211</link>:
<emphasis>operator&gt;&gt;(istream&amp;, string&amp;) doesn't set failbit</emphasis>
</term>
<listitem><para>If nothing is extracted into the string, <code>op&gt;&gt;</code> now
sets <code>failbit</code> (which can cause an exception, etc., etc.).
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#214">214</link>:
+ <varlistentry xml:id="manual.bugs.dr214"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#214">214</link>:
<emphasis>set::find() missing const overload</emphasis>
</term>
<listitem><para>Both <code>set</code> and <code>multiset</code> were missing
@@ -449,47 +451,47 @@ requirements of the license of GCC.
for const instances.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#231">231</link>:
+ <varlistentry xml:id="manual.bugs.dr231"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#231">231</link>:
<emphasis>Precision in iostream?</emphasis>
</term>
<listitem><para>For conversion from a floating-point type, <code>str.precision()</code>
is specified in the conversion specification.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#233">233</link>:
+ <varlistentry xml:id="manual.bugs.dr233"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#233">233</link>:
<emphasis>Insertion hints in associative containers</emphasis>
</term>
<listitem><para>Implement N1780, first check before then check after, insert as close
to hint as possible.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#235">235</link>:
+ <varlistentry xml:id="manual.bugs.dr235"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#235">235</link>:
<emphasis>No specification of default ctor for reverse_iterator</emphasis>
</term>
<listitem><para>The declaration of <code>reverse_iterator</code> lists a default constructor.
However, no specification is given what this constructor should do.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#241">241</link>:
+ <varlistentry xml:id="manual.bugs.dr241"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#241">241</link>:
<emphasis>Does unique_copy() require CopyConstructible and Assignable?</emphasis>
</term>
<listitem><para>Add a helper for forward_iterator/output_iterator, fix the existing
one for input_iterator/output_iterator to not rely on Assignability.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#243">243</link>:
+ <varlistentry xml:id="manual.bugs.dr243"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#243">243</link>:
<emphasis>get and getline when sentry reports failure</emphasis>
</term>
<listitem><para>Store a null character only if the character array has a non-zero size.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#251">251</link>:
+ <varlistentry xml:id="manual.bugs.dr251"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#251">251</link>:
<emphasis>basic_stringbuf missing allocator_type</emphasis>
</term>
<listitem><para>This nested typedef was originally not specified.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#253">253</link>:
+ <varlistentry xml:id="manual.bugs.dr253"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#253">253</link>:
<emphasis>valarray helper functions are almost entirely useless</emphasis>
</term>
<listitem><para>Make the copy constructor and copy-assignment operator declarations
@@ -497,60 +499,60 @@ requirements of the license of GCC.
definitions.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#265">265</link>:
+ <varlistentry xml:id="manual.bugs.dr265"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#265">265</link>:
<emphasis>std::pair::pair() effects overly restrictive</emphasis>
</term>
<listitem><para>The default ctor would build its members from copies of temporaries;
now it simply uses their respective default ctors.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#266">266</link>:
+ <varlistentry xml:id="manual.bugs.dr266"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#266">266</link>:
<emphasis>bad_exception::~bad_exception() missing Effects clause</emphasis>
</term>
<listitem><para>The <code>bad_</code>* classes no longer have destructors (they
are trivial), since no description of them was ever given.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#271">271</link>:
+ <varlistentry xml:id="manual.bugs.dr271"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#271">271</link>:
<emphasis>basic_iostream missing typedefs</emphasis>
</term>
<listitem><para>The typedefs it inherits from its base classes can't be used, since
(for example) <code>basic_iostream&lt;T&gt;::traits_type</code> is ambiguous.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#275">275</link>:
+ <varlistentry xml:id="manual.bugs.dr275"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#275">275</link>:
<emphasis>Wrong type in num_get::get() overloads</emphasis>
</term>
<listitem><para>Similar to 118.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#280">280</link>:
+ <varlistentry xml:id="manual.bugs.dr280"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#280">280</link>:
<emphasis>Comparison of reverse_iterator to const reverse_iterator</emphasis>
</term>
<listitem><para>Add global functions with two template parameters.
(NB: not added for now a templated assignment operator)
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#292">292</link>:
+ <varlistentry xml:id="manual.bugs.dr292"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#292">292</link>:
<emphasis>Effects of a.copyfmt (a)</emphasis>
</term>
<listitem><para>If <code>(this == &amp;rhs)</code> do nothing.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#300">300</link>:
+ <varlistentry xml:id="manual.bugs.dr300"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#300">300</link>:
<emphasis>List::merge() specification incomplete</emphasis>
</term>
<listitem><para>If <code>(this == &amp;x)</code> do nothing.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#303">303</link>:
+ <varlistentry xml:id="manual.bugs.dr303"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#303">303</link>:
<emphasis>Bitset input operator underspecified</emphasis>
</term>
<listitem><para>Basically, compare the input character to
<code>is.widen(0)</code> and <code>is.widen(1)</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#305">305</link>:
+ <varlistentry xml:id="manual.bugs.dr305"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#305">305</link>:
<emphasis>Default behavior of codecvt&lt;wchar_t, char,
mbstate_t&gt;::length()</emphasis>
</term>
@@ -558,20 +560,20 @@ requirements of the license of GCC.
mbstate_t&gt;::do_length</code> must return.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#328">328</link>:
+ <varlistentry xml:id="manual.bugs.dr328"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#328">328</link>:
<emphasis>Bad sprintf format modifier in
money_put&lt;&gt;::do_put()</emphasis>
</term>
<listitem><para>Change the format string to "%.0Lf".
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#365">365</link>:
+ <varlistentry xml:id="manual.bugs.dr365"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#365">365</link>:
<emphasis>Lack of const-qualification in clause 27</emphasis>
</term>
<listitem><para>Add const overloads of <code>is_open</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#387">387</link>:
+ <varlistentry xml:id="manual.bugs.dr387"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#387">387</link>:
<emphasis>std::complex over-encapsulated</emphasis>
</term>
<listitem><para>Add the <code>real(T)</code> and <code>imag(T)</code>
@@ -580,20 +582,20 @@ requirements of the license of GCC.
free functions.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#389">389</link>:
+ <varlistentry xml:id="manual.bugs.dr389"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#389">389</link>:
<emphasis>Const overload of valarray::operator[] returns
by value</emphasis>
</term>
<listitem><para>Change it to return a <code>const T&amp;</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#396">396</link>:
+ <varlistentry xml:id="manual.bugs.dr396"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#396">396</link>:
<emphasis>what are characters zero and one</emphasis>
</term>
<listitem><para>Implement the proposed resolution.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#402">402</link>:
+ <varlistentry xml:id="manual.bugs.dr402"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#402">402</link>:
<emphasis>Wrong new expression in [some_]allocator::construct</emphasis>
</term>
<listitem><para>Replace "new" with "::new".
@@ -607,7 +609,7 @@ requirements of the license of GCC.
<listitem><para>Tweak the debug-mode checks in _Safe_iterator.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#409">409</link>:
+ <varlistentry xml:id="manual.bugs.dr409"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#409">409</link>:
<emphasis>Closing an fstream should clear the error state</emphasis>
</term>
<listitem><para>Have <code>open</code> clear the error flags.
@@ -619,57 +621,57 @@ requirements of the license of GCC.
<listitem><para>Implement Option 3, as per N1599.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#432">432</link>:
+ <varlistentry xml:id="manual.bugs.dr432"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#432">432</link>:
<emphasis>stringbuf::overflow() makes only one write position
available</emphasis>
</term>
<listitem><para>Implement the resolution, beyond DR 169.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#434">434</link>:
+ <varlistentry xml:id="manual.bugs.dr434"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#434">434</link>:
<emphasis>bitset::to_string() hard to use</emphasis>
</term>
<listitem><para>Add three overloads, taking fewer template arguments.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#438">438</link>:
+ <varlistentry xml:id="manual.bugs.dr438"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#438">438</link>:
<emphasis>Ambiguity in the "do the right thing" clause</emphasis>
</term>
<listitem><para>Implement the resolution, basically cast less.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#445">445</link>:
+ <varlistentry xml:id="manual.bugs.dr445"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#445">445</link>:
<emphasis>iterator_traits::reference unspecified for some iterator categories</emphasis>
</term>
<listitem><para>Change <code>istreambuf_iterator::reference</code> in C++11 mode.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#453">453</link>:
+ <varlistentry xml:id="manual.bugs.dr453"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#453">453</link>:
<emphasis>basic_stringbuf::seekoff need not always fail for an empty stream</emphasis>
</term>
<listitem><para>Don't fail if the next pointer is null and newoff is zero.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#455">455</link>:
+ <varlistentry xml:id="manual.bugs.dr455"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#455">455</link>:
<emphasis>cerr::tie() and wcerr::tie() are overspecified</emphasis>
</term>
<listitem><para>Initialize cerr tied to cout and wcerr tied to wcout.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#464">464</link>:
+ <varlistentry xml:id="manual.bugs.dr464"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#464">464</link>:
<emphasis>Suggestion for new member functions in standard containers</emphasis>
</term>
<listitem><para>Add <code>data()</code> to <code>std::vector</code> and
<code>at(const key_type&amp;)</code> to <code>std::map</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#467">467</link>:
+ <varlistentry xml:id="manual.bugs.dr467"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#467">467</link>:
<emphasis>char_traits::lt(), compare(), and memcmp()</emphasis>
</term>
<listitem><para>Change <code>lt</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#508">508</link>:
+ <varlistentry xml:id="manual.bugs.dr508"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#508">508</link>:
<emphasis>Bad parameters for ranlux64_base_01</emphasis>
</term>
<listitem><para>Fix the parameters.
@@ -688,7 +690,7 @@ requirements of the license of GCC.
<listitem><para>Use &amp;value.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#538">538</link>:
+ <varlistentry xml:id="manual.bugs.dr538"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#538">538</link>:
<emphasis>241 again: Does unique_copy() require CopyConstructible
and Assignable?</emphasis>
</term>
@@ -696,7 +698,7 @@ requirements of the license of GCC.
input_iterator' value_type.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#539">539</link>:
+ <varlistentry xml:id="manual.bugs.dr539"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#539">539</link>:
<emphasis>partial_sum and adjacent_difference should mention
requirements</emphasis>
</term>
@@ -704,250 +706,250 @@ requirements of the license of GCC.
in adjacent_difference.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#541">541</link>:
+ <varlistentry xml:id="manual.bugs.dr541"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#541">541</link>:
<emphasis>shared_ptr template assignment and void</emphasis>
</term>
<listitem><para>Add an auto_ptr&lt;void&gt; specialization.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#543">543</link>:
+ <varlistentry xml:id="manual.bugs.dr543"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#543">543</link>:
<emphasis>valarray slice default constructor</emphasis>
</term>
<listitem><para>Follow the straightforward proposed resolution.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#550">550</link>:
+ <varlistentry xml:id="manual.bugs.dr550"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#550">550</link>:
<emphasis>What should the return type of pow(float,int) be?</emphasis>
</term>
<listitem><para>In C++11 mode, remove the pow(float,int), etc., signatures.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#586">586</link>:
+ <varlistentry xml:id="manual.bugs.dr586"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#586">586</link>:
<emphasis>string inserter not a formatted function</emphasis>
</term>
<listitem><para>Change it to be a formatted output function (i.e. catch exceptions).
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#596">596</link>:
+ <varlistentry xml:id="manual.bugs.dr596"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#596">596</link>:
<emphasis>27.8.1.3 Table 112 omits "a+" and "a+b" modes</emphasis>
</term>
<listitem><para>Add the missing modes to fopen_mode.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#630">630</link>:
+ <varlistentry xml:id="manual.bugs.dr630"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#630">630</link>:
<emphasis>arrays of valarray</emphasis>
</term>
<listitem><para>Implement the simple resolution.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#660">660</link>:
+ <varlistentry xml:id="manual.bugs.dr660"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#660">660</link>:
<emphasis>Missing bitwise operations</emphasis>
</term>
<listitem><para>Add the missing operations.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#691">691</link>:
+ <varlistentry xml:id="manual.bugs.dr691"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#691">691</link>:
<emphasis>const_local_iterator cbegin, cend missing from TR1</emphasis>
</term>
<listitem><para>In C++11 mode add cbegin(size_type) and cend(size_type)
to the unordered containers.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#693">693</link>:
+ <varlistentry xml:id="manual.bugs.dr693"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#693">693</link>:
<emphasis>std::bitset::all() missing</emphasis>
</term>
<listitem><para>Add it, consistently with the discussion.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#695">695</link>:
+ <varlistentry xml:id="manual.bugs.dr695"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#695">695</link>:
<emphasis>ctype&lt;char&gt;::classic_table() not accessible</emphasis>
</term>
<listitem><para>Make the member functions table and classic_table public.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#696">696</link>:
+ <varlistentry xml:id="manual.bugs.dr696"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#696">696</link>:
<emphasis>istream::operator&gt;&gt;(int&amp;) broken</emphasis>
</term>
<listitem><para>Implement the straightforward resolution.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#761">761</link>:
+ <varlistentry xml:id="manual.bugs.dr761"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#761">761</link>:
<emphasis>unordered_map needs an at() member function</emphasis>
</term>
<listitem><para>In C++11 mode, add at() and at() const.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#775">775</link>:
+ <varlistentry xml:id="manual.bugs.dr775"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#775">775</link>:
<emphasis>Tuple indexing should be unsigned?</emphasis>
</term>
<listitem><para>Implement the int -&gt; size_t replacements.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#776">776</link>:
+ <varlistentry xml:id="manual.bugs.dr776"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#776">776</link>:
<emphasis>Undescribed assign function of std::array</emphasis>
</term>
<listitem><para>In C++11 mode, remove assign, add fill.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#781">781</link>:
+ <varlistentry xml:id="manual.bugs.dr781"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#781">781</link>:
<emphasis>std::complex should add missing C99 functions</emphasis>
</term>
<listitem><para>In C++11 mode, add std::proj.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#809">809</link>:
+ <varlistentry xml:id="manual.bugs.dr809"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#809">809</link>:
<emphasis>std::swap should be overloaded for array types</emphasis>
</term>
<listitem><para>Add the overload.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#853">853</link>:
+ <varlistentry xml:id="manual.bugs.dr853"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#853">853</link>:
<emphasis>to_string needs updating with zero and one</emphasis>
</term>
<listitem><para>Update / add the signatures.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#865">865</link>:
+ <varlistentry xml:id="manual.bugs.dr865"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#865">865</link>:
<emphasis>More algorithms that throw away information</emphasis>
</term>
<listitem><para>The traditional HP / SGI return type and value is blessed
by the resolution of the DR.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#1339">1339</link>:
+ <varlistentry xml:id="manual.bugs.dr1339"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#1339">1339</link>:
<emphasis>uninitialized_fill_n should return the end of its range</emphasis>
</term>
<listitem><para>Return the end of the filled range.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2021">2021</link>:
+ <varlistentry xml:id="manual.bugs.dr2021"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2021">2021</link>:
<emphasis>Further incorrect uses of <code>result_of</code></emphasis>
</term>
<listitem><para>Correctly decay types in signature of <code>std::async</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2049">2049</link>:
+ <varlistentry xml:id="manual.bugs.dr2049"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2049">2049</link>:
<emphasis><code>is_destructible</code> underspecified</emphasis>
</term>
<listitem><para>Handle non-object types.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2056">2056</link>:
+ <varlistentry xml:id="manual.bugs.dr2056"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2056">2056</link>:
<emphasis>future_errc enums start with value 0 (invalid value for broken_promise)</emphasis>
</term>
<listitem><para>Reorder enumerators.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2059">2059</link>:
+ <varlistentry xml:id="manual.bugs.dr2059"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2059">2059</link>:
<emphasis>C++0x ambiguity problem with map::erase</emphasis>
</term>
<listitem><para>Add additional overloads.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2062">2062</link>:
+ <varlistentry xml:id="manual.bugs.dr2062"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2062">2062</link>:
<emphasis>2062. Effect contradictions w/o no-throw guarantee of <code>std::function</code> swaps</emphasis>
</term>
<listitem><para>Add <code>noexcept</code> to swap functions.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2063">2063</link>:
+ <varlistentry xml:id="manual.bugs.dr2063"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2063">2063</link>:
<emphasis>Contradictory requirements for string move assignment</emphasis>
</term>
<listitem><para>Respect propagation trait for move assignment.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2064">2064</link>:
+ <varlistentry xml:id="manual.bugs.dr2064"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2064">2064</link>:
<emphasis>More noexcept issues in basic_string</emphasis>
</term>
<listitem><para>Add noexcept to the comparison operators.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2067">2067</link>:
+ <varlistentry xml:id="manual.bugs.dr2067"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2067">2067</link>:
<emphasis>packaged_task should have deleted copy c'tor with const parameter</emphasis>
</term>
<listitem><para>Fix signatures.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2101">2101</link>:
+ <varlistentry xml:id="manual.bugs.dr2101"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2101">2101</link>:
<emphasis>Some transformation types can produce impossible types</emphasis>
</term>
<listitem><para>Use the referenceable type concept.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2106">2106</link>:
+ <varlistentry xml:id="manual.bugs.dr2106"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2106">2106</link>:
<emphasis>move_iterator wrapping iterators returning prvalues</emphasis>
</term>
<listitem><para>Change the <code>reference</code> type.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2108">2108</link>:
+ <varlistentry xml:id="manual.bugs.dr2108"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2108">2108</link>:
<emphasis>No way to identify allocator types that always compare equal</emphasis>
</term>
<listitem><para>Define and use <code>is_always_equal</code> even for C++11.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2118">2118</link>:
+ <varlistentry xml:id="manual.bugs.dr2118"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2118">2118</link>:
<emphasis><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis>
</term>
<listitem><para>Adjust constraints to allow safe conversions.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2127">2127</link>:
+ <varlistentry xml:id="manual.bugs.dr2127"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2127">2127</link>:
<emphasis>Move-construction with <code>raw_storage_iterator</code></emphasis>
</term>
<listitem><para>Add assignment operator taking an rvalue.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2132">2132</link>:
+ <varlistentry xml:id="manual.bugs.dr2132"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2132">2132</link>:
<emphasis><code>std::function</code> ambiguity</emphasis>
</term>
<listitem><para>Constrain the constructor to only accept callable types.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2141">2141</link>:
+ <varlistentry xml:id="manual.bugs.dr2141"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2141">2141</link>:
<emphasis><code>common_type</code> trait produces reference types</emphasis>
</term>
<listitem><para>Use <code>decay</code> for the result type.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2144">2144</link>:
+ <varlistentry xml:id="manual.bugs.dr2144"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2144">2144</link>:
<emphasis>Missing <code>noexcept</code> specification in <code>type_index</code></emphasis>
</term>
<listitem><para>Add <code>noexcept</code>
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2145">2145</link>:
+ <varlistentry xml:id="manual.bugs.dr2145"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2145">2145</link>:
<emphasis><code>error_category</code> default constructor</emphasis>
</term>
<listitem><para>Declare a public constexpr constructor.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2162">2162</link>:
+ <varlistentry xml:id="manual.bugs.dr2162"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2162">2162</link>:
<emphasis><code>allocator_traits::max_size</code> missing <code>noexcept</code></emphasis>
</term>
<listitem><para>Add <code>noexcept</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2187">2187</link>:
+ <varlistentry xml:id="manual.bugs.dr2187"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2187">2187</link>:
<emphasis><code>vector&lt;bool&gt;</code> is missing <code>emplace</code> and <code>emplace_back</code> member functions</emphasis>
</term>
<listitem><para>Add <code>emplace</code> and <code>emplace_back</code> member functions.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2192">2192</link>:
+ <varlistentry xml:id="manual.bugs.dr2192"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2192">2192</link>:
<emphasis>Validity and return type of <code>std::abs(0u)</code> is unclear</emphasis>
</term>
<listitem><para>Move all declarations to a common header and remove the
generic <code>abs</code> which accepted unsigned arguments.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2196">2196</link>:
+ <varlistentry xml:id="manual.bugs.dr2196"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2196">2196</link>:
<emphasis>Specification of <code>is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</emphasis>
</term>
<listitem><para>Use the referenceable type concept.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2212">2212</link>:
+ <varlistentry xml:id="manual.bugs.dr2212"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2212">2212</link>:
<emphasis><code>tuple_size</code> for <code>const pair</code> request <code>&lt;tuple&gt;</code> header</emphasis>
</term>
<listitem><para>The <code>tuple_size</code> and <code>tuple_element</code>
@@ -955,56 +957,56 @@ requirements of the license of GCC.
is included by <code>&lt;array&gt;</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2296">2296</link>:
+ <varlistentry xml:id="manual.bugs.dr2296"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2296">2296</link>:
<emphasis><code>std::addressof</code> should be constexpr</emphasis>
</term>
<listitem><para>Use <code>__builtin_addressof</code> and add
<code>constexpr</code> to <code>addressof</code> for C++17 and later.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2313">2313</link>:
+ <varlistentry xml:id="manual.bugs.dr2313"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2313">2313</link>:
<emphasis><code>tuple_size</code> should always derive from <code>integral_constant&lt;size_t, N&gt;</code></emphasis>
</term>
<listitem><para>Update definitions of the partial specializations for const and volatile types.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2328">2328</link>:
+ <varlistentry xml:id="manual.bugs.dr2328"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2328">2328</link>:
<emphasis>Rvalue stream extraction should use perfect forwarding</emphasis>
</term>
<listitem><para>Use perfect forwarding for right operand.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2329">2329</link>:
+ <varlistentry xml:id="manual.bugs.dr2329"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2329">2329</link>:
<emphasis><code>regex_match()/regex_search()</code> with <code>match_results</code> should forbid temporary strings</emphasis>
</term>
<listitem><para>Add deleted overloads for rvalue strings.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2332">2332</link>:
+ <varlistentry xml:id="manual.bugs.dr2332"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2332">2332</link>:
<emphasis><code>regex_iterator/regex_token_iterator</code> should forbid temporary regexes</emphasis>
</term>
<listitem><para>Add deleted constructors.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2399">2399</link>:
+ <varlistentry xml:id="manual.bugs.dr2399"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2399">2399</link>:
<emphasis><code>shared_ptr</code>'s constructor from <code>unique_ptr</code> should be constrained</emphasis>
</term>
<listitem><para>Constrain the constructor to require convertibility.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2400">2400</link>:
+ <varlistentry xml:id="manual.bugs.dr2400"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2400">2400</link>:
<emphasis><code>shared_ptr</code>'s <code>get_deleter()</code> should use <code>addressof()</code></emphasis>
</term>
<listitem><para>Use <code>addressof</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2401">2401</link>:
+ <varlistentry xml:id="manual.bugs.dr2401"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2401">2401</link>:
<emphasis><code>std::function</code> needs more <code>noexcept</code></emphasis>
</term>
<listitem><para>Add <code>noexcept</code> to the assignment and comparisons.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2407">2407</link>:
+ <varlistentry xml:id="manual.bugs.dr2407"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2407">2407</link>:
<emphasis><code>packaged_task(allocator_arg_t, const Allocator&amp;, F&amp;&amp;)</code>
should neither be constrained nor <code>explicit</code>
</emphasis>
@@ -1012,74 +1014,74 @@ requirements of the license of GCC.
<listitem><para>Remove <code>explicit</code> from the constructor.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2415">2415</link>:
+ <varlistentry xml:id="manual.bugs.dr2415"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2415">2415</link>:
<emphasis>Inconsistency between <code>unique_ptr</code> and <code>shared_ptr</code></emphasis>
</term>
<listitem><para>Create empty an <code>shared_ptr</code> from an empty
<code>unique_ptr</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2418">2418</link>:
+ <varlistentry xml:id="manual.bugs.dr2418"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2418">2418</link>:
<emphasis><code>apply</code> does not work with member pointers</emphasis>
</term>
<listitem><para>Use <code>mem_fn</code> for member pointers.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2440">2440</link>:
+ <varlistentry xml:id="manual.bugs.dr2440"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2440">2440</link>:
<emphasis><code>seed_seq::size()</code> should be <code>noexcept</code></emphasis>
</term>
<listitem><para>Add <code>noexcept</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2441">2441</link>:
+ <varlistentry xml:id="manual.bugs.dr2441"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2441">2441</link>:
<emphasis>Exact-width atomic typedefs should be provided</emphasis>
</term>
<listitem><para>Define the typedefs.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2442">2442</link>:
+ <varlistentry xml:id="manual.bugs.dr2442"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2442">2442</link>:
<emphasis><code>call_once()</code> shouldn't <code>DECAY_COPY()</code></emphasis>
</term>
<listitem><para>Remove indirection through call wrapper that made copies
of arguments and forward arguments straight to <code>std::invoke</code>.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2454">2454</link>:
+ <varlistentry xml:id="manual.bugs.dr2454"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2454">2454</link>:
<emphasis>Add <code>raw_storage_iterator::base()</code> member
</emphasis>
</term>
<listitem><para>Add the <code>base()</code> member function.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2455">2455</link>:
+ <varlistentry xml:id="manual.bugs.dr2455"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2455">2455</link>:
<emphasis>Allocator default construction should be allowed to throw
</emphasis>
</term>
<listitem><para>Make <code>noexcept</code> specifications conditional.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2458">2458</link>:
+ <varlistentry xml:id="manual.bugs.dr2458"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2458">2458</link>:
<emphasis>N3778 and new library deallocation signatures
</emphasis>
</term>
<listitem><para>Remove unused overloads.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2459">2459</link>:
+ <varlistentry xml:id="manual.bugs.dr2459"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2459">2459</link>:
<emphasis><code>std::polar</code> should require a non-negative rho
</emphasis>
</term>
<listitem><para>Add debug mode assertion.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2466">2466</link>:
+ <varlistentry xml:id="manual.bugs.dr2466"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2466">2466</link>:
<emphasis><code>allocator_traits::max_size()</code> default behavior is incorrect
</emphasis>
</term>
<listitem><para>Divide by the object type.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2484">2484</link>:
+ <varlistentry xml:id="manual.bugs.dr2484"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2484">2484</link>:
<emphasis><code>rethrow_if_nested()</code> is doubly unimplementable
</emphasis>
</term>
@@ -1087,21 +1089,21 @@ requirements of the license of GCC.
ill-formed.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2583">2583</link>:
+ <varlistentry xml:id="manual.bugs.dr2583"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2583">2583</link>:
<emphasis>There is no way to supply an allocator for <code>basic_string(str, pos)</code>
</emphasis>
</term>
<listitem><para>Add new constructor
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2684">2684</link>:
+ <varlistentry xml:id="manual.bugs.dr2684"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2684">2684</link>:
<emphasis><code>priority_queue</code> lacking comparator typedef
</emphasis>
</term>
<listitem><para>Define the <code>value_compare</code> typedef.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2770">2770</link>:
+ <varlistentry xml:id="manual.bugs.dr2770"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2770">2770</link>:
<emphasis><code>tuple_size&lt;const T&gt;</code> specialization is not
SFINAE compatible and breaks decomposition declarations
</emphasis>
@@ -1110,7 +1112,7 @@ requirements of the license of GCC.
only use it if valid.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2781">2781</link>:
+ <varlistentry xml:id="manual.bugs.dr2781"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2781">2781</link>:
<emphasis>Contradictory requirements for <code>std::function</code>
and <code>std::reference_wrapper</code>
</emphasis>
@@ -1119,7 +1121,7 @@ requirements of the license of GCC.
arguments and store them directly as the target object.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2802">2802</link>:
+ <varlistentry xml:id="manual.bugs.dr2802"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2802">2802</link>:
<emphasis>Add noexcept to several <code>shared_ptr</code> related
functions
</emphasis>
@@ -1127,14 +1129,14 @@ requirements of the license of GCC.
<listitem><para>Add noexcept.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2873">2873</link>:
+ <varlistentry xml:id="manual.bugs.dr2873"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2873">2873</link>:
<emphasis><code>shared_ptr</code> constructor requirements for a deleter
</emphasis>
</term>
<listitem><para>Use rvalues for deleters.
</para></listitem></varlistentry>
- <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2942">2942</link>:
+ <varlistentry xml:id="manual.bugs.dr2942"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2942">2942</link>:
<emphasis>LWG 2873's resolution missed
<code>weak_ptr::owner_before</code>
</emphasis>
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 5c0e1b9f8c1..6ce29fd30be 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -991,6 +991,24 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe
</listitem></varlistentry>
</variablelist>
+ <varlistentry><term><code>_GLIBCXX_SANITIZE_VECTOR</code></term>
+ <listitem>
+ <para>
+ Undefined by default. When defined, <classname>std::vector</classname>
+ operations will be annotated so that AddressSanitizer can detect
+ invalid accesses to the unused capacity of a
+ <classname>std::vector</classname>. These annotations are only
+ enabled for
+ <classname>std::vector&lt;T, std::allocator&lt;T&gt;&gt;</classname>
+ and only when <classname>std::allocator</classname> is derived from
+ <xref linkend="allocator.impl"><classname>new_allocator</classname>
+ or <classname>malloc_allocator</classname></xref>. The annotations
+ must be present on all vector operations or none, so this macro must
+ be defined to the same value for all translation units that create,
+ destroy or modify vectors.
+ </para>
+ </listitem></varlistentry>
+
</section>
<section xml:id="manual.intro.using.abi" xreflabel="Dual ABI">
diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h
index 3ff4ff71230..673b98e7867 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.h
@@ -615,8 +615,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_FIter
upper_bound(_FIter, _FIter, const _Tp&, _Compare);
-_GLIBCXX_END_NAMESPACE_VERSION
-
_GLIBCXX_BEGIN_NAMESPACE_ALGO
template<typename _FIter>
@@ -845,6 +843,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate);
_GLIBCXX_END_NAMESPACE_ALGO
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#ifdef _GLIBCXX_PARALLEL
diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h
index 318e41b7c55..f0b8682b4fe 100644
--- a/libstdc++-v3/include/bits/basic_ios.h
+++ b/libstdc++-v3/include/bits/basic_ios.h
@@ -157,8 +157,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
setstate(iostate __state)
{ this->clear(this->rdstate() | __state); }
- // Flip the internal state on for the proper state bits, then re
- // throws the propagated exception if bit also set in
+ // Flip the internal state on for the proper state bits, then
+ // rethrows the propagated exception if bit also set in
// exceptions().
void
_M_setstate(iostate __state)
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 519d686063e..a343d7b1628 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -2918,7 +2918,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
int
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const;
- };
+
+ // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
+ template<typename, typename, typename> friend class basic_stringbuf;
+ };
_GLIBCXX_END_NAMESPACE_CXX11
#else // !_GLIBCXX_USE_CXX11_ABI
// Reference-counted COW string implentation
@@ -6467,8 +6470,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
-
#if __cplusplus > 201103L
#define __cpp_lib_string_udls 201304
@@ -6477,8 +6478,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
{
inline namespace string_literals
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
_GLIBCXX_DEFAULT_ABI_TAG
inline basic_string<char>
operator""s(const char* __str, size_t __len)
@@ -6503,12 +6502,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return basic_string<char32_t>{__str, __len}; }
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
} // inline namespace string_literals
} // inline namespace literals
#endif // __cplusplus > 201103L
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 3e3905010f7..d5d1d24ee1a 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -267,88 +267,58 @@ namespace __gnu_cxx
# define _GLIBCXX_DEFAULT_ABI_TAG
#endif
-
// Defined if inline namespaces are used for versioning.
#define _GLIBCXX_INLINE_VERSION
// Inline namespace for symbol versioning.
#if _GLIBCXX_INLINE_VERSION
+# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 {
+# define _GLIBCXX_END_NAMESPACE_VERSION }
namespace std
{
- inline namespace __8 { }
-
- namespace rel_ops { inline namespace __8 { } }
-
- namespace tr1
- {
- inline namespace __8 { }
- namespace placeholders { inline namespace __8 { } }
- namespace regex_constants { inline namespace __8 { } }
- namespace __detail { inline namespace __8 { } }
- }
-
- namespace tr2
- { inline namespace __8 { } }
-
- namespace decimal { inline namespace __8 { } }
-
-#if __cplusplus >= 201103L
- namespace chrono { inline namespace __8 { } }
- namespace placeholders { inline namespace __8 { } }
- namespace regex_constants { inline namespace __8 { } }
- namespace this_thread { inline namespace __8 { } }
-
+inline _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201402L
inline namespace literals {
- inline namespace chrono_literals { inline namespace __8 { } }
- inline namespace complex_literals { inline namespace __8 { } }
- inline namespace string_literals { inline namespace __8 { } }
+ inline namespace chrono_literals { }
+ inline namespace complex_literals { }
+ inline namespace string_literals { }
#if __cplusplus > 201402L
- inline namespace string_view_literals { inline namespace __8 { } }
+ inline namespace string_view_literals { }
#endif // C++17
}
#endif // C++14
-#endif // C++11
-
- namespace __detail {
- inline namespace __8 { }
-#if __cplusplus > 201402L
- namespace __variant { inline namespace __8 { } }
-#endif
- }
+_GLIBCXX_END_NAMESPACE_VERSION
}
namespace __gnu_cxx
{
- inline namespace __8 { }
- namespace __detail { inline namespace __8 { } }
+inline _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_END_NAMESPACE_VERSION
}
-# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 {
-# define _GLIBCXX_END_NAMESPACE_VERSION }
+
#else
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_END_NAMESPACE_VERSION
#endif
-
// Inline namespaces for special modes: debug, parallel, profile.
#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) \
|| defined(_GLIBCXX_PROFILE)
namespace std
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
// Non-inline namespace for components replaced by alternates in active mode.
namespace __cxx1998
{
-# if _GLIBCXX_INLINE_VERSION
- inline namespace __8 { }
-# endif
-
# if _GLIBCXX_USE_CXX11_ABI
inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
# endif
}
+_GLIBCXX_END_NAMESPACE_VERSION
+
// Inline namespace for debug mode.
# ifdef _GLIBCXX_DEBUG
inline namespace __debug { }
@@ -396,25 +366,23 @@ namespace std
#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PROFILE)
# define _GLIBCXX_STD_C __cxx1998
# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \
- namespace _GLIBCXX_STD_C { _GLIBCXX_BEGIN_NAMESPACE_VERSION
-# define _GLIBCXX_END_NAMESPACE_CONTAINER \
- _GLIBCXX_END_NAMESPACE_VERSION }
+ namespace _GLIBCXX_STD_C {
+# define _GLIBCXX_END_NAMESPACE_CONTAINER }
#else
# define _GLIBCXX_STD_C std
-# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_VERSION
-# define _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_VERSION
+# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+# define _GLIBCXX_END_NAMESPACE_CONTAINER
#endif
#ifdef _GLIBCXX_PARALLEL
# define _GLIBCXX_STD_A __cxx1998
# define _GLIBCXX_BEGIN_NAMESPACE_ALGO \
- namespace _GLIBCXX_STD_A { _GLIBCXX_BEGIN_NAMESPACE_VERSION
-# define _GLIBCXX_END_NAMESPACE_ALGO \
- _GLIBCXX_END_NAMESPACE_VERSION }
+ namespace _GLIBCXX_STD_A {
+# define _GLIBCXX_END_NAMESPACE_ALGO }
#else
# define _GLIBCXX_STD_A std
-# define _GLIBCXX_BEGIN_NAMESPACE_ALGO _GLIBCXX_BEGIN_NAMESPACE_VERSION
-# define _GLIBCXX_END_NAMESPACE_ALGO _GLIBCXX_END_NAMESPACE_VERSION
+# define _GLIBCXX_BEGIN_NAMESPACE_ALGO
+# define _GLIBCXX_END_NAMESPACE_ALGO
#endif
// GLIBCXX_ABI Deprecated
diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index 38a6e82aaef..d25ad690178 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -58,6 +58,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
@@ -1107,6 +1108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index f319b7f0607..9d86fcc1568 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -43,6 +43,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
@@ -1440,6 +1441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __lx.swap(__ly); }
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _FORWARD_LIST_H
diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc
index b823b09e1af..64bd9c4bf13 100644
--- a/libstdc++-v3/include/bits/forward_list.tcc
+++ b/libstdc++-v3/include/bits/forward_list.tcc
@@ -32,6 +32,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
@@ -493,6 +494,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _FORWARD_LIST_TCC */
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index b1beff86ab5..12ea977b997 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -649,11 +649,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else if (_M_writing)
{
- if (overflow() == traits_type::eof())
- return __ret;
- _M_set_buffer(-1);
- _M_writing = false;
- }
+ if (overflow() == traits_type::eof())
+ return __ret;
+ _M_set_buffer(-1);
+ _M_writing = false;
+ }
// Optimization in the always_noconv() case, to be generalized in the
// future: when __n > __buflen we read directly instead of using the
@@ -662,57 +662,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
- && __testin)
- {
- // First, copy the chars already present in the buffer.
- const streamsize __avail = this->egptr() - this->gptr();
- if (__avail != 0)
- {
- traits_type::copy(__s, this->gptr(), __avail);
- __s += __avail;
- this->setg(this->eback(), this->gptr() + __avail,
- this->egptr());
- __ret += __avail;
- __n -= __avail;
- }
-
- // Need to loop in case of short reads (relatively common
- // with pipes).
- streamsize __len;
- for (;;)
- {
- __len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
- __n);
- if (__len == -1)
- __throw_ios_failure(__N("basic_filebuf::xsgetn "
- "error reading the file"));
- if (__len == 0)
- break;
-
- __n -= __len;
- __ret += __len;
- if (__n == 0)
- break;
+ && __testin)
+ {
+ // First, copy the chars already present in the buffer.
+ const streamsize __avail = this->egptr() - this->gptr();
+ if (__avail != 0)
+ {
+ traits_type::copy(__s, this->gptr(), __avail);
+ __s += __avail;
+ this->setg(this->eback(), this->gptr() + __avail, this->egptr());
+ __ret += __avail;
+ __n -= __avail;
+ }
- __s += __len;
- }
+ // Need to loop in case of short reads (relatively common
+ // with pipes).
+ streamsize __len;
+ for (;;)
+ {
+ __len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n);
+ if (__len == -1)
+ __throw_ios_failure(__N("basic_filebuf::xsgetn "
+ "error reading the file"));
+ if (__len == 0)
+ break;
- if (__n == 0)
- {
- _M_set_buffer(0);
- _M_reading = true;
- }
- else if (__len == 0)
- {
- // If end of file is reached, set 'uncommitted'
- // mode, thus allowing an immediate write without
- // an intervening seek.
- _M_set_buffer(-1);
- _M_reading = false;
- }
- }
+ __n -= __len;
+ __ret += __len;
+ if (__n == 0)
+ break;
+
+ __s += __len;
+ }
+
+ if (__n == 0)
+ {
+ // Set _M_reading. Buffer is already in initial 'read' mode.
+ _M_reading = true;
+ }
+ else if (__len == 0)
+ {
+ // If end of file is reached, set 'uncommitted'
+ // mode, thus allowing an immediate write without
+ // an intervening seek.
+ _M_set_buffer(-1);
+ _M_reading = false;
+ }
+ }
else
- __ret += __streambuf_type::xsgetn(__s, __n);
+ __ret += __streambuf_type::xsgetn(__s, __n);
return __ret;
}
@@ -729,7 +727,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const bool __testout = (_M_mode & ios_base::out
|| _M_mode & ios_base::app);
if (__check_facet(_M_codecvt).always_noconv()
- && __testout && !_M_reading)
+ && __testout && !_M_reading)
{
// Measurement would reveal the best choice.
const streamsize __chunk = 1ul << 10;
@@ -839,8 +837,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_writing)
__computed_off = this->pptr() - this->pbase();
- off_type __file_off = _M_file.seekoff(0, ios_base::cur);
- if (__file_off != off_type(-1))
+ off_type __file_off = _M_file.seekoff(0, ios_base::cur);
+ if (__file_off != off_type(-1))
{
__ret = __file_off + __computed_off;
__ret.state(__state);
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 8af8c498de2..a3a31d1fb11 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -43,12 +43,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _RehashPolicy, typename _Traits>
class _Hashtable;
-_GLIBCXX_END_NAMESPACE_VERSION
-
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @defgroup hashtable-detail Base and Implementation Classes
* @ingroup unordered_associative_containers
@@ -2122,8 +2118,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
//@} hashtable-detail
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _HASHTABLE_POLICY_H
diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h
index e5a107db4bc..e68b4305517 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -469,13 +469,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Request a seek relative to the current end of the sequence.
static const seekdir end = _S_end;
- // Annex D.6
+#if __cplusplus <= 201402L
+ // Annex D.6 (removed in C++17)
typedef int io_state;
typedef int open_mode;
typedef int seek_dir;
typedef std::streampos streampos;
typedef std::streamoff streamoff;
+#endif
// Callbacks;
/**
diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc
index b390f743bba..92df9d126ef 100644
--- a/libstdc++-v3/include/bits/istream.tcc
+++ b/libstdc++-v3/include/bits/istream.tcc
@@ -48,28 +48,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
ios_base::iostate __err = ios_base::goodbit;
if (__in.good())
- {
- if (__in.tie())
- __in.tie()->flush();
- if (!__noskip && bool(__in.flags() & ios_base::skipws))
- {
- const __int_type __eof = traits_type::eof();
- __streambuf_type* __sb = __in.rdbuf();
- __int_type __c = __sb->sgetc();
-
- const __ctype_type& __ct = __check_facet(__in._M_ctype);
- while (!traits_type::eq_int_type(__c, __eof)
- && __ct.is(ctype_base::space,
- traits_type::to_char_type(__c)))
- __c = __sb->snextc();
+ __try
+ {
+ if (__in.tie())
+ __in.tie()->flush();
+ if (!__noskip && bool(__in.flags() & ios_base::skipws))
+ {
+ const __int_type __eof = traits_type::eof();
+ __streambuf_type* __sb = __in.rdbuf();
+ __int_type __c = __sb->sgetc();
+
+ const __ctype_type& __ct = __check_facet(__in._M_ctype);
+ while (!traits_type::eq_int_type(__c, __eof)
+ && __ct.is(ctype_base::space,
+ traits_type::to_char_type(__c)))
+ __c = __sb->snextc();
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 195. Should basic_istream::sentry's constructor ever
- // set eofbit?
- if (traits_type::eq_int_type(__c, __eof))
- __err |= ios_base::eofbit;
- }
- }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 195. Should basic_istream::sentry's constructor ever
+ // set eofbit?
+ if (traits_type::eq_int_type(__c, __eof))
+ __err |= ios_base::eofbit;
+ }
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __in._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __in._M_setstate(ios_base::badbit); }
if (__in.good() && __err == ios_base::goodbit)
_M_ok = true;
diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc
index fcb8353e09f..e21dab54263 100644
--- a/libstdc++-v3/include/bits/list.tcc
+++ b/libstdc++-v3/include/bits/list.tcc
@@ -58,6 +58,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
@@ -594,6 +595,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _LIST_TCC */
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 1ad0eb5ab66..9a74677b393 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -1487,7 +1487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
protected:
virtual
- ~ctype_byname() { };
+ ~ctype_byname() { }
};
/// 22.2.1.4 Class ctype_byname specializations.
@@ -2486,7 +2486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
/// Destructor.
virtual
- ~num_put() { };
+ ~num_put() { }
//@{
/**
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h
index 0cd307fb5ed..0068cd3addd 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.h
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.h
@@ -898,7 +898,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
explicit
time_put_byname(const char*, size_t __refs = 0)
: time_put<_CharT, _OutIter>(__refs)
- { };
+ { }
#if __cplusplus >= 201103L
explicit
diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index 5f47b0e7bae..373f9556524 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -47,10 +47,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{ return __builtin_addressof(__r); }
+#if __cplusplus >= 201103L
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
-#if __cplusplus >= 201103L
#include <type_traits> // Brings in std::declval too.
namespace std _GLIBCXX_VISIBILITY(default)
@@ -153,8 +154,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// @} group utilities
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
#define _GLIBCXX_MOVE(__val) std::move(__val)
#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
@@ -163,10 +162,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_FORWARD(_Tp, __val) (__val)
#endif
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @addtogroup utilities
* @{
diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h
index 10cfec21181..0e51c223433 100644
--- a/libstdc++-v3/include/bits/quoted_string.h
+++ b/libstdc++-v3/include/bits/quoted_string.h
@@ -39,9 +39,9 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
- namespace __detail {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ namespace __detail {
/**
* @brief Struct for delimited strings.
*/
@@ -155,9 +155,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
return __is;
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index bb761ec8fb0..2b022b2f469 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -58,15 +58,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RealType
generate_canonical(_UniformRandomNumberGenerator& __g);
-_GLIBCXX_END_NAMESPACE_VERSION
-
/*
* Implementation-space details.
*/
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _UIntType, size_t __w,
bool = __w < static_cast<size_t>
(std::numeric_limits<_UIntType>::digits)>
@@ -189,11 +185,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
_Engine& _M_g;
};
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @addtogroup random_generators Random Number Generators
* @ingroup random
@@ -520,7 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
static constexpr result_type
min()
- { return 0; };
+ { return 0; }
/**
* @brief Gets the largest possible value in the output range.
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 63d1c020285..95bcf0a163e 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -34,13 +34,13 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/*
* (Further) implementation-space details.
*/
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// General case for x = (ax + c) mod m -- use Schrage's algorithm
// to avoid integer overflow.
//
@@ -89,11 +89,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
return __result;
}
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
constexpr _UIntType
linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier;
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index 0bb88cb6afb..32e7159eec9 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -39,12 +39,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
class match_results;
_GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_END_NAMESPACE_VERSION
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
enum class _RegexExecutorPolicy : int
{ _S_auto, _S_alternate };
@@ -53,19 +50,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RegexExecutorPolicy __policy,
bool __match_mode>
bool
- __regex_algo_impl(_BiIter __s,
- _BiIter __e,
+ __regex_algo_impl(_BiIter __s,
+ _BiIter __e,
match_results<_BiIter, _Alloc>& __m,
const basic_regex<_CharT, _TraitsT>& __re,
regex_constants::match_flag_type __flags);
template<typename, typename, typename, bool>
class _Executor;
-
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CXX11
/**
@@ -87,9 +81,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
struct regex_traits
{
public:
- typedef _Ch_type char_type;
- typedef std::basic_string<char_type> string_type;
- typedef std::locale locale_type;
+ typedef _Ch_type char_type;
+ typedef std::basic_string<char_type> string_type;
+ typedef std::locale locale_type;
private:
struct _RegexMask
{
@@ -397,8 +391,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
"regex traits class must have the same char_type");
// types:
- typedef _Ch_type value_type;
- typedef _Rx_traits traits_type;
+ typedef _Ch_type value_type;
+ typedef _Rx_traits traits_type;
typedef typename traits_type::string_type string_type;
typedef regex_constants::syntax_option_type flag_type;
typedef typename traits_type::locale_type locale_type;
@@ -771,20 +765,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
__detail::_RegexExecutorPolicy, bool>
- friend bool __detail::
-#if _GLIBCXX_INLINE_VERSION
- __8:: // Required due to PR c++/59256
-#endif
- __regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
- const basic_regex<_Cp, _Rp>&,
- regex_constants::match_flag_type);
+ friend bool
+ __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
+ const basic_regex<_Cp, _Rp>&,
+ regex_constants::match_flag_type);
template<typename, typename, typename, bool>
friend class __detail::_Executor;
- flag_type _M_flags;
- locale_type _M_loc;
- _AutomatonPtr _M_automaton;
+ flag_type _M_flags;
+ locale_type _M_loc;
+ _AutomatonPtr _M_automaton;
};
#if __cpp_deduction_guides >= 201606
@@ -837,8 +828,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
public:
typedef typename __iter_traits::value_type value_type;
typedef typename __iter_traits::difference_type difference_type;
- typedef _BiIter iterator;
- typedef std::basic_string<value_type> string_type;
+ typedef _BiIter iterator;
+ typedef std::basic_string<value_type> string_type;
bool matched;
@@ -923,14 +914,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/** @brief Standard regex submatch over a C-style null-terminated string. */
- typedef sub_match<const char*> csub_match;
+ typedef sub_match<const char*> csub_match;
/** @brief Standard regex submatch over a standard string. */
typedef sub_match<string::const_iterator> ssub_match;
#ifdef _GLIBCXX_USE_WCHAR_T
/** @brief Regex submatch over a C-style null-terminated wide string. */
- typedef sub_match<const wchar_t*> wcsub_match;
+ typedef sub_match<const wchar_t*> wcsub_match;
/** @brief Regex submatch over a standard wide string. */
typedef sub_match<wstring::const_iterator> wssub_match;
@@ -1548,16 +1539,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @name 10.? Public Types
*/
//@{
- typedef sub_match<_Bi_iter> value_type;
- typedef const value_type& const_reference;
- typedef const_reference reference;
- typedef typename _Base_type::const_iterator const_iterator;
- typedef const_iterator iterator;
+ typedef sub_match<_Bi_iter> value_type;
+ typedef const value_type& const_reference;
+ typedef const_reference reference;
+ typedef typename _Base_type::const_iterator const_iterator;
+ typedef const_iterator iterator;
typedef typename __iter_traits::difference_type difference_type;
typedef typename allocator_traits<_Alloc>::size_type size_type;
- typedef _Alloc allocator_type;
+ typedef _Alloc allocator_type;
typedef typename __iter_traits::value_type char_type;
- typedef std::basic_string<char_type> string_type;
+ typedef std::basic_string<char_type> string_type;
//@}
public:
@@ -1872,13 +1863,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
__detail::_RegexExecutorPolicy, bool>
- friend bool __detail::
-#if _GLIBCXX_INLINE_VERSION
- __8:: // Required due to PR c++/59256
-#endif
- __regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
- const basic_regex<_Cp, _Rp>&,
- regex_constants::match_flag_type);
+ friend bool
+ __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
+ const basic_regex<_Cp, _Rp>&,
+ regex_constants::match_flag_type);
void
_M_resize(unsigned int __size)
@@ -1911,10 +1899,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_Bi_iter _M_begin;
};
- typedef match_results<const char*> cmatch;
- typedef match_results<string::const_iterator> smatch;
+ typedef match_results<const char*> cmatch;
+ typedef match_results<string::const_iterator> smatch;
#ifdef _GLIBCXX_USE_WCHAR_T
- typedef match_results<const wchar_t*> wcmatch;
+ typedef match_results<const wchar_t*> wcmatch;
typedef match_results<wstring::const_iterator> wsmatch;
#endif
@@ -1994,11 +1982,11 @@ _GLIBCXX_END_NAMESPACE_CXX11
template<typename _Bi_iter, typename _Alloc,
typename _Ch_type, typename _Rx_traits>
inline bool
- regex_match(_Bi_iter __s,
- _Bi_iter __e,
- match_results<_Bi_iter, _Alloc>& __m,
+ regex_match(_Bi_iter __s,
+ _Bi_iter __e,
+ match_results<_Bi_iter, _Alloc>& __m,
const basic_regex<_Ch_type, _Rx_traits>& __re,
- regex_constants::match_flag_type __flags
+ regex_constants::match_flag_type __flags
= regex_constants::match_default)
{
return __detail::__regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
@@ -2452,11 +2440,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
public:
typedef basic_regex<_Ch_type, _Rx_traits> regex_type;
- typedef match_results<_Bi_iter> value_type;
- typedef std::ptrdiff_t difference_type;
- typedef const value_type* pointer;
- typedef const value_type& reference;
- typedef std::forward_iterator_tag iterator_category;
+ typedef match_results<_Bi_iter> value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef const value_type* pointer;
+ typedef const value_type& reference;
+ typedef std::forward_iterator_tag iterator_category;
/**
* @brief Provides a singular iterator, useful for indicating
@@ -2543,18 +2531,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
private:
- _Bi_iter _M_begin;
- _Bi_iter _M_end;
- const regex_type* _M_pregex;
- regex_constants::match_flag_type _M_flags;
- match_results<_Bi_iter> _M_match;
+ _Bi_iter _M_begin;
+ _Bi_iter _M_end;
+ const regex_type* _M_pregex;
+ regex_constants::match_flag_type _M_flags;
+ match_results<_Bi_iter> _M_match;
};
- typedef regex_iterator<const char*> cregex_iterator;
- typedef regex_iterator<string::const_iterator> sregex_iterator;
+ typedef regex_iterator<const char*> cregex_iterator;
+ typedef regex_iterator<string::const_iterator> sregex_iterator;
#ifdef _GLIBCXX_USE_WCHAR_T
- typedef regex_iterator<const wchar_t*> wcregex_iterator;
- typedef regex_iterator<wstring::const_iterator> wsregex_iterator;
+ typedef regex_iterator<const wchar_t*> wcregex_iterator;
+ typedef regex_iterator<wstring::const_iterator> wsregex_iterator;
#endif
// [7.12.2] Class template regex_token_iterator
@@ -2571,12 +2559,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
class regex_token_iterator
{
public:
- typedef basic_regex<_Ch_type, _Rx_traits> regex_type;
- typedef sub_match<_Bi_iter> value_type;
- typedef std::ptrdiff_t difference_type;
- typedef const value_type* pointer;
- typedef const value_type& reference;
- typedef std::forward_iterator_tag iterator_category;
+ typedef basic_regex<_Ch_type, _Rx_traits> regex_type;
+ typedef sub_match<_Bi_iter> value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef const value_type* pointer;
+ typedef const value_type& reference;
+ typedef std::forward_iterator_tag iterator_category;
public:
/**
@@ -2778,25 +2766,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_result = nullptr;
}
- _Position _M_position;
- std::vector<int> _M_subs;
- value_type _M_suffix;
- std::size_t _M_n;
- const value_type* _M_result;
+ _Position _M_position;
+ std::vector<int> _M_subs;
+ value_type _M_suffix;
+ std::size_t _M_n;
+ const value_type* _M_result;
// Show whether _M_subs contains -1
- bool _M_has_m1;
+ bool _M_has_m1;
};
/** @brief Token iterator for C-style NULL-terminated strings. */
- typedef regex_token_iterator<const char*> cregex_token_iterator;
+ typedef regex_token_iterator<const char*> cregex_token_iterator;
/** @brief Token iterator for standard strings. */
- typedef regex_token_iterator<string::const_iterator> sregex_token_iterator;
+ typedef regex_token_iterator<string::const_iterator> sregex_token_iterator;
#ifdef _GLIBCXX_USE_WCHAR_T
/** @brief Token iterator for C-style NULL-terminated wide strings. */
- typedef regex_token_iterator<const wchar_t*> wcregex_token_iterator;
+ typedef regex_token_iterator<const wchar_t*> wcregex_token_iterator;
/** @brief Token iterator for standard wide-character strings. */
typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator;
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index dc32a49dcd9..fc2d5846c46 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -30,10 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
// Result of merging regex_match and regex_search.
//
// __policy now can be _S_auto (auto dispatch) and _S_alternate (use
@@ -118,12 +118,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return __ret;
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Ch_type>
template<typename _Fwd_iter>
typename regex_traits<_Ch_type>::string_type
@@ -663,4 +659,3 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
-
diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h
index a5fab6356cc..00d1bd295cd 100644
--- a/libstdc++-v3/include/bits/regex_automaton.h
+++ b/libstdc++-v3/include/bits/regex_automaton.h
@@ -35,10 +35,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
/**
* @defgroup regex-detail Base and Implementation Classes
* @ingroup regex
@@ -393,8 +393,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
//@} regex-detail
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <bits/regex_automaton.tcc>
diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc
index 727bde1f6c6..573b059a251 100644
--- a/libstdc++-v3/include/bits/regex_automaton.tcc
+++ b/libstdc++-v3/include/bits/regex_automaton.tcc
@@ -30,10 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
#ifdef _GLIBCXX_DEBUG
inline std::ostream&
_State_base::_M_print(std::ostream& ostr) const
@@ -233,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return _StateSeq(_M_nfa, __m[_M_start], __m[_M_end]);
}
+} // namespace __detail
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace __detail
} // namespace
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index 2c00939f6f9..5d46cd43bd3 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -37,12 +37,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
class regex_traits;
_GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_END_NAMESPACE_VERSION
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @addtogroup regex-detail
* @{
@@ -575,8 +572,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
//@} regex-detail
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <bits/regex_compiler.tcc>
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index a6d8016d87f..1f7dd91b643 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -55,10 +55,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
template<typename _TraitsT>
_Compiler<_TraitsT>::
_Compiler(_IterT __b, _IterT __e,
@@ -633,7 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}() ^ _M_is_non_matching;
}
+} // namespace __detail
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace __detail
} // namespace
diff --git a/libstdc++-v3/include/bits/regex_constants.h b/libstdc++-v3/include/bits/regex_constants.h
index dad2d637aa8..12c9eea4985 100644
--- a/libstdc++-v3/include/bits/regex_constants.h
+++ b/libstdc++-v3/include/bits/regex_constants.h
@@ -32,6 +32,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/**
* @defgroup regex Regular Expressions
*
@@ -45,8 +47,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
*/
namespace regex_constants
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @name 5.1 Regular Expression Syntax Options
*/
@@ -408,10 +408,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __a = __a ^ __b; }
//@}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace regex_constants
-
/* @} */ // group regex
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h
index 55f6db9cf7a..f2a3389e984 100644
--- a/libstdc++-v3/include/bits/regex_error.h
+++ b/libstdc++-v3/include/bits/regex_error.h
@@ -32,6 +32,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/**
* @addtogroup regex
* @{
@@ -39,8 +41,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
namespace regex_constants
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @name 5.3 Error Types
*/
@@ -120,11 +120,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr error_type error_stack(_S_error_stack);
//@}
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace regex_constants
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// [7.8] Class regex_error
/**
* @brief A regular expression exception class.
diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h
index 61054742870..3d1f2516f50 100644
--- a/libstdc++-v3/include/bits/regex_executor.h
+++ b/libstdc++-v3/include/bits/regex_executor.h
@@ -32,10 +32,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
/**
* @addtogroup regex-detail
* @{
@@ -251,8 +251,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
//@} regex-detail
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <bits/regex_executor.tcc>
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index 9d4ece74416..226e05856e1 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -30,10 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
template<typename _BiIter, typename _Alloc, typename _TraitsT,
bool __dfs_mode>
bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
@@ -513,7 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __left_is_word != __right_is_word;
}
+} // namespace __detail
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace __detail
} // namespace
diff --git a/libstdc++-v3/include/bits/regex_scanner.h b/libstdc++-v3/include/bits/regex_scanner.h
index 37ad862a669..670efeda69f 100644
--- a/libstdc++-v3/include/bits/regex_scanner.h
+++ b/libstdc++-v3/include/bits/regex_scanner.h
@@ -30,10 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
/**
* @addtogroup regex-detail
* @{
@@ -265,8 +265,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
//@} regex-detail
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <bits/regex_scanner.tcc>
diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc
index ad0b0477f3c..c65bfe2f68d 100644
--- a/libstdc++-v3/include/bits/regex_scanner.tcc
+++ b/libstdc++-v3/include/bits/regex_scanner.tcc
@@ -48,10 +48,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
template<typename _CharT>
_Scanner<_CharT>::
_Scanner(typename _Scanner::_IterT __begin,
@@ -584,6 +584,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/specfun.h b/libstdc++-v3/include/bits/specfun.h
index 82bd02e227a..0aaebeab7ac 100644
--- a/libstdc++-v3/include/bits/specfun.h
+++ b/libstdc++-v3/include/bits/specfun.h
@@ -1203,6 +1203,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Confluent hypergeometric functions
@@ -1302,6 +1303,7 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
return std::__detail::__hyperg<__type>(__a, __b, __c, __x);
}
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __gnu_cxx
#pragma GCC visibility pop
diff --git a/libstdc++-v3/include/bits/sstream.tcc b/libstdc++-v3/include/bits/sstream.tcc
index 72e8742b4cf..56c53bc5923 100644
--- a/libstdc++-v3/include/bits/sstream.tcc
+++ b/libstdc++-v3/include/bits/sstream.tcc
@@ -88,6 +88,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return traits_type::not_eof(__c);
const __size_type __capacity = _M_string.capacity();
+
+#if _GLIBCXX_USE_CXX11_ABI
+ if ((this->epptr() - this->pbase()) < __capacity)
+ {
+ // There is additional capacity in _M_string that can be used.
+ char_type* __base = const_cast<char_type*>(_M_string.data());
+ _M_pbump(__base, __base + __capacity, this->pptr() - this->pbase());
+ if (_M_mode & ios_base::in)
+ {
+ const __size_type __nget = this->gptr() - this->eback();
+ const __size_type __eget = this->egptr() - this->eback();
+ this->setg(__base, __base + __nget, __base + __eget + 1);
+ }
+ *this->pptr() = traits_type::to_char_type(__c);
+ this->pbump(1);
+ return __c;
+ }
+#endif
+
const __size_type __max_size = _M_string.max_size();
const bool __testput = this->pptr() < this->epptr();
if (__builtin_expect(!__testput && __capacity == __max_size, false))
@@ -110,7 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __size_type __opt_len = std::max(__size_type(2 * __capacity),
__size_type(512));
const __size_type __len = std::min(__opt_len, __max_size);
- __string_type __tmp;
+ __string_type __tmp(_M_string.get_allocator());
__tmp.reserve(__len);
if (this->pbase())
__tmp.assign(this->pbase(), this->epptr() - this->pbase());
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 246193f38c7..ea413b1b155 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -3857,8 +3857,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // C++11
-_GLIBCXX_END_NAMESPACE_VERSION
-
_GLIBCXX_BEGIN_NAMESPACE_ALGO
/**
@@ -5831,13 +5829,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
"sample size must be an integer type");
typename iterator_traits<_PopulationIterator>::difference_type __d = __n;
- return std::__sample(__first, __last, __pop_cat{}, __out, __samp_cat{},
- __d, std::forward<_UniformRandomBitGenerator>(__g));
+ return _GLIBCXX_STD_A::
+ __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d,
+ std::forward<_UniformRandomBitGenerator>(__g));
}
#endif // C++17
#endif // C++14
_GLIBCXX_END_NAMESPACE_ALGO
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_ALGO_H */
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 0a49e6ff66c..f68ecb22b82 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1020,8 +1020,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__lg(unsigned long long __n)
{ return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); }
-_GLIBCXX_END_NAMESPACE_VERSION
-
_GLIBCXX_BEGIN_NAMESPACE_ALGO
/**
@@ -1411,6 +1409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
#endif
_GLIBCXX_END_NAMESPACE_ALGO
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
// NB: This file is included within many other C++ includes, as a way
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index bf4b23eb2d3..d24e760d01b 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -62,6 +62,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef unsigned long _Bit_type;
@@ -552,6 +553,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
};
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
// Declare a partial specialization of vector<T, Alloc>.
@@ -559,6 +561,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
@@ -1305,6 +1308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
};
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index e03e7f5808f..48b2bc7f5eb 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -67,6 +67,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
@@ -2325,6 +2326,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#undef _GLIBCXX_DEQUE_BUF_SIZE
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_DEQUE_H */
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 18c6e3f625e..88667a568c3 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -984,15 +984,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it)
{ return __it.base(); }
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
#if __cplusplus >= 201103L
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @addtogroup iterators
* @{
@@ -1243,9 +1236,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
-> decltype(__miter_base(__it.base()))
{ return __miter_base(__it.base()); }
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter)
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \
std::__make_move_if_noexcept_iterator(_Iter)
@@ -1254,6 +1244,9 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
#endif // C++11
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
#ifdef _GLIBCXX_DEBUG
# include <debug/stl_iterator.h>
#endif
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
index e14a22ce255..86a93d34fa1 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
@@ -66,14 +66,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Forward declaration for the overloads of __distance.
template <typename> struct _List_iterator;
template <typename> struct _List_const_iterator;
_GLIBCXX_END_NAMESPACE_CONTAINER
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _InputIterator>
inline _GLIBCXX14_CONSTEXPR
typename iterator_traits<_InputIterator>::difference_type
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 232885af79d..cef94f728ef 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -66,10 +66,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// Supporting structures are split into common and templated
// types; the latter publicly inherits from the former in an
// effort to reduce code duplication. This results in some
@@ -99,7 +99,64 @@ namespace std _GLIBCXX_VISIBILITY(default)
_M_unhook() _GLIBCXX_USE_NOEXCEPT;
};
- _GLIBCXX_END_NAMESPACE_VERSION
+ /// The %list node header.
+ struct _List_node_header : public _List_node_base
+ {
+#if _GLIBCXX_USE_CXX11_ABI
+ std::size_t _M_size;
+#endif
+
+ _List_node_header() _GLIBCXX_NOEXCEPT
+ { _M_init(); }
+
+#if __cplusplus >= 201103L
+ _List_node_header(_List_node_header&& __x) noexcept
+ : _List_node_base{ __x._M_next, __x._M_prev }
+# if _GLIBCXX_USE_CXX11_ABI
+ , _M_size(__x._M_size)
+# endif
+ {
+ if (__x._M_base()->_M_next == __x._M_base())
+ this->_M_next = this->_M_prev = this;
+ else
+ {
+ this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base();
+ __x._M_init();
+ }
+ }
+
+ void
+ _M_move_nodes(_List_node_header&& __x)
+ {
+ _List_node_base* const __xnode = __x._M_base();
+ if (__xnode->_M_next == __xnode)
+ _M_init();
+ else
+ {
+ _List_node_base* const __node = this->_M_base();
+ __node->_M_next = __xnode->_M_next;
+ __node->_M_prev = __xnode->_M_prev;
+ __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
+# if _GLIBCXX_USE_CXX11_ABI
+ _M_size = __x._M_size;
+# endif
+ __x._M_init();
+ }
+ }
+#endif
+
+ void
+ _M_init() _GLIBCXX_NOEXCEPT
+ {
+ this->_M_next = this->_M_prev = this;
+#if _GLIBCXX_USE_CXX11_ABI
+ this->_M_size = 0;
+#endif
+ }
+
+ private:
+ _List_node_base* _M_base() { return this; }
+ };
} // namespace detail
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
@@ -323,23 +380,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
struct _List_impl
: public _Node_alloc_type
{
-#if _GLIBCXX_USE_CXX11_ABI
- _List_node<size_t> _M_node;
-#else
- __detail::_List_node_base _M_node;
-#endif
+ __detail::_List_node_header _M_node;
- _List_impl() _GLIBCXX_NOEXCEPT
- : _Node_alloc_type(), _M_node()
+ _List_impl() _GLIBCXX_NOEXCEPT_IF( noexcept(_Node_alloc_type()) )
+ : _Node_alloc_type()
{ }
_List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT
- : _Node_alloc_type(__a), _M_node()
+ : _Node_alloc_type(__a)
{ }
#if __cplusplus >= 201103L
+ _List_impl(_List_impl&&) = default;
+
_List_impl(_Node_alloc_type&& __a) noexcept
- : _Node_alloc_type(std::move(__a)), _M_node()
+ : _Node_alloc_type(std::move(__a))
{ }
#endif
};
@@ -347,13 +402,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_List_impl _M_impl;
#if _GLIBCXX_USE_CXX11_ABI
- size_t _M_get_size() const { return *_M_impl._M_node._M_valptr(); }
+ size_t _M_get_size() const { return _M_impl._M_node._M_size; }
- void _M_set_size(size_t __n) { *_M_impl._M_node._M_valptr() = __n; }
+ void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; }
- void _M_inc_size(size_t __n) { *_M_impl._M_node._M_valptr() += __n; }
+ void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; }
- void _M_dec_size(size_t __n) { *_M_impl._M_node._M_valptr() -= __n; }
+ void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; }
size_t
_M_distance(const __detail::_List_node_base* __first,
@@ -361,7 +416,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ return _S_distance(__first, __last); }
// return the stored size
- size_t _M_node_count() const { return *_M_impl._M_node._M_valptr(); }
+ size_t _M_node_count() const { return _M_get_size(); }
#else
// dummy implementations used when the size is not stored
size_t _M_get_size() const { return 0; }
@@ -397,44 +452,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
{ return _M_impl; }
- _List_base()
- : _M_impl()
- { _M_init(); }
+#if __cplusplus >= 201103L
+ _List_base() = default;
+#else
+ _List_base() { }
+#endif
_List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT
: _M_impl(__a)
- { _M_init(); }
+ { }
#if __cplusplus >= 201103L
- _List_base(_List_base&& __x) noexcept
- : _M_impl(std::move(__x._M_get_Node_allocator()))
- { _M_move_nodes(std::move(__x)); }
+ _List_base(_List_base&&) = default;
_List_base(_List_base&& __x, _Node_alloc_type&& __a)
: _M_impl(std::move(__a))
{
if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
_M_move_nodes(std::move(__x));
- else
- _M_init(); // Caller must move individual elements.
+ // else caller must move individual elements.
}
void
_M_move_nodes(_List_base&& __x)
- {
- auto* const __xnode = std::__addressof(__x._M_impl._M_node);
- if (__xnode->_M_next == __xnode)
- _M_init();
- else
- {
- auto* const __node = std::__addressof(_M_impl._M_node);
- __node->_M_next = __xnode->_M_next;
- __node->_M_prev = __xnode->_M_prev;
- __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
- _M_set_size(__x._M_get_size());
- __x._M_init();
- }
- }
+ { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); }
#endif
// This is what actually destroys the list.
@@ -446,11 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
void
_M_init() _GLIBCXX_NOEXCEPT
- {
- this->_M_impl._M_node._M_next = &this->_M_impl._M_node;
- this->_M_impl._M_node._M_prev = &this->_M_impl._M_node;
- _M_set_size(0);
- }
+ { this->_M_impl._M_node._M_init(); }
};
/**
@@ -586,11 +623,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/**
* @brief Creates a %list with no elements.
*/
- list()
#if __cplusplus >= 201103L
- noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value)
+ list() = default;
+#else
+ list() { }
#endif
- : _Base() { }
/**
* @brief Creates a %list with no elements.
@@ -657,13 +694,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus >= 201103L
/**
* @brief %List move constructor.
- * @param __x A %list of identical element and allocator types.
*
- * The newly-created %list contains the exact contents of @a __x.
- * The contents of @a __x are a valid, but unspecified %list.
+ * The newly-created %list contains the exact contents of the moved
+ * instance. The contents of the moved instance are a valid, but
+ * unspecified %list.
*/
- list(list&& __x) noexcept
- : _Base(std::move(__x)) { }
+ list(list&&) = default;
/**
* @brief Builds a %list from an initializer_list
@@ -1838,17 +1874,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_move_assign(list&& __x, true_type) noexcept
{
this->_M_clear();
- if (__x.empty())
- this->_M_init();
- else
- {
- this->_M_impl._M_node._M_next = __x._M_impl._M_node._M_next;
- this->_M_impl._M_node._M_next->_M_prev = &this->_M_impl._M_node;
- this->_M_impl._M_node._M_prev = __x._M_impl._M_node._M_prev;
- this->_M_impl._M_node._M_prev->_M_next = &this->_M_impl._M_node;
- this->_M_set_size(__x._M_get_size());
- __x._M_init();
- }
+ this->_M_move_nodes(std::move(__x));
std::__alloc_on_move(this->_M_get_Node_allocator(),
__x._M_get_Node_allocator());
}
@@ -1964,7 +1990,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
_GLIBCXX_END_NAMESPACE_CONTAINER
#if _GLIBCXX_USE_CXX11_ABI
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Detect when distance is used to compute the size of the whole list.
template<typename _Tp>
@@ -1983,12 +2008,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_STD_C::_List_const_iterator<_Tp> __last,
input_iterator_tag)
{
- typedef _GLIBCXX_STD_C::_List_node<size_t> _Sentinel;
+ typedef __detail::_List_node_header _Sentinel;
_GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last;
++__beyond;
- bool __whole = __first == __beyond;
+ const bool __whole = __first == __beyond;
if (__builtin_constant_p (__whole) && __whole)
- return *static_cast<const _Sentinel*>(__last._M_node)->_M_valptr();
+ return static_cast<const _Sentinel*>(__last._M_node)->_M_size;
ptrdiff_t __n = 0;
while (__first != __last)
@@ -1998,9 +2023,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return __n;
}
+#endif
_GLIBCXX_END_NAMESPACE_VERSION
-#endif
} // namespace std
#endif /* _STL_LIST_H */
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 30339536f57..0e8a98a96c1 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -65,6 +65,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
@@ -1437,7 +1438,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::map access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
@@ -1456,9 +1456,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_MAP_H */
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index 7dc22a96a59..7e3cea48a47 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -63,6 +63,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
@@ -1102,7 +1103,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::multimap access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
@@ -1121,9 +1121,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_MULTIMAP_H */
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index 60a3db844cb..517e77e9372 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -63,6 +63,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Compare, typename _Alloc>
@@ -953,7 +954,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::multiset access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
@@ -971,9 +971,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_MULTISET_H */
diff --git a/libstdc++-v3/include/bits/stl_relops.h b/libstdc++-v3/include/bits/stl_relops.h
index a2614bd3040..e2a0e25ca31 100644
--- a/libstdc++-v3/include/bits/stl_relops.h
+++ b/libstdc++-v3/include/bits/stl_relops.h
@@ -66,10 +66,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace rel_ops
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/** @namespace std::rel_ops
* @brief The generated relational operators are sequestered here.
*/
@@ -125,10 +125,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
inline bool
operator>=(const _Tp& __x, const _Tp& __y)
{ return !(__x < __y); }
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace rel_ops
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_RELOPS_H */
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index 817bc2d870f..e804a7cae70 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -63,6 +63,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Compare, typename _Alloc>
@@ -969,7 +970,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::set access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
@@ -986,8 +986,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} //namespace std
#endif /* _STL_SET_H */
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 7ee3ce96890..69cb8030208 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -65,8 +65,15 @@
#include <debug/assertions.h>
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
+extern "C" void
+__sanitizer_annotate_contiguous_container(const void*, const void*,
+ const void*, const void*);
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/// See bits/stl_deque.h's _Deque_base for an explanation.
@@ -106,6 +113,121 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::swap(_M_finish, __x._M_finish);
std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
+
+#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
+ template<typename = _Tp_alloc_type>
+ struct _Asan
+ {
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
+ ::size_type size_type;
+
+ static void _S_shrink(_Vector_impl&, size_type) { }
+ static void _S_on_dealloc(_Vector_impl&) { }
+
+ typedef _Vector_impl& _Reinit;
+
+ struct _Grow
+ {
+ _Grow(_Vector_impl&, size_type) { }
+ void _M_grew(size_type) { }
+ };
+ };
+
+ // Enable ASan annotations for memory obtained from std::allocator.
+ template<typename _Up>
+ struct _Asan<allocator<_Up> >
+ {
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
+ ::size_type size_type;
+
+ // Adjust ASan annotation for [_M_start, _M_end_of_storage) to
+ // mark end of valid region as __curr instead of __prev.
+ static void
+ _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr)
+ {
+ __sanitizer_annotate_contiguous_container(__impl._M_start,
+ __impl._M_end_of_storage, __prev, __curr);
+ }
+
+ static void
+ _S_grow(_Vector_impl& __impl, size_type __n)
+ { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); }
+
+ static void
+ _S_shrink(_Vector_impl& __impl, size_type __n)
+ { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); }
+
+ static void
+ _S_on_dealloc(_Vector_impl& __impl)
+ {
+ if (__impl._M_start)
+ _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage);
+ }
+
+ // Used on reallocation to tell ASan unused capacity is invalid.
+ struct _Reinit
+ {
+ explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
+ {
+ // Mark unused capacity as valid again before deallocating it.
+ _S_on_dealloc(_M_impl);
+ }
+
+ ~_Reinit()
+ {
+ // Mark unused capacity as invalid after reallocation.
+ if (_M_impl._M_start)
+ _S_adjust(_M_impl, _M_impl._M_end_of_storage,
+ _M_impl._M_finish);
+ }
+
+ _Vector_impl& _M_impl;
+
+#if __cplusplus >= 201103L
+ _Reinit(const _Reinit&) = delete;
+ _Reinit& operator=(const _Reinit&) = delete;
+#endif
+ };
+
+ // Tell ASan when unused capacity is initialized to be valid.
+ struct _Grow
+ {
+ _Grow(_Vector_impl& __impl, size_type __n)
+ : _M_impl(__impl), _M_n(__n)
+ { _S_grow(_M_impl, __n); }
+
+ ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); }
+
+ void _M_grew(size_type __n) { _M_n -= __n; }
+
+#if __cplusplus >= 201103L
+ _Grow(const _Grow&) = delete;
+ _Grow& operator=(const _Grow&) = delete;
+#endif
+ private:
+ _Vector_impl& _M_impl;
+ size_type _M_n;
+ };
+ };
+
+#define _GLIBCXX_ASAN_ANNOTATE_REINIT \
+ typename _Base::_Vector_impl::template _Asan<>::_Reinit const \
+ __attribute__((__unused__)) __reinit_guard(this->_M_impl)
+#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \
+ typename _Base::_Vector_impl::template _Asan<>::_Grow \
+ __attribute__((__unused__)) __grow_guard(this->_M_impl, (n))
+#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n)
+#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \
+ _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n)
+#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \
+ _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl)
+#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR)
+#define _GLIBCXX_ASAN_ANNOTATE_REINIT
+#define _GLIBCXX_ASAN_ANNOTATE_GROW(n)
+#define _GLIBCXX_ASAN_ANNOTATE_GREW(n)
+#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n)
+#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC
+#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
};
public:
@@ -159,8 +281,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
~_Vector_base() _GLIBCXX_NOEXCEPT
- { _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
- - this->_M_impl._M_start); }
+ {
+ _M_deallocate(_M_impl._M_start,
+ _M_impl._M_end_of_storage - _M_impl._M_start);
+ }
public:
_Vector_impl _M_impl;
@@ -190,7 +314,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
};
-
/**
* @brief A standard container which offers fixed time access to
* individual elements in any order.
@@ -431,8 +554,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* responsibility.
*/
~vector() _GLIBCXX_NOEXCEPT
- { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
- _M_get_Tp_allocator()); }
+ {
+ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC;
+ }
/**
* @brief %Vector assignment operator.
@@ -940,9 +1066,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_realloc_insert(end(), __x);
@@ -977,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__glibcxx_requires_nonempty();
--this->_M_impl._M_finish;
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
}
#if __cplusplus >= 201103L
@@ -1510,8 +1639,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
_M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT
{
- std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
- this->_M_impl._M_finish = __pos;
+ if (size_type __n = this->_M_impl._M_finish - __pos)
+ {
+ std::_Destroy(__pos, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ this->_M_impl._M_finish = __pos;
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n);
+ }
}
iterator
@@ -1655,6 +1789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _STL_VECTOR_H */
diff --git a/libstdc++-v3/include/bits/uniform_int_dist.h b/libstdc++-v3/include/bits/uniform_int_dist.h
index af7ac14bccf..16509c4ef8a 100644
--- a/libstdc++-v3/include/bits/uniform_int_dist.h
+++ b/libstdc++-v3/include/bits/uniform_int_dist.h
@@ -36,10 +36,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
/* Determine whether number is a power of 2. */
template<typename _Tp>
inline bool
@@ -47,11 +47,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
return ((__x - 1) & __x) == 0;
};
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Uniform discrete distribution for random numbers.
* A discrete random distribution on the range @f$[min, max]@f$ with equal
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 4ef30ccccd6..df1302c80c0 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -32,6 +32,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/// Base types for unordered_map.
@@ -1911,7 +1912,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::unordered_map access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Hash1, typename _Eq1,
typename _Alloc, typename _Hash2, typename _Eq2>
@@ -1959,9 +1959,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
{ return __map._M_h; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _UNORDERED_MAP_H */
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index 85c2562f89e..df57915f31a 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -32,6 +32,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/// Base types for unordered_set.
@@ -1557,7 +1558,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::unordered_set access to internals of compatible sets.
template<typename _Val, typename _Hash1, typename _Eq1, typename _Alloc,
typename _Hash2, typename _Eq2>
@@ -1604,9 +1604,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set)
{ return __set._M_h; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _UNORDERED_SET_H */
diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h
index 89d4e435659..4d60716b494 100644
--- a/libstdc++-v3/include/bits/uses_allocator.h
+++ b/libstdc++-v3/include/bits/uses_allocator.h
@@ -109,6 +109,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__ret._M_a = std::__addressof(__a);
return __ret;
}
+
+ template<typename _Tp, typename _Alloc, typename... _Args>
+ void
+ __use_alloc(const _Alloc&&) = delete;
+
#if __cplusplus > 201402L
template <typename _Tp, typename _Alloc>
inline constexpr bool uses_allocator_v =
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index 8d688661c82..f14caaa713f 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -58,6 +58,7 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
@@ -73,6 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __tmp = _M_allocate_and_copy(__n,
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -97,9 +99,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
@@ -122,9 +126,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == end())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
{
@@ -157,6 +163,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_MOVE3(__position + 1, end(), __position);
--this->_M_impl._M_finish;
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
+ _GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
return __position;
}
@@ -181,6 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (&__x != this)
{
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
#if __cplusplus >= 201103L
if (_Alloc_traits::_S_propagate_on_copy_assign())
{
@@ -245,10 +253,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
else if (__n > size())
{
std::fill(begin(), end(), __val);
+ const size_type __add = __n - size();
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__add);
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
- __n - size(), __val,
- _M_get_Tp_allocator());
+ __add, __val, _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__add);
}
else
_M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val));
@@ -284,6 +294,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (__len > capacity())
{
pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -300,10 +311,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_ForwardIterator __mid = __first;
std::advance(__mid, size());
std::copy(__first, __mid, this->_M_impl._M_start);
+ const size_type __attribute__((__unused__)) __n = __len - size();
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_copy_a(__mid, __last,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
}
}
@@ -317,9 +331,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == cend())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::move(__v));
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
_M_insert_aux(begin() + __n, std::move(__v));
@@ -340,9 +356,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
if (__position == cend())
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
}
else
{
@@ -370,10 +388,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_insert_aux(iterator __position, const _Tp& __x)
#endif
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(1);
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
- _GLIBCXX_MOVE(*(this->_M_impl._M_finish
- - 1)));
+ _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1)));
++this->_M_impl._M_finish;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(1);
#if __cplusplus < 201103L
_Tp __x_copy = __x;
#endif
@@ -443,11 +462,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
- this->_M_impl._M_end_of_storage
- - this->_M_impl._M_start);
+ this->_M_impl._M_end_of_storage - this->_M_impl._M_start);
this->_M_impl._M_start = __new_start;
this->_M_impl._M_finish = __new_finish;
this->_M_impl._M_end_of_storage = __new_start + __len;
@@ -473,11 +492,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __old_finish(this->_M_impl._M_finish);
if (__elems_after > __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
this->_M_impl._M_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
__old_finish - __n, __old_finish);
std::fill(__position.base(), __position.base() + __n,
@@ -485,15 +506,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
else
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
__n - __elems_after,
__x_copy,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);
std::__uninitialized_move_a(__position.base(), __old_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);
std::fill(__position.base(), __old_finish, __x_copy);
}
}
@@ -536,6 +560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -559,9 +584,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (size_type(this->_M_impl._M_end_of_storage
- this->_M_impl._M_finish) >= __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
this->_M_impl._M_finish =
std::__uninitialized_default_n_a(this->_M_impl._M_finish,
__n, _M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
}
else
{
@@ -587,6 +614,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -606,6 +634,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
if (capacity() == size())
return false;
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
return std::__shrink_to_fit_aux<vector>::_S_do_it(*this);
}
#endif
@@ -617,10 +646,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_range_insert(iterator __pos, _InputIterator __first,
_InputIterator __last, std::input_iterator_tag)
{
- for (; __first != __last; ++__first)
+ if (__pos == end())
+ {
+ for (; __first != __last; ++__first)
+ insert(end(), *__first);
+ }
+ else if (__first != __last)
{
- __pos = insert(__pos, *__first);
- ++__pos;
+ vector __tmp(__first, __last, _M_get_Tp_allocator());
+ insert(__pos,
+ _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.begin()),
+ _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.end()));
}
}
@@ -641,11 +677,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __old_finish(this->_M_impl._M_finish);
if (__elems_after > __n)
{
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
this->_M_impl._M_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
__old_finish - __n, __old_finish);
std::copy(__first, __last, __position);
@@ -654,15 +692,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
_ForwardIterator __mid = __first;
std::advance(__mid, __elems_after);
+ _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
std::__uninitialized_copy_a(__mid, __last,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __n - __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);
std::__uninitialized_move_a(__position.base(),
__old_finish,
this->_M_impl._M_finish,
_M_get_Tp_allocator());
this->_M_impl._M_finish += __elems_after;
+ _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);
std::copy(__first, __mid, __position);
}
}
@@ -694,6 +735,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
@@ -856,6 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#if __cplusplus >= 201103L
@@ -902,4 +945,9 @@ _GLIBCXX_END_NAMESPACE_VERSION
#endif // C++11
+#undef _GLIBCXX_ASAN_ANNOTATE_REINIT
+#undef _GLIBCXX_ASAN_ANNOTATE_GROW
+#undef _GLIBCXX_ASAN_ANNOTATE_GREW
+#undef _GLIBCXX_ASAN_ANNOTATE_SHRINK
+
#endif /* _VECTOR_TCC */
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 6e7508f6939..71f70ce6b73 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -513,9 +513,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tanh(_Tp __x)
{ return __builtin_tanh(__x); }
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
#if _GLIBCXX_USE_C99_MATH
#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
@@ -533,10 +530,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
#undef islessgreater
#undef isunordered
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#if __cplusplus >= 201103L
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
@@ -952,13 +945,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __builtin_isunordered(__type(__f1), __type(__f2));
}
-#endif
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
+#endif // C++11
#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
-#endif
+#endif /* _GLIBCXX_USE_C99_MATH */
#if __cplusplus >= 201103L
@@ -1072,10 +1061,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
#undef truncf
#undef truncl
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// types
using ::double_t;
using ::float_t;
@@ -1856,17 +1841,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_trunc(__x); }
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
#endif // _GLIBCXX_USE_C99_MATH_TR1
-
#endif // C++11
#if __cplusplus > 201402L
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// [c.math.hypot3], three-dimensional hypotenuse
#define __cpp_lib_hypot 201603
@@ -1905,10 +1883,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type;
return std::__hypot3<__type>(__x, __y, __z);
}
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# include <bits/specfun.h>
diff --git a/libstdc++-v3/include/c_std/cmath b/libstdc++-v3/include/c_std/cmath
index c5b5a470f87..8fc5736601d 100644
--- a/libstdc++-v3/include/c_std/cmath
+++ b/libstdc++-v3/include/c_std/cmath
@@ -449,9 +449,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tanh(_Tp __x)
{ return __builtin_tanh(__x); }
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
#if _GLIBCXX_USE_C99_MATH
#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
@@ -469,10 +466,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
#undef islessgreater
#undef isunordered
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
int>::__type
@@ -582,10 +575,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __builtin_isunordered(__type(__f1), __type(__f2));
}
+#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
+#endif /* _GLIBCXX_USE_C99_MATH */
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
-#endif
-
#endif
diff --git a/libstdc++-v3/include/decimal/decimal b/libstdc++-v3/include/decimal/decimal
index b167a7ac7f2..adc4619d944 100644
--- a/libstdc++-v3/include/decimal/decimal
+++ b/libstdc++-v3/include/decimal/decimal
@@ -42,6 +42,8 @@ that is currently not available.
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/**
* @defgroup decimal Decimal Floating-Point Arithmetic
* @ingroup numerics
@@ -55,8 +57,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
*/
namespace decimal
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
class decimal32;
class decimal64;
class decimal128;
@@ -483,10 +483,10 @@ namespace decimal
};
#define _GLIBCXX_USE_DECIMAL_ 1
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace decimal
// @} group decimal
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <decimal/decimal.h>
diff --git a/libstdc++-v3/include/decimal/decimal.h b/libstdc++-v3/include/decimal/decimal.h
index ede6e57c998..d4118962614 100644
--- a/libstdc++-v3/include/decimal/decimal.h
+++ b/libstdc++-v3/include/decimal/decimal.h
@@ -37,10 +37,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace decimal
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// ISO/IEC TR 24733 3.2.[234].1 Construct/copy/destroy.
inline decimal32::decimal32(decimal64 __r) : __val(__r.__getval()) {}
@@ -461,8 +461,9 @@ namespace decimal
#undef _DEFINE_DECIMAL_COMPARISON_LHS
#undef _DEFINE_DECIMAL_COMPARISON_RHS
#undef _DEFINE_DECIMAL_COMPARISONS
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace decimal
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif /* _GLIBCXX_DECIMAL_IMPL */
diff --git a/libstdc++-v3/include/experimental/algorithm b/libstdc++-v3/include/experimental/algorithm
index a7ab0e84c12..15391b1e9f2 100644
--- a/libstdc++-v3/include/experimental/algorithm
+++ b/libstdc++-v3/include/experimental/algorithm
@@ -40,12 +40,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _ForwardIterator, typename _Searcher>
inline _ForwardIterator
search(_ForwardIterator __first, _ForwardIterator __last,
@@ -81,10 +81,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__d,
std::forward<_UniformRandomNumberGenerator>(__g));
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any
index 36c0680c25a..984306dfce8 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -43,12 +43,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @defgroup any Type-safe container of any type
* @ingroup experimental
@@ -520,9 +520,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// @} group any
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/array b/libstdc++-v3/include/experimental/array
index 11cb924e087..9d758f7d149 100644
--- a/libstdc++-v3/include/experimental/array
+++ b/libstdc++-v3/include/experimental/array
@@ -40,12 +40,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_make_array 201505
/**
* @defgroup make_array Array creation functions
@@ -104,10 +104,10 @@ template <typename _Tp, size_t _Nm>
}
// @} group make_array
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/bits/erase_if.h b/libstdc++-v3/include/experimental/bits/erase_if.h
index 7dc47dbb3eb..cc89ffad900 100644
--- a/libstdc++-v3/include/experimental/bits/erase_if.h
+++ b/libstdc++-v3/include/experimental/bits/erase_if.h
@@ -39,13 +39,14 @@
namespace std
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Container, typename _Predicate>
void
__erase_nodes_if(_Container& __cont, _Predicate __pred)
@@ -59,10 +60,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
++__iter;
}
}
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
} // inline namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/bits/fs_dir.h b/libstdc++-v3/include/experimental/bits/fs_dir.h
index 0efaf944f60..1ff0d9b6def 100644
--- a/libstdc++-v3/include/experimental/bits/fs_dir.h
+++ b/libstdc++-v3/include/experimental/bits/fs_dir.h
@@ -40,14 +40,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @ingroup filesystem
* @{
@@ -352,10 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_END_NAMESPACE_CXX11
// @} group filesystem
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace v1
} // namespace filesystem
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/experimental/bits/fs_fwd.h b/libstdc++-v3/include/experimental/bits/fs_fwd.h
index c5aeefe41a7..7b851a3d4a8 100644
--- a/libstdc++-v3/include/experimental/bits/fs_fwd.h
+++ b/libstdc++-v3/include/experimental/bits/fs_fwd.h
@@ -40,17 +40,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
-#if _GLIBCXX_INLINE_VERSION
-inline namespace __8 { }
-#endif
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#if _GLIBCXX_USE_CXX11_ABI
inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
#endif
@@ -282,10 +279,11 @@ _GLIBCXX_END_NAMESPACE_CXX11
bool is_symlink(file_status) noexcept;
// @} group filesystem
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace v1
} // namespace filesystem
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/experimental/bits/fs_ops.h b/libstdc++-v3/include/experimental/bits/fs_ops.h
index 1b455f541ba..387537260e0 100644
--- a/libstdc++-v3/include/experimental/bits/fs_ops.h
+++ b/libstdc++-v3/include/experimental/bits/fs_ops.h
@@ -38,14 +38,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @ingroup filesystem
* @{
@@ -286,10 +286,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
path temp_directory_path(error_code& __ec);
// @} group filesystem
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace v1
} // namespace filesystem
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h
index 3d639447254..cde3897b8e5 100644
--- a/libstdc++-v3/include/experimental/bits/fs_path.h
+++ b/libstdc++-v3/include/experimental/bits/fs_path.h
@@ -55,13 +55,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus == 201402L
@@ -1080,10 +1081,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
// @} group filesystem
_GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace v1
} // namespace filesystem
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/experimental/bits/lfts_config.h b/libstdc++-v3/include/experimental/bits/lfts_config.h
index ecc40c4327f..3b832706da0 100644
--- a/libstdc++-v3/include/experimental/bits/lfts_config.h
+++ b/libstdc++-v3/include/experimental/bits/lfts_config.h
@@ -35,30 +35,25 @@
#if _GLIBCXX_INLINE_VERSION
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace chrono
{
namespace experimental
{
-inline namespace fundamentals_v1 { inline namespace __8 { } }
-inline namespace fundamentals_v2 { inline namespace __8 { } }
+inline namespace fundamentals_v1 { }
+inline namespace fundamentals_v2 { }
} // namespace experimental
} // namespace chrono
namespace experimental
{
-inline namespace fundamentals_v1 {
- inline namespace __8 { }
- namespace __detail { inline namespace __8 { } }
-}
-inline namespace fundamentals_v2 {
- inline namespace __8 { }
- namespace pmr { inline namespace __8 { } }
- namespace __detail { inline namespace __8 { } }
-} // namespace fundamentals_v2
-inline namespace literals { inline namespace string_view_literals {
- inline namespace __8 { }
-} } // namespace literals::string_view_literals
+inline namespace fundamentals_v1 { }
+inline namespace fundamentals_v2 { }
+inline namespace literals { inline namespace string_view_literals { } }
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
#endif
diff --git a/libstdc++-v3/include/experimental/bits/shared_ptr.h b/libstdc++-v3/include/experimental/bits/shared_ptr.h
index 27f22d23618..ef391eb641f 100644
--- a/libstdc++-v3/include/experimental/bits/shared_ptr.h
+++ b/libstdc++-v3/include/experimental/bits/shared_ptr.h
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// 8.2.1
template<typename _Tp> class shared_ptr;
@@ -659,13 +659,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
mutable weak_ptr<_Tp> _M_weak_this;
};
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/// std::hash specialization for shared_ptr.
template<typename _Tp>
struct hash<experimental::shared_ptr<_Tp>>
diff --git a/libstdc++-v3/include/experimental/bits/string_view.tcc b/libstdc++-v3/include/experimental/bits/string_view.tcc
index 03863d0a9df..e66932d1ac0 100644
--- a/libstdc++-v3/include/experimental/bits/string_view.tcc
+++ b/libstdc++-v3/include/experimental/bits/string_view.tcc
@@ -42,12 +42,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _CharT, typename _Traits>
typename basic_string_view<_CharT, _Traits>::size_type
basic_string_view<_CharT, _Traits>::
@@ -222,10 +222,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return npos;
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/chrono b/libstdc++-v3/include/experimental/chrono
index 4247c9df746..71e36d2d86d 100644
--- a/libstdc++-v3/include/experimental/chrono
+++ b/libstdc++-v3/include/experimental/chrono
@@ -44,20 +44,21 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace chrono {
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// See C++14 §20.12.4, customization traits
template <typename _Rep>
constexpr bool treat_as_floating_point_v =
treat_as_floating_point<_Rep>::value;
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
} // namespace chrono
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/deque b/libstdc++-v3/include/experimental/deque
index c92476f915d..0180a750883 100644
--- a/libstdc++-v3/include/experimental/deque
+++ b/libstdc++-v3/include/experimental/deque
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp, typename _Alloc, typename _Predicate>
void
erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
@@ -63,19 +63,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__cont.end());
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Tp>
- using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ namespace pmr {
+ template<typename _Tp>
+ using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>;
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/filesystem b/libstdc++-v3/include/experimental/filesystem
index 2f353693dbe..7953c802cd3 100644
--- a/libstdc++-v3/include/experimental/filesystem
+++ b/libstdc++-v3/include/experimental/filesystem
@@ -44,14 +44,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @ingroup filesystem
*/
@@ -65,11 +65,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__what += " [" + _M_path2.string() + ']';
return __what;
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace v1
} // namespace filesystem
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
diff --git a/libstdc++-v3/include/experimental/forward_list b/libstdc++-v3/include/experimental/forward_list
index 1c835aca07e..5109cb57ade 100644
--- a/libstdc++-v3/include/experimental/forward_list
+++ b/libstdc++-v3/include/experimental/forward_list
@@ -40,12 +40,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp, typename _Alloc, typename _Predicate>
inline void
erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)
@@ -59,19 +59,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(__cont, [&](__elem_type& __elem) { return __elem == __value; });
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Tp>
- using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ namespace pmr {
+ template<typename _Tp>
+ using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>;
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 4639e6f6cb3..3327399b4d4 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -49,12 +49,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// See C++14 §20.9.9, Function object binders
/// Variable template for std::is_bind_expression
@@ -368,14 +368,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return __last;
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_not_fn 201406
/// [func.not_fn] Function template not_fn
@@ -386,10 +382,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
return std::_Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/iterator b/libstdc++-v3/include/experimental/iterator
index 8a8395da759..553009c92b0 100644
--- a/libstdc++-v3/include/experimental/iterator
+++ b/libstdc++-v3/include/experimental/iterator
@@ -45,12 +45,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_ostream_joiner 201411
/// Output iterator that inserts a delimiter between elements.
@@ -105,10 +105,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_ostream_joiner(basic_ostream<_CharT, _Traits>& __os,
_DelimT&& __delimiter)
{ return { __os, std::forward<_DelimT>(__delimiter) }; }
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/list b/libstdc++-v3/include/experimental/list
index 9409431c4d8..94663ad030a 100644
--- a/libstdc++-v3/include/experimental/list
+++ b/libstdc++-v3/include/experimental/list
@@ -40,12 +40,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp, typename _Alloc, typename _Predicate>
inline void
erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred)
@@ -59,19 +59,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(__cont, [&](__elem_type& __elem) { return __elem == __value; });
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp>
using list = std::list<_Tp, polymorphic_allocator<_Tp>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map
index 2bbc1bd5a11..85055967fa5 100644
--- a/libstdc++-v3/include/experimental/map
+++ b/libstdc++-v3/include/experimental/map
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
@@ -59,26 +59,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
{ __detail::__erase_nodes_if(__cont, __pred); }
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
- using map
+ namespace pmr {
+ template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
+ using map
= std::map<_Key, _Tp, _Compare,
polymorphic_allocator<pair<const _Key, _Tp>>>;
- template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
- using multimap
+ template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
+ using multimap
= std::multimap<_Key, _Tp, _Compare,
polymorphic_allocator<pair<const _Key, _Tp>>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
-
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/memory b/libstdc++-v3/include/experimental/memory
index 7467674db81..33a154bf50c 100644
--- a/libstdc++-v3/include/experimental/memory
+++ b/libstdc++-v3/include/experimental/memory
@@ -47,12 +47,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_observer_ptr 201411
template <typename _Tp>
@@ -231,8 +231,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
return !(__p1 < __p2);
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
@@ -250,6 +248,8 @@ template <typename _Tp>
}
};
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource
index 653189c1079..f4ecc5ab1d3 100644
--- a/libstdc++-v3/include/experimental/memory_resource
+++ b/libstdc++-v3/include/experimental/memory_resource
@@ -37,11 +37,11 @@
#include <experimental/bits/lfts_config.h>
namespace std {
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental {
inline namespace fundamentals_v2 {
namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_memory_resources 201402L
class memory_resource;
@@ -168,8 +168,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Tp1, typename... _Args> //used here
void construct(_Tp1* __p, _Args&&... __args)
{
- auto __use_tag = __use_alloc<_Tp1, memory_resource*,
- _Args...>(this->resource());
+ memory_resource* const __resource = this->resource();
+ auto __use_tag
+ = __use_alloc<_Tp1, memory_resource*, _Args...>(__resource);
_M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
}
@@ -180,10 +181,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple<_Args1...> __x,
tuple<_Args2...> __y)
{
+ memory_resource* const __resource = this->resource();
auto __x_use_tag =
- __use_alloc<_Tp1, memory_resource*, _Args1...>(this->resource());
+ __use_alloc<_Tp1, memory_resource*, _Args1...>(__resource);
auto __y_use_tag =
- __use_alloc<_Tp2, memory_resource*, _Args2...>(this->resource());
+ __use_alloc<_Tp2, memory_resource*, _Args2...>(__resource);
::new(__p) std::pair<_Tp1, _Tp2>(piecewise_construct,
_M_construct_p(__x_use_tag, __x),
@@ -377,11 +379,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__r = new_delete_resource();
return __get_default_resource().exchange(__r);
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
diff --git a/libstdc++-v3/include/experimental/numeric b/libstdc++-v3/include/experimental/numeric
index b7b8207069f..33e7b55ef90 100644
--- a/libstdc++-v3/include/experimental/numeric
+++ b/libstdc++-v3/include/experimental/numeric
@@ -44,12 +44,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_gcd_lcm 201411
/// Greatest common divisor
@@ -75,10 +75,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(!is_same<_Nn, bool>::value, "lcm arguments are not bools");
return std::__detail::__lcm(__m, __n);
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional
index 4a1e71d4234..d4c58a600bf 100644
--- a/libstdc++-v3/include/experimental/optional
+++ b/libstdc++-v3/include/experimental/optional
@@ -57,12 +57,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @defgroup optional Optional values
* @ingroup experimental
@@ -980,9 +980,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
// @} group optional
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
-}
+} // namespace experimental
// [X.Y.12]
template<typename _Tp>
@@ -1001,7 +1000,9 @@ _GLIBCXX_END_NAMESPACE_VERSION
return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
}
};
-}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/propagate_const b/libstdc++-v3/include/experimental/propagate_const
index 719e17aa3d0..639f21a979e 100644
--- a/libstdc++-v3/include/experimental/propagate_const
+++ b/libstdc++-v3/include/experimental/propagate_const
@@ -43,12 +43,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @defgroup propagate_const Const-propagating wrapper
* @ingroup experimental
@@ -424,7 +424,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// @} group propagate_const
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
@@ -533,6 +532,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef experimental::propagate_const<_Tp> second_argument_type;
typedef bool result_type;
};
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/random b/libstdc++-v3/include/experimental/random
index e28df5df721..2d22544e9ca 100644
--- a/libstdc++-v3/include/experimental/random
+++ b/libstdc++-v3/include/experimental/random
@@ -33,10 +33,10 @@
#include <experimental/bits/lfts_config.h>
namespace std {
-namespace experimental {
-inline namespace fundamentals_v2 {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace experimental {
+inline namespace fundamentals_v2 {
#define __cpp_lib_experimental_randint 201511
inline std::default_random_engine&
@@ -71,10 +71,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_S_randint_engine().seed(__value);
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
diff --git a/libstdc++-v3/include/experimental/ratio b/libstdc++-v3/include/experimental/ratio
index ffbae76ca79..bc2d0f267b2 100644
--- a/libstdc++-v3/include/experimental/ratio
+++ b/libstdc++-v3/include/experimental/ratio
@@ -44,12 +44,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// See C++14 §20.11.5, ratio comparison
template <typename _R1, typename _R2>
constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value;
@@ -63,10 +63,10 @@ template <typename _R1, typename _R2>
constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value;
template <typename _R1, typename _R2>
constexpr bool ratio_greater_equal_v = ratio_greater_equal<_R1, _R2>::value;
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/regex b/libstdc++-v3/include/experimental/regex
index 9b5679fc78e..bfcaf6b85c3 100644
--- a/libstdc++-v3/include/experimental/regex
+++ b/libstdc++-v3/include/experimental/regex
@@ -40,13 +40,14 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
namespace pmr
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _BidirectionalIterator>
@@ -60,11 +61,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
typedef match_results<wstring::const_iterator> wsmatch;
_GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set
index a10617bb2a9..fba136c90c5 100644
--- a/libstdc++-v3/include/experimental/set
+++ b/libstdc++-v3/include/experimental/set
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Key, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
@@ -59,23 +59,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
{ __detail::__erase_nodes_if(__cont, __pred); }
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Key, typename _Compare = less<_Key>>
- using set = std::set<_Key, _Compare, polymorphic_allocator<_Key>>;
-
- template<typename _Key, typename _Compare = less<_Key>>
- using multiset = std::multiset<_Key, _Compare,
- polymorphic_allocator<_Key>>;
+ namespace pmr {
+ template<typename _Key, typename _Compare = less<_Key>>
+ using set = std::set<_Key, _Compare, polymorphic_allocator<_Key>>;
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ template<typename _Key, typename _Compare = less<_Key>>
+ using multiset = std::multiset<_Key, _Compare,
+ polymorphic_allocator<_Key>>;
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/source_location b/libstdc++-v3/include/experimental/source_location
index b06d8b651ae..a7fa95549b3 100644
--- a/libstdc++-v3/include/experimental/source_location
+++ b/libstdc++-v3/include/experimental/source_location
@@ -32,10 +32,10 @@
#include <cstdint>
namespace std {
-namespace experimental {
-inline namespace fundamentals_v2 {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace experimental {
+inline namespace fundamentals_v2 {
#define __cpp_lib_experimental_source_location 201505
struct source_location
@@ -77,10 +77,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
uint_least32_t _M_line;
uint_least32_t _M_col;
};
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
diff --git a/libstdc++-v3/include/experimental/string b/libstdc++-v3/include/experimental/string
index 5347991959e..893013b1869 100644
--- a/libstdc++-v3/include/experimental/string
+++ b/libstdc++-v3/include/experimental/string
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _CharT, typename _Traits, typename _Alloc,
typename _Predicate>
inline void
@@ -64,30 +64,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__cont.end());
}
-_GLIBCXX_END_NAMESPACE_VERSION
+ namespace pmr {
+ _GLIBCXX_BEGIN_NAMESPACE_CXX11
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-_GLIBCXX_BEGIN_NAMESPACE_CXX11
+ // basic_string using polymorphic allocator in namespace pmr
+ template<typename _CharT, typename _Traits = char_traits<_CharT>>
+ using basic_string =
+ std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>;
- // basic_string using polymorphic allocator in namespace pmr
- template<typename _CharT, typename _Traits = char_traits<_CharT>>
- using basic_string =
- std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>;
-
- // basic_string typedef names using polymorphic allocator in namespace
- // std::experimental::pmr
- typedef basic_string<char> string;
- typedef basic_string<char16_t> u16string;
- typedef basic_string<char32_t> u32string;
- typedef basic_string<wchar_t> wstring;
-
-_GLIBCXX_END_NAMESPACE_CXX11
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ // basic_string typedef names using polymorphic allocator in namespace
+ // std::experimental::pmr
+ typedef basic_string<char> string;
+ typedef basic_string<char16_t> u16string;
+ typedef basic_string<char32_t> u32string;
+ typedef basic_string<wchar_t> wstring;
+ _GLIBCXX_END_NAMESPACE_CXX11
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index bd212ac3719..5cec5597744 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -45,12 +45,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_string_view 201411
/**
@@ -434,23 +434,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _CharT* _M_str;
};
-_GLIBCXX_END_NAMESPACE_VERSION
-
// [string.view.comparison], non-member basic_string_view comparison functions
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Identity transform to create a non-deduced context, so that only one
// argument participates in template argument deduction and the other
// argument gets implicitly converted to the deduced type. See n3766.html.
template<typename _Tp>
using __idt = common_type_t<_Tp>;
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _CharT, typename _Traits>
inline bool
operator==(basic_string_view<_CharT, _Traits> __x,
@@ -577,15 +571,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
#endif
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
// [string.view.hash], hash support:
-
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
struct hash;
@@ -647,7 +637,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
{ };
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
namespace experimental
{
@@ -656,8 +645,6 @@ namespace experimental
{
inline namespace string_view_literals
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
inline constexpr basic_string_view<char>
operator""sv(const char* __str, size_t __len)
{ return basic_string_view<char>{__str, __len}; }
@@ -677,11 +664,11 @@ namespace experimental
operator""sv(const char32_t* __str, size_t __len)
{ return basic_string_view<char32_t>{__str, __len}; }
#endif
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace string_literals
} // namespace literals
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <experimental/bits/string_view.tcc>
diff --git a/libstdc++-v3/include/experimental/system_error b/libstdc++-v3/include/experimental/system_error
index 2b4855dba72..2bad7503b2f 100644
--- a/libstdc++-v3/include/experimental/system_error
+++ b/libstdc++-v3/include/experimental/system_error
@@ -44,22 +44,22 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// See C++14 §19.5, System error support
template <typename _Tp>
constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value;
template <typename _Tp>
constexpr bool is_error_condition_enum_v =
is_error_condition_enum<_Tp>::value;
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/tuple b/libstdc++-v3/include/experimental/tuple
index 879636eecd8..a12fa0a3327 100644
--- a/libstdc++-v3/include/experimental/tuple
+++ b/libstdc++-v3/include/experimental/tuple
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// See C++14 §20.4.2.5, tuple helper classes
template <typename _Tp>
constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
@@ -71,10 +71,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::forward<_Tuple>(__t),
_Indices{});
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/type_traits b/libstdc++-v3/include/experimental/type_traits
index 7ec06308ba9..3885c168e31 100644
--- a/libstdc++-v3/include/experimental/type_traits
+++ b/libstdc++-v3/include/experimental/type_traits
@@ -44,12 +44,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_type_trait_variable_templates 201402
// See C++14 §20.10.4.1, primary type categories
@@ -218,13 +218,10 @@ template <typename _From, typename _To>
// raw_invocation_type (still unimplemented)
// invocation_type_t (still unimplemented)
// raw_invocation_type_t (still unimplemented)
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v1
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_detect 201505
// [meta.detect]
@@ -299,10 +296,10 @@ template<typename... _Bn>
template<typename _Pp>
constexpr bool negation_v
= negation<_Pp>::value;
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cplusplus <= 201103L
diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map
index fbc44b267b5..cddd5b3d78c 100644
--- a/libstdc++-v3/include/experimental/unordered_map
+++ b/libstdc++-v3/include/experimental/unordered_map
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
inline void
@@ -61,28 +61,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Predicate __pred)
{ __detail::__erase_nodes_if(__cont, __pred); }
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
- typename _Pred = equal_to<_Key>>
- using unordered_map
+ namespace pmr {
+ template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
+ typename _Pred = equal_to<_Key>>
+ using unordered_map
= std::unordered_map<_Key, _Tp, _Hash, _Pred,
polymorphic_allocator<pair<const _Key, _Tp>>>;
- template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
- typename _Pred = equal_to<_Key>>
- using unordered_multimap
+ template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
+ typename _Pred = equal_to<_Key>>
+ using unordered_multimap
= std::unordered_multimap<_Key, _Tp, _Hash, _Pred,
polymorphic_allocator<pair<const _Key, _Tp>>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set
index 3c8fe255275..816327f9ba7 100644
--- a/libstdc++-v3/include/experimental/unordered_set
+++ b/libstdc++-v3/include/experimental/unordered_set
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
typename _Predicate>
inline void
@@ -61,27 +61,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Predicate __pred)
{ __detail::__erase_nodes_if(__cont, __pred); }
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Key, typename _Hash = hash<_Key>,
- typename _Pred = equal_to<_Key>>
- using unordered_set
+ namespace pmr {
+ template<typename _Key, typename _Hash = hash<_Key>,
+ typename _Pred = equal_to<_Key>>
+ using unordered_set
= std::unordered_set<_Key, _Hash, _Pred, polymorphic_allocator<_Key>>;
- template<typename _Key, typename _Hash = hash<_Key>,
- typename _Pred = equal_to<_Key>>
- using unordered_multiset
+ template<typename _Key, typename _Hash = hash<_Key>,
+ typename _Pred = equal_to<_Key>>
+ using unordered_multiset
= std::unordered_multiset<_Key, _Hash, _Pred,
polymorphic_allocator<_Key>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/experimental/utility b/libstdc++-v3/include/experimental/utility
index db85c5cc62c..5d21d67e387 100644
--- a/libstdc++-v3/include/experimental/utility
+++ b/libstdc++-v3/include/experimental/utility
@@ -34,16 +34,16 @@
#include <experimental/bits/lfts_config.h>
namespace std {
-namespace experimental {
-inline namespace fundamentals_v2 {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace experimental {
+inline namespace fundamentals_v2 {
// 3.1.2, erased-type placeholder
using erased_type = std::__erased_type;
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
diff --git a/libstdc++-v3/include/experimental/vector b/libstdc++-v3/include/experimental/vector
index b75a3bc7ce4..e77dd2e4771 100644
--- a/libstdc++-v3/include/experimental/vector
+++ b/libstdc++-v3/include/experimental/vector
@@ -41,12 +41,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace experimental
{
inline namespace fundamentals_v2
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_experimental_erase_if 201411
template<typename _Tp, typename _Alloc, typename _Predicate>
@@ -65,19 +65,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__cont.end());
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
-namespace pmr {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename _Tp>
- using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>;
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace pmr
+ namespace pmr {
+ template<typename _Tp>
+ using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>;
+ } // namespace pmr
} // namespace fundamentals_v2
} // namespace experimental
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index 3e3126985b7..65541a499eb 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -44,12 +44,13 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
using std::size_t;
using std::ptrdiff_t;
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
/** @class __mini_vector bitmap_allocator.h bitmap_allocator.h
*
* @brief __mini_vector<> is a stripped down version of the
@@ -501,12 +502,8 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
size_t __mask = 1 << __pos;
*__pbmap |= __mask;
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/** @brief Generic Version of the bsf instruction.
*/
inline size_t
@@ -1134,4 +1131,3 @@ _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __gnu_cxx
#endif
-
diff --git a/libstdc++-v3/include/ext/codecvt_specializations.h b/libstdc++-v3/include/ext/codecvt_specializations.h
index 1f0452f4f80..fdc5c5b98bf 100644
--- a/libstdc++-v3/include/ext/codecvt_specializations.h
+++ b/libstdc++-v3/include/ext/codecvt_specializations.h
@@ -41,8 +41,8 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
-_GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_CXX11
/// Extension to use iconv for dealing with character encodings.
// This includes conversions and comparisons between various character
@@ -215,8 +215,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename std::fpos<state_type> pos_type;
};
-_GLIBCXX_END_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_CXX11
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random
index d93757b08dd..3665b285de7 100644
--- a/libstdc++-v3/include/ext/random
+++ b/libstdc++-v3/include/ext/random
@@ -112,7 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr result_type
min()
- { return 0; };
+ { return 0; }
static constexpr result_type
max()
@@ -184,6 +184,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef __SSE2__
__m128i _M_state[_M_nstate];
#endif
+#ifdef __ARM_NEON
+#ifdef __aarch64__
+ __Uint32x4_t _M_state[_M_nstate];
+#endif
+#endif
uint32_t _M_state32[_M_nstate32];
result_type _M_stateT[state_size];
} __attribute__ ((__aligned__ (16)));
diff --git a/libstdc++-v3/include/ext/rope b/libstdc++-v3/include/ext/rope
index 785205cb2b5..9f707a75960 100644
--- a/libstdc++-v3/include/ext/rope
+++ b/libstdc++-v3/include/ext/rope
@@ -65,6 +65,8 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
enum { _S_max_rope_depth = 45 };
@@ -76,8 +78,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
using std::allocator;
using std::_Destroy;
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// See libstdc++/36832.
template<typename _ForwardIterator, typename _Allocator>
void
@@ -150,7 +150,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class char_producer
{
public:
- virtual ~char_producer() { };
+ virtual ~char_producer() { }
virtual void
operator()(size_t __start_pos, size_t __len,
@@ -314,7 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// compile-time would do. Hence this should all be private
// for now.
// The symmetry with char_producer is accidental and temporary.
- virtual ~_Rope_char_consumer() { };
+ virtual ~_Rope_char_consumer() { }
virtual bool
operator()(const _CharT* __buffer, size_t __len) = 0;
@@ -924,9 +924,9 @@ protected:
~_Rope_self_destruct_ptr()
{ _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
#if __cpp_exceptions
- _Rope_self_destruct_ptr() : _M_ptr(0) { };
+ _Rope_self_destruct_ptr() : _M_ptr(0) { }
#else
- _Rope_self_destruct_ptr() { };
+ _Rope_self_destruct_ptr() { }
#endif
_Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p)
: _M_ptr(__p) { }
@@ -1153,7 +1153,7 @@ protected:
typedef const _CharT* pointer;
public:
- _Rope_const_iterator() { };
+ _Rope_const_iterator() { }
_Rope_const_iterator(const _Rope_const_iterator& __x)
: _Rope_iterator_base<_CharT,_Alloc>(__x) { }
@@ -1325,7 +1325,7 @@ protected:
_Rope_iterator()
{
this->_M_root = 0; // Needed for reference counting.
- };
+ }
_Rope_iterator(const _Rope_iterator& __x)
: _Rope_iterator_base<_CharT, _Alloc>(__x)
@@ -2937,10 +2937,10 @@ _GLIBCXX_END_NAMESPACE_VERSION
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
template<>
struct hash<__gnu_cxx::crope>
{
@@ -2967,9 +2967,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return 13 * __str[0] + 5 * __str[__size - 1] + __size;
}
};
+} // namespace tr1
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace tr1
} // namespace std
# include <ext/ropeimpl.h>
diff --git a/libstdc++-v3/include/ext/ropeimpl.h b/libstdc++-v3/include/ext/ropeimpl.h
index 471b13f4f95..9e88ce14c18 100644
--- a/libstdc++-v3/include/ext/ropeimpl.h
+++ b/libstdc++-v3/include/ext/ropeimpl.h
@@ -844,7 +844,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
_Rope_flatten_char_consumer(_CharT* __buffer)
- { _M_buf_ptr = __buffer; };
+ { _M_buf_ptr = __buffer; }
~_Rope_flatten_char_consumer() {}
@@ -897,8 +897,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Insert_ostream& _M_o;
public:
_Rope_insert_char_consumer(_Insert_ostream& __writer)
- : _M_o(__writer) {};
- ~_Rope_insert_char_consumer() { };
+ : _M_o(__writer) {}
+ ~_Rope_insert_char_consumer() { }
// Caller is presumed to own the ostream
bool operator() (const _CharT* __leaf, size_t __n);
// Returns true to continue traversal.
diff --git a/libstdc++-v3/include/ext/typelist.h b/libstdc++-v3/include/ext/typelist.h
index 46e653b40c5..3999c153501 100644
--- a/libstdc++-v3/include/ext/typelist.h
+++ b/libstdc++-v3/include/ext/typelist.h
@@ -127,18 +127,7 @@ namespace typelist
template<typename T1, typename T2, typename T3,
typename T4, typename T5, typename T6>
struct create6;
-} // namespace typelist
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-
-namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-namespace typelist
-{
namespace detail
{
template<typename Fn, typename Typelist_Chain>
@@ -366,10 +355,6 @@ namespace detail
typedef typename append_type::type::root type;
};
} // namespace detail
-} // namespace typelist
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
@@ -392,12 +377,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN18(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) >
#define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN19(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) >
-namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-namespace typelist
-{
template<typename Fn, typename Typelist>
void
apply(Fn& fn, Typelist)
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index c3a6ba8f873..1bcbf524a7b 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -45,6 +45,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
/**
* @defgroup chrono Time
* @ingroup utilities
@@ -58,19 +60,13 @@ namespace std _GLIBCXX_VISIBILITY(default)
*/
namespace chrono
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Rep, typename _Period = ratio<1>>
struct duration;
template<typename _Clock, typename _Dur = typename _Clock::duration>
struct time_point;
-
- _GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
template<typename _CT, typename _Period1, typename _Period2>
@@ -117,12 +113,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
common_type<_Duration1, _Duration2>>::type, _Clock>::type
{ };
-_GLIBCXX_END_NAMESPACE_VERSION
-
namespace chrono
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// Primary template for duration_cast impl.
template<typename _ToDur, typename _CF, typename _CR,
bool _NumIsOne = false, bool _DenIsOne = false>
@@ -871,8 +863,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
using high_resolution_clock = system_clock;
} // end inline namespace _V2
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace chrono
#if __cplusplus > 201103L
@@ -883,8 +873,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
{
inline namespace chrono_literals
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Rep, unsigned long long _Val>
struct _Checked_integral_constant
: integral_constant<_Rep, static_cast<_Rep>(_Val)>
@@ -959,22 +947,19 @@ _GLIBCXX_END_NAMESPACE_VERSION
operator""ns()
{ return __check_overflow<chrono::nanoseconds, _Digits...>(); }
- _GLIBCXX_END_NAMESPACE_VERSION
} // inline namespace chrono_literals
} // inline namespace literals
namespace chrono
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- using namespace literals::chrono_literals;
-
- _GLIBCXX_END_NAMESPACE_VERSION
+ using namespace literals::chrono_literals;
} // namespace chrono
#endif // __cplusplus > 201103L
// @} group chrono
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif //_GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 6342c98e88a..bd8b09d84f0 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -1937,14 +1937,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::complex<__type>(__x, -__type());
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
#if __cplusplus > 201103L
inline namespace literals {
inline namespace complex_literals {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
#define __cpp_lib_complex_udls 201309
constexpr std::complex<float>
@@ -1971,12 +1967,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator""il(unsigned long long __num)
{ return std::complex<long double>{0.0L, static_cast<long double>(__num)}; }
-_GLIBCXX_END_NAMESPACE_VERSION
} // inline namespace complex_literals
} // inline namespace literals
#endif // C++14
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++11
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 465b3ec7792..a6d121bb150 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -259,15 +259,12 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
*/
template<int _Num> struct _Placeholder { };
- _GLIBCXX_END_NAMESPACE_VERSION
-
/** @namespace std::placeholders
* @brief ISO C++11 entities sub-namespace for functional.
* @ingroup binders
*/
namespace placeholders
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
/* Define a large number of placeholders. There is no way to
* simplify this with variadic templates, because we're introducing
* unique names for each.
@@ -301,11 +298,8 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
extern const _Placeholder<27> _27;
extern const _Placeholder<28> _28;
extern const _Placeholder<29> _29;
- _GLIBCXX_END_NAMESPACE_VERSION
}
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* Partial specialization of is_placeholder that provides the placeholder
* number for the placeholder objects defined by libstdc++.
diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream
index 1fa25555771..233cc6b0145 100644
--- a/libstdc++-v3/include/std/istream
+++ b/libstdc++-v3/include/std/istream
@@ -150,9 +150,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* whatever data is appropriate for the type of the argument.
*
* If an exception is thrown during extraction, ios_base::badbit
- * will be turned on in the stream's error state without causing an
- * ios_base::failure to be thrown. The original exception will then
- * be rethrown.
+ * will be turned on in the stream's error state (without causing an
+ * ios_base::failure to be thrown) and the original exception will
+ * be rethrown if badbit is set in the exceptions mask.
*/
//@{
@@ -286,9 +286,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* by gcount().
*
* If an exception is thrown during extraction, ios_base::badbit
- * will be turned on in the stream's error state without causing an
- * ios_base::failure to be thrown. The original exception will then
- * be rethrown.
+ * will be turned on in the stream's error state (without causing an
+ * ios_base::failure to be thrown) and the original exception will
+ * be rethrown if badbit is set in the exceptions mask.
*/
/**
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index df48b460571..fadb9f60481 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -557,7 +557,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#if __cplusplus > 201402L
-#define __cpp_lib_scoped_lock 201703
+#define __cpp_lib_scoped_lock 201707
/** @brief A scoped lock type for multiple lockable objects.
*
* A scoped_lock controls mutex ownership within a scope, releasing
@@ -570,7 +570,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
{ std::lock(__m...); }
- explicit scoped_lock(_MutexTypes&... __m, adopt_lock_t) noexcept
+ explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
: _M_devices(std::tie(__m...))
{ } // calling thread owns mutex
@@ -609,7 +609,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit scoped_lock(mutex_type& __m) : _M_device(__m)
{ _M_device.lock(); }
- explicit scoped_lock(mutex_type& __m, adopt_lock_t) noexcept
+ explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
: _M_device(__m)
{ } // calling thread owns mutex
diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index c7abbc1b681..17d629db81d 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -79,10 +79,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace __detail
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
// std::abs is not constexpr and doesn't support unsigned integers.
template<typename _Tp>
constexpr
@@ -117,11 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* __detail::__abs_integral(__n)
: 0;
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
+} // namespace __detail
#if __cplusplus > 201402L
diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream
index 2a56d734806..e84b60c6417 100644
--- a/libstdc++-v3/include/std/sstream
+++ b/libstdc++-v3/include/std/sstream
@@ -112,7 +112,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
explicit
basic_stringbuf(const __string_type& __str,
ios_base::openmode __mode = ios_base::in | ios_base::out)
- : __streambuf_type(), _M_mode(), _M_string(__str.data(), __str.size())
+ : __streambuf_type(), _M_mode(),
+ _M_string(__str.data(), __str.size(), __str.get_allocator())
{ _M_stringbuf_init(__mode); }
#if __cplusplus >= 201103L
@@ -165,14 +166,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__string_type
str() const
{
- __string_type __ret;
+ __string_type __ret(_M_string.get_allocator());
if (this->pptr())
{
// The current egptr() may not be the actual string end.
if (this->pptr() > this->egptr())
- __ret = __string_type(this->pbase(), this->pptr());
+ __ret.assign(this->pbase(), this->pptr());
else
- __ret = __string_type(this->pbase(), this->egptr());
+ __ret.assign(this->pbase(), this->egptr());
}
else
__ret = _M_string;
@@ -302,18 +303,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
: _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
{
- const _CharT* __str = __from._M_string.data();
+ const _CharT* const __str = __from._M_string.data();
+ const _CharT* __end = nullptr;
if (__from.eback())
{
- _M_goff[0] = __from.eback() - __str;
- _M_goff[1] = __from.gptr() - __str;
- _M_goff[2] = __from.egptr() - __str;
+ _M_goff[0] = __from.eback() - __str;
+ _M_goff[1] = __from.gptr() - __str;
+ _M_goff[2] = __from.egptr() - __str;
+ __end = __from.egptr();
}
if (__from.pbase())
{
_M_poff[0] = __from.pbase() - __str;
_M_poff[1] = __from.pptr() - __from.pbase();
_M_poff[2] = __from.epptr() - __str;
+ if (__from.pptr() > __end)
+ __end = __from.pptr();
+ }
+
+ // Set _M_string length to the greater of the get and put areas.
+ if (__end)
+ {
+ // The const_cast avoids changing this constructor's signature,
+ // because it is exported from the dynamic library.
+ auto& __mut_from = const_cast<basic_stringbuf&>(__from);
+ __mut_from._M_string._M_length(__end - __str);
}
}
diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf
index 862c4fdbe6d..a05b46e8199 100644
--- a/libstdc++-v3/include/std/streambuf
+++ b/libstdc++-v3/include/std/streambuf
@@ -768,8 +768,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
overflow(int_type __c = traits_type::eof())
{ return traits_type::eof(); }
-#if _GLIBCXX_USE_DEPRECATED
- // Annex D.6
+#if _GLIBCXX_USE_DEPRECATED && __cplusplus <= 201402L
+ // Annex D.6 (removed in C++17)
public:
/**
* @brief Tosses a character.
@@ -779,6 +779,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* See http://gcc.gnu.org/ml/libstdc++/2002-05/msg00168.html
*/
+#if __cplusplus >= 201103L
+ [[__deprecated__("stossc is deprecated, use sbumpc instead")]]
+#endif
void
stossc()
{
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 311d6d725b3..88a7686618c 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -427,23 +427,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_t _M_len;
const _CharT* _M_str;
};
-_GLIBCXX_END_NAMESPACE_VERSION
// [string.view.comparison], non-member basic_string_view comparison function
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Identity transform to create a non-deduced context, so that only one
// argument participates in template argument deduction and the other
// argument gets implicitly converted to the deduced type. See n3766.html.
template<typename _Tp>
using __idt = common_type_t<_Tp>;
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _CharT, typename _Traits>
inline bool
operator==(basic_string_view<_CharT, _Traits> __x,
@@ -634,14 +629,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_fast_hash<hash<u32string_view>> : std::false_type
{ };
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
inline namespace literals
{
inline namespace string_view_literals
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
inline constexpr basic_string_view<char>
operator""sv(const char* __str, size_t __len)
{ return basic_string_view<char>{__str, __len}; }
@@ -661,11 +653,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator""sv(const char32_t* __str, size_t __len)
{ return basic_string_view<char32_t>{__str, __len}; }
#endif
-
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace string_literals
} // namespace literals
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#include <bits/string_view.tcc>
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index 8e2cb68e295..17db5ce87ae 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -321,16 +321,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __out << __id._M_thread;
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
/** @namespace std::this_thread
* @brief ISO C++ 2011 entities sub-namespace for thread.
* 30.3.2 Namespace this_thread.
*/
namespace this_thread
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/// get_id
inline thread::id
get_id() noexcept
@@ -398,12 +394,11 @@ _GLIBCXX_END_NAMESPACE_VERSION
__now = _Clock::now();
}
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
}
// @} group threads
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index e5fe9f927c1..d0c22e35d0f 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -50,12 +50,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
namespace __variant
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<size_t _Np, typename... _Types>
struct _Nth_type;
@@ -67,12 +67,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _Nth_type<0, _First, _Rest...>
{ using type = _First; };
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __variant
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename... _Types> class tuple;
template<typename... _Types> class variant;
template <typename> struct hash;
@@ -141,13 +138,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
get(const variant<_Types...>&&);
-_GLIBCXX_END_NAMESPACE_VERSION
-
namespace __detail
{
namespace __variant
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Returns the first apparence of _Tp in _Types.
// Returns sizeof...(_Types) if _Tp is not in _Types.
template<typename _Tp, typename... _Types>
@@ -295,6 +289,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__variant::__ref_cast<_Tp>(__t));
}
+ template<typename... _Types>
+ struct _Traits
+ {
+ static constexpr bool _S_default_ctor =
+ is_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
+ static constexpr bool _S_copy_ctor =
+ (is_copy_constructible_v<_Types> && ...);
+ static constexpr bool _S_move_ctor =
+ (is_move_constructible_v<_Types> && ...);
+ static constexpr bool _S_copy_assign =
+ _S_copy_ctor && _S_move_ctor
+ && (is_copy_assignable_v<_Types> && ...);
+ static constexpr bool _S_move_assign =
+ _S_move_ctor
+ && (is_move_assignable_v<_Types> && ...);
+
+ static constexpr bool _S_trivial_dtor =
+ (is_trivially_destructible_v<_Types> && ...);
+ static constexpr bool _S_trivial_copy_ctor =
+ (is_trivially_copy_constructible_v<_Types> && ...);
+ static constexpr bool _S_trivial_move_ctor =
+ (is_trivially_move_constructible_v<_Types> && ...);
+ static constexpr bool _S_trivial_copy_assign =
+ _S_trivial_dtor && (is_trivially_copy_assignable_v<_Types> && ...);
+ static constexpr bool _S_trivial_move_assign =
+ _S_trivial_dtor && (is_trivially_move_assignable_v<_Types> && ...);
+
+ // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
+ // are always nothrow.
+ static constexpr bool _S_nothrow_default_ctor =
+ is_nothrow_default_constructible_v<
+ typename _Nth_type<0, _Types...>::type>;
+ static constexpr bool _S_nothrow_copy_ctor = false;
+ static constexpr bool _S_nothrow_move_ctor =
+ (is_nothrow_move_constructible_v<_Types> && ...);
+ static constexpr bool _S_nothrow_copy_assign = false;
+ static constexpr bool _S_nothrow_move_assign =
+ _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...);
+ };
+
// Defines members and ctors.
template<typename... _Types>
union _Variadic_union { };
@@ -360,6 +394,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Variant_storage()
{ _M_reset(); }
+ void*
+ _M_storage() const
+ {
+ return const_cast<void*>(static_cast<const void*>(
+ std::addressof(_M_u)));
+ }
+
+ constexpr bool
+ _M_valid() const noexcept
+ {
+ return this->_M_index != __index_type(variant_npos);
+ }
+
_Variadic_union<_Types...> _M_u;
using __index_type = __select_index<_Types...>;
__index_type _M_index;
@@ -379,59 +426,108 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void _M_reset()
{ _M_index = variant_npos; }
+ void*
+ _M_storage() const
+ {
+ return const_cast<void*>(static_cast<const void*>(
+ std::addressof(_M_u)));
+ }
+
+ constexpr bool
+ _M_valid() const noexcept
+ {
+ return this->_M_index != __index_type(variant_npos);
+ }
+
_Variadic_union<_Types...> _M_u;
using __index_type = __select_index<_Types...>;
__index_type _M_index;
};
- // Helps SFINAE on special member functions. Otherwise it can live in variant
- // class.
template<typename... _Types>
- struct _Variant_base :
- _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...),
- _Types...>
- {
- using _Storage =
- _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...),
- _Types...>;
+ using _Variant_storage_alias =
+ _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
- constexpr
- _Variant_base()
- noexcept(is_nothrow_default_constructible_v<
- variant_alternative_t<0, variant<_Types...>>>)
- : _Variant_base(in_place_index<0>) { }
+ // The following are (Copy|Move) (ctor|assign) layers for forwarding
+ // triviality and handling non-trivial SMF behaviors.
- _Variant_base(const _Variant_base& __rhs)
+ template<bool, typename... _Types>
+ struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
+ {
+ using _Base = _Variant_storage_alias<_Types...>;
+ using _Base::_Base;
+
+ _Copy_ctor_base(const _Copy_ctor_base& __rhs)
+ noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
{
if (__rhs._M_valid())
{
static constexpr void (*_S_vtable[])(void*, void*) =
{ &__erased_ctor<_Types&, const _Types&>... };
- _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
+ _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
this->_M_index = __rhs._M_index;
}
}
- _Variant_base(_Variant_base&& __rhs)
- noexcept((is_nothrow_move_constructible_v<_Types> && ...))
+ _Copy_ctor_base(_Copy_ctor_base&&) = default;
+ _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default;
+ _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default;
+ };
+
+ template<typename... _Types>
+ struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...>
+ {
+ using _Base = _Variant_storage_alias<_Types...>;
+ using _Base::_Base;
+ };
+
+ template<typename... _Types>
+ using _Copy_ctor_alias =
+ _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>;
+
+ template<bool, typename... _Types>
+ struct _Move_ctor_base : _Copy_ctor_alias<_Types...>
+ {
+ using _Base = _Copy_ctor_alias<_Types...>;
+ using _Base::_Base;
+
+ _Move_ctor_base(_Move_ctor_base&& __rhs)
+ noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
{
if (__rhs._M_valid())
{
static constexpr void (*_S_vtable[])(void*, void*) =
{ &__erased_ctor<_Types&, _Types&&>... };
- _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
+ _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
this->_M_index = __rhs._M_index;
}
}
- template<size_t _Np, typename... _Args>
- constexpr explicit
- _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
- : _Storage(__i, std::forward<_Args>(__args)...)
- { }
+ _Move_ctor_base(const _Move_ctor_base&) = default;
+ _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
+ _Move_ctor_base& operator=(_Move_ctor_base&&) = default;
+ };
+
+ template<typename... _Types>
+ struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...>
+ {
+ using _Base = _Copy_ctor_alias<_Types...>;
+ using _Base::_Base;
+ };
+
+ template<typename... _Types>
+ using _Move_ctor_alias =
+ _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>;
+
+ template<bool, typename... _Types>
+ struct _Copy_assign_base : _Move_ctor_alias<_Types...>
+ {
+ using _Base = _Move_ctor_alias<_Types...>;
+ using _Base::_Base;
- _Variant_base&
- operator=(const _Variant_base& __rhs)
+ _Copy_assign_base&
+ operator=(const _Copy_assign_base& __rhs)
+ noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
{
if (this->_M_index == __rhs._M_index)
{
@@ -439,16 +535,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
static constexpr void (*_S_vtable[])(void*, void*) =
{ &__erased_assign<_Types&, const _Types&>... };
- _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
+ _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
}
}
else
{
- _Variant_base __tmp(__rhs);
- this->~_Variant_base();
+ _Copy_assign_base __tmp(__rhs);
+ this->~_Copy_assign_base();
__try
{
- ::new (this) _Variant_base(std::move(__tmp));
+ ::new (this) _Copy_assign_base(std::move(__tmp));
}
__catch (...)
{
@@ -460,12 +556,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- void _M_destructive_move(_Variant_base&& __rhs)
+ _Copy_assign_base(const _Copy_assign_base&) = default;
+ _Copy_assign_base(_Copy_assign_base&&) = default;
+ _Copy_assign_base& operator=(_Copy_assign_base&&) = default;
+ };
+
+ template<typename... _Types>
+ struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...>
+ {
+ using _Base = _Move_ctor_alias<_Types...>;
+ using _Base::_Base;
+ };
+
+ template<typename... _Types>
+ using _Copy_assign_alias =
+ _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign,
+ _Types...>;
+
+ template<bool, typename... _Types>
+ struct _Move_assign_base : _Copy_assign_alias<_Types...>
+ {
+ using _Base = _Copy_assign_alias<_Types...>;
+ using _Base::_Base;
+
+ void _M_destructive_move(_Move_assign_base&& __rhs)
{
- this->~_Variant_base();
+ this->~_Move_assign_base();
__try
{
- ::new (this) _Variant_base(std::move(__rhs));
+ ::new (this) _Move_assign_base(std::move(__rhs));
}
__catch (...)
{
@@ -474,40 +593,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
- _Variant_base&
- operator=(_Variant_base&& __rhs)
- noexcept((is_nothrow_move_constructible_v<_Types> && ...)
- && (is_nothrow_move_assignable_v<_Types> && ...))
+ _Move_assign_base&
+ operator=(_Move_assign_base&& __rhs)
+ noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
{
if (this->_M_index == __rhs._M_index)
{
if (__rhs._M_valid())
{
static constexpr void (*_S_vtable[])(void*, void*) =
- { &__erased_assign<_Types&, _Types&&>... };
- _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
+ { &__erased_assign<_Types&, const _Types&>... };
+ _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
}
}
else
{
- _M_destructive_move(std::move(__rhs));
+ _Move_assign_base __tmp(__rhs);
+ this->~_Move_assign_base();
+ __try
+ {
+ ::new (this) _Move_assign_base(std::move(__tmp));
+ }
+ __catch (...)
+ {
+ this->_M_index = variant_npos;
+ __throw_exception_again;
+ }
}
+ __glibcxx_assert(this->_M_index == __rhs._M_index);
return *this;
}
- void*
- _M_storage() const
- {
- return const_cast<void*>(static_cast<const void*>(
- std::addressof(_Storage::_M_u)));
- }
+ _Move_assign_base(const _Move_assign_base&) = default;
+ _Move_assign_base(_Move_assign_base&&) = default;
+ _Move_assign_base& operator=(const _Move_assign_base&) = default;
+ };
- constexpr bool
- _M_valid() const noexcept
- {
- return this->_M_index !=
- typename _Storage::__index_type(variant_npos);
- }
+ template<typename... _Types>
+ struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...>
+ {
+ using _Base = _Copy_assign_alias<_Types...>;
+ using _Base::_Base;
+ };
+
+ template<typename... _Types>
+ using _Move_assign_alias =
+ _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign,
+ _Types...>;
+
+ template<typename... _Types>
+ struct _Variant_base : _Move_assign_alias<_Types...>
+ {
+ using _Base = _Move_assign_alias<_Types...>;
+
+ constexpr
+ _Variant_base()
+ noexcept(_Traits<_Types...>::_S_nothrow_default_ctor)
+ : _Variant_base(in_place_index<0>) { }
+
+ template<size_t _Np, typename... _Args>
+ constexpr explicit
+ _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
+ : _Base(__i, std::forward<_Args>(__args)...)
+ { }
+
+ _Variant_base(const _Variant_base&) = default;
+ _Variant_base(_Variant_base&&) = default;
+ _Variant_base& operator=(const _Variant_base&) = default;
+ _Variant_base& operator=(_Variant_base&&) = default;
};
// For how many times does _Tp appear in _Tuple?
@@ -720,12 +873,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::index_sequence<__indices...>>
: _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __variant
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp, typename... _Types>
inline constexpr bool holds_alternative(const variant<_Types...>& __v)
noexcept
@@ -882,16 +1032,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class variant
: private __detail::__variant::_Variant_base<_Types...>,
private _Enable_default_constructor<
- is_default_constructible_v<
- variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>,
+ __detail::__variant::_Traits<_Types...>::_S_default_ctor,
+ variant<_Types...>>,
private _Enable_copy_move<
- (is_copy_constructible_v<_Types> && ...),
- (is_copy_constructible_v<_Types> && ...)
- && (is_move_constructible_v<_Types> && ...)
- && (is_copy_assignable_v<_Types> && ...),
- (is_move_constructible_v<_Types> && ...),
- (is_move_constructible_v<_Types> && ...)
- && (is_move_assignable_v<_Types> && ...),
+ __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
+ __detail::__variant::_Traits<_Types...>::_S_copy_assign,
+ __detail::__variant::_Traits<_Types...>::_S_move_ctor,
+ __detail::__variant::_Traits<_Types...>::_S_move_assign,
variant<_Types...>>
{
private:
@@ -905,8 +1052,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using _Base = __detail::__variant::_Variant_base<_Types...>;
using _Default_ctor_enabler =
_Enable_default_constructor<
- is_default_constructible_v<
- variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>;
+ __detail::__variant::_Traits<_Types...>::_S_default_ctor,
+ variant<_Types...>>;
template<typename _Tp>
static constexpr bool
@@ -933,21 +1080,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr size_t __index_of =
__detail::__variant::__index_of_v<_Tp, _Types...>;
+ using _Traits = __detail::__variant::_Traits<_Types...>;
+
public:
- constexpr variant()
- noexcept(is_nothrow_default_constructible_v<__to_type<0>>) = default;
- variant(const variant&) = default;
- variant(variant&&)
- noexcept((is_nothrow_move_constructible_v<_Types> && ...)) = default;
+ variant() = default;
+ variant(const variant& __rhs) = default;
+ variant(variant&&) = default;
+ variant& operator=(const variant&) = default;
+ variant& operator=(variant&&) = default;
+ ~variant() = default;
template<typename _Tp,
typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
+ typename = enable_if_t<(sizeof...(_Types)>0)>,
typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
constexpr
variant(_Tp&& __t)
noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
- : variant(in_place_index<__accepted_index<_Tp&&>>, std::forward<_Tp>(__t))
+ : variant(in_place_index<__accepted_index<_Tp&&>>,
+ std::forward<_Tp>(__t))
{ __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
template<typename _Tp, typename... _Args,
@@ -955,7 +1107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& is_constructible_v<_Tp, _Args&&...>>>
constexpr explicit
variant(in_place_type_t<_Tp>, _Args&&... __args)
- : variant(in_place_index<__index_of<_Tp>>, std::forward<_Args>(__args)...)
+ : variant(in_place_index<__index_of<_Tp>>,
+ std::forward<_Args>(__args)...)
{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
template<typename _Tp, typename _Up, typename... _Args,
@@ -988,13 +1141,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Default_ctor_enabler(_Enable_default_constructor_tag{})
{ __glibcxx_assert(index() == _Np); }
- ~variant() = default;
-
- variant& operator=(const variant&) = default;
- variant& operator=(variant&&)
- noexcept((is_nothrow_move_constructible_v<_Types> && ...)
- && (is_nothrow_move_assignable_v<_Types> && ...)) = default;
-
template<typename _Tp>
enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
@@ -1089,7 +1235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr size_t index() const noexcept
{
if (this->_M_index ==
- typename _Base::_Storage::__index_type(variant_npos))
+ typename _Base::__index_type(variant_npos))
return variant_npos;
return this->_M_index;
}
@@ -1133,7 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr bool \
(*_S_erased_##__NAME[])(const variant&, const variant&) = \
{ &__detail::__variant::__erased_##__NAME< \
- const variant&, __indices>... }; \
+ const variant&, __indices>... }; \
template<size_t... __indices> \
constexpr inline bool \
_M_##__NAME(const variant& __rhs, \
@@ -1157,18 +1303,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
template<size_t _Np, typename _Vp>
- friend constexpr decltype(auto) __detail::__variant::
-#if _GLIBCXX_INLINE_VERSION
- __8:: // Required due to PR c++/59256
-#endif
- __get(_Vp&& __v);
+ friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v);
template<typename _Vp>
- friend void* __detail::__variant::
-#if _GLIBCXX_INLINE_VERSION
- __8:: // Required due to PR c++/59256
-#endif
- __get_storage(_Vp&& __v);
+ friend void* __detail::__variant::__get_storage(_Vp&& __v);
#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
template<typename... _Tp> \
@@ -1279,7 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename... _Types>
struct hash<variant<_Types...>>
: private __detail::__variant::_Variant_hash_base<
- variant<_Types...>, std::index_sequence_for<_Types...>>,
+ variant<_Types...>, std::index_sequence_for<_Types...>>,
public __variant_hash_call_base<_Types...>
{
using result_type = size_t;
diff --git a/libstdc++-v3/include/tr1/array b/libstdc++-v3/include/tr1/array
index 606d019ade3..04c43411941 100644
--- a/libstdc++-v3/include/tr1/array
+++ b/libstdc++-v3/include/tr1/array
@@ -35,10 +35,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/**
* @brief A standard container for storing a fixed size sequence of elements.
*
@@ -243,9 +243,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline const _Tp&
get(const array<_Tp, _Nm>& __arr)
{ return __arr[_Int]; }
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_ARRAY
diff --git a/libstdc++-v3/include/tr1/bessel_function.tcc b/libstdc++-v3/include/tr1/bessel_function.tcc
index 7ba4c8a7f0d..7ac733d73b8 100644
--- a/libstdc++-v3/include/tr1/bessel_function.tcc
+++ b/libstdc++-v3/include/tr1/bessel_function.tcc
@@ -50,6 +50,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -64,8 +66,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Compute the gamma functions required by the Temme series
* expansions of @f$ N_\nu(x) @f$ and @f$ K_\nu(x) @f$.
@@ -626,13 +626,13 @@ namespace tr1
return __n_n;
}
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_BESSEL_FUNCTION_TCC
diff --git a/libstdc++-v3/include/tr1/beta_function.tcc b/libstdc++-v3/include/tr1/beta_function.tcc
index 2770eef3cd3..7463356906f 100644
--- a/libstdc++-v3/include/tr1/beta_function.tcc
+++ b/libstdc++-v3/include/tr1/beta_function.tcc
@@ -48,6 +48,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -62,8 +64,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Return the beta function: \f$B(x,y)\f$.
*
@@ -195,13 +195,13 @@ namespace tr1
else
return __beta_lgamma(__x, __y);
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_BETA_FUNCTION_TCC
diff --git a/libstdc++-v3/include/tr1/cmath b/libstdc++-v3/include/tr1/cmath
index b24e8c2a7d3..720452e4f5a 100644
--- a/libstdc++-v3/include/tr1/cmath
+++ b/libstdc++-v3/include/tr1/cmath
@@ -145,10 +145,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
#if _GLIBCXX_USE_C99_MATH_TR1
// Using declarations to bring names from libc's <math.h> into std::tr1.
@@ -1059,16 +1059,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// @}
-#endif
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-}
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-namespace tr1
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#endif /* _GLIBCXX_USE_C99_MATH_TR1 */
// DR 550. What should the return type of pow(float,int) be?
// NB: C++11 and TR1 != C++03.
@@ -1135,20 +1126,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif // C++11
-
-
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-}
-
#if _GLIBCXX_USE_STD_SPEC_FUNCS
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-namespace tr1
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @defgroup tr1_math_spec_func Mathematical Special Functions
* @ingroup numerics
@@ -1250,12 +1229,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using std::sph_neumann;
/* @} */ // tr1_math_spec_func
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-}
#else // ! _GLIBCXX_USE_STD_SPEC_FUNCS
+} // namespace tr1
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
#include <bits/stl_algobase.h>
#include <limits>
#include <tr1/type_traits>
@@ -1274,10 +1255,10 @@ _GLIBCXX_END_NAMESPACE_VERSION
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/**
* @defgroup tr1_math_spec_func Mathematical Special Functions
* @ingroup numerics
@@ -1680,9 +1661,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/* @} */ // tr1_math_spec_func
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-}
#endif // _GLIBCXX_USE_STD_SPEC_FUNCS
+} // namespace tr1
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
#endif // _GLIBCXX_TR1_CMATH
diff --git a/libstdc++-v3/include/tr1/complex b/libstdc++-v3/include/tr1/complex
index 10dce9d1bb4..2e7d05cf227 100644
--- a/libstdc++-v3/include/tr1/complex
+++ b/libstdc++-v3/include/tr1/complex
@@ -35,10 +35,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/**
* @addtogroup complex_numbers
* @{
@@ -412,9 +412,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return std::pow(__x, __y); }
// @} group complex_numbers
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_COMPLEX
diff --git a/libstdc++-v3/include/tr1/ell_integral.tcc b/libstdc++-v3/include/tr1/ell_integral.tcc
index 01f9313a256..4bd22e5eebc 100644
--- a/libstdc++-v3/include/tr1/ell_integral.tcc
+++ b/libstdc++-v3/include/tr1/ell_integral.tcc
@@ -44,6 +44,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
#elif defined(_GLIBCXX_TR1_CMATH)
namespace tr1
@@ -56,8 +58,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Return the Carlson elliptic function @f$ R_F(x,y,z) @f$
* of the first kind.
@@ -745,12 +745,12 @@ namespace tr1
return __Pi + _Tp(2) * __n * __comp_ellint_3(__k, __nu);
}
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_ELL_INTEGRAL_TCC
diff --git a/libstdc++-v3/include/tr1/exp_integral.tcc b/libstdc++-v3/include/tr1/exp_integral.tcc
index 8e6f55178e7..663b2ce2f73 100644
--- a/libstdc++-v3/include/tr1/exp_integral.tcc
+++ b/libstdc++-v3/include/tr1/exp_integral.tcc
@@ -49,6 +49,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
#elif defined(_GLIBCXX_TR1_CMATH)
namespace tr1
@@ -61,8 +63,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _Tp> _Tp __expint_E1(_Tp);
/**
@@ -522,12 +522,12 @@ namespace tr1
else
return __expint_Ei(__x);
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_EXP_INTEGRAL_TCC
diff --git a/libstdc++-v3/include/tr1/functional b/libstdc++-v3/include/tr1/functional
index 256f94d8a5f..cb40e90e255 100644
--- a/libstdc++-v3/include/tr1/functional
+++ b/libstdc++-v3/include/tr1/functional
@@ -48,18 +48,15 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-#if __cplusplus >= 201103L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#if __cplusplus >= 201103L
template<int> struct _Placeholder;
template<typename> class _Bind;
template<typename, typename> class _Bind_result;
-_GLIBCXX_END_NAMESPACE_VERSION
#endif
namespace tr1
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _MemberPointer>
class _Mem_fn;
template<typename _Tp, typename _Class>
@@ -855,14 +852,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// The type of placeholder objects defined by libstdc++.
template<int _Num> struct _Placeholder { };
-_GLIBCXX_END_NAMESPACE_VERSION
-
/** @namespace std::tr1::placeholders
* @brief Sub-namespace for tr1/functional.
*/
namespace placeholders
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
/* Define a large number of placeholders. There is no way to
* simplify this with variadic templates, because we're introducing
* unique names for each.
@@ -899,10 +893,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
_Placeholder<28> _28;
_Placeholder<29> _29;
}
- _GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* Partial specialization of is_placeholder that provides the placeholder
* number for the placeholder objects defined by libstdc++.
@@ -2247,12 +2239,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
swap(function<_Signature>& __x, function<_Signature>& __y)
{ __x.swap(__y); }
-
-_GLIBCXX_END_NAMESPACE_VERSION
}
#if __cplusplus >= 201103L
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename> struct is_placeholder;
@@ -2301,8 +2290,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Signature>>
: true_type { };
+#endif // C++11
_GLIBCXX_END_NAMESPACE_VERSION
-#endif
}
#endif // _GLIBCXX_TR1_FUNCTIONAL
diff --git a/libstdc++-v3/include/tr1/functional_hash.h b/libstdc++-v3/include/tr1/functional_hash.h
index acc766ddd53..f8cff25257f 100644
--- a/libstdc++-v3/include/tr1/functional_hash.h
+++ b/libstdc++-v3/include/tr1/functional_hash.h
@@ -34,10 +34,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/// Class template hash.
// Declaration of default hash functor std::tr1::hash. The types for
// which std::tr1::hash<T> is well-defined is in clause 6.3.3. of the PDTR.
@@ -192,9 +192,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_PURE size_t
hash<const wstring&>::operator()(const wstring&) const;
#endif
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_FUNCTIONAL_HASH_H
diff --git a/libstdc++-v3/include/tr1/gamma.tcc b/libstdc++-v3/include/tr1/gamma.tcc
index dbbca1e9e80..7c4a664e5c9 100644
--- a/libstdc++-v3/include/tr1/gamma.tcc
+++ b/libstdc++-v3/include/tr1/gamma.tcc
@@ -50,6 +50,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -62,8 +64,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief This returns Bernoulli numbers from a table or by summation
* for larger values.
@@ -466,13 +466,13 @@ namespace tr1
return __result;
}
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_TR1_GAMMA_TCC
diff --git a/libstdc++-v3/include/tr1/hashtable.h b/libstdc++-v3/include/tr1/hashtable.h
index 8dc7a41ad5e..6e798cfd1dd 100644
--- a/libstdc++-v3/include/tr1/hashtable.h
+++ b/libstdc++-v3/include/tr1/hashtable.h
@@ -37,10 +37,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
// Class template _Hashtable, class definition.
// Meaning of class template _Hashtable's template parameters
@@ -1173,9 +1173,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_exception_again;
}
}
+} // namespace tr1
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace tr1
} // namespace std
#endif // _GLIBCXX_TR1_HASHTABLE_H
diff --git a/libstdc++-v3/include/tr1/hashtable_policy.h b/libstdc++-v3/include/tr1/hashtable_policy.h
index f44d0cf9a73..9a75443ccb6 100644
--- a/libstdc++-v3/include/tr1/hashtable_policy.h
+++ b/libstdc++-v3/include/tr1/hashtable_policy.h
@@ -30,12 +30,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace tr1
{
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// Helper function: return distance(first, last) for forward
// iterators, or 0 for input iterators.
template<class _Iterator>
@@ -772,7 +772,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1 _M_h1;
_H2 _M_h2;
};
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
}
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
diff --git a/libstdc++-v3/include/tr1/hypergeometric.tcc b/libstdc++-v3/include/tr1/hypergeometric.tcc
index 49af5f98d96..dc9f176e27a 100644
--- a/libstdc++-v3/include/tr1/hypergeometric.tcc
+++ b/libstdc++-v3/include/tr1/hypergeometric.tcc
@@ -43,6 +43,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -57,8 +59,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief This routine returns the confluent hypergeometric function
* by series expansion.
@@ -773,13 +773,13 @@ namespace tr1
else
return __hyperg_luke(__a, __b, __c, __x);
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_HYPERGEOMETRIC_TCC
diff --git a/libstdc++-v3/include/tr1/legendre_function.tcc b/libstdc++-v3/include/tr1/legendre_function.tcc
index ea2a511d977..16fee54e9c4 100644
--- a/libstdc++-v3/include/tr1/legendre_function.tcc
+++ b/libstdc++-v3/include/tr1/legendre_function.tcc
@@ -48,6 +48,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -62,8 +64,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Return the Legendre polynomial by recursion on order
* @f$ l @f$.
@@ -301,13 +301,13 @@ namespace tr1
}
}
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_LEGENDRE_FUNCTION_TCC
diff --git a/libstdc++-v3/include/tr1/modified_bessel_func.tcc b/libstdc++-v3/include/tr1/modified_bessel_func.tcc
index d21e3c7de66..79d7d7578fa 100644
--- a/libstdc++-v3/include/tr1/modified_bessel_func.tcc
+++ b/libstdc++-v3/include/tr1/modified_bessel_func.tcc
@@ -50,6 +50,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
#elif defined(_GLIBCXX_TR1_CMATH)
namespace tr1
@@ -62,8 +64,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Compute the modified Bessel functions @f$ I_\nu(x) @f$ and
* @f$ K_\nu(x) @f$ and their first derivatives
@@ -430,12 +430,12 @@ namespace tr1
return;
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_MODIFIED_BESSEL_FUNC_TCC
diff --git a/libstdc++-v3/include/tr1/poly_hermite.tcc b/libstdc++-v3/include/tr1/poly_hermite.tcc
index 80ea2187e4f..8136284310c 100644
--- a/libstdc++-v3/include/tr1/poly_hermite.tcc
+++ b/libstdc++-v3/include/tr1/poly_hermite.tcc
@@ -41,6 +41,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
#elif defined(_GLIBCXX_TR1_CMATH)
namespace tr1
@@ -53,8 +55,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief This routine returns the Hermite polynomial
* of order n: \f$ H_n(x) \f$ by recursion on n.
@@ -120,12 +120,12 @@ namespace tr1
else
return __poly_hermite_recursion(__n, __x);
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_POLY_HERMITE_TCC
diff --git a/libstdc++-v3/include/tr1/poly_laguerre.tcc b/libstdc++-v3/include/tr1/poly_laguerre.tcc
index 0c33c032040..420b1f34db4 100644
--- a/libstdc++-v3/include/tr1/poly_laguerre.tcc
+++ b/libstdc++-v3/include/tr1/poly_laguerre.tcc
@@ -43,6 +43,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -57,8 +59,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief This routine returns the associated Laguerre polynomial
* of order @f$ n @f$, degree @f$ \alpha @f$ for large n.
@@ -317,13 +317,13 @@ namespace tr1
inline _Tp
__laguerre(unsigned int __n, _Tp __x)
{ return __poly_laguerre<unsigned int, _Tp>(__n, 0, __x); }
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_POLY_LAGUERRE_TCC
diff --git a/libstdc++-v3/include/tr1/random.h b/libstdc++-v3/include/tr1/random.h
index 67654a8bb8f..79a5b8f8cd4 100644
--- a/libstdc++-v3/include/tr1/random.h
+++ b/libstdc++-v3/include/tr1/random.h
@@ -35,6 +35,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace tr1
{
// [5.1] Random number generation
@@ -50,8 +52,6 @@ namespace tr1
*/
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<typename _UIntType, int __w,
bool = __w < std::numeric_limits<_UIntType>::digits>
struct _Shift
@@ -212,12 +212,8 @@ namespace tr1
private:
_Engine* _M_g;
};
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* Produces random numbers on a given distribution function using a
* non-uniform random number generation engine.
@@ -594,7 +590,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
result_type
min() const
- { return 0; };
+ { return 0; }
result_type
max() const
@@ -2410,8 +2406,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/* @} */ // group tr1_random_distributions_continuous
/* @} */ // group tr1_random_distributions
/* @} */ // group tr1_random
-_GLIBCXX_END_NAMESPACE_VERSION
}
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_RANDOM_H
diff --git a/libstdc++-v3/include/tr1/random.tcc b/libstdc++-v3/include/tr1/random.tcc
index 265bd0bc2db..25f444a1644 100644
--- a/libstdc++-v3/include/tr1/random.tcc
+++ b/libstdc++-v3/include/tr1/random.tcc
@@ -33,6 +33,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace tr1
{
/*
@@ -40,8 +42,6 @@ namespace tr1
*/
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// General case for x = (ax + c) mod m -- use Schrage's algorithm to avoid
// integer overflow.
//
@@ -92,11 +92,8 @@ namespace tr1
__calc(_Tp __x)
{ return __a * __x + __c; }
};
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
const _UIntType
linear_congruential<_UIntType, __a, __c, __m>::multiplier;
@@ -1713,9 +1710,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__os.precision(__precision);
return __os;
}
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif
diff --git a/libstdc++-v3/include/tr1/regex b/libstdc++-v3/include/tr1/regex
index bfb5ef770d4..6cb8c154e86 100644
--- a/libstdc++-v3/include/tr1/regex
+++ b/libstdc++-v3/include/tr1/regex
@@ -45,6 +45,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace tr1
{
/**
@@ -58,8 +60,6 @@ namespace tr1
*/
namespace regex_constants
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @name 5.1 Regular Expression Syntax Options
*/
@@ -397,11 +397,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static const error_type error_stack(_S_error_stack);
//@}
-_GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// [7.8] Class regex_error
/**
* @brief A regular expression exception class.
@@ -2722,9 +2719,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
//@}
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_REGEX
diff --git a/libstdc++-v3/include/tr1/riemann_zeta.tcc b/libstdc++-v3/include/tr1/riemann_zeta.tcc
index b4992f265ae..130cef63c45 100644
--- a/libstdc++-v3/include/tr1/riemann_zeta.tcc
+++ b/libstdc++-v3/include/tr1/riemann_zeta.tcc
@@ -46,6 +46,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
# define _GLIBCXX_MATH_NS ::std
#elif defined(_GLIBCXX_TR1_CMATH)
@@ -60,8 +62,6 @@ namespace tr1
// Implementation-space details.
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/**
* @brief Compute the Riemann zeta function @f$ \zeta(s) @f$
* by summation for s > 1.
@@ -431,13 +431,13 @@ namespace tr1
inline _Tp
__hurwitz_zeta(_Tp __a, _Tp __s)
{ return __hurwitz_zeta_glob(__a, __s); }
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#undef _GLIBCXX_MATH_NS
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_RIEMANN_ZETA_TCC
diff --git a/libstdc++-v3/include/tr1/shared_ptr.h b/libstdc++-v3/include/tr1/shared_ptr.h
index f702cd68972..95ac9775b9b 100644
--- a/libstdc++-v3/include/tr1/shared_ptr.h
+++ b/libstdc++-v3/include/tr1/shared_ptr.h
@@ -51,10 +51,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/**
* @brief Exception possibly thrown by @c shared_ptr.
* @ingroup exceptions
@@ -1162,9 +1162,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
mutable weak_ptr<_Tp> _M_weak_this;
};
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _TR1_SHARED_PTR_H
diff --git a/libstdc++-v3/include/tr1/special_function_util.h b/libstdc++-v3/include/tr1/special_function_util.h
index 9d40a16ca6c..c4e9c476150 100644
--- a/libstdc++-v3/include/tr1/special_function_util.h
+++ b/libstdc++-v3/include/tr1/special_function_util.h
@@ -38,6 +38,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#if _GLIBCXX_USE_STD_SPEC_FUNCS
#elif defined(_GLIBCXX_TR1_CMATH)
namespace tr1
@@ -47,8 +49,6 @@ namespace tr1
#endif
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
/// A class to encapsulate type dependent floating point
/// constants. Not everything will be able to be expressed as
/// type logic.
@@ -130,12 +130,12 @@ namespace tr1
{ return __builtin_isnanl(__x); }
#endif
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
#if ! _GLIBCXX_USE_STD_SPEC_FUNCS && defined(_GLIBCXX_TR1_CMATH)
} // namespace tr1
#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif // _GLIBCXX_TR1_SPECIAL_FUNCTION_UTIL_H
diff --git a/libstdc++-v3/include/tr1/tuple b/libstdc++-v3/include/tr1/tuple
index fe53a8b99b0..997542d241b 100644
--- a/libstdc++-v3/include/tr1/tuple
+++ b/libstdc++-v3/include/tr1/tuple
@@ -38,10 +38,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
// Adds a const reference to a non-reference type.
template<typename _Tp>
struct __add_c_ref
@@ -418,9 +418,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_Swallow_assign ignore;
}; // anonymous namespace
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_TUPLE
diff --git a/libstdc++-v3/include/tr1/type_traits b/libstdc++-v3/include/tr1/type_traits
index abdb83b48ec..83dd7b7dcf2 100644
--- a/libstdc++-v3/include/tr1/type_traits
+++ b/libstdc++-v3/include/tr1/type_traits
@@ -35,10 +35,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
/**
* @addtogroup metaprogramming
* @{
@@ -679,9 +679,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#undef _DEFINE_SPEC
/// @} group metaprogramming
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_TYPE_TRAITS
diff --git a/libstdc++-v3/include/tr1/unordered_map.h b/libstdc++-v3/include/tr1/unordered_map.h
index 34776aeea58..a27654a45d2 100644
--- a/libstdc++-v3/include/tr1/unordered_map.h
+++ b/libstdc++-v3/include/tr1/unordered_map.h
@@ -29,10 +29,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
// NB: When we get typedef templates these class definitions
// will be unnecessary.
template<class _Key, class _Tp,
@@ -272,7 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
{ __x.swap(__y); }
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
diff --git a/libstdc++-v3/include/tr1/unordered_set.h b/libstdc++-v3/include/tr1/unordered_set.h
index f9d04901cc5..df24ca6b299 100644
--- a/libstdc++-v3/include/tr1/unordered_set.h
+++ b/libstdc++-v3/include/tr1/unordered_set.h
@@ -29,10 +29,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
// NB: When we get typedef templates these class definitions
// will be unnecessary.
template<class _Value,
@@ -261,7 +261,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
{ __x.swap(__y); }
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
diff --git a/libstdc++-v3/include/tr1/utility b/libstdc++-v3/include/tr1/utility
index 91076d9882c..f114160005f 100644
--- a/libstdc++-v3/include/tr1/utility
+++ b/libstdc++-v3/include/tr1/utility
@@ -37,10 +37,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr1
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr1
+{
template<class _Tp>
class tuple_size;
@@ -100,9 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline const typename tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&
get(const std::pair<_Tp1, _Tp2>& __in)
{ return __pair_get<_Int>::__const_get(__in); }
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR1_UTILITY
diff --git a/libstdc++-v3/include/tr2/bool_set b/libstdc++-v3/include/tr2/bool_set
index 9d55b3c0ebd..f89a8658932 100644
--- a/libstdc++-v3/include/tr2/bool_set
+++ b/libstdc++-v3/include/tr2/bool_set
@@ -36,10 +36,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
/**
* bool_set
*
@@ -310,10 +310,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool_set
operator!=(bool_set __s, bool_set __t)
{ return ! (__s == __t); }
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#include <tr2/bool_set.tcc>
diff --git a/libstdc++-v3/include/tr2/bool_set.tcc b/libstdc++-v3/include/tr2/bool_set.tcc
index a5fd898a822..1ffcccac901 100644
--- a/libstdc++-v3/include/tr2/bool_set.tcc
+++ b/libstdc++-v3/include/tr2/bool_set.tcc
@@ -33,10 +33,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
bool_set::_Bool_set_val
bool_set::_S_not[4] =
{ _S_true_, _S_false, _S_indet, _S_empty };
@@ -68,10 +68,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ _S_false, _S_true_, _S_indet, _S_empty },
{ _S_indet, _S_indet, _S_indet, _S_empty },
{ _S_empty, _S_empty, _S_empty, _S_empty } };
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
// I object to these things.
// The stuff in locale facets are for basic types.
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
index ff4e5887eb9..4d16f8178b6 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -42,10 +42,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
/**
* @defgroup dynamic_bitset Dynamic Bitset.
* @ingroup extensions
@@ -1220,9 +1220,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @}
*/
+} // tr2
_GLIBCXX_END_NAMESPACE_VERSION
-} // tr2
} // std
#include <tr2/dynamic_bitset.tcc>
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset.tcc b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
index 7b64580ccfc..c2875e54257 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset.tcc
+++ b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
@@ -34,10 +34,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
// Definitions of non-inline functions from __dynamic_bitset_base.
template<typename _WordT, typename _Alloc>
void
@@ -272,9 +272,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__is.setstate(__state);
return __is;
}
+} // tr2
_GLIBCXX_END_NAMESPACE_VERSION
-} // tr2
} // std
#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET_TCC */
diff --git a/libstdc++-v3/include/tr2/ratio b/libstdc++-v3/include/tr2/ratio
index c0a2d4d3065..a9b71c8f121 100644
--- a/libstdc++-v3/include/tr2/ratio
+++ b/libstdc++-v3/include/tr2/ratio
@@ -30,10 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
template<intmax_t _Pn, size_t _Bit,
bool = _Bit < static_cast<size_t>
(std::numeric_limits<intmax_t>::digits)>
@@ -53,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef ratio<__safe_lshift<1, 60>::__value, 1> exbi;
//typedef ratio<__safe_lshift<1, 70>::__value, 1> zebi;
//typedef ratio<__safe_lshift<1, 80>::__value, 1> yobi;
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
index 35f621500d6..b442ba5dc64 100644
--- a/libstdc++-v3/include/tr2/type_traits
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -35,10 +35,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-namespace tr2
-{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace tr2
+{
/**
* @addtogroup metaprogramming
* @{
@@ -98,9 +98,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/// @} group metaprogramming
+}
_GLIBCXX_END_NAMESPACE_VERSION
}
-}
#endif // _GLIBCXX_TR2_TYPE_TRAITS
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 04f172cebd0..795b33c4e6a 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -68,7 +68,7 @@ namespace std
class bad_array_new_length : public bad_alloc
{
public:
- bad_array_new_length() throw() { };
+ bad_array_new_length() throw() { }
// This declaration is not useless:
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 8122cf81834..04f413adf04 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1555,15 +1555,15 @@ def build_libstdcxx_dictionary ():
libstdcxx_printer.add_container('std::', 'forward_list',
StdForwardListPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'unordered_map',
+ libstdcxx_printer.add_version('std::', 'tr1::shared_ptr', SharedPointerPrinter)
+ libstdcxx_printer.add_version('std::', 'tr1::weak_ptr', SharedPointerPrinter)
+ libstdcxx_printer.add_version('std::', 'tr1::unordered_map',
Tr1UnorderedMapPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'unordered_set',
+ libstdcxx_printer.add_version('std::', 'tr1::unordered_set',
Tr1UnorderedSetPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap',
+ libstdcxx_printer.add_version('std::', 'tr1::unordered_multimap',
Tr1UnorderedMapPrinter)
- libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
+ libstdcxx_printer.add_version('std::', 'tr1::unordered_multiset',
Tr1UnorderedSetPrinter)
# These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases.
diff --git a/libstdc++-v3/src/c++11/chrono.cc b/libstdc++-v3/src/c++11/chrono.cc
index 39a52aea619..337860c23d8 100644
--- a/libstdc++-v3/src/c++11/chrono.cc
+++ b/libstdc++-v3/src/c++11/chrono.cc
@@ -41,10 +41,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace chrono
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// XXX GLIBCXX_ABI Deprecated
inline namespace _V2 {
@@ -97,9 +97,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
}
} // end inline namespace _V2
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace chrono
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/src/c++11/compatibility-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-c++0x.cc
index 358263baff4..811ccb5f120 100644
--- a/libstdc++-v3/src/c++11/compatibility-c++0x.cc
+++ b/libstdc++-v3/src/c++11/compatibility-c++0x.cc
@@ -44,6 +44,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
// gcc-4.4.0
// <mutex> exported std::lock_error
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
@@ -130,7 +132,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
constexpr bool system_clock::is_monotonic;
} // namespace chrono
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// gcc-5 replaces this with _V2::error_category
class error_category
{
@@ -169,7 +170,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(const error_category& __other) const noexcept
{ return this != &__other; }
};
-_GLIBCXX_END_NAMESPACE_VERSION
// gcc-4.9.0
// LWG 2145 changes this constructor to constexpr i.e. inline
@@ -215,7 +215,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
const system_error_category system_category_instance{};
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
const error_category&
system_category() noexcept { return system_category_instance; }
@@ -227,7 +226,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_CONST const error_categoryxx& system_category() noexcept;
_GLIBCXX_CONST const error_categoryxx& generic_category() noexcept;
}
-_GLIBCXX_END_NAMESPACE_VERSION
error_condition
error_category::default_error_condition(int __i) const noexcept
@@ -254,5 +252,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
return false;
}
+_GLIBCXX_END_NAMESPACE_VERSION
}
#endif
diff --git a/libstdc++-v3/src/c++11/compatibility-chrono.cc b/libstdc++-v3/src/c++11/compatibility-chrono.cc
index e401375928d..941eaf83556 100644
--- a/libstdc++-v3/src/c++11/compatibility-chrono.cc
+++ b/libstdc++-v3/src/c++11/compatibility-chrono.cc
@@ -38,10 +38,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace chrono
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// NB: Default configuration was no realtime.
struct system_clock
{
@@ -84,9 +84,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
(__from(chrono::seconds(__sec)));
#endif
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace chrono
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/src/c++11/cxx11-shim_facets.cc b/libstdc++-v3/src/c++11/cxx11-shim_facets.cc
index b69959f4f13..fbff59eb5f0 100644
--- a/libstdc++-v3/src/c++11/cxx11-shim_facets.cc
+++ b/libstdc++-v3/src/c++11/cxx11-shim_facets.cc
@@ -45,6 +45,8 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
// Base class of facet shims, holds a reference to the underlying facet
// that the shim forwards to.
class locale::facet::__shim
@@ -67,8 +69,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
namespace __facet_shims
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
namespace // unnamed
{
template<typename C>
@@ -777,10 +777,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool, ios_base&, wchar_t, long double, const __any_string*);
#endif
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __facet_shims
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Create a new shim facet of type WHICH that forwards calls to F.
// F is the replacement facet provided by the user, WHICH is the ID of
// F's "other ABI twin" which we are replacing with a shim.
diff --git a/libstdc++-v3/src/c++11/hashtable_c++0x.cc b/libstdc++-v3/src/c++11/hashtable_c++0x.cc
index 1b099928942..3ddc10c72f7 100644
--- a/libstdc++-v3/src/c++11/hashtable_c++0x.cc
+++ b/libstdc++-v3/src/c++11/hashtable_c++0x.cc
@@ -34,12 +34,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
#include "../shared/hashtable-aux.cc"
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
// Return a prime no smaller than n.
std::size_t
_Prime_rehash_policy::_M_next_bkt(std::size_t __n) const
@@ -111,7 +111,7 @@ namespace __detail
else
return std::make_pair(false, 0);
}
+} // namespace __detail
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace __detail
} // namespace std
diff --git a/libstdc++-v3/src/c++11/placeholders.cc b/libstdc++-v3/src/c++11/placeholders.cc
index fad78f2e98d..48a05fab365 100644
--- a/libstdc++-v3/src/c++11/placeholders.cc
+++ b/libstdc++-v3/src/c++11/placeholders.cc
@@ -30,9 +30,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace placeholders
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
extern const _Placeholder<1> _1{};
extern const _Placeholder<2> _2{};
extern const _Placeholder<3> _3{};
@@ -62,6 +63,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
extern const _Placeholder<27> _27{};
extern const _Placeholder<28> _28{};
extern const _Placeholder<29> _29{};
- _GLIBCXX_END_NAMESPACE_VERSION
}
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index 4a94bdd2f8c..cd6d9fe6635 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -180,12 +180,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __n;
}
-_GLIBCXX_END_NAMESPACE_VERSION
-
namespace this_thread
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
void
__sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
{
@@ -217,10 +213,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
::Sleep(chrono::milliseconds(__s).count() + ms);
#endif
}
-
-_GLIBCXX_END_NAMESPACE_VERSION
}
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/src/c++98/bitmap_allocator.cc b/libstdc++-v3/src/c++98/bitmap_allocator.cc
index 5a9696d97e0..b16c29143f1 100644
--- a/libstdc++-v3/src/c++98/bitmap_allocator.cc
+++ b/libstdc++-v3/src/c++98/bitmap_allocator.cc
@@ -26,9 +26,10 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
template class __mini_vector<
std::pair<bitmap_allocator<char>::_Alloc_block*,
bitmap_allocator<char>::_Alloc_block*> >;
@@ -41,11 +42,8 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
template size_t** __lower_bound(size_t**, size_t**, size_t const&,
free_list::_LT_pointer_compare);
- _GLIBCXX_END_NAMESPACE_VERSION
}
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
size_t*
free_list::
_M_get(size_t __sz) throw(std::bad_alloc)
diff --git a/libstdc++-v3/src/c++98/hashtable_tr1.cc b/libstdc++-v3/src/c++98/hashtable_tr1.cc
index 199b8fd5a5a..ac320696ad2 100644
--- a/libstdc++-v3/src/c++98/hashtable_tr1.cc
+++ b/libstdc++-v3/src/c++98/hashtable_tr1.cc
@@ -26,8 +26,12 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace tr1
{
#include "../shared/hashtable-aux.cc"
}
+
+_GLIBCXX_END_NAMESPACE_VERSION
}
diff --git a/libstdc++-v3/src/c++98/list.cc b/libstdc++-v3/src/c++98/list.cc
index 3de7d2d0e02..25e72717eca 100644
--- a/libstdc++-v3/src/c++98/list.cc
+++ b/libstdc++-v3/src/c++98/list.cc
@@ -52,10 +52,10 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
namespace __detail
{
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
void
_List_node_base::swap(_List_node_base& __x,
_List_node_base& __y) _GLIBCXX_USE_NOEXCEPT
@@ -141,7 +141,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
__prev_node->_M_next = __next_node;
__next_node->_M_prev = __prev_node;
}
-
- _GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/src/shared/hashtable-aux.cc b/libstdc++-v3/src/shared/hashtable-aux.cc
index 01c01fa3155..f1d19974bd7 100644
--- a/libstdc++-v3/src/shared/hashtable-aux.cc
+++ b/libstdc++-v3/src/shared/hashtable-aux.cc
@@ -24,7 +24,6 @@
namespace __detail
{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
// The sentinel value is kept only for abi backward compatibility.
extern const unsigned long __prime_list[] = // 256 + 1 or 256 + 48 + 1
{
@@ -90,5 +89,4 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
18446744073709551557ul, 18446744073709551557ul
#endif
};
-_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
index c0d1a6e5885..b5105dff38b 100644
--- a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
@@ -26,6 +26,6 @@ test01()
// std::numeric_limits<int64_t>::max() == 9223372036854775807;
auto h = 9223372036854775808h;
- // { dg-error "cannot be represented" "" { target *-*-* } 892 }
+ // { dg-error "cannot be represented" "" { target *-*-* } 880 }
}
// { dg-prune-output "in constexpr expansion" } // needed for -O0
diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc
index 189e97bf984..17f74187098 100644
--- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc
@@ -30,4 +30,4 @@ void test01()
test_type d; // { dg-error "required from here" }
}
-// { dg-error "rep cannot be a duration" "" { target *-*-* } 308 }
+// { dg-error "rep cannot be a duration" "" { target *-*-* } 300 }
diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc
index 501de5ee752..282a9dbdc85 100644
--- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc
@@ -31,5 +31,5 @@ void test01()
test_type d; // { dg-error "required from here" }
}
-// { dg-error "must be a specialization of ratio" "" { target *-*-* } 309 }
+// { dg-error "must be a specialization of ratio" "" { target *-*-* } 301 }
// { dg-prune-output "not a member" }
diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc
index a56bb96f5d0..c57f9d947a5 100644
--- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc
+++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc
@@ -32,4 +32,4 @@ void test01()
test_type d; // { dg-error "required from here" }
}
-// { dg-error "period must be positive" "" { target *-*-* } 311 }
+// { dg-error "period must be positive" "" { target *-*-* } 303 }
diff --git a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
index c7830d7b2d4..d098164c0f7 100644
--- a/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/c_neg.cc
@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 86 }
+// { dg-error "static assertion failed" "" { target *-*-* } 87 }
#include <list>
diff --git a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
index 7d073fe822b..0ca36d4b5a6 100644
--- a/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/f_neg.cc
@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 86 }
+// { dg-error "static assertion failed" "" { target *-*-* } 87 }
#include <utility>
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
index d80c1259c02..39d3e76ee82 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
@@ -180,6 +180,7 @@ void test12()
std::uninitialized_default_construct(target, target+10);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
@@ -198,6 +199,7 @@ void test13()
std::uninitialized_value_construct(target, target+10);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
@@ -216,6 +218,7 @@ void test14()
std::uninitialized_default_construct_n(target, 10);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
@@ -234,6 +237,7 @@ void test15()
std::uninitialized_value_construct_n(target, 10);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
@@ -254,6 +258,7 @@ void test16()
std::uninitialized_move(source.begin(), source.end(), target);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
@@ -273,6 +278,7 @@ void test17()
std::uninitialized_move_n(source.begin(), 10, target);
} catch (...) {
}
+ free(target);
VERIFY(ctor_count == 5);
VERIFY(del_count == 5);
throw_after = 0;
diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc b/libstdc++-v3/testsuite/20_util/variant/compile.cc
index 06e8eb31ee8..e5f7538ba42 100644
--- a/libstdc++-v3/testsuite/20_util/variant/compile.cc
+++ b/libstdc++-v3/testsuite/20_util/variant/compile.cc
@@ -88,10 +88,12 @@ void copy_ctor()
{
static_assert(is_copy_constructible_v<variant<int, string>>, "");
static_assert(!is_copy_constructible_v<variant<AllDeleted, string>>, "");
+ static_assert(is_trivially_copy_constructible_v<variant<int>>, "");
+ static_assert(!is_trivially_copy_constructible_v<variant<std::string>>, "");
{
variant<int> a;
- static_assert(!noexcept(variant<int>(a)), "");
+ static_assert(noexcept(variant<int>(a)), "");
}
{
variant<string> a;
@@ -103,7 +105,7 @@ void copy_ctor()
}
{
variant<int, char> a;
- static_assert(!noexcept(variant<int, char>(a)), "");
+ static_assert(noexcept(variant<int, char>(a)), "");
}
}
@@ -111,6 +113,8 @@ void move_ctor()
{
static_assert(is_move_constructible_v<variant<int, string>>, "");
static_assert(!is_move_constructible_v<variant<AllDeleted, string>>, "");
+ static_assert(is_trivially_move_constructible_v<variant<int>>, "");
+ static_assert(!is_trivially_move_constructible_v<variant<std::string>>, "");
static_assert(!noexcept(variant<int, Empty>(declval<variant<int, Empty>>())), "");
static_assert(noexcept(variant<int, DefaultNoexcept>(declval<variant<int, DefaultNoexcept>>())), "");
}
@@ -148,13 +152,15 @@ void copy_assign()
{
static_assert(is_copy_assignable_v<variant<int, string>>, "");
static_assert(!is_copy_assignable_v<variant<AllDeleted, string>>, "");
+ static_assert(is_trivially_copy_assignable_v<variant<int>>, "");
+ static_assert(!is_trivially_copy_assignable_v<variant<string>>, "");
{
variant<Empty> a;
static_assert(!noexcept(a = a), "");
}
{
variant<DefaultNoexcept> a;
- static_assert(!noexcept(a = a), "");
+ static_assert(noexcept(a = a), "");
}
}
@@ -162,6 +168,8 @@ void move_assign()
{
static_assert(is_move_assignable_v<variant<int, string>>, "");
static_assert(!is_move_assignable_v<variant<AllDeleted, string>>, "");
+ static_assert(is_trivially_move_assignable_v<variant<int>>, "");
+ static_assert(!is_trivially_move_assignable_v<variant<string>>, "");
{
variant<Empty> a;
static_assert(!noexcept(a = std::move(a)), "");
@@ -454,3 +462,92 @@ void test_emplace()
static_assert(!has_type_emplace<variant<AllDeleted>, AllDeleted>(0), "");
static_assert(!has_index_emplace<variant<AllDeleted>, 0>(0), "");
}
+
+void test_triviality()
+{
+#define TEST_TEMPLATE(DT, CC, MC, CA, MA, CC_VAL, MC_VAL, CA_VAL, MA_VAL) \
+ { \
+ struct A \
+ { \
+ ~A() DT; \
+ A(const A&) CC; \
+ A(A&&) MC; \
+ A& operator=(const A&) CA; \
+ A& operator=(A&&) MA; \
+ }; \
+ static_assert(CC_VAL == is_trivially_copy_constructible_v<variant<A>>, ""); \
+ static_assert(MC_VAL == is_trivially_move_constructible_v<variant<A>>, ""); \
+ static_assert(CA_VAL == is_trivially_copy_assignable_v<variant<A>>, ""); \
+ static_assert(MA_VAL == is_trivially_move_assignable_v<variant<A>>, ""); \
+ }
+ TEST_TEMPLATE(=default, =default, =default, =default, =default, true, true, true, true)
+ TEST_TEMPLATE(=default, =default, =default, =default, {}, true, true, true, false)
+ TEST_TEMPLATE(=default, =default, =default, {}, =default, true, true, false, true)
+ TEST_TEMPLATE(=default, =default, =default, {}, {}, true, true, false, false)
+ TEST_TEMPLATE(=default, =default, {}, =default, =default, true, false, true, true)
+ TEST_TEMPLATE(=default, =default, {}, =default, {}, true, false, true, false)
+ TEST_TEMPLATE(=default, =default, {}, {}, =default, true, false, false, true)
+ TEST_TEMPLATE(=default, =default, {}, {}, {}, true, false, false, false)
+ TEST_TEMPLATE(=default, {}, =default, =default, =default, false, true, true, true)
+ TEST_TEMPLATE(=default, {}, =default, =default, {}, false, true, true, false)
+ TEST_TEMPLATE(=default, {}, =default, {}, =default, false, true, false, true)
+ TEST_TEMPLATE(=default, {}, =default, {}, {}, false, true, false, false)
+ TEST_TEMPLATE(=default, {}, {}, =default, =default, false, false, true, true)
+ TEST_TEMPLATE(=default, {}, {}, =default, {}, false, false, true, false)
+ TEST_TEMPLATE(=default, {}, {}, {}, =default, false, false, false, true)
+ TEST_TEMPLATE(=default, {}, {}, {}, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, =default, =default, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, =default, =default, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, =default, {}, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, =default, {}, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, {}, =default, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, {}, =default, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, {}, {}, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, =default, {}, {}, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, =default, =default, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, =default, =default, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, =default, {}, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, =default, {}, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, {}, =default, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, {}, =default, {}, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, {}, {}, =default, false, false, false, false)
+ TEST_TEMPLATE( {}, {}, {}, {}, {}, false, false, false, false)
+#undef TEST_TEMPLATE
+
+#define TEST_TEMPLATE(CC, MC, CA, MA) \
+ { \
+ struct A \
+ { \
+ A(const A&) CC; \
+ A(A&&) MC; \
+ A& operator=(const A&) CA; \
+ A& operator=(A&&) MA; \
+ }; \
+ static_assert(!is_trivially_copy_constructible_v<variant<AllDeleted, A>>, ""); \
+ static_assert(!is_trivially_move_constructible_v<variant<AllDeleted, A>>, ""); \
+ static_assert(!is_trivially_copy_assignable_v<variant<AllDeleted, A>>, ""); \
+ static_assert(!is_trivially_move_assignable_v<variant<AllDeleted, A>>, ""); \
+ }
+ TEST_TEMPLATE(=default, =default, =default, =default)
+ TEST_TEMPLATE(=default, =default, =default, {})
+ TEST_TEMPLATE(=default, =default, {}, =default)
+ TEST_TEMPLATE(=default, =default, {}, {})
+ TEST_TEMPLATE(=default, {}, =default, =default)
+ TEST_TEMPLATE(=default, {}, =default, {})
+ TEST_TEMPLATE(=default, {}, {}, =default)
+ TEST_TEMPLATE(=default, {}, {}, {})
+ TEST_TEMPLATE( {}, =default, =default, =default)
+ TEST_TEMPLATE( {}, =default, =default, {})
+ TEST_TEMPLATE( {}, =default, {}, =default)
+ TEST_TEMPLATE( {}, =default, {}, {})
+ TEST_TEMPLATE( {}, {}, =default, =default)
+ TEST_TEMPLATE( {}, {}, =default, {})
+ TEST_TEMPLATE( {}, {}, {}, =default)
+ TEST_TEMPLATE( {}, {}, {}, {})
+#undef TEST_TEMPLATE
+
+ static_assert(is_trivially_copy_constructible_v<variant<DefaultNoexcept, int, char, float, double>>, "");
+ static_assert(is_trivially_move_constructible_v<variant<DefaultNoexcept, int, char, float, double>>, "");
+ static_assert(is_trivially_copy_assignable_v<variant<DefaultNoexcept, int, char, float, double>>, "");
+ static_assert(is_trivially_move_assignable_v<variant<DefaultNoexcept, int, char, float, double>>, "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/variant/deduction.cc b/libstdc++-v3/testsuite/20_util/variant/deduction.cc
new file mode 100644
index 00000000000..33bc9d2a40e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/variant/deduction.cc
@@ -0,0 +1,39 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <variant>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+ typename require_same<T, U>::type
+ check_type(U&) { }
+
+void
+test01()
+{
+ std::variant<int, double> x(3);
+
+ std::variant copy = x;
+ check_type<decltype(x)>(copy);
+ std::variant move = std::move(x);
+ check_type<decltype(x)>(move);
+}
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
index 4c23c7f60e2..c0a18ce5d5c 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/5.cc
@@ -37,34 +37,7 @@ void test04()
#ifdef _GLIBCXX_HAVE_SETENV
- const char* LANG_orig = getenv("LANG") ? strdup(getenv("LANG")) : "";
- const char* LC_ALL_orig = getenv("LC_ALL") ? strdup(getenv("LC_ALL")) : "";
- const char* LC_CTYPE_orig =
- getenv("LC_CTYPE") ? strdup(getenv("LC_CTYPE")) : "";
- const char* LC_NUMERIC_orig =
- getenv("LC_NUMERIC") ? strdup(getenv("LC_NUMERIC")) : "";
- const char* LC_TIME_orig =
- getenv("LC_TIME") ? strdup(getenv("LC_TIME")) : "";
- const char* LC_COLLATE_orig =
- getenv("LC_COLLATE") ? strdup(getenv("LC_COLLATE")) : "";
- const char* LC_MONETARY_orig =
- getenv("LC_MONETARY") ? strdup(getenv("LC_MONETARY")) : "";
- const char* LC_MESSAGES_orig =
- getenv("LC_MESSAGES") ? strdup(getenv("LC_MESSAGES")) : "";
-#if _GLIBCXX_NUM_CATEGORIES
- const char* LC_PAPER_orig =
- getenv("LC_PAPER") ? strdup(getenv("LC_PAPER")) : "";
- const char* LC_NAME_orig =
- getenv("LC_NAME") ? strdup(getenv("LC_NAME")) : "";
- const char* LC_ADDRESS_orig =
- getenv("LC_ADDRESS") ? strdup(getenv("LC_ADDRESS")) : "";
- const char* LC_TELEPHONE_orig =
- getenv("LC_TELEPHONE") ? strdup(getenv("LC_TELEPHONE")) : "";
- const char* LC_MEASUREMENT_orig =
- getenv("LC_MEASUREMENT") ? strdup(getenv("LC_MEASUREMENT")) : "";
- const char* LC_IDENTIFICATION_orig =
- getenv("LC_IDENTIFICATION") ? strdup(getenv("LC_IDENTIFICATION")) : "";
-#endif
+ char* LANG_orig = strdup(getenv("LANG") ? getenv("LANG") : "");
// Check that a "POSIX" LC_ALL is equivalent to "C".
if (!setenv("LC_ALL", "POSIX", 1))
@@ -91,12 +64,11 @@ void test04()
VERIFY( loc.name() == "en_PH" );
}
setenv("LC_ALL", "", 1);
- setenv("LANG", LANG_orig ? LANG_orig : "", 1);
- setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1);
+ setenv("LANG", LANG_orig, 1);
}
// NB: LANG checks all LC_* macro settings. As such, all LC_* macros
- // must be cleared for these tests, and then restored.
+ // must be cleared for these tests.
setenv("LC_ALL", "", 1);
setenv("LC_CTYPE", "", 1);
setenv("LC_NUMERIC", "", 1);
@@ -173,26 +145,9 @@ void test04()
}
#endif
- // Restore the environment.
- setenv("LANG", LANG_orig ? LANG_orig : "", 1);
- setenv("LC_ALL", LC_ALL_orig ? LC_ALL_orig : "", 1);
- setenv("LC_CTYPE", LC_CTYPE_orig ? LC_CTYPE_orig : "", 1);
- setenv("LC_NUMERIC", LC_NUMERIC_orig ? LC_NUMERIC_orig : "", 1);
- setenv("LC_TIME", LC_TIME_orig ? LC_TIME_orig : "", 1);
- setenv("LC_COLLATE", LC_COLLATE_orig ? LC_COLLATE_orig : "", 1);
- setenv("LC_MONETARY", LC_MONETARY_orig ? LC_MONETARY_orig : "", 1);
- setenv("LC_MESSAGES", LC_MESSAGES_orig ? LC_MESSAGES_orig : "", 1);
-#if _GLIBCXX_NUM_CATEGORIES
- setenv("LC_PAPER", LC_PAPER_orig ? LC_PAPER_orig : "", 1);
- setenv("LC_NAME", LC_NAME_orig ? LC_NAME_orig : "", 1);
- setenv("LC_ADDRESS", LC_ADDRESS_orig ? LC_ADDRESS_orig : "", 1);
- setenv("LC_TELEPHONE", LC_TELEPHONE_orig ? LC_TELEPHONE_orig : "", 1);
- setenv("LC_MEASUREMENT", LC_MEASUREMENT_orig ? LC_MEASUREMENT_orig : "", 1);
- setenv("LC_IDENTIFICATION",
- LC_IDENTIFICATION_orig ? LC_IDENTIFICATION_orig : "", 1);
-#endif
+ free(LANG_orig);
-#endif
+#endif // _GLIBCXX_HAVE_SETENV
}
int main()
diff --git a/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc
new file mode 100644
index 00000000000..0604e067252
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc
@@ -0,0 +1,71 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-options "-O0" }
+// { dg-xfail-run-if "PR c++/65816" { *-*-* } }
+
+#include <list>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+#include <ext/aligned_buffer.h>
+
+using T = int;
+
+using __gnu_test::default_init_allocator;
+
+void test01()
+{
+ typedef default_init_allocator<T> alloc_type;
+ typedef std::list<T, alloc_type> test_type;
+
+ __gnu_cxx::__aligned_buffer<test_type> buf;
+ __builtin_memset(buf._M_addr(), ~0, sizeof(test_type));
+
+ VERIFY( buf._M_ptr()->get_allocator().state != 0 );
+
+ test_type *tmp = ::new(buf._M_addr()) test_type();
+
+ VERIFY( tmp->get_allocator().state == 0 );
+
+ tmp->~test_type();
+}
+
+void test02()
+{
+ typedef default_init_allocator<T> alloc_type;
+ typedef std::list<T, alloc_type> test_type;
+
+ __gnu_cxx::__aligned_buffer<test_type> buf;
+ __builtin_memset(buf._M_addr(), ~0, sizeof(test_type));
+
+ VERIFY( buf._M_ptr()->get_allocator().state != 0 );
+
+ test_type *tmp = ::new(buf._M_addr()) test_type;
+
+ VERIFY( tmp->get_allocator().state == 0 );
+
+ tmp->~test_type();
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/sample/81221.cc b/libstdc++-v3/testsuite/25_algorithms/sample/81221.cc
new file mode 100644
index 00000000000..28ec0e3152a
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/sample/81221.cc
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+// { dg-require-parallel-mode "" }
+
+#include <algorithm>
diff --git a/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc b/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
index d88f145d754..8c3494d7041 100644
--- a/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
@@ -31,9 +31,9 @@ test01()
std::gcd(0.1, 0.1); // { dg-error "from here" }
}
-// { dg-error "integers" "" { target *-*-* } 134 }
-// { dg-error "integers" "" { target *-*-* } 135 }
-// { dg-error "not bools" "" { target *-*-* } 136 }
-// { dg-error "not bools" "" { target *-*-* } 137 }
+// { dg-error "integers" "" { target *-*-* } 130 }
+// { dg-error "integers" "" { target *-*-* } 131 }
+// { dg-error "not bools" "" { target *-*-* } 132 }
+// { dg-error "not bools" "" { target *-*-* } 133 }
// { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" }
diff --git a/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc b/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
index f2d82894531..abcac4f18c1 100644
--- a/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
@@ -31,9 +31,9 @@ test01()
std::lcm(0.1, 0.1); // { dg-error "from here" }
}
-// { dg-error "integers" "" { target *-*-* } 147 }
-// { dg-error "integers" "" { target *-*-* } 148 }
-// { dg-error "not bools" "" { target *-*-* } 149 }
-// { dg-error "not bools" "" { target *-*-* } 150 }
+// { dg-error "integers" "" { target *-*-* } 143 }
+// { dg-error "integers" "" { target *-*-* } 144 }
+// { dg-error "not bools" "" { target *-*-* } 145 }
+// { dg-error "not bools" "" { target *-*-* } 146 }
// { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" }
diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
index ad2cbc6e71b..22485222f28 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
@@ -9,6 +9,6 @@ std::__detail::_Adaptor<std::mt19937, unsigned long> aurng(urng);
auto x = std::generate_canonical<std::size_t,
std::numeric_limits<std::size_t>::digits>(urng);
-// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 160 }
+// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 156 }
-// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3314 }
+// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3311 }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc
new file mode 100644
index 00000000000..ea8dbc1259b
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-require-fileio "" }
+
+// PR libstdc++/81395
+
+#include <fstream>
+#include <cstring> // for std::memset
+#include <cstdio> // For BUFSIZ
+
+using std::memset;
+
+int main()
+{
+ {
+ std::filebuf fb;
+ fb.open("test.txt", std::ios::out);
+ char data[BUFSIZ];
+ memset(data, 'A', sizeof(data));
+ fb.sputn(data, sizeof(data));
+ }
+
+ std::filebuf fb;
+ fb.open("test.txt", std::ios::in|std::ios::out);
+ char buf[BUFSIZ];
+ memset(buf, 0, sizeof(buf));
+ fb.sgetn(buf, sizeof(buf));
+ // Switch from reading to writing without seeking first:
+ fb.sputn("B", 1);
+ fb.pubsync();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc b/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc
new file mode 100644
index 00000000000..e49d2b1ad1f
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-require-fileio "" }
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::ifstream in(".");
+ if (in)
+ {
+ int x;
+ in >> x;
+ VERIFY( in.bad() );
+ }
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc
new file mode 100644
index 00000000000..9c08c7236da
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <streambuf>
+#include <istream>
+#include <testsuite_hooks.h>
+
+struct SB : std::streambuf
+{
+ virtual int_type underflow() { throw 1; }
+};
+
+void
+test01()
+{
+ SB sb;
+ std::istream is(&sb);
+ int i;
+ is >> i;
+ VERIFY( is.bad() );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/81381.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/81381.cc
new file mode 100644
index 00000000000..865449d72ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/cons/81381.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+// PR libstdc++/81381
+
+#include <memory>
+#include <sstream>
+#include <testsuite_allocator.h>
+
+using Alloc = __gnu_test::uneq_allocator<char>;
+using String = std::basic_string<char, std::char_traits<char>, Alloc>;
+
+struct SB : std::basic_stringbuf<char, std::char_traits<char>, Alloc>
+{
+ SB(const String& s) : basic_stringbuf(s) { }
+
+ using basic_stringbuf::overflow;
+};
+
+int main()
+{
+ String s(Alloc(23));
+ SB b(s);
+ b.overflow('a');
+ VERIFY( b.str().get_allocator() == s.get_allocator() );
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringstream/assign/81338.cc b/libstdc++-v3/testsuite/27_io/basic_stringstream/assign/81338.cc
new file mode 100644
index 00000000000..30370c0dd42
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_stringstream/assign/81338.cc
@@ -0,0 +1,40 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::stringstream ss;
+ for (int i = 0; i < 100; ++i)
+ {
+ ss << 'a';
+ VERIFY( static_cast<bool>(ss) );
+ VERIFY( ss.str() == "a" );
+ ss = std::stringstream();
+ }
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/27_io/types/1.cc b/libstdc++-v3/testsuite/27_io/types/1.cc
index 88f6ff868d7..0756f8a1709 100644
--- a/libstdc++-v3/testsuite/27_io/types/1.cc
+++ b/libstdc++-v3/testsuite/27_io/types/1.cc
@@ -15,6 +15,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-do compile { target c++14_down } }
+
// 27.4.2.1 - Types [lib.ios.types]
#include <ios>
@@ -27,9 +29,3 @@ void test01()
typedef std::ios_base::streampos streampos_type;
typedef std::ios_base::streamoff streamoff_type;
}
-
-int main(void)
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/27_io/types/4.cc b/libstdc++-v3/testsuite/27_io/types/4.cc
new file mode 100644
index 00000000000..ee1a77736ce
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/types/4.cc
@@ -0,0 +1,29 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+// In C++17 these names are not reserved by the library.
+#define io_state 1
+#define open_mode 2
+#define seek_dir 3
+#define stossc 4
+#include <streambuf>
+
+template class std::basic_streambuf<char>;
+template class std::basic_streambuf<wchar_t>;
diff --git a/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/1.cc b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/1.cc
index 9f1b48c809a..e420ab08378 100644
--- a/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/1.cc
@@ -79,7 +79,7 @@ void test01()
try
{
- std::scoped_lock<BasicLockable> l(m, std::adopt_lock);
+ std::scoped_lock<BasicLockable> l(std::adopt_lock, m);
}
catch (...)
{
@@ -113,7 +113,7 @@ void test02()
try
{
- std::scoped_lock<Lockable<1>, Lockable<2>> l(m1, m2, std::adopt_lock);
+ std::scoped_lock<Lockable<1>, Lockable<2>> l(std::adopt_lock, m1, m2);
VERIFY( m1.m.locked );
VERIFY( m2.m.locked );
}
diff --git a/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc
index 399de7a5ae6..7d4f5bfc386 100644
--- a/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc
@@ -51,3 +51,28 @@ test01()
std::scoped_lock l2(m2, m3);
check_type<std::scoped_lock<Lockable, std::mutex>>(l2);
}
+
+void
+test02()
+{
+ std::scoped_lock l0(std::adopt_lock);
+ check_type<std::scoped_lock<>>(l0);
+
+ struct BasicLockable {
+ void lock() { }
+ void unlock() { }
+ } m1;
+
+ std::scoped_lock l1(std::adopt_lock, m1);
+ check_type<std::scoped_lock<BasicLockable>>(l1);
+
+ struct Lockable {
+ void lock() { }
+ void unlock() { }
+ bool try_lock() { return true; }
+ } m2;
+
+ std::mutex m3;
+ std::scoped_lock l2(std::adopt_lock, m2, m3);
+ check_type<std::scoped_lock<Lockable, std::mutex>>(l2);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/scoped_lock/requirements/typedefs.cc b/libstdc++-v3/testsuite/30_threads/scoped_lock/requirements/typedefs.cc
index 55756d87262..0a8903ebaab 100644
--- a/libstdc++-v3/testsuite/30_threads/scoped_lock/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/30_threads/scoped_lock/requirements/typedefs.cc
@@ -25,6 +25,12 @@
#include <mutex>
+#ifndef __cpp_lib_scoped_lock
+# error "Feature-test macro for scoped_lock missing"
+#elif __cpp_lib_scoped_lock != 201707
+# error "Feature-test macro for scoped_lock has wrong value"
+#endif
+
void test01()
{
// Check for required typedefs
diff --git a/libstdc++-v3/testsuite/abi/pr42230.cc b/libstdc++-v3/testsuite/abi/pr42230.cc
index 2a338995336..48156e4ba18 100644
--- a/libstdc++-v3/testsuite/abi/pr42230.cc
+++ b/libstdc++-v3/testsuite/abi/pr42230.cc
@@ -3,6 +3,7 @@
#include <cxxabi.h>
#include <cassert>
#include <cstddef>
+#include <cstdlib>
int main()
{
@@ -12,5 +13,6 @@ int main()
char* ret = abi::__cxa_demangle("e", 0, &length, &cc);
assert( (cc < 0 && !ret) || (ret && length) );
+ std::free(ret);
return 0;
}
diff --git a/libstdc++-v3/testsuite/performance/23_containers/insert/81476.cc b/libstdc++-v3/testsuite/performance/23_containers/insert/81476.cc
new file mode 100644
index 00000000000..2b76469ae11
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/23_containers/insert/81476.cc
@@ -0,0 +1,86 @@
+// Copyright (C) 2012-2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ std::default_random_engine eng;
+ std::uniform_int_distribution<unsigned> r(0, 127);
+
+ time_counter time;
+ resource_counter resource;
+
+ std::vector<std::vector<char>> vecs(10000);
+ for (auto& v : vecs)
+ {
+ v.resize(1000);
+ for (auto& c : v)
+ c = r(eng);
+ }
+
+ start_counters(time, resource);
+ std::vector<char> res;
+ for (auto& v : vecs)
+ res.insert(res.begin(), v.begin(), v.end());
+ stop_counters(time, resource);
+ report_performance(__FILE__, "insert pointers", time, resource);
+
+ struct input_iterator : std::vector<char>::iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using base = std::vector<char>::iterator;
+
+ input_iterator(base it) : base(it) { }
+ };
+
+ start_counters(time, resource);
+ std::vector<char> res2;
+ for (auto& v : vecs)
+ {
+ auto begin = input_iterator(v.begin());
+ auto end = input_iterator(v.end());
+ res2.insert(res2.begin(), begin, end);
+ }
+ stop_counters(time, resource);
+ report_performance(__FILE__, "insert input iterators", time, resource);
+
+ start_counters(time, resource);
+ std::vector<char> res3;
+ for (auto rev = vecs.rbegin(); rev != vecs.rend(); ++rev)
+ res3.insert(res3.end(), rev->begin(), rev->end());
+ stop_counters(time, resource);
+ report_performance(__FILE__, "insert pointers end", time, resource);
+
+ start_counters(time, resource);
+ std::vector<char> res4;
+ for (auto rev = vecs.rbegin(); rev != vecs.rend(); ++rev)
+ res4.insert(res4.end(), rev->begin(), rev->end());
+ stop_counters(time, resource);
+ report_performance(__FILE__, "insert input iterators end", time, resource);
+
+ VERIFY(res2 == res);
+ VERIFY(res3 == res);
+ VERIFY(res4 == res);
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 4d7f4ca3a65..d18429a55b2 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -590,21 +590,26 @@ create_symbols(const char* file)
}
-const char*
+std::string
demangle(const std::string& mangled)
{
- const char* name;
+ std::string name;
if (mangled[0] != '_' || mangled[1] != 'Z')
{
// This is not a mangled symbol, thus has "C" linkage.
- name = mangled.c_str();
+ name = mangled;
}
else
{
// Use __cxa_demangle to demangle.
int status = 0;
- name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
- if (!name)
+ char* ptr = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
+ if (ptr)
+ {
+ name = ptr;
+ free(ptr);
+ }
+ else
{
switch (status)
{
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.h b/libstdc++-v3/testsuite/util/testsuite_abi.h
index 8275b23e162..77c5656177f 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.h
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.h
@@ -94,5 +94,5 @@ compare_symbols(const char* baseline_file, const char* test_file, bool verb);
symbols
create_symbols(const char* file);
-const char*
+std::string
demangle(const std::string& mangled);
diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.cc b/libstdc++-v3/testsuite/util/testsuite_hooks.cc
index d1063e3d8d7..74e755dfe28 100644
--- a/libstdc++-v3/testsuite/util/testsuite_hooks.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_hooks.cc
@@ -131,8 +131,11 @@ namespace __gnu_test
verify_demangle(const char* mangled, const char* wanted)
{
int status = 0;
- const char* s = abi::__cxa_demangle(mangled, 0, 0, &status);
- if (!s)
+ const char* s = 0;
+ char* demangled = abi::__cxa_demangle(mangled, 0, 0, &status);
+ if (demangled)
+ s = demangled;
+ else
{
switch (status)
{
@@ -156,6 +159,7 @@ namespace __gnu_test
std::string w(wanted);
if (w != s)
std::__throw_runtime_error(s);
+ free(demangled);
}
void
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index 6771ae2cea6..d61b2162c14 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -539,14 +539,14 @@ namespace __gnu_test
struct test_container
{
typename ItType<T>::ContainerType bounds;
- test_container(T* _first, T* _last):bounds(_first, _last)
+ test_container(T* _first, T* _last) : bounds(_first, _last)
{ }
#if __cplusplus >= 201103L
- template<std::size_t N>
- explicit
- test_container(T (&arr)[N]) : test_container(arr, arr+N)
- { }
+ template<std::size_t N>
+ explicit
+ test_container(T (&arr)[N]) : test_container(arr, arr+N)
+ { }
#endif
ItType<T>
@@ -574,6 +574,6 @@ namespace __gnu_test
ItType<T>
end()
{ return it(bounds.last); }
- };
+ };
}
#endif
diff --git a/lto-plugin/ChangeLog b/lto-plugin/ChangeLog
index c1859e2bbee..d3617a12ea3 100644
--- a/lto-plugin/ChangeLog
+++ b/lto-plugin/ChangeLog
@@ -1,3 +1,10 @@
+2017-07-21 Georg-Johann Lay <avr@gjlay.de>
+
+ PR lto/81487
+ * lto-plugin.c (claim_file_handler): Use xasprintf instead of
+ asprintf.
+ [hi!=0]: Swap hi and lo arguments supplied to xasprintf.
+
2017-01-17 Jakub Jelinek <jakub@redhat.com>
PR other/79046
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index f713c5dab0d..27fcfbeca09 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -975,17 +975,16 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
if (file->offset != 0)
{
- char *objname;
/* We pass the offset of the actual file, not the archive header.
Can't use PRIx64, because that's C99, so we have to print the
- 64-bit hex int as two 32-bit ones. */
- int lo, hi, t;
+ 64-bit hex int as two 32-bit ones. Use xasprintf instead of
+ asprintf because asprintf doesn't work as expected on some older
+ mingw32 hosts. */
+ int lo, hi;
lo = file->offset & 0xffffffff;
hi = ((int64_t)file->offset >> 32) & 0xffffffff;
- t = hi ? asprintf (&objname, "%s@0x%x%08x", file->name, lo, hi)
- : asprintf (&objname, "%s@0x%x", file->name, lo);
- check (t >= 0, LDPL_FATAL, "asprintf failed");
- lto_file.name = objname;
+ lto_file.name = hi ? xasprintf ("%s@0x%x%08x", file->name, hi, lo)
+ : xasprintf ("%s@0x%x", file->name, lo);
}
else
{