aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2014-02-21 17:12:25 +0000
committerMichael Meissner <meissner@linux.vnet.ibm.com>2014-02-21 17:12:25 +0000
commit9559ad3ea4fa35dee1443e9f24806da2474a0716 (patch)
tree8ecc152c5e47c8786c2a01e0a3e0457e6aa8ddf4
parent3572db357f94aaeb6738dc25157a495825325cb7 (diff)
Merge up to 208009
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ibm/gcc-4_8-prefixes@208010 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/BASE-VER2
-rw-r--r--gcc/ChangeLog1827
-rw-r--r--gcc/ChangeLog.ibm1579
-rw-r--r--gcc/ChangeLog.meissner4
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in6
-rw-r--r--gcc/REVISION2
-rw-r--r--gcc/ada/ChangeLog64
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in2
-rw-r--r--gcc/ada/gcc-interface/Makefile.in8
-rw-r--r--gcc/ada/gcc-interface/cuintp.c21
-rw-r--r--gcc/ada/gcc-interface/decl.c8
-rw-r--r--gcc/ada/gcc-interface/trans.c159
-rw-r--r--gcc/ada/gcc-interface/utils.c142
-rw-r--r--gcc/ada/indepsw-darwin.adb67
-rw-r--r--gcc/alias.c17
-rw-r--r--gcc/asan.c9
-rw-r--r--gcc/builtins.c14
-rw-r--r--gcc/builtins.def3
-rw-r--r--gcc/c-family/ChangeLog23
-rw-r--r--gcc/c-family/c-ada-spec.c2
-rw-r--r--gcc/c-family/c-common.c9
-rw-r--r--gcc/c/ChangeLog19
-rw-r--r--gcc/c/c-decl.c4
-rw-r--r--gcc/c/c-typeck.c7
-rw-r--r--gcc/calls.c9
-rw-r--r--gcc/cfgcleanup.c36
-rw-r--r--gcc/cfgexpand.c18
-rw-r--r--gcc/cfgrtl.c12
-rw-r--r--gcc/cgraph.c43
-rw-r--r--gcc/cgraph.h1
-rw-r--r--gcc/cgraphbuild.c20
-rw-r--r--gcc/combine.c38
-rw-r--r--gcc/common/config/s390/s390-common.c2
-rw-r--r--gcc/config.gcc75
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c1
-rw-r--r--gcc/config/aarch64/aarch64-linux.h2
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def11
-rw-r--r--gcc/config/aarch64/aarch64-simd.md207
-rw-r--r--gcc/config/aarch64/aarch64.md16
-rw-r--r--gcc/config/aarch64/arm_neon.h877
-rw-r--r--gcc/config/aarch64/iterators.md61
-rw-r--r--gcc/config/aarch64/predicates.md5
-rw-r--r--gcc/config/alpha/alpha.c1
-rw-r--r--gcc/config/arm/arm.c51
-rw-r--r--gcc/config/arm/iterators.md4
-rw-r--r--gcc/config/arm/neon.md44
-rw-r--r--gcc/config/arm/vfp.md28
-rw-r--r--gcc/config/avr/avr-fixed.md51
-rw-r--r--gcc/config/avr/avr-protos.h3
-rw-r--r--gcc/config/avr/avr.c104
-rw-r--r--gcc/config/avr/avr.md2
-rw-r--r--gcc/config/cris/cris.md27
-rw-r--r--gcc/config/cris/predicates.md4
-rw-r--r--gcc/config/darwin-protos.h1
-rw-r--r--gcc/config/darwin.c30
-rw-r--r--gcc/config/i386/bmiintrin.h60
-rw-r--r--gcc/config/i386/driver-i386.c48
-rw-r--r--gcc/config/i386/i386.c528
-rw-r--r--gcc/config/i386/i386.h60
-rw-r--r--gcc/config/i386/i386.md100
-rw-r--r--gcc/config/i386/sse.md72
-rw-r--r--gcc/config/i386/t-rtems7
-rw-r--r--gcc/config/i386/winnt.c5
-rw-r--r--gcc/config/i386/x86-64.h3
-rw-r--r--gcc/config/i386/xopintrin.h8
-rw-r--r--gcc/config/m68k/m68k.c10
-rw-r--r--gcc/config/mips/driver-native.c10
-rw-r--r--gcc/config/mips/mips.c20
-rw-r--r--gcc/config/mips/mips.h5
-rw-r--r--gcc/config/mips/mips.md79
-rw-r--r--gcc/config/pa/pa.c21
-rw-r--r--gcc/config/pa/pa.md28
-rw-r--r--gcc/config/rs6000/altivec.md1080
-rw-r--r--gcc/config/rs6000/constraints.md52
-rw-r--r--gcc/config/rs6000/dfp.md33
-rw-r--r--gcc/config/rs6000/htmintrin.h4
-rw-r--r--gcc/config/rs6000/linux64.h25
-rw-r--r--gcc/config/rs6000/option-defaults.h1
-rw-r--r--gcc/config/rs6000/ppc-asm.h25
-rw-r--r--gcc/config/rs6000/predicates.md40
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def8
-rw-r--r--gcc/config/rs6000/rs6000-c.c45
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def10
-rw-r--r--gcc/config/rs6000/rs6000-opts.h3
-rw-r--r--gcc/config/rs6000/rs6000-protos.h6
-rw-r--r--gcc/config/rs6000/rs6000.c2876
-rw-r--r--gcc/config/rs6000/rs6000.h87
-rw-r--r--gcc/config/rs6000/rs6000.md1400
-rw-r--r--gcc/config/rs6000/rs6000.opt51
-rw-r--r--gcc/config/rs6000/rtems.h3
-rw-r--r--gcc/config/rs6000/sync.md110
-rw-r--r--gcc/config/rs6000/sysv4.h32
-rw-r--r--gcc/config/rs6000/sysv4le.h7
-rw-r--r--gcc/config/rs6000/t-linux6410
-rw-r--r--gcc/config/rs6000/t-linux64bele7
-rw-r--r--gcc/config/rs6000/t-linux64le3
-rw-r--r--gcc/config/rs6000/t-linux64lebe7
-rw-r--r--gcc/config/rs6000/vector.md40
-rw-r--r--gcc/config/rs6000/vsx.md907
-rw-r--r--gcc/config/s390/htmintrin.h57
-rw-r--r--gcc/config/s390/htmxlintrin.h189
-rw-r--r--gcc/config/s390/predicates.md12
-rw-r--r--gcc/config/s390/s390-modes.def9
-rw-r--r--gcc/config/s390/s390-protos.h4
-rw-r--r--gcc/config/s390/s390.c819
-rw-r--r--gcc/config/s390/s390.h46
-rw-r--r--gcc/config/s390/s390.md293
-rw-r--r--gcc/config/s390/s390.opt12
-rw-r--r--gcc/config/s390/s390intrin.h33
-rw-r--r--gcc/config/sh/constraints.md7
-rw-r--r--gcc/config/sh/predicates.md11
-rw-r--r--gcc/config/sh/sh-protos.h2
-rw-r--r--gcc/config/sh/sh.c21
-rw-r--r--gcc/config/sh/sh.md117
-rw-r--r--gcc/config/sh/sh.opt2
-rw-r--r--gcc/config/sparc/leon.md66
-rw-r--r--gcc/config/sparc/sparc-opts.h1
-rw-r--r--gcc/config/sparc/sparc.c362
-rw-r--r--gcc/config/sparc/sparc.h46
-rw-r--r--gcc/config/sparc/sparc.md45
-rw-r--r--gcc/config/sparc/sparc.opt13
-rw-r--r--gcc/config/sparc/sync.md15
-rw-r--r--gcc/config/sparc/t-rtems4
-rw-r--r--gcc/config/sparc/t-sparc2
-rwxr-xr-xgcc/configure66
-rw-r--r--gcc/configure.ac26
-rw-r--r--gcc/cp/ChangeLog161
-rw-r--r--gcc/cp/call.c9
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/cp-tree.h25
-rw-r--r--gcc/cp/cvt.c29
-rw-r--r--gcc/cp/decl.c23
-rw-r--r--gcc/cp/decl2.c28
-rw-r--r--gcc/cp/except.c3
-rw-r--r--gcc/cp/init.c1
-rw-r--r--gcc/cp/name-lookup.c6
-rw-r--r--gcc/cp/parser.c13
-rw-r--r--gcc/cp/pt.c73
-rw-r--r--gcc/cp/semantics.c23
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/cp/typeck2.c2
-rw-r--r--gcc/cse.c12
-rw-r--r--gcc/doc/extend.texi329
-rw-r--r--gcc/doc/implement-cxx.texi4
-rw-r--r--gcc/doc/invoke.texi147
-rw-r--r--gcc/doc/md.texi36
-rw-r--r--gcc/explow.c6
-rw-r--r--gcc/expr.c57
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/fold-const.c142
-rw-r--r--gcc/fortran/ChangeLog138
-rw-r--r--gcc/fortran/check.c2
-rw-r--r--gcc/fortran/class.c2
-rw-r--r--gcc/fortran/decl.c8
-rw-r--r--gcc/fortran/dump-parse-tree.c3
-rw-r--r--gcc/fortran/expr.c8
-rw-r--r--gcc/fortran/interface.c7
-rw-r--r--gcc/fortran/invoke.texi3
-rw-r--r--gcc/fortran/match.c42
-rw-r--r--gcc/fortran/module.c2
-rw-r--r--gcc/fortran/primary.c2
-rw-r--r--gcc/fortran/resolve.c91
-rw-r--r--gcc/fortran/trans-array.c35
-rw-r--r--gcc/fortran/trans-expr.c1
-rw-r--r--gcc/fortran/trans-intrinsic.c10
-rw-r--r--gcc/fortran/trans-io.c30
-rw-r--r--gcc/function.c31
-rw-r--r--gcc/genoutput.c4
-rw-r--r--gcc/gimple-fold.c2
-rw-r--r--gcc/gimple-low.c1
-rw-r--r--gcc/gimple-ssa-strength-reduction.c22
-rw-r--r--gcc/gimple.c102
-rw-r--r--gcc/gimple.h11
-rw-r--r--gcc/gimplify.c62
-rw-r--r--gcc/go/ChangeLog62
-rw-r--r--gcc/go/go-gcc.cc281
-rw-r--r--gcc/go/go-lang.c4
-rw-r--r--gcc/go/gofrontend/backend.h69
-rw-r--r--gcc/go/gofrontend/expressions.cc583
-rw-r--r--gcc/go/gofrontend/expressions.h39
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc369
-rw-r--r--gcc/go/gofrontend/gogo.cc349
-rw-r--r--gcc/go/gofrontend/gogo.h62
-rw-r--r--gcc/go/gofrontend/import.h5
-rw-r--r--gcc/go/gofrontend/lex.cc23
-rw-r--r--gcc/go/gofrontend/parse.cc31
-rw-r--r--gcc/go/gofrontend/runtime.cc7
-rw-r--r--gcc/go/gofrontend/runtime.def6
-rw-r--r--gcc/go/gofrontend/statements.cc73
-rw-r--r--gcc/go/gofrontend/statements.h46
-rw-r--r--gcc/go/gofrontend/types.cc405
-rw-r--r--gcc/go/gofrontend/types.h69
-rw-r--r--gcc/ifcvt.c11
-rw-r--r--gcc/ipa-prop.c75
-rw-r--r--gcc/ipa-pure-const.c8
-rw-r--r--gcc/ipa-split.c10
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/loop-iv.c12
-rw-r--r--gcc/loop-unswitch.c11
-rw-r--r--gcc/lra-assigns.c17
-rw-r--r--gcc/lra-coalesce.c31
-rw-r--r--gcc/lra-constraints.c4
-rw-r--r--gcc/lto/ChangeLog4
-rw-r--r--gcc/mode-switching.c7
-rw-r--r--gcc/objc/ChangeLog4
-rw-r--r--gcc/objcp/ChangeLog4
-rw-r--r--gcc/omp-low.c4
-rw-r--r--gcc/optabs.c25
-rw-r--r--gcc/passes.c13
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/print-rtl.c2
-rw-r--r--gcc/recog.c69
-rw-r--r--gcc/recog.h52
-rw-r--r--gcc/regcprop.c18
-rw-r--r--gcc/reginfo.c21
-rw-r--r--gcc/reorg.c14
-rw-r--r--gcc/simplify-rtx.c15
-rw-r--r--gcc/stmt.c36
-rw-r--r--gcc/testsuite/ChangeLog1040
-rw-r--r--gcc/testsuite/ChangeLog.ibm341
-rw-r--r--gcc/testsuite/c-c++-common/fold-divmul-1.c11
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr58257.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr59467.c68
-rw-r--r--gcc/testsuite/c-c++-common/pr59032.c30
-rw-r--r--gcc/testsuite/c-c++-common/pr59037.c12
-rw-r--r--gcc/testsuite/c-c++-common/pr59280.c4
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr58794-1.c29
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr58794-2.c21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/access02.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template6.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype57.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi9.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr57981.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual14.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic144.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic145.C13
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr58979.C4
-rw-r--r--gcc/testsuite/g++.dg/eh/ppc64-sighandle-cr.C54
-rw-r--r--gcc/testsuite/g++.dg/ext/pr57362.C199
-rw-r--r--gcc/testsuite/g++.dg/ext/pr57735.C145
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr59297.C25
-rw-r--r--gcc/testsuite/g++.dg/inherit/virtual11.C17
-rw-r--r--gcc/testsuite/g++.dg/opt/pr58006.C22
-rw-r--r--gcc/testsuite/g++.dg/opt/pr58165.C14
-rw-r--r--gcc/testsuite/g++.dg/opt/pr58864.C21
-rw-r--r--gcc/testsuite/g++.dg/opt/pr59470.C188
-rw-r--r--gcc/testsuite/g++.dg/opt/pr59647.C32
-rw-r--r--gcc/testsuite/g++.dg/parse/crash62.C6
-rw-r--r--gcc/testsuite/g++.dg/parse/using4.C20
-rw-r--r--gcc/testsuite/g++.dg/pr57878.C226
-rw-r--r--gcc/testsuite/g++.dg/template/abstract1.C12
-rw-r--r--gcc/testsuite/g++.dg/template/delete2.C26
-rw-r--r--gcc/testsuite/g++.dg/template/inherit9.C15
-rw-r--r--gcc/testsuite/g++.dg/template/partial14.C16
-rw-r--r--gcc/testsuite/g++.dg/tm/noexcept-6.C23
-rw-r--r--gcc/testsuite/g++.dg/torture/pr59163.C30
-rw-r--r--gcc/testsuite/g++.dg/tree-prof/pr59255.C29
-rw-r--r--gcc/testsuite/g++.dg/uninit-pred-4.C16
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-var-21.C31
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/misc9.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58088.c5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58164.c8
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-1.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-2.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58997.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr59362.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr59803.c27
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20131127-1.c34
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58209.c32
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58277-1.c102
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58277-2.c98
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58364.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58365.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58385.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58564.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58574.c219
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58726.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58831.c40
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58984.c57
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59014-2.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59014.c25
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59101.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59358.c44
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr59388.c11
-rw-r--r--gcc/testsuite/gcc.dg/20050922-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/20050922-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr56417.c9
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-6.c13
-rw-r--r--gcc/testsuite/gcc.dg/builtin-object-size-14.c28
-rw-r--r--gcc/testsuite/gcc.dg/builtin-object-size-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr59610.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr46309.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr56977.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr57518.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr57980.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr58010.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr58145-1.c37
-rw-r--r--gcc/testsuite/gcc.dg/pr58145-2.c51
-rw-r--r--gcc/testsuite/gcc.dg/pr58463.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr58668.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr58805.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr59011.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr59351.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr59827.c15
-rw-r--r--gcc/testsuite/gcc.dg/stack-usage-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-14gf.c10
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-1f.c8
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-4gf.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57343.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57381.c25
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57417.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57488.c58
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57517.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57521.c51
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57656.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57685.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58041.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58079.c107
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-1.c51
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-2.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-3.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58223.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58228.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58246.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58539.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58670.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58779.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58830.c42
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58941.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58956.c30
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59047.c39
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59139.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59164.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59288.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59330.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59715.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c1
-rw-r--r--gcc/testsuite/gcc.dg/vmx/eg-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/vmx/extract-be-order.c33
-rw-r--r--gcc/testsuite/gcc.dg/vmx/extract-vsx-be-order.c19
-rw-r--r--gcc/testsuite/gcc.dg/vmx/extract-vsx.c16
-rw-r--r--gcc/testsuite/gcc.dg/vmx/extract.c21
-rw-r--r--gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c15
-rw-r--r--gcc/testsuite/gcc.dg/vmx/insert-be-order.c65
-rw-r--r--gcc/testsuite/gcc.dg/vmx/insert-vsx-be-order.c34
-rw-r--r--gcc/testsuite/gcc.dg/vmx/insert-vsx.c28
-rw-r--r--gcc/testsuite/gcc.dg/vmx/insert.c37
-rw-r--r--gcc/testsuite/gcc.dg/vmx/merge-be-order.c96
-rw-r--r--gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c46
-rw-r--r--gcc/testsuite/gcc.dg/vmx/merge-vsx.c39
-rw-r--r--gcc/testsuite/gcc.dg/vmx/merge.c77
-rw-r--r--gcc/testsuite/gcc.dg/vmx/mult-even-odd-be-order.c64
-rw-r--r--gcc/testsuite/gcc.dg/vmx/mult-even-odd.c43
-rw-r--r--gcc/testsuite/gcc.dg/vmx/pack-be-order.c136
-rw-r--r--gcc/testsuite/gcc.dg/vmx/pack.c108
-rw-r--r--gcc/testsuite/gcc.dg/vmx/perm-be-order.c74
-rw-r--r--gcc/testsuite/gcc.dg/vmx/perm.c69
-rw-r--r--gcc/testsuite/gcc.dg/vmx/sn7153.c4
-rw-r--r--gcc/testsuite/gcc.dg/vmx/splat-be-order.c59
-rw-r--r--gcc/testsuite/gcc.dg/vmx/splat-vsx-be-order.c37
-rw-r--r--gcc/testsuite/gcc.dg/vmx/splat-vsx.c31
-rw-r--r--gcc/testsuite/gcc.dg/vmx/splat.c47
-rw-r--r--gcc/testsuite/gcc.dg/vmx/sum2s-be-order.c19
-rw-r--r--gcc/testsuite/gcc.dg/vmx/sum2s.c13
-rw-r--r--gcc/testsuite/gcc.dg/vmx/unpack-be-order.c88
-rw-r--r--gcc/testsuite/gcc.dg/vmx/unpack.c67
-rw-r--r--gcc/testsuite/gcc.dg/vmx/vec-set.c14
-rw-r--r--gcc/testsuite/gcc.dg/vmx/vsums-be-order.c19
-rw-r--r--gcc/testsuite/gcc.dg/vmx/vsums.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr58460.c35
-rw-r--r--gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c112
-rw-r--r--gcc/testsuite/gcc.target/arm/lp1189445.c18
-rw-r--r--gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c25
-rw-r--r--gcc/testsuite/gcc.target/arm/pr54300.C61
-rw-r--r--gcc/testsuite/gcc.target/arm/pr58041.c30
-rw-r--r--gcc/testsuite/gcc.target/arm/require-pic-register-loc.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb1-Os-mult.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c11
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c11
-rw-r--r--gcc/testsuite/gcc.target/arm/vrinta-ce.c15
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vmovapd-256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vmovapd-256-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vzeroupper-16.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vzeroupper-18.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/bmi-1.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/bmi-2.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/movabs-1.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr30315.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/pr43662.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr43869.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57003.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57459.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58137.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58218.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58690.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59021.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59034-1.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59034-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59405.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59470.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59625.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-movapd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-movapd-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-frczX.c60
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-1.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-2.c9
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-3.c14
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-4.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-5.c20
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-6.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/pr59137.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bool3-av.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bool3-p7.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bool3-p8.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/darwin-longlong.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp-dd-2.c26
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp-td-2.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp-td-3.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-double1.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-double2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-float1.c11
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-float2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-long1.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-long2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move.h17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/no-r11-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/no-r11-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/no-r11-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-fp.c139
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr42747.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr43154.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr48258-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr57744.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr57949-1.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr57949-2.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr58330.c11
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr58673-1.c78
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr58673-2.c217
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr59054.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr60137.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr60203.c40
-rw-r--r--gcc/testsuite/gcc.target/powerpc/quad-atomic.c67
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-1.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-3.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-4.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-5.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/rs6000-ldouble-3.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c6
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-1.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-10.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-11.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-12.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-2.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-3.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-4.c26
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-5.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-6.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-7.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-8.c28
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-9.c21
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c27
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c27
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c27
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c11
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c28
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c11
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c68
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-builtins-1.c1073
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-builtins-2.c682
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-builtins-compile-1.c165
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-builtins-compile-2.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-builtins-compile-3.c37
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-nofloat-1.c12
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-nofloat-2.c55
-rw-r--r--gcc/testsuite/gcc.target/s390/s390.exp13
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-19.c9
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr58314.c102
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-1.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-1.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-2.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/pr38891.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-1.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-2.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-3.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c2
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_9.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_10.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_11.f9043
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_8.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_9.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/derived_external_function_1.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/dynamic_dispatch_12.f9074
-rw-r--r--gcc/testsuite/gfortran.dg/extends_15.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/generic_28.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr59467.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/inline_sum_5.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/nan_7.f901
-rw-r--r--gcc/testsuite/gfortran.dg/optional_class_1.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_43.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/reshape_6.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/select_type_34.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/transfer_intrinsic_6.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_15.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/use_29.f9015
-rw-r--r--gcc/testsuite/gfortran.fortran-torture/compile/pr57517.f9013
-rw-r--r--gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f9033
-rw-r--r--gcc/testsuite/gnat.dg/array_bounds_test2.adb25
-rw-r--r--gcc/testsuite/gnat.dg/in_out_parameter4.adb30
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization16.adb24
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization16_pkg.adb8
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization16_pkg.ads7
-rw-r--r--gcc/testsuite/gnat.dg/opt28.adb31
-rw-r--r--gcc/testsuite/gnat.dg/opt28.ads8
-rw-r--r--gcc/testsuite/gnat.dg/opt28_pkg.ads11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug086.go4
-rw-r--r--gcc/testsuite/lib/target-supports.exp16
-rw-r--r--gcc/tree-affine.c17
-rw-r--r--gcc/tree-call-cdce.c23
-rw-r--r--gcc/tree-cfg.c34
-rw-r--r--gcc/tree-dfa.c95
-rw-r--r--gcc/tree-flow.h1
-rw-r--r--gcc/tree-if-conv.c85
-rw-r--r--gcc/tree-loop-distribution.c21
-rw-r--r--gcc/tree-object-size.c48
-rw-r--r--gcc/tree-parloops.c15
-rw-r--r--gcc/tree-predcom.c130
-rw-r--r--gcc/tree-sra.c11
-rw-r--r--gcc/tree-ssa-ccp.c3
-rw-r--r--gcc/tree-ssa-dce.c34
-rw-r--r--gcc/tree-ssa-loop-im.c77
-rw-r--r--gcc/tree-ssa-loop-niter.c27
-rw-r--r--gcc/tree-ssa-pre.c6
-rw-r--r--gcc/tree-ssa-reassoc.c20
-rw-r--r--gcc/tree-ssa-sccvn.c27
-rw-r--r--gcc/tree-ssa-sink.c2
-rw-r--r--gcc/tree-ssa-strlen.c22
-rw-r--r--gcc/tree-ssa-structalias.c41
-rw-r--r--gcc/tree-ssa-tail-merge.c3
-rw-r--r--gcc/tree-ssa-ter.c53
-rw-r--r--gcc/tree-tailcall.c13
-rw-r--r--gcc/tree-vect-data-refs.c9
-rw-r--r--gcc/tree-vect-loop.c60
-rw-r--r--gcc/tree-vect-stmts.c3
-rw-r--r--gcc/tree-vrp.c28
-rw-r--r--gcc/tree.h2
-rw-r--r--gcc/value-prof.c3
579 files changed, 27774 insertions, 5672 deletions
diff --git a/gcc/BASE-VER b/gcc/BASE-VER
index 326ec6355f3..f99c6583c35 100644
--- a/gcc/BASE-VER
+++ b/gcc/BASE-VER
@@ -1 +1 @@
-4.8.2
+4.8.3
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2ff557bcbc8..1106279df84 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,1828 @@
+2014-01-16 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2014-01-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_hard_regno_mode_ok): Use
+ VALID_AVX256_REG_OR_OI_MODE.
+
+ 2013-09-05 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/58139
+ * reginfo.c (choose_hard_reg_mode): Scan through all mode classes
+ looking for widest mode.
+
+2014-01-16 Marek Polacek <polacek@redhat.com>
+
+ Backported from mainline
+ 2014-01-16 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/59827
+ * gimple-low.c (gimple_check_call_args): Don't use DECL_ARG_TYPE if
+ it is error_mark_node.
+
+2014-01-15 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/59803
+ * config/s390/s390.c (s390_preferred_reload_class): Don't return
+ ADDR_REGS for invalid symrefs in non-PIC code.
+
+2014-01-14 Uros Bizjak <ubizjak@gmail.com>
+
+ Revert:
+ 2014-01-08 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_data_alignment): Calculate max_align
+ from prefetch_block tune setting.
+
+2014-01-13 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2014-01-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59745
+ * tree-predcom.c (tree_predictive_commoning_loop): Call
+ free_affine_expand_cache if giving up because components is NULL.
+
+2014-01-10 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * config/arm/arm.c (arm_expand_neon_args): Call expand_expr
+ with EXPAND_MEMORY for NEON_ARG_MEMORY; check if the returned
+ rtx is const0_rtx or not.
+
+2014-01-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_expand_tbegin): Remove jump over CC
+ extraction in good case.
+
+2014-01-10 Huacai Chen <chenhc@lemote.com>
+
+ * config/mips/driver-native.c (host_detect_local_cpu): Handle new
+ kernel strings for Loongson-2E/2F/3A.
+
+2014-01-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59715
+ * tree-flow.h (split_critical_edges): Declare.
+ * tree-cfg.c (split_critical_edges): Export.
+ * tree-ssa-sink.c (execute_sink_code): Split critical edges.
+
+2014-01-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.h (ISA_HAS_WSBH): Define.
+ * config/mips/mips.md (UNSPEC_WSBH, UNSPEC_DSBH, UNSPEC_DSHD): New
+ constants.
+ (bswaphi2, bswapsi2, bswapdi2, wsbh, dsbh, dshd): New patterns.
+
+2014-01-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR rtl-optimization/59137
+ * reorg.c (steal_delay_list_from_target): Call update_block for
+ elided insns.
+ (steal_delay_list_from_fallthrough, relax_delay_slots): Likewise.
+
+2014-01-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ Revert:
+ 2012-10-07 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.c (mips_truncated_op_cost): New function.
+ (mips_rtx_costs): Adjust test for BADDU.
+ * config/mips/mips.md (*baddu_di<mode>): Push truncates to operands.
+
+ 2012-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.md (*baddu_si_eb, *baddu_si_el): Merge into...
+ (*baddu_si): ...this new pattern.
+
+2014-01-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59125
+ PR tree-optimization/54570
+ * tree-ssa-sccvn.c (copy_reference_ops_from_ref): When inlining
+ is not complete do not treat component-references with offset zero
+ but different fields as equal.
+ * tree-object-size.c: Include tree-phinodes.h and ssa-iterators.h.
+ (compute_object_sizes): Apply TLC. Propagate the constant
+ results into all uses and fold their stmts.
+ * passes.def (pass_all_optimizations): Move pass_object_sizes
+ after the first pass_forwprop and before pass_fre.
+
+ 2013-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59362
+ * tree-object-size.c (object_sizes): Change into array of
+ vec<unsigned HOST_WIDE_INT>.
+ (compute_builtin_object_size): Check computed bitmap for
+ non-NULL instead of object_sizes. Call safe_grow on object_sizes
+ vector if new SSA_NAMEs appeared.
+ (init_object_sizes): Check computed bitmap for non-NULL.
+ Call safe_grow on object_sizes elements instead of initializing
+ it with XNEWVEC.
+ (fini_object_sizes): Call release on object_sizes elements, don't
+ set it to NULL.
+
+2014-01-09 Richard Earnshaw <rearnsha@arm.com>
+
+ PR rtl-optimization/54300
+ * regcprop.c (copyprop_hardreg_forward_1): Ensure any unused
+ outputs in a single-set are killed from the value chains.
+
+2014-01-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/59724
+ * ifcvt.c (cond_exec_process_if_block): Don't call
+ flow_find_head_matching_sequence with 0 longest_match.
+ * cfgcleanup.c (flow_find_head_matching_sequence): Count even
+ non-active insns if !stop_after.
+ (try_head_merge_bb): Revert 2014-01-07 changes.
+
+2014-01-09 Hans-Peter Nilsson <hp@axis.com>
+
+ Backport from mainline
+ 2013-12-23 Hans-Peter Nilsson <hp@axis.com>
+
+ PR middle-end/59584
+ * config/cris/predicates.md (cris_nonsp_register_operand):
+ New define_predicate.
+ * config/cris/cris.md: Replace register_operand with
+ cris_nonsp_register_operand for destinations in all
+ define_splits where a register is set more than once.
+
+2014-01-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2013-12-25 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59587
+ * config/i386/i386.c (struct ptt): Add a field for processor name.
+ (processor_target_table): Sync with processor_type. Add
+ processor names.
+ (cpu_names): Removed.
+ (ix86_option_override_internal): Default x_ix86_tune_string
+ to processor_target_table[TARGET_CPU_DEFAULT].name.
+ (ix86_function_specific_print): Assert arch and tune <
+ PROCESSOR_max. Use processor_target_table to print arch and
+ tune names.
+ * config/i386/i386.h (TARGET_CPU_DEFAULT): Default to
+ PROCESSOR_GENERIC32.
+ (target_cpu_default): Removed.
+ (processor_type): Reordered.
+
+2014-01-08 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2014-01-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_data_alignment): Calculate max_align
+ from prefetch_block tune setting.
+ (nocona_cost): Correct size of prefetch block to 64.
+
+2014-01-08 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/59610
+ * ipa-prop.c (ipa_compute_jump_functions): Bail out if not optimizing.
+ (parm_preserved_before_stmt_p): Assume modification present when not
+ optimizing.
+
+2014-01-07 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/59652
+ * config/pa/pa.c (pa_legitimate_address_p): Return false before reload
+ for 14-bit register offsets when INT14_OK_STRICT is false.
+
+2014-01-07 Roland Stigge <stigge@antcom.de>
+ Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR 57386/target
+ * config/rs6000/rs6000.c (rs6000_legitimate_offset_address_p):
+ Only check TFmode for SPE constants. Don't check TImode or TDmode.
+
+2014-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58668
+ * cfgcleanup.c (flow_find_cross_jump): Don't count
+ any jumps if dir_p is NULL. Remove p1 variable and make USE/CLOBBER
+ check consistent with other places.
+ (flow_find_head_matching_sequence): Don't count USE or CLOBBER insns.
+ (try_head_merge_bb): Adjust for the flow_find_head_matching_sequence
+ counting change.
+ * ifcvt.c (count_bb_insns): Don't count USE or CLOBBER insns.
+
+2014-01-07 Mike Stump <mikestump@comcast.net>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/59436
+ * tree.h (struct tree_optimization_option): Change optabs
+ type from unsigned char * to void *.
+ * optabs.c (init_tree_optimization_optabs): Adjust
+ TREE_OPTIMIZATION_OPTABS initialization.
+
+2014-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-12-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58956
+ PR middle-end/59470
+ * gimple.h (walk_stmt_load_store_addr_fn): New typedef.
+ (walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
+ for callback params.
+ * gimple.c (walk_stmt_load_store_ops): Likewise.
+ (walk_stmt_load_store_addr_ops): Likewise. Adjust all callback
+ calls to supply the gimple operand containing the base tree
+ as an extra argument.
+ * tree-ssa-ter.c (find_ssaname, find_ssaname_in_store): New helper
+ functions.
+ (find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
+ same_root_var if USE is used somewhere in the stores of the stmt.
+ * ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
+ argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
+ * ipa-pure-const.c (check_load, check_store, check_ipa_load,
+ check_ipa_store): Likewise.
+ * gimple.c (gimple_ior_addresses_taken_1): Likewise.
+ * ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
+ (verify_non_ssa_vars, visit_bb): Adjust their callers.
+ * cfgexpand.c (add_scope_conflicts_1): Use
+ walk_stmt_load_store_addr_fn type for visit variable.
+ (visit_op, visit_conflict): Remove name of the stmt
+ argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
+ * tree-sra.c (asm_visit_addr): Likewise. Remove name of the data
+ argument and ATTRIBUTE_UNUSED.
+ * cgraphbuild.c (mark_address, mark_load, mark_store): Add another
+ unnamed tree argument.
+
+2014-01-03 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config/m68k/m68k.c (handle_move_double): Handle pushes with
+ overlapping registers also for registers other than the stack
+ pointer.
+
+2014-01-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/59625
+ * config/i386/i386.c (ix86_avoid_jump_mispredicts): Don't consider
+ asm goto as jump.
+
+2014-01-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/59647
+ * cse.c (cse_process_notes_1): Don't substitute negative VOIDmode
+ new_rtx into UNSIGNED_FLOAT rtxes.
+
+2013-12-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (output file options): Document -fada-spec-parent.
+
+2013-12-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/driver-i386.c (decode_caches_intel): Add missing entries.
+
+2013-12-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59255
+ Backported from mainline
+ 2013-08-19 Dehao Chen <dehao@google.com>
+
+ * value-prof.c (gimple_ic): Fix the bug of adding EH edge.
+
+2013-12-19 James Greenhalgh <james.greenhalgh@arm.com>
+
+ Backport from Mainline.
+ 2013-05-01 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64-simd-builtins.def (cmhs): Rename to...
+ (cmgeu): ...This.
+ (cmhi): Rename to...
+ (cmgtu): ...This.
+ * config/aarch64/aarch64-simd.md
+ (simd_mode): Add SF.
+ (aarch64_vcond_internal): Use new names for unsigned comparison insns.
+ (aarch64_cm<optab><mode>): Rewrite to not use UNSPECs.
+ * config/aarch64/aarch64.md (*cstore<mode>_neg): Rename to...
+ (cstore<mode>_neg): ...This.
+ * config/aarch64/iterators.md
+ (VALLF): new.
+ (unspec): Remove UNSPEC_CM<EQ, LE, LT, GE, GT, HS, HI, TST>.
+ (COMPARISONS): New.
+ (UCOMPARISONS): Likewise.
+ (optab): Add missing comparisons.
+ (n_optab): New.
+ (cmp_1): Likewise.
+ (cmp_2): Likewise.
+ (CMP): Likewise.
+ (cmp): Remove.
+ (VCMP_S): Likewise.
+ (VCMP_U): Likewise.
+ (V_cmp_result): Add DF, SF modes.
+ (v_cmp_result): Likewise.
+ (v): Likewise.
+ (vmtype): Likewise.
+ * config/aarch64/predicates.md (aarch64_reg_or_fp_zero): New.
+
+ Partial Backport from mainline.
+ 2013-05-01 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/arm_neon.h
+ (vc<eq, lt, le, gt, ge, tst><qsd>_<u><8,16,32,64>): Remap
+ to builtins or C as appropriate.
+
+2013-12-19 Dominik Vogt <vogt@linux.vnet.ibm.com>
+ Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ Backport from mainline
+ 2013-12-19 Dominik Vogt <vogt@linux.vnet.ibm.com>
+ * config/s390/s390.c (s390_hotpatch_trampoline_halfwords_default): New
+ constant
+ (s390_hotpatch_trampoline_halfwords_max): New constant
+ (s390_hotpatch_trampoline_halfwords): New static variable
+ (get_hotpatch_attribute): New function
+ (s390_handle_hotpatch_attribute): New function
+ (s390_attribute_table): New target specific attribute table to implement
+ the hotpatch attribute
+ (s390_option_override): Parse hotpatch options
+ (s390_function_num_hotpatch_trampoline_halfwords): New function
+ (s390_can_inline_p): Implement target hook to
+ suppress hotpatching for explicitly inlined functions
+ (s390_asm_output_function_label): Generate hotpatch prologue
+ (TARGET_ATTRIBUTE_TABLE): Define to implement target attribute table
+ (TARGET_CAN_INLINE_P): Define to implement target hook
+ * config/s390/s390.opt (mhotpatch): New options -mhotpatch, -mhotpatch=
+ * config/s390/s390-protos.h (s390_asm_output_function_label): Add
+ prototype
+ * config/s390/s390.h (ASM_OUTPUT_FUNCTION_LABEL): Target specific
+ function label generation for hotpatching
+ (FUNCTION_BOUNDARY): Align functions to eight bytes
+ * doc/extend.texi: Document hotpatch attribute
+ * doc/invoke.texi: Document -mhotpatch option
+
+2013-12-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/arm/arm.c (arm_expand_epilogue_apcs_frame): Fix thinko.
+
+2013-12-12 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR middle-end/59470
+ * lra-coalesce.c (lra_coalesce): Invalidate inheritance pseudo
+ values if necessary.
+
+2013-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/59467
+ * gimplify.c (omp_check_private): Add copyprivate argument, if it
+ is true, don't check omp_privatize_by_reference.
+ (gimplify_scan_omp_clauses): For OMP_CLAUSE_COPYPRIVATE verify
+ decl is private in outer context. Adjust omp_check_private caller.
+
+2013-12-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/58295
+ * simplify-rtx.c (simplify_truncation): Restrict the distribution for
+ WORD_REGISTER_OPERATIONS targets.
+
+2013-12-10 Kai Tietz <ktietz@redhat.com>
+
+ PR target/56807
+ * config/i386/i386.c (ix86_expand_prologue): Address saved
+ registers stack-relative, not via frame-pointer.
+
+2013-12-09 Alan Modra <amodra@gmail.com>
+
+ Apply from mainline
+ 2013-12-05 Alan Modra <amodra@gmail.com>
+ * configure.ac (BUILD_CXXFLAGS) Don't use ALL_CXXFLAGS for
+ build != host.
+ <recursive call for build != host>: Clear GMPINC. Don't bother
+ saving CFLAGS.
+ * configure: Regenerate.
+
+2013-12-08 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-12-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59405
+ * config/i386/i386.c (type_natural_mode): Properly handle
+ size 8 for !TARGET_64BIT.
+
+2013-12-07 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config.gcc (microblaze*-*-rtems*): Add TARGET_BIG_ENDIAN_DEFAULT.
+
+2013-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59388
+ * tree-ssa-reassoc.c (update_range_test): If op == range->exp,
+ gimplify tem after stmt rather than before it.
+
+2013-12-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-11-26 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/58314
+ PR target/50751
+ * config/sh/sh.c (max_mov_insn_displacement, disp_addr_displacement):
+ Prefix function names with 'sh_'. Make them non-static.
+ * config/sh/sh-protos.h (sh_disp_addr_displacement,
+ sh_max_mov_insn_displacement): Add declarations.
+ * config/sh/constraints.md (Q): Reject QImode.
+ (Sdd): Use match_code "mem".
+ (Snd): Fix erroneous matching of non-memory operands.
+ * config/sh/predicates.md (short_displacement_mem_operand): New
+ predicate.
+ (general_movsrc_operand): Disallow PC relative QImode loads.
+ * config/sh/sh.md (*mov<mode>_reg_reg): Remove it.
+ (*movqi, *movhi): Merge both insns into...
+ (*mov<mode>): ... this new insn. Replace generic 'm' constraints with
+ 'Snd' and 'Sdd' constraints. Calculate insn length dynamically based
+ on the operand types.
+
+2013-12-06 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59334
+ * tree-ssa-dce.c (eliminate_unnecessary_stmts): Fix bug
+ in previous commit.
+
+ 2013-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59330
+ * tree-ssa-dce.c (eliminate_unnecessary_stmts): Simplify
+ and fix delayed marking of free calls not necessary.
+
+2013-12-06 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59288
+ * tree-vect-loop.c (get_initial_def_for_induction): Do not
+ re-analyze the PHI but use STMT_VINFO_LOOP_PHI_EVOLUTION_PART.
+
+ 2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59164
+ * tree-vect-loop.c (vect_analyze_loop_operations): Adjust
+ check whether we can create an epilogue loop to reflect the
+ cases where we create one.
+
+ 2013-09-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58137
+ * tree-vect-stmts.c (get_vectype_for_scalar_type_and_size):
+ Do not create vectors of pointers.
+ * tree-vect-loop.c (get_initial_def_for_induction): Use proper
+ types for the components of the vector initializer.
+ * tree-cfg.c (verify_gimple_assign_binary): Remove special-casing
+ allowing pointer vectors with PLUS_EXPR/MINUS_EXPR.
+
+2013-12-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ PR target/59343
+ * config/sh/sh.md (*cbranch_t): Check that there are no labels between
+ the s1 insn and the testing insn. Remove REG_DEAD note from s1 insn.
+
+2013-12-05 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58956
+ * tree-ssa-ter.c (find_replaceable_in_bb): Avoid forwarding
+ loads into stmts that may clobber it.
+
+2013-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58726
+ * combine.c (force_to_mode): Fix comment typo. Don't destructively
+ modify x for ROTATE, ROTATERT and IF_THEN_ELSE.
+
+2013-12-04 Jakub Jelinek <jakub@redhat.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59163
+ * config/i386/i386.c (ix86_legitimate_combined_insn): If for
+ !TARGET_AVX there is misaligned MEM operand with vector mode
+ and get_attr_ssememalign is 0, return false.
+ (ix86_expand_special_args_builtin): Add get_pointer_alignment
+ computed alignment and for non-temporal loads/stores also
+ at least GET_MODE_ALIGNMENT as MEM_ALIGN.
+ * config/i386/sse.md
+ (<sse>_loadu<ssemodesuffix><avxsizesuffix>,
+ <sse>_storeu<ssemodesuffix><avxsizesuffix>,
+ <sse2>_loaddqu<avxsizesuffix>,
+ <sse2>_storedqu<avxsizesuffix>, <sse3>_lddqu<avxsizesuffix>,
+ sse_vmrcpv4sf2, sse_vmrsqrtv4sf2, sse2_cvtdq2pd, sse_movhlps,
+ sse_movlhps, sse_storehps, sse_loadhps, sse_loadlps,
+ *vec_interleave_highv2df, *vec_interleave_lowv2df,
+ *vec_extractv2df_1_sse, sse2_loadhpd, sse2_loadlpd, sse2_movsd,
+ sse4_1_<code>v8qiv8hi2, sse4_1_<code>v4qiv4si2,
+ sse4_1_<code>v4hiv4si2, sse4_1_<code>v2qiv2di2,
+ sse4_1_<code>v2hiv2di2, sse4_1_<code>v2siv2di2, sse4_2_pcmpestr,
+ *sse4_2_pcmpestr_unaligned, sse4_2_pcmpestri, sse4_2_pcmpestrm,
+ sse4_2_pcmpestr_cconly, sse4_2_pcmpistr, *sse4_2_pcmpistr_unaligned,
+ sse4_2_pcmpistri, sse4_2_pcmpistrm, sse4_2_pcmpistr_cconly): Add
+ ssememalign attribute.
+ * config/i386/i386.md (ssememalign): New define_attr.
+
+2013-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/59011
+ * gimplify.c (nonlocal_vla_vars): New variable.
+ (gimplify_var_or_parm_decl): Put VAR_DECLs for VLAs into
+ nonlocal_vla_vars chain.
+ (gimplify_body): Call declare_vars on nonlocal_vla_vars chain
+ if outer_bind has DECL_INITIAL (current_function_decl) block.
+
+ PR target/58864
+ * optabs.c (emit_conditional_move): Save and restore
+ pending_stack_adjust and stack_pointer_delta if cmove can't be used.
+
+2013-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59358
+ * tree-vrp.c (union_ranges): To check for the partially
+ overlapping ranges or adjacent ranges, also compare *vr0max
+ with vr1max.
+
+2013-12-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59139
+ * tree-ssa-loop-niter.c (chain_of_csts_start): Properly match
+ code in get_val_for.
+ (get_val_for): Use gcc_checking_asserts.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR middle-end/59037
+ * fold-const.c (fold_indirect_ref_1): Don't create out-of-bounds
+ BIT_FIELD_REF.
+ * gimplify.c (gimple_fold_indirect_ref): Same.
+
+2013-12-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/i386/winnt.c (i386_pe_asm_named_section): Be prepared for an
+ identifier node.
+
+2013-12-01 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * expr.c (emit_group_store): Fix off-by-one BITFIELD_END argument.
+
+2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/iterators.md (vrint_conds): New int attribute.
+ * config/arm/vfp.md (<vrint_pattern><SDF:mode>2): Set conds attribute.
+ (smax<mode>3): Likewise.
+ (smin<mode>3): Likewise.
+
+2013-11-28 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-11-27 Uros Bizjak <ubizjak@gmail.com>
+ Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+
+ PR target/56788
+ * gcc.target/i386/xop-frczX.c: New test.
+
+2013-11-28 Terry Guo <terry.guo@arm.com>
+
+ Backport mainline r205391
+ 2013-11-26 Terry Guo <terry.guo@arm.com>
+
+ * config/arm/arm.c (require_pic_register): Handle high pic base
+ register for thumb-1.
+ (arm_load_pic_register): Also initialize high pic base register.
+ * doc/invoke.texi: Update documentation for option -mpic-register.
+
+2013-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59014
+ * tree-vrp.c (register_edge_assert_for_1): Don't look
+ through conversions from non-integral types or through
+ narrowing conversions.
+
+2013-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/59138
+ * expr.c (emit_group_store): Don't write past the end of the structure.
+ (store_bit_field): Fix formatting.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-09-17 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/sparc/t-rtems: Add leon3 multilibs.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-08-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * configure.ac: Add GAS check for LEON instructions on SPARC.
+ * configure: Regenerate.
+ * config.in: Likewise.
+ * config.gcc (with_cpu): Remove sparc-leon*-* and deal with LEON in the
+ sparc*-*-* block.
+ * config/sparc/sparc.opt (LEON, LEON3): New masks.
+ * config/sparc/sparc.h (ASM_CPU32_DEFAULT_SPEC): Set to AS_LEON_FLAG
+ for LEON or LEON3.
+ (ASM_CPU_SPEC): Pass AS_LEON_FLAG if -mcpu=leon or -mcpu=leon3.
+ (AS_LEON_FLAG): New macro.
+ * config/sparc/sparc.c (sparc_option_override): Set MASK_LEON for leon
+ and MASK_LEON3 for leon3 and unset them if HAVE_AS_LEON is not defined.
+ Deal with LEON and LEON3 for the memory model.
+ * config/sparc/sync.md (atomic_compare_and_swap<mode>): Enable if LEON3
+ (atomic_compare_and_swap<mode>_1): Likewise.
+ (*atomic_compare_and_swap<mode>_1): Likewise.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-07-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (SPARC Options): Document new leon3 processor value.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-07-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config.gcc (sparc*-*-*): Accept leon3 processor.
+ (sparc-leon*-*): Merge with sparc*-*-* and add leon3 support.
+ * doc/invoke.texi (SPARC Options): Adjust -mfix-ut699 entry.
+ * config/sparc/sparc-opts.h (enum processor_type): Add PROCESSOR_LEON3.
+ * config/sparc/sparc.opt (enum processor_type): Add leon3.
+ (mfix-ut699): Adjust comment.
+ * config/sparc/sparc.h (TARGET_CPU_leon3): New define.
+ (CPP_CPU32_DEFAULT_SPEC): Add leon3 support.
+ (CPP_CPU_SPEC): Likewise.
+ (ASM_CPU_SPEC): Likewise.
+ * config/sparc/sparc.c (leon3_cost): New constant.
+ (sparc_option_override): Add leon3 support.
+ (mem_ref): New function.
+ (sparc_gate_work_around_errata): Return true if -mfix-ut699 is enabled.
+ (sparc_do_work_around_errata): Look into the instruction in the delay
+ slot and adjust accordingly. Add fix for the data cache nullify issues
+ of the UT699. Change insertion position for the NOP.
+ * config/sparc/leon.md (leon_fpalu, leon_fpmds, write_buf): Delete.
+ (leon3_load): New reservation.
+ (leon_store): Bump latency to 2.
+ (grfpu): New automaton.
+ (grfpu_alu): New unit.
+ (grfpu_ds): Likewise.
+ (leon_fp_alu): Adjust.
+ (leon_fp_mult): Delete.
+ (leon_fp_div): Split into leon_fp_divs and leon_fp_divd.
+ (leon_fp_sqrt): Split into leon_fp_sqrts and leon_fp_sqrtd.
+ * config/sparc/sparc.md (cpu): Add leon3.
+ * config/sparc/sync.md (atomic_exchangesi): Disable if -mfix-ut699.
+ (swapsi): Likewise.
+ (atomic_test_and_set): Likewise.
+ (ldstub): Likewise.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-04-10 Steven Bosscher <steven@gcc.gnu.org>
+
+ * config/sparc/sparc.c: Include tree-pass.h.
+ (TARGET_MACHINE_DEPENDENT_REORG): Do not redefine.
+ (sparc_reorg): Rename to sparc_do_work_around_errata. Move to
+ head of file. Change return type. Split off gate function.
+ (sparc_gate_work_around_errata): New function.
+ (pass_work_around_errata): New pass definition.
+ (insert_pass_work_around_errata) New pass insert definition to
+ insert pass_work_around_errata just after delayed-branch scheduling.
+ (sparc_option_override): Insert the pass.
+ * config/sparc/t-sparc (sparc.o): Add TREE_PASS_H dependence.
+
+2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ Backport from mainline
+ 2013-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (SPARC Options): Document -mfix-ut699.
+ * builtins.c (expand_builtin_mathfn) <BUILT_IN_SQRT>: Try to widen the
+ mode if the instruction isn't available in the original mode.
+ * config/sparc/sparc.opt (mfix-ut699): New option.
+ * config/sparc/sparc.md (muldf3_extend): Disable if -mfix-ut699.
+ (divdf3): Turn into expander.
+ (divdf3_nofix): New insn.
+ (divdf3_fix): Likewise.
+ (divsf3): Disable if -mfix-ut699.
+ (sqrtdf2): Turn into expander.
+ (sqrtdf2_nofix): New insn.
+ (sqrtdf2_fix): Likewise.
+ (sqrtsf2): Disable if -mfix-ut699.
+
+2013-11-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * print-rtl.c (print_rtx) <case MEM>: Output a space if no MEM_EXPR.
+
+2013-11-21 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR bootstrap/57683
+ Backport from mainline: r197467 and r198999.
+ 2013-04-03 Jeff Law <law@redhat.com>
+
+ * Makefile.in (lra-constraints.o): Depend on $(OPTABS_H).
+ (lra-eliminations.o): Likewise.
+
+ 2013-05-16 Jeff Law <law@redhat.com>
+
+ * Makefile.in (tree-switch-conversion.o): Depend on $(OPTABS_H).
+
+2013-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/59207
+ * config/sparc/sparc.c (sparc_fold_builtin) <case CODE_FOR_pdist_vis>:
+ Make sure neg2_ovf is set before being used.
+
+2013-11-20 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+ Dominik Vogt <vogt@linux.vnet.ibm.com>
+
+ Backport from mainline
+ * config/s390/s390.c (s390_canonicalize_comparison): Don't fold
+ int comparisons with an out of range condition code.
+ (s390_optimize_nonescaping_tx): Skip empty BBs.
+ Generate the new tbegin RTX when removing the FPR clobbers (with
+ two SETs).
+ (s390_expand_tbegin): Fix the retry loop counter. Copy CC to the
+ result before doing the retry calculations.
+ (s390_init_builtins): Make tbegin "returns_twice" and tabort
+ "noreturn".
+ * config/s390/s390.md (UNSPECV_TBEGIN_TDB): New constant used for
+ the TDB setting part of an tbegin.
+ ("tbegin_1", "tbegin_nofloat_1"): Add a set for the TDB.
+ ("tx_assist"): Set unused argument to an immediate zero instead of
+ loading zero into a GPR and pass it as argument.
+ * config/s390/htmxlintrin.h (__TM_simple_begin, __TM_begin):
+ Remove inline and related attributes.
+ (__TM_nesting_depth, __TM_is_user_abort, __TM_is_named_user_abort)
+ (__TM_is_illegal, __TM_is_footprint_exceeded)
+ (__TM_is_nested_too_deep, __TM_is_conflict): Fix format value
+ check.
+
+2013-11-19 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-11-18 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_decompose_address): Use REG_P instead of
+ ix86_address_subreg_operand. Move subreg checks to
+ ix86_validate_address_register. Move address override check to
+ ix86_legitimate_address_p.
+ (ix86_validate_address_register): New function.
+ (ix86_legitimate_address_p): Call ix86_validate_address_register
+ to validate base and index registers. Add address override check
+ from ix86_decompose_address.
+ (ix86_decompose_address): Remove.
+
+ Backport from mainline
+ 2013-11-17 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59153
+ * config/i386/i386.c (ix86_address_subreg_operand): Do not
+ reject non-integer subregs.
+ (ix86_decompose_address): Do not reject invalid CONST_INT RTXes.
+ Move check for invalid x32 constant addresses ...
+ (ix86_legitimate_address_p): ... here.
+
+2013-11-19 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-07 Richard Biener <rguenther@suse.de>
+
+ * tree-dfa.c (get_ref_base_and_extent): Fix casting.
+
+2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57517
+ * tree-predcom.c (combinable_refs_p): Verify the combination
+ is always executed when the refs are.
+
+2013-11-19 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58941
+ * tree-dfa.c (get_ref_base_and_extent): Merge common code
+ in MEM_REF and TARGET_MEM_REF handling. Make sure to
+ process trailing array detection before diving into the
+ view-converted object (and possibly apply some extra offset).
+
+2013-11-18 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58794
+ * fold-const.c (operand_equal_p): Compare FIELD_DECL operand
+ of COMPONENT_REFs with OEP_CONSTANT_ADDRESS_OF left in place.
+
+ 2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58742
+ * fold-const.c (fold_binary_loc): Fold ((T) (X /[ex] C)) * C
+ to (T) X for sign-changing conversions (or no conversion).
+
+ 2013-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58653
+ * tree-predcom.c (ref_at_iteration): Rewrite to generate
+ a MEM_REF.
+ (prepare_initializers_chain): Adjust.
+
+ PR tree-optimization/59047
+ * tree-predcom.c (ref_at_iteration): Handle bitfield accesses
+ properly.
+
+ 2013-10-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58143
+ * tree-ssa-loop-im.c (arith_code_with_undefined_signed_overflow):
+ New function.
+ (rewrite_to_defined_overflow): Likewise.
+ (move_computations_dom_walker::before_dom): Rewrite stmts
+ with undefined signed overflow that are not always executed
+ into unsigned arithmetic.
+
+2013-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-11-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * mode-switching.c (optimize_mode_switching): Mark block as
+ nontransparent, if last_mode at block exit is different from no_mode.
+
+ Backport from mainline
+ 2013-11-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59021
+ * config/i386/i386.c (ix86_avx_u128_mode_needed): Require
+ AVX_U128_DIRTY mode for call_insn RTXes that use AVX256 registers.
+ (ix86_avx_u128_mode_needed): Return AVX_U128_DIRTY mode for call_insn
+ RTXes that return in AVX256 register.
+
+2013-11-14 Jakub Jelinek <jakub@redhat.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59101
+ * config/i386/i386.md (*anddi_2): Only allow CCZmode if
+ operands[2] satisfies_constraint_Z that might have bit 31 set.
+
+2013-11-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backported from mainline
+ 2013-11-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59088
+ * config/i386/i386.c (initial_ix86_tune_features): Set
+ X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL and
+ X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL for m_HASWELL.
+
+2013-11-11 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ Backported from mainline
+ 2013-10-30 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ PR target/58854
+ * config/arm/arm.c (arm_expand_epilogue_apcs_frame): Emit blockage
+
+2013-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58970
+ * expr.c (get_bit_range): Handle *offset == NULL_TREE.
+ (expand_assignment): If *bitpos is negative, set *offset
+ and adjust *bitpos, so that it is not negative.
+
+ 2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58997
+ * loop-iv.c (iv_subreg): For IV_UNKNOWN_EXTEND, expect
+ get_iv_value to be in iv->mode rather than iv->extend_mode.
+ (iv_extend): Likewise. Otherwise, if iv->extend != extend,
+ use lowpart_subreg on get_iv_value before calling simplify_gen_unary.
+ * loop-unswitch.c (may_unswitch_on): Make sure op[i] is in the right
+ mode.
+
+2013-11-10 Karlson2k <k2k@narod.ru>
+ Kai Tietz <ktietz@redhat.com>
+
+ Merged from trunk
+ PR plugins/52872
+ * configure.ac: Adding for exported symbols check
+ and for rdynamic-check executable-extension.
+ * configure: Regenerated.
+
+2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59034
+ * config/i386/i386.md (push peepholer/splitter): Use Pmode
+ with stack_pointer_rtx.
+
+2013-11-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/t-rtems (MULTILIB_MATCHES): Fix option typos.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58984
+ * ipa-prop.c (ipa_load_from_parm_agg_1): Add SIZE_P argument,
+ set *SIZE_P if non-NULL on success.
+ (ipa_load_from_parm_agg, ipa_analyze_indirect_call_uses): Adjust
+ callers.
+ (ipcp_transform_function): Likewise. Punt if size of access
+ is different from TYPE_SIZE on v->value's type.
+
+2013-11-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2013-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/58690
+ * config/i386/i386.c (ix86_copy_addr_to_reg): New function.
+ (ix86_expand_movmem): Replace copy_addr_to_reg with
+ ix86_copy_addr_to_reg.
+ (ix86_expand_setmem): Likewise.
+
+2013-10-29 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-08 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR rtl-optimization/58079
+ * combine.c (combine_simplify_rtx): Avoid using SUBST if
+ simplify_comparison has widened a comparison with an integer.
+
+2013-10-29 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/58789
+ Backport from mainline
+ 2013-05-09 Martin Jambor <mjambor@suse.cz>
+
+ PR lto/57084
+ * gimple-fold.c (canonicalize_constructor_val): Call
+ cgraph_get_create_real_symbol_node instead of cgraph_get_create_node.
+
+ Backport from mainline
+ 2013-03-16 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.h (cgraph_get_create_real_symbol_node): Declare.
+ * cgraph.c (cgraph_get_create_real_symbol_node): New function.
+ * cgrpahbuild.c: Use cgraph_get_create_real_symbol_node instead
+ of cgraph_get_create_node.
+ * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
+
+2013-10-28 Tom de Vries <tom@codesourcery.com>
+
+ * cfgexpand.c (gimple_expand_cfg): Remove test for parm_birth_insn.
+ Don't commit insertions after NOTE_INSN_FUNCTION_BEG.
+
+2013-10-26 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-10-22 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58779
+ * config/i386/i386.c (put_condition_code) <case GTU, case LEU>:
+ Remove CCCmode handling.
+ <case LTU>: Return 'c' suffix for CCCmode.
+ <case GEU>: Return 'nc' suffix for CCCmode.
+ (ix86_cc_mode) <case GTU, case LEU>: Do not generate overflow checks.
+ * config/i386/i386.md (*sub<mode>3_cconly_overflow): Remove.
+ (*sub<mode>3_cc_overflow): Ditto.
+ (*subsi3_zext_cc_overflow): Ditto.
+
+2013-10-26 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-10-19 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58792
+ * config/i386/i386.c (ix86_function_value_regno): Add DX_REG,
+ ST1_REG and XMM1_REG for 32bit and 64bit targets. Also add DI_REG
+ and SI_REG for 64bit SYSV ABI targets.
+
+2013-08-25 Richard Henderson <rth@twiddle.net>
+
+ PR rtl/58542
+ * optabs.c (maybe_emit_atomic_exchange): Use create_input_operand
+ instead of create_convert_operand_to.
+ (maybe_emit_sync_lock_test_and_set): Likewise.
+ (expand_atomic_compare_and_swap): Likewise.
+ (maybe_emit_compare_and_swap_exchange_loop): Don't convert_modes.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/58831
+ * alias.c (init_alias_analysis): At the beginning of each iteration, set
+ the reg_seen[N] bit if static_reg_base_value[N] is non-null.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * recog.c (search_ofs): New static variable moved from...
+ (peep2_find_free_register): ...here.
+ (peephole2_optimize): Initialize it.
+
+2013-10-24 David Edelsohn <dje.gcc@gmail.com>
+
+ Backport from mainline
+ 2013-10-23 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/58838
+ * config/rs6000/rs6000.md (mulsi3_internal1 and splitter): Add
+ TARGET_32BIT final condition.
+ (mulsi3_internal2 and splitter): Same.
+
+2013-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/58805
+ * tree-ssa-tail-merge.c (stmt_local_def): Add gimple_vdef check.
+
+2013-10-23 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-06-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57488
+ * tree-ssa-pre.c (insert): Clear NEW sets before each iteration.
+
+2013-10-16 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+
+ Backport from mainline
+ 2013-10-16 Ganesh Gopalasubramanian
+ <Ganesh.Gopalasubramanian@amd.com>
+
+ * config/i386/i386.c (ix86_option_override_internal): Enable FMA4
+ for AMD bdver3.
+
+2013-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ * BASE-VER: Set to 4.8.3.
+ * DEV-PHASE: Set to prerelease.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-12 James Greenhalgh <james.greenhalgh@arm.com>
+
+ Backport from mainline.
+ 2013-10-12 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/arm_neon.h
+ (vtbx<1,3>_<psu>8): Fix register constriants.
+
+2013-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58670
+ * stmt.c (expand_asm_operands): Add FALLTHRU_BB argument,
+ if any labels are in FALLTHRU_BB, use a special label emitted
+ immediately after the asm goto insn rather than label_rtx
+ of the LABEL_DECL.
+ (expand_asm_stmt): Adjust caller.
+ * cfgrtl.c (commit_one_edge_insertion): Force splitting of
+ edge if the last insn in predecessor is a jump with single successor,
+ but it isn't simplejump_p.
+
+2013-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ Backport from mainline
+ 2013-09-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58539
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Honor
+ the fact that debug statements are not taking part in loop-closed
+ SSA construction.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_register_info): Make the call-saved FPR
+ loop to work also for 31bit ABI.
+ Save the stack pointer for frame_size > 0.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.md ("tbegin", "tbegin_nofloat", "tbegin_retry")
+ ("tbegin_retry_nofloat", "tend", "tabort", "tx_assist"): Remove
+ constraint letters from expanders.
+ ("tbegin_retry", "tbegin_retry_nofloat"): Change predicate of the
+ retry count to general_operand.
+ ("tabort"): Give operand 0 a mode.
+ ("tabort_1"): Add mode and constraint letter for operand 0.
+ * doc/extend.texi: Fix protoype of __builtin_non_tx_store.
+
+2013-10-04 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ Backport from mainline.
+
+ PR target/58460
+ * config/aarch64/aarch64.md (*add_<shift>_<mode>)
+ (*add_<shift>_si_uxtw,*add_mul_imm_<mode>)
+ (*sub_<shift>_<mode>)
+ (*sub_<shift>_si_uxtw,*sub_mul_imm_<mode>, *sub_mul_imm_si_uxtw):
+ Remove k constraint.
+
+2013-10-02 John David Anglin <danglin@gcc.gnu.org>
+
+ * config.gcc (hppa*64*-*-linux*): Don't add pa/t-linux to tmake_file.
+
+2013-10-01 Jakub Jelinek <jakub@redhat.com>
+ Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/58574
+ * config/s390/s390.c (s390_chunkify_start): Handle tablejump_p first,
+ continue when done, for other jumps look through PARALLEL
+ unconditionally.
+
+2013-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58564
+ * fold-const.c (fold_ternary_loc): For A < 0 : <sign bit of A> : 0
+ optimization, punt if sign_bit_p looked through any zero extension.
+
+2013-09-27 Paulo Matos <pmatos@broadcom.com>
+
+ Backport from mainline.
+
+ PR middle-end/58463
+ 2013-03-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56716
+ * tree-ssa-structalias.c (perform_var_substitution): Adjust
+ dumping for ref nodes.
+
+2013-09-27 Paulo Matos <pmatos@broadcom.com>
+
+ Backport from mainline.
+
+ 2013-09-27 Paulo Matos <pmatos@broadcom.com>
+ PR middle-end/58463
+ * gcc.dg/pr58463.c: New test.
+
+2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
+ assignment statements.
+
+2013-09-23 Alan Modra <amodra@gmail.com>
+
+ PR target/58330
+ * config/rs6000/rs6000.md (bswapdi2_64bit): Disable for volatile mems.
+
+2013-09-23 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/predicates.md (add_cint_operand): New.
+ (reg_or_add_cint_operand, small_toc_ref): Use add_cint_operand.
+ * config/rs6000/rs6000.md (largetoc_high_plus): Restrict offset
+ using add_cint_operand.
+ (largetoc_high_plus_aix): Likewise.
+ * config/rs6000/rs6000.c (toc_relative_expr_p): Use add_cint_operand.
+
+2013-09-20 John David Anglin <danglin@gcc.gnu.org>
+
+ PR middle-end/56791
+ * config/pa/pa.c (pa_option_override): Disable auto increment and
+ decrement instructions until reload is completed.
+
+ * config/pa/pa.md: In "scc" insn patterns, change output template to
+ handle const0_rtx in reg_or_0_operand operands.
+
+2013-09-19 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (expand_omp_sections): Always pass len - 1 to
+ GOMP_sections_start, even if !exit_reachable.
+
+2013-09-18 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.c (arm_expand_prologue): Validate architecture supports
+ LDRD/STRD before accepting tuning preferences.
+ (arm_expand_epilogue): Likewise.
+
+2013-09-18 Daniel Morris <danielm@ecoscentric.com>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58458
+ * doc/implement-cxx.texi: Fix references to the C++ standards.
+
+2013-09-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/58088
+ * fold-const.c (mask_with_trailing_zeros): New function.
+ (fold_binary_loc): Make sure we don't recurse infinitely
+ when the X in (X & C1) | C2 is a tree of the form (Y * K1) & K2.
+ Use mask_with_trailing_zeros where appropriate.
+
+2013-09-14 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/58382
+ * config/pa/pa.c (pa_expand_prologue): Change mode in gen_rtx_POST_INC
+ calls to word_mode.
+
+2013-09-13 Christian Bruel <christian.bruel@st.com>
+
+ PR target/58314
+ * config/sh/sh.md (mov<mode>_reg_reg): Allow memory reloads.
+
+2013-09-11 Andi Kleen <ak@linux.intel.com>
+
+ Backport from mainline
+ * doc/extend.texi: Use __atomic_store_n instead of
+ __atomic_store in HLE example.
+
+2013-09-11 Andi Kleen <ak@linux.intel.com>
+
+ Backport from mainline
+ * doc/extend.texi: Dont use __atomic_clear in HLE
+ example. Fix typo.
+
+2013-09-11 Andi Kleen <ak@linux.intel.com>
+
+ Backport from mainline
+ * doc/extend.texi: Document that __atomic_clear and
+ __atomic_test_and_set should only be used with bool.
+
+2013-09-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58377
+ * passes.c (init_optimization_passes): Split critical edges
+ before late uninit warning pass in the -Og pipeline.
+
+2013-09-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58385
+ * fold-const.c (build_range_check): If both low and high are NULL,
+ use omit_one_operand_loc to preserve exp side-effects.
+
+2013-09-10 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/58361
+ * arm/vfp.md (combine_vcvt_f32_<FCVTI32typename>): Fix pattern to
+ support conditional execution.
+ (combine_vcvt_f64_<FCVTI32typename>): Likewise.
+
+2013-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58365
+ * cfgcleanup.c (merge_memattrs): Also clear MEM_READONLY_P
+ resp. MEM_NOTRAP_P if they differ, or set MEM_VOLATILE_P if
+ it differs.
+
+2013-09-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58364
+ * tree-ssa-reassoc.c (init_range_entry): For BIT_NOT_EXPR on
+ BOOLEAN_TYPE, only invert in_p and continue with arg0 if
+ the current range can't be an unconditional true or false.
+
+2013-09-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/57735
+ Backport from mainline
+ 2013-04-30 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * explow.c (plus_constant): Pass "mode" to immed_double_int_const.
+ Use gen_int_mode rather than GEN_INT.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57521
+ * tree-if-conv.c (if_convertible_bb_p): Verify that at least
+ one edge is non-critical.
+ (find_phi_replacement_condition): Make sure to use a non-critical
+ edge. Cleanup and remove old bug workarounds.
+ (bb_postdominates_preds): Remove.
+ (if_convertible_loop_p_1): Do not compute post-dominators.
+ (combine_blocks): Do not free post-dominators.
+ (main_tree_if_conversion): Likewise.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-09-03 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57656
+ * fold-const.c (negate_expr_p): Fix division case.
+ (negate_expr): Likewise.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57685
+ * tree-vrp.c (register_edge_assert_for_1): Recurse only for
+ single-use operands to avoid exponential complexity.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58223
+ * tree-loop-distribution.c (has_anti_dependence): Rename to ...
+ (has_anti_or_output_dependence): ... this and adjust to also
+ look for output dependences.
+ (mark_nodes_having_upstream_mem_writes): Adjust.
+ (rdg_flag_uses): Likewise.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58246
+ * tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Properly
+ handle the dominance check inside a basic-block.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58228
+ * tree-vect-data-refs.c (vect_analyze_data_ref_access): Do not
+ allow invariant loads in nested loop vectorization.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58010
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Remove
+ assert that we have a loop-closed PHI.
+
+2013-09-01 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-31 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/alpha.c (alpha_emit_conditional_move): Update
+ "cmp" RTX before signed_comparison_operator check to account
+ for "code" changes.
+
+2013-09-01 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md: Allow "const 0" operand 1 in "scc" insns.
+
+2013-08-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58277
+ * tree-ssa-strlen.c (strlen_enter_block): If do_invalidate gave up
+ after seeing too many stmts with vdef in between dombb and current
+ bb, invalidate everything.
+
+2013-08-29 Oleg Endo <olegendo@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-08-05 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR other/12081
+ * recog.h (rtx (*insn_gen_fn) (rtx, ...)): Replace typedef with new
+ class insn_gen_fn.
+ * expr.c (move_by_pieces_1, store_by_pieces_2): Replace argument
+ rtx (*) (rtx, ...) with insn_gen_fn.
+ * genoutput.c (output_insn_data): Cast gen_? function pointers to
+ insn_gen_fn::stored_funcptr. Add initializer braces.
+
+ Backport from mainline
+ 2013-08-07 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR other/12081
+ * config/rs6000/rs6000.c (gen_2arg_fn_t): Remove typedef.
+ (rs6000_emit_swdiv_high_precision, rs6000_emit_swdiv_low_precision,
+ rs6000_emit_swrsqrt): Don't cast result of GEN_FCN to gen_2arg_fn_t.
+
+2013-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-05-27 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57381
+ PR tree-optimization/57417
+ * tree-ssa-sccvn.c (vn_reference_fold_indirect): Fix test
+ for unchanged base.
+ (set_ssa_val_to): Compare addresses using
+ get_addr_base_and_unit_offset.
+
+ PR tree-optimization/57396
+ * tree-affine.c (double_int_constant_multiple_p): Properly
+ return false for val == 0 and div != 0.
+
+ PR tree-optimization/57343
+ * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Do not
+ use multiple_of_p if not TYPE_OVERFLOW_UNDEFINED.
+ (number_of_iterations_cond): Do not build the folded tree.
+
+2013-08-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58257
+ * omp-low.c (copy_var_decl): Copy over TREE_NO_WARNING flag.
+
+2013-08-28 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-06-24 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/56977
+ * passes.c (init_optimization_passes): Move pass_fold_builtins
+ and pass_dce earlier with -Og.
+
+2013-08-28 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Update
+ Haswell processor detection.
+
+ Backport from mainline
+ 2013-08-27 Christian Widmer <shadow@umbrox.de>
+
+ PR target/57927
+ * config/i386/driver-i386.c (host_detect_local_cpu): Add detection
+ of Ivy Bridge and Haswell processors. Assume core-avx2 for unknown
+ AVX2 capable processors.
+
+2013-08-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/58218
+ * config/i386/x86-64.h (TARGET_SECTION_TYPE_FLAGS): Define.
+ * config/i386/i386.c (x86_64_elf_section_type_flags): New function.
+
+ PR tree-optimization/58209
+ * tree-tailcall.c (find_tail_calls): Give up for pointer result types
+ if m or a is non-NULL.
+
+2013-08-21 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/56979
+ * arm.c (aapcs_vfp_allocate): Decompose the argument if the
+ suggested mode for the assignment isn't compatible with the
+ registers required.
+
+2013-08-20 Alan Modra <amodra@gmail.com>
+
+ PR target/57865
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Correct ool_adjust.
+ (rs6000_emit_epilogue): Likewise.
+
+2013-08-19 Peter Bergner <bergner@vnet.ibm.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ Backport from mainline
+ * config/rs6000/dfp.md (*negtd2_fpr): Handle non-overlapping
+ destination and source operands.
+
+2013-08-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58006
+ * tree-parloops.c (take_address_of): Don't ICE if get_name
+ returns NULL.
+ (eliminate_local_variables_stmt): Remove clobber stmts.
+
+2013-08-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58164
+ * gimple.c (walk_stmt_load_store_addr_ops): For visit_addr
+ walk gimple_goto_dest of GIMPLE_GOTO.
+
+ PR tree-optimization/58165
+ * tree-call-cdce.c (shrink_wrap_one_built_in_call): If
+ bi_call must be the last stmt in a bb, don't split_block, instead
+ use fallthru edge from it and give up if there is none.
+ Release conds vector when returning early.
+
+2013-08-15 David Given <dg@cowlark.com>
+
+ Backport from mainline
+ 2013-04-26 Vladimir Makarov <vmakarov@redhat.com>
+
+ * lra-constraints.c (process_alt_operands): Use #if HAVE_ATTR_enable
+ instead of #ifdef.
+
+2013-08-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58145
+ * tree-sra.c (build_ref_for_offset): If prev_base has
+ TREE_THIS_VOLATILE or TREE_SIDE_EFFECTS, propagate it to MEM_REF.
+
+2013-08-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/htmxlintrin.h: Add file missing from last commit.
+ * config/s390/htmintrin.h: Likewise.
+ * config/s390/s390intrin.h: Likewise.
+
+2013-08-14 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-13 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (*sse2_maskmovdqu): Emit addr32 prefix
+ when Pmode != word_mode. Add length_address attribute.
+ (sse3_monitor_<mode>): Merge from sse3_monitor and
+ sse3_monitor64_<mode> insn patterns. Emit addr32 prefix when
+ Pmode != word_mode. Update insn length attribute.
+ * config/i386/i386.c (ix86_option_override_internal): Update
+ ix86_gen_monitor selection for merged sse3_monitor insn.
+
+2013-08-14 Jakub Jelinek <jakub@redhat.com>
+ Alexandre Oliva <aoliva@redhat.com>
+
+ PR target/58067
+ * config/i386/i386.c (ix86_delegitimize_address): For CM_MEDIUM_PIC
+ and CM_LARGE_PIC ix86_cmodel fall thru into the -m32 code, handle
+ there also UNSPEC_PLTOFF.
+
+2013-08-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/56417
+ * asan.c (instrument_strlen_call): Fix typo in comment.
+ Use char * type even for the lhs of POINTER_PLUS_EXPR.
+
+2013-08-13 Vladimir Makarov <vmakarov@redhat.com>
+
+ Backport from mainline
+ 2013-06-06 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/57459
+ * lra-constraints.c (update_ebb_live_info): Fix typo for operand
+ type when setting live regs.
+
+2013-08-13 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/57980
+ * tree-tailcall.c (process_assignment): Return false
+ when not dealing with integers or floats.
+
+2013-08-12 Andrew Haley <aph@redhat.com>
+
+ Backport from mainline:
+ * 2013-07-11 Andreas Schwab <schwab@suse.de>
+
+ * config/aarch64/aarch64-linux.h (CPP_SPEC): Define.
+
+2013-08-13 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-12 Perez Read <netfirewall@gmail.com>
+
+ PR target/58132
+ * config/i386/i386.md (*movabs<mode>_1): Add <ptrsize> PTR before
+ operand 0 for intel asm alternative.
+ (*movabs<mode>_2): Ditto for operand 1.
+
+2013-08-09 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ Backport from mainline:
+ 2013-08-09 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * config/arm/neon.md (vcond): Fix floating-point vector
+ comparisons against 0.
+
+2013-08-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline:
+ 2013-08-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/neon.md (movmisalign<mode>): Disable when we
+ don't allow unaligned accesses.
+ (*movmisalign<mode>_neon_store): Likewise.
+ (*movmisalign<mode>_neon_load): Likewise.
+ (*movmisalign<mode>_neon_store): Likewise.
+ (*movmisalign<mode>_neon_load): Likewise.
+
+2013-08-06 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/58041
+ * gimple-ssa-strength-reduction.c (replace_ref): Make sure built
+ MEM_REF has proper alignment information.
+
+2013-08-05 Richard Earnshaw <rearnsha@arm.com>
+
+ PR rtl-optimization/57708
+ * recog.c (peep2_find_free_register): Validate all regs in a
+ multi-reg mode.
+
+2013-08-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.c (sparc_emit_membar_for_model) <SMM_TSO>: Add
+ the implied StoreLoad barrier for atomic operations if before.
+
+2013-08-02 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ Backports from mainline:
+ 2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c: Rename UNSPEC_CCU_TO_INT to
+ UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
+ (struct machine_function): Add tbegin_p.
+ (s390_canonicalize_comparison): Fold CC mode compares to
+ conditional jump if possible.
+ (s390_emit_jump): Return the emitted jump.
+ (s390_branch_condition_mask, s390_branch_condition_mnemonic):
+ Handle CCRAWmode compares.
+ (s390_option_override): Default to -mhtm if available.
+ (s390_reg_clobbered_rtx): Handle floating point regs as well.
+ (s390_regs_ever_clobbered): Use s390_regs_ever_clobbered also for
+ FPRs instead of df_regs_ever_live_p.
+ (s390_optimize_nonescaping_tx): New function.
+ (s390_init_frame_layout): Extend clobbered_regs array to cover
+ FPRs as well.
+ (s390_emit_prologue): Call s390_optimize_nonescaping_tx.
+ (s390_expand_tbegin): New function.
+ (enum s390_builtin): New enum definition.
+ (code_for_builtin): New array definition.
+ (s390_init_builtins): New function.
+ (s390_expand_builtin): New function.
+ (TARGET_INIT_BUILTINS): Define.
+ (TARGET_EXPAND_BUILTIN): Define.
+ * common/config/s390/s390-common.c (processor_flags_table): Add PF_TX.
+ * config/s390/predicates.md (s390_comparison): Handle CCRAWmode.
+ (s390_alc_comparison): Likewise.
+ * config/s390/s390-modes.def: Add CCRAWmode.
+ * config/s390/s390.h (processor_flags): Add PF_TX.
+ (TARGET_CPU_HTM): Define macro.
+ (TARGET_HTM): Define macro.
+ (TARGET_CPU_CPP_BUILTINS): Define __HTM__ for htm.
+ * config/s390/s390.md: Rename UNSPEC_CCU_TO_INT to
+ UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
+ (UNSPECV_TBEGIN, UNSPECV_TBEGINC, UNSPECV_TEND, UNSPECV_TABORT)
+ (UNSPECV_ETND, UNSPECV_NTSTG, UNSPECV_PPA): New unspecv enum
+ values.
+ (TBEGIN_MASK, TBEGINC_MASK): New constants.
+ ("*cc_to_int"): Move up.
+ ("*mov<mode>cc", "*cjump_64", "*cjump_31"): Accept integer
+ constants other than 0.
+ ("*ccraw_to_int"): New insn and splitter definition.
+ ("tbegin", "tbegin_nofloat", "tbegin_retry")
+ ("tbegin_retry_nofloat", "tbeginc", "tend", "tabort")
+ ("tx_assist"): New expander.
+ ("tbegin_1", "tbegin_nofloat_1", "*tbeginc_1", "*tend_1")
+ ("*tabort_1", "etnd", "ntstg", "*ppa"): New insn definition.
+ * config/s390/s390.opt: Add -mhtm option.
+ * config/s390/s390-protos.h (s390_emit_jump): Add return type.
+ * config/s390/htmxlintrin.h: New file.
+ * config/s390/htmintrin.h: New file.
+ * config/s390/s390intrin.h: New file.
+ * doc/extend.texi: Document htm builtins.
+ * config.gcc: Add the new header files to extra_headers.
+
+ 2013-07-17 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c: (s390_expand_builtin): Allow -mhtm to be
+ enabled without -march=zEC12.
+ * config/s390/s390.h (TARGET_HTM): Do not require EC12 machine
+ flags to be set.
+
+2013-08-01 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+
+ Backport from mainline
+ 2013-05-13 Ganesh Gopalasubramanian
+ <Ganesh.Gopalasubramanian@amd.com>
+
+ * config/i386/i386.c (processor_target_table): Modified default
+ alignment values for AMD BD and BT architectures.
+
+2013-07-31 Sriraman Tallam <tmsriram@google.com>
+
+ * config/i386/i386.c (dispatch_function_versions): Fix array
+ indexing of function_version_info to match actual_versions.
+
+2013-07-31 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config.gcc (*-*-rtems*): Use __cxa_atexit by default.
+ * config/rs6000/rtems.h (TARGET_LIBGCC_SDATA_SECTION): Define.
+
+2013-07-31 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ Backport from mainline
+ 2013-03-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.h (TARGET_FLT_EVAL_METHOD): Define.
+
+ 2013-07-23 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/linux-unwind.h: Use the proper dwarf to hard reg
+ mapping for FPRs when creating the fallback framestate.
+
+ 2013-07-29 Dominik Vogt <vogt@linux.vnet.ibm.com>
+
+ * config/s390/s390.md ("movcc"): Swap load and store instructions.
+
+2013-07-25 Terry Guo <terry.guo@arm.com>
+
+ Backport from mainline:
+ 2013-07-25 Terry Guo <terry.guo@arm.com>
+
+ * config/arm/arm.c (thumb1_size_rtx_costs): Assign proper cost for
+ shift_add/shift_sub0/shift_sub1 RTXs.
+
+2013-07-22 Iain Sandoe <iain@codesourcery.com>
+
+ Backport from mainline:
+ 2013-07-22 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (nonlocal_goto_receiver): Delete insn if
+ it is not needed after split.
+
+ 2013-07-20 Iain Sandoe <iain@codesourcery.com>
+
+ PR target/51784
+ * config/i386/i386.c (output_set_got) [TARGET_MACHO]: Adjust to emit a
+ second label for nonlocal goto receivers. Don't output pic base labels
+ unless we're producing PIC; mark that action unreachable().
+ (ix86_save_reg): If the function contains a nonlocal label, save the
+ PIC base reg.
+ * config/darwin-protos.h (machopic_should_output_picbase_label): New.
+ * gcc/config/darwin.c (emitted_pic_label_num): New GTY.
+ (update_pic_label_number_if_needed): New.
+ (machopic_output_function_base_name): Adjust for nonlocal receiver
+ case.
+ (machopic_should_output_picbase_label): New.
+ * config/i386/i386.md (enum unspecv): UNSPECV_NLGR: New.
+ (nonlocal_goto_receiver): New insn and split.
+
+2013-07-19 Wei Mi <wmi@google.com>
+
+ Backport from mainline:
+ 2013-07-18 Vladimir Makarov <vmakarov@redhat.com>
+ Wei Mi <wmi@google.com>
+
+ PR rtl-optimization/57878
+ * lra-assigns.c (assign_by_spills): Move non_reload_pseudos to the
+ top. Promote lra_assert to gcc_assert.
+ (reload_pseudo_compare_func): Check regs first for reload pseudos.
+
+2013-07-11 Georg-Johann Lay <avr@gjlay.de>
+
+ Backport from 2013-07-19 trunk r201051.
+
+ PR target/57516
+ * config/avr/avr-fixed.md (round<mode>3_const): Turn expander to insn.
+ * config/avr/avr.md (adjust_len): Add `round'.
+ * config/avr/avr-protos.h (avr_out_round): New prototype.
+ (avr_out_plus): Add `out_label' argument.
+ * config/avr/avr.c (avr_out_plus_1): Add `out_label' argument.
+ (avr_out_plus): Pass down `out_label' to avr_out_plus_1.
+ Handle the case where `insn' is just a pattern.
+ (avr_out_bitop): Handle the case where `insn' is just a pattern.
+ (avr_out_round): New function.
+ (avr_adjust_insn_length): Handle ADJUST_LEN_ROUND.
+
+2013-07-19 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * config/i386/bmiintrin.h (_bextr_u32): New.
+ (_bextr_u64): Ditto.
+ (_blsi_u32): New.
+ (_blsi_u64): Ditto.
+ (_blsr_u32): Ditto.
+ (_blsr_u64): Ditto.
+ (_blsmsk_u32): Ditto.
+ (_blsmsk_u64): Ditto.
+ (_tzcnt_u32): Ditto.
+ (_tzcnt_u64): Ditto.
+
+2013-07-17 James Greenhalgh <james.greenhalgh@arm.com>
+
+ Backport From mainline:
+ 2013-07-03 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64-builtins.c
+ (aarch64_simd_expand_builtin): Handle AARCH64_SIMD_STORE1.
+ * config/aarch64/aarch64-simd-builtins.def (ld1): New.
+ (st1): Likewise.
+ * config/aarch64/aarch64-simd.md
+ (aarch64_ld1<VALL:mode>): New.
+ (aarch64_st1<VALL:mode>): Likewise.
+ * config/aarch64/arm_neon.h
+ (vld1<q>_<fpsu><8, 16, 32, 64>): Convert to RTL builtins.
+
2013-07-11 Georg-Johann Lay <avr@gjlay.de>
Backport from 2013-07-11 trunk r200901.
@@ -17,7 +1842,7 @@
2013-07-10 Georg-Johann Lay <avr@gjlay.de>
Backport from 2013-07-10 trunk r200870.
-
+
PR target/57506
* config/avr/avr-mcus.def (atmega16hva, atmega16hva2, atmega16hvb)
(atmega16m1, atmega16u4, atmega32a, atmega32c1, atmega32hvb)
diff --git a/gcc/ChangeLog.ibm b/gcc/ChangeLog.ibm
index cdf4e6711e7..d44469a1932 100644
--- a/gcc/ChangeLog.ibm
+++ b/gcc/ChangeLog.ibm
@@ -1,3 +1,1582 @@
+2014-02-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207919.
+ 2014-02-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (vspltis_constant): Fix most significant
+ bit of zero.
+
+2014-02-18 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline r207868.
+ 2014-02-18 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/60203
+ * config/rs6000/rs6000.md (mov<mode>_64bit, TF/TDmode moves):
+ Split 64-bit moves into 2 patterns. Do not allow the use of
+ direct move for TDmode in little endian, since the decimal value
+ has little endian bytes within a word, but the 64-bit pieces are
+ ordered in a big endian fashion, and normal subreg's of TDmode are
+ not allowed.
+ (mov<mode>_64bit_dm): Likewise.
+ (movtd_64bit_nodm): Likewise.
+
+2014-02-16 Bill Schmidt <wschmidt@Linux.vnet.ibm.com>
+
+ Backport from mainline r207815.
+ 2014-02-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (p8_vmrgew): Handle little endian
+ targets.
+ (p8_vmrgow): Likewise.
+
+2014-02-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207814.
+ 2014-02-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_xxpermdi_<mode>): Handle little
+ endian targets.
+
+2014-02-15 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline r207808.
+ 2014-02-15 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/60203
+ * config/rs6000/rs6000.md (rreg): Add TFmode, TDmode constraints.
+ (mov<mode>_internal, TFmode/TDmode): Split TFmode/TDmode moves
+ into 64-bit and 32-bit moves. On 64-bit moves, add support for
+ using direct move instructions on ISA 2.07. Also adjust
+ instruction length for 64-bit.
+ (mov<mode>_64bit, TFmode/TDmode): Likewise.
+ (mov<mode>_32bit, TFmode/TDmode): Likewise.
+
+2014-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline r207699.
+ 2014-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/60137
+ * config/rs6000/rs6000.md (128-bit GPR splitter): Add a splitter
+ for VSX/Altivec vectors that land in GPR registers.
+
+2014-02-06 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r207658
+ 2014-02-06 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/sysv4.h (ENDIAN_SELECT): Do not attempt to enforce
+ big-endian mode for -mcall-aixdesc, -mcall-freebsd, -mcall-netbsd,
+ -mcall-openbsd, or -mcall-linux.
+ (CC1_ENDIAN_BIG_SPEC): Remove.
+ (CC1_ENDIAN_LITTLE_SPEC): Remove.
+ (CC1_ENDIAN_DEFAULT_SPEC): Remove.
+ (CC1_SPEC): Remove (always empty) %cc1_endian_... spec.
+ (SUBTARGET_EXTRA_SPECS): Remove %cc1_endian_big, %cc1_endian_little,
+ and %cc1_endian_default.
+ * config/rs6000/sysv4le.h (CC1_ENDIAN_DEFAULT_SPEC): Remove.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207525
+ 2014-02-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Change
+ CODE_FOR_altivec_vpku[hw]um to
+ CODE_FOR_altivec_vpku[hw]um_direct.
+ * config/rs6000/altivec.md (vec_unpacks_hi_<VP_small_lc>): Change
+ UNSPEC_VUNPACK_HI_SIGN to UNSPEC_VUNPACK_HI_SIGN_DIRECT.
+ (vec_unpacks_lo_<VP_small_lc>): Change UNSPEC_VUNPACK_LO_SIGN to
+ UNSPEC_VUNPACK_LO_SIGN_DIRECT.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207521
+ 2014-02-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (altivec_vsum2sws): Adjust code
+ generation for -maltivec=be.
+ (altivec_vsumsws): Simplify redundant test.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207520
+ 2014-02-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * altivec.md (UNSPEC_VPACK_UNS_UNS_MOD_DIRECT): New unspec.
+ (UNSPEC_VUNPACK_HI_SIGN_DIRECT): Likewise.
+ (UNSPEC_VUNPACK_LO_SIGN_DIRECT): Likewise.
+ (mulv8hi3): Use gen_altivec_vpkuwum_direct instead of
+ gen_altivec_vpkuwum.
+ (altivec_vpkpx): Test for VECTOR_ELT_ORDER_BIG instead of for
+ BYTES_BIG_ENDIAN.
+ (altivec_vpks<VI_char>ss): Likewise.
+ (altivec_vpks<VI_char>us): Likewise.
+ (altivec_vpku<VI_char>us): Likewise.
+ (altivec_vpku<VI_char>um): Likewise.
+ (altivec_vpku<VI_char>um_direct): New (copy of
+ altivec_vpku<VI_char>um that still relies on BYTES_BIG_ENDIAN, for
+ internal use).
+ (altivec_vupkhs<VU_char>): Emit vupkls* instead of vupkhs* when
+ target is little endian and -maltivec=be is not specified.
+ (*altivec_vupkhs<VU_char>_direct): New (copy of
+ altivec_vupkhs<VU_char> that always emits vupkhs*, for internal
+ use).
+ (altivec_vupkls<VU_char>): Emit vupkhs* instead of vupkls* when
+ target is little endian and -maltivec=be is not specified.
+ (*altivec_vupkls<VU_char>_direct): New (copy of
+ altivec_vupkls<VU_char> that always emits vupkls*, for internal
+ use).
+ (altivec_vupkhpx): Emit vupklpx instead of vupkhpx when target is
+ little endian and -maltivec=be is not specified.
+ (altivec_vupklpx): Emit vupkhpx instead of vupklpx when target is
+ little endian and -maltivec=be is not specified.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207415
+ 2014-02-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_le): Generalize
+ for vector types other than V16QImode.
+ * config/rs6000/altivec.md (altivec_vperm_<mode>): Change to a
+ define_expand, and call altivec_expand_vec_perm_le when producing
+ code with little endian element order.
+ (*altivec_vperm_<mode>_internal): New insn having previous
+ behavior of altivec_vperm_<mode>.
+ (altivec_vperm_<mode>_uns): Change to a define_expand, and call
+ altivec_expand_vec_perm_le when producing code with little endian
+ element order.
+ (*altivec_vperm_<mode>_uns_internal): New insn having previous
+ behavior of altivec_vperm_<mode>_uns.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207414
+ 2014-02-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (UNSPEC_VSUMSWS_DIRECT): New unspec.
+ (altivec_vsumsws): Add handling for -maltivec=be with a little
+ endian target.
+ (altivec_vsumsws_direct): New.
+ (reduc_splus_<mode>): Call gen_altivec_vsumsws_direct instead of
+ gen_altivec_vsumsws.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207326
+ 2014-01-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Remove
+ unused variable "field".
+ * config/rs6000/vsx.md (vsx_mergel_<mode>): Add missing DONE.
+ (vsx_mergeh_<mode>): Likewise.
+ * config/rs6000/altivec.md (altivec_vmrghb): Likewise.
+ (altivec_vmrghh): Likewise.
+ (altivec_vmrghw): Likewise.
+ (altivec_vmrglb): Likewise.
+ (altivec_vmrglh): Likewise.
+ (altivec_vmrglw): Likewise.
+ (altivec_vspltb): Add missing uses.
+ (altivec_vsplth): Likewise.
+ (altivec_vspltw): Likewise.
+ (altivec_vspltsf): Likewise.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207318
+ 2014-01-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc/config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
+ gen_vsx_xxspltw_v4sf_direct instead of gen_vsx_xxspltw_v4sf;
+ remove element index adjustment for endian (now handled in vsx.md
+ and altivec.md).
+ (altivec_expand_vec_perm_const): Use
+ gen_altivec_vsplt[bhw]_direct instead of gen_altivec_vsplt[bhw].
+ * gcc/config/rs6000/vsx.md (UNSPEC_VSX_XXSPLTW): New unspec.
+ (vsx_xxspltw_<mode>): Adjust element index for little endian.
+ * gcc/config/rs6000/altivec.md (altivec_vspltb): Divide into a
+ define_expand and a new define_insn *altivec_vspltb_internal;
+ adjust for -maltivec=be on a little endian target.
+ (altivec_vspltb_direct): New.
+ (altivec_vsplth): Divide into a define_expand and a new
+ define_insn *altivec_vsplth_internal; adjust for -maltivec=be on a
+ little endian target.
+ (altivec_vsplth_direct): New.
+ (altivec_vspltw): Divide into a define_expand and a new
+ define_insn *altivec_vspltw_internal; adjust for -maltivec=be on a
+ little endian target.
+ (altivec_vspltw_direct): New.
+ (altivec_vspltsf): Divide into a define_expand and a new
+ define_insn *altivec_vspltsf_internal; adjust for -maltivec=be on
+ a little endian target.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207262
+ 2014-01-29 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Use
+ CODE_FOR_altivec_vmrg*_direct rather than CODE_FOR_altivec_vmrg*.
+ * config/rs6000/vsx.md (vsx_mergel_<mode>): Adjust for
+ -maltivec=be with LE targets.
+ (vsx_mergeh_<mode>): Likewise.
+ * config/rs6000/altivec.md (UNSPEC_VMRG[HL]_DIRECT): New
+ unspecs.
+ (mulv8hi3): Use gen_altivec_vmrg[hl]w_direct.
+ (altivec_vmrghb): Replace with define_expand and new
+ *altivec_vmrghb_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrghb_direct): New define_insn.
+ (altivec_vmrghh): Replace with define_expand and new
+ *altivec_vmrghh_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrghh_direct): New define_insn.
+ (altivec_vmrghw): Replace with define_expand and new
+ *altivec_vmrghw_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrghw_direct): New define_insn.
+ (*altivec_vmrghsf): Adjust for endianness.
+ (altivec_vmrglb): Replace with define_expand and new
+ *altivec_vmrglb_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrglb_direct): New define_insn.
+ (altivec_vmrglh): Replace with define_expand and new
+ *altivec_vmrglh_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrglh_direct): New define_insn.
+ (altivec_vmrglw): Replace with define_expand and new
+ *altivec_vmrglw_internal insn; adjust for -maltivec=be with LE
+ targets.
+ (altivec_vmrglw_direct): New define_insn.
+ (*altivec_vmrglsf): Adjust for endianness.
+ (vec_widen_umult_hi_v16qi): Use gen_altivec_vmrghh_direct.
+ (vec_widen_umult_lo_v16qi): Use gen_altivec_vmrglh_direct.
+ (vec_widen_smult_hi_v16qi): Use gen_altivec_vmrghh_direct.
+ (vec_widen_smult_lo_v16qi): Use gen_altivec_vmrglh_direct.
+ (vec_widen_umult_hi_v8hi): Use gen_altivec_vmrghw_direct.
+ (vec_widen_umult_lo_v8hi): Use gen_altivec_vmrglw_direct.
+ (vec_widen_smult_hi_v8hi): Use gen_altivec_vmrghw_direct.
+ (vec_widen_smult_lo_v8hi): Use gen_altivec_vmrglw_direct.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207062
+ 2014-01-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Remove
+ correction for little endian...
+ * config/rs6000/vsx.md (vsx_xxpermdi2_<mode>_1): ...and move it to
+ here.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206641
+ 2014-01-15 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * config/rs6000/altivec.md (mulv8hi3): Explicitly generate vmulesh
+ and vmulosh rather than call gen_vec_widen_smult_*.
+ (vec_widen_umult_even_v16qi): Test VECTOR_ELT_ORDER_BIG rather
+ than BYTES_BIG_ENDIAN to determine use of even or odd instruction.
+ (vec_widen_smult_even_v16qi): Likewise.
+ (vec_widen_umult_even_v8hi): Likewise.
+ (vec_widen_smult_even_v8hi): Likewise.
+ (vec_widen_umult_odd_v16qi): Likewise.
+ (vec_widen_smult_odd_v16qi): Likewise.
+ (vec_widen_umult_odd_v8hi): Likewise.
+ (vec_widen_smult_odd_v8hi): Likewise.
+ (vec_widen_umult_hi_v16qi): Explicitly generate vmuleub and
+ vmuloub rather than call gen_vec_widen_umult_*.
+ (vec_widen_umult_lo_v16qi): Likewise.
+ (vec_widen_smult_hi_v16qi): Explicitly generate vmulesb and
+ vmulosb rather than call gen_vec_widen_smult_*.
+ (vec_widen_smult_lo_v16qi): Likewise.
+ (vec_widen_umult_hi_v8hi): Explicitly generate vmuleuh and vmulouh
+ rather than call gen_vec_widen_umult_*.
+ (vec_widen_umult_lo_v8hi): Likewise.
+ (vec_widen_smult_hi_v8hi): Explicitly gnerate vmulesh and vmulosh
+ rather than call gen_vec_widen_smult_*.
+ (vec_widen_smult_lo_v8hi): Likewise.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206590
+ 2014-01-13 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin):
+ Implement -maltivec=be for vec_insert and vec_extract.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206541
+ 2014-01-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-builtin.def: Fix pasto for VPKSDUS.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206494
+ 2014-01-09 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * doc/invoke.texi: Add -maltivec={be,le} options, and document
+ default element-order behavior for -maltivec.
+ * config/rs6000/rs6000.opt: Add -maltivec={be,le} options.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Ensure
+ that -maltivec={le,be} implies -maltivec; disallow -maltivec=le
+ when targeting big endian, at least for now.
+ * config/rs6000/rs6000.h: Add #define of VECTOR_ELT_ORDER_BIG.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206443
+ 2014-01-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Remove
+ two duplicate entries.
+
+2014-02-04 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.opt (-mlra): Add switch to enable the LRA
+ register allocator.
+
+ * config/rs6000/rs6000.c (TARGET_LRA_P): Add support for -mlra to
+ enable the LRA register allocator. Back port the changes from the
+ trunk to enable LRA.
+ (rs6000_legitimate_offset_address_p): Likewise.
+ (legitimate_lo_sum_address_p): Likewise.
+ (use_toc_relative_ref): Likewise.
+ (rs6000_legitimate_address_p): Likewise.
+ (rs6000_emit_move): Likewise.
+ (rs6000_secondary_memory_needed_mode): Likewise.
+ (rs6000_alloc_sdmode_stack_slot): Likewise.
+ (rs6000_lra_p): Likewise.
+
+ * config/rs6000/sync.md (load_lockedti): Copy TI/PTI variables by
+ 64-bit parts to force the register allocator to allocate even/odd
+ register pairs for the quad word atomic instructions.
+ (store_conditionalti): Likewise.
+
+2014-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from mainline
+ 2014-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59909
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Document
+ -mquad-memory-atomic. Update -mquad-memory documentation to say
+ it is only used for non-atomic loads/stores.
+
+ * config/rs6000/predicates.md (quad_int_reg_operand): Allow either
+ -mquad-memory or -mquad-memory-atomic switches.
+
+ * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER): Add
+ -mquad-memory-atomic to ISA 2.07 support.
+
+ * config/rs6000/rs6000.opt (-mquad-memory-atomic): Add new switch
+ to separate support of normal quad word memory operations (ldq,
+ stq) from the atomic quad word memory operations.
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Add
+ support to separate non-atomic quad word operations from atomic
+ quad word operations. Disable non-atomic quad word operations in
+ little endian mode so that we don't have to swap words after the
+ load and before the store.
+ (quad_load_store_p): Add comment about atomic quad word support.
+ (rs6000_opt_masks): Add -mquad-memory-atomic to the list of
+ options printed with -mdebug=reg.
+
+ * config/rs6000/rs6000.h (TARGET_SYNC_TI): Use
+ -mquad-memory-atomic as the test for whether we have quad word
+ atomic instructions.
+ (TARGET_SYNC_HI_QI): If either -mquad-memory-atomic,
+ -mquad-memory, or -mp8-vector are used, allow byte/half-word
+ atomic operations.
+
+ * config/rs6000/sync.md (load_lockedti): Insure that the address
+ is a proper indexed or indirect address for the lqarx instruction.
+ On little endian systems, swap the hi/lo registers after the lqarx
+ instruction.
+ (load_lockedpti): Use indexed_or_indirect_operand predicate to
+ insure the address is valid for the lqarx instruction.
+ (store_conditionalti): Insure that the address is a proper indexed
+ or indirect address for the stqcrx. instruction. On little endian
+ systems, swap the hi/lo registers before doing the stqcrx.
+ instruction.
+ (store_conditionalpti): Use indexed_or_indirect_operand predicate to
+ insure the address is valid for the stqcrx. instruction.
+
+ * gcc/config/rs6000/rs6000-c.c (rs6000_target_modify_macros):
+ Define __QUAD_MEMORY__ and __QUAD_MEMORY_ATOMIC__ based on what
+ type of quad memory support is available.
+
+2014-01-22 Alan Modra <amodra@gmail.com>
+
+ Apply mainline r202190, powerpc64le multilibs and multiarch dir
+ 2013-09-03 Alan Modra <amodra@gmail.com>
+
+ * config.gcc (powerpc*-*-linux*): Add support for little-endian
+ multilibs to big-endian target and vice versa.
+ * config/rs6000/t-linux64: Use := assignment on all vars.
+ (MULTILIB_EXTRA_OPTS): Remove fPIC.
+ (MULTILIB_OSDIRNAMES): Specify using mapping from multilib_options.
+ * config/rs6000/t-linux64le: New file.
+ * config/rs6000/t-linux64bele: New file.
+ * config/rs6000/t-linux64lebe: New file.
+
+2014-01-16 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from mainline
+ 2014-01-16 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59844
+ * config/rs6000/rs6000.md (reload_vsx_from_gprsf): Add little
+ endian support, remove tests for WORDS_BIG_ENDIAN.
+ (p8_mfvsrd_3_<mode>): Likewise.
+ (reload_gpr_from_vsx<mode>): Likewise.
+ (reload_gpr_from_vsxsf): Likewise.
+ (p8_mfvsrd_4_disf): Likewise.
+
+2014-01-16 Peter Bergner <bergner@vnet.ibm.com>
+
+ Merge up to 206665.
+ * REVISION: Update subversion id.
+
+2014-01-13 Peter Bergner <bergner@vnet.ibm.com>
+
+ Merge up to 206579.
+ * REVISION: Update subversion id.
+
+2014-01-08 Peter Bergner <bergner@vnet.ibm.com>
+
+ Merge up to 206404.
+ * REVISION: Update subversion id.
+
+2013-12-10 Peter Bergner <bergner@vnet.ibm.com>
+
+ Merge up to 205847.
+ * REVISION: Update subversion id.
+
+2013-12-03 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2013-12-03 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/htmintrin.h (_TEXASR_INSTRUCTION_FETCH_CONFLICT): Fix
+ typo in macro name.
+ (_TEXASRU_INSTRUCTION_FETCH_CONFLICT): Likewise.
+
+2013-11-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205333
+ 2013-11-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Correct
+ for little endian.
+
+2013-11-23 Alan Modra <amodra@gmail.com>
+
+ Apply mainline r205299.
+ * config/rs6000/vsx.md (fusion peepholes): Disable when !TARGET_VSX.
+
+2013-11-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-11-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59054
+ * config/rs6000/rs6000.md (movdi_internal32): Eliminate
+ constraints that would allow DImode into the traditional Altivec
+ registers, but cause undesirable code generation when loading 0 as
+ a constant.
+ (movdi_internal64): Likewise.
+ (cmp<mode>_fpr): Do not use %x for CR register output.
+ (extendsfdf2_fpr): Fix constraints when -mallow-upper-df and
+ -mallow-upper-sf debug switches are used.
+
+2013-11-21 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205241
+ 2013-11-21 Bill Schmidt <wschmidt@vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_pack_trunc_v2df): Revert previous
+ little endian change.
+ (vec_pack_sfix_trunc_v2df): Likewise.
+ (vec_pack_ufix_trunc_v2df): Likewise.
+ * config/rs6000/rs6000.c (rs6000_expand_interleave): Correct
+ double checking of endianness.
+
+2013-11-21 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline r205233.
+ 2013-11-21 Peter Bergner <bergner@vnet.ibm.com>
+
+ * doc/extend.texi: Document htm builtins.
+
+2013-11-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205146
+ 2013-11-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_set_<mode>): Adjust for little endian.
+ (vsx_extract_<mode>): Likewise.
+ (*vsx_extract_<mode>_one_le): New LE variant on
+ *vsx_extract_<mode>_zero.
+ (vsx_extract_v4sf): Adjust for little endian.
+
+2013-11-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r205123:
+
+ 2013-11-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
+ allow subregs of TDmode in FPRs of smaller size in little-endian.
+ (rs6000_split_multireg_move): When splitting an access to TDmode
+ in FPRs, do not use simplify_gen_subreg.
+
+2013-11-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205080
+ 2013-11-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Adjust
+ V16QI vector splat case for little endian.
+
+2013-11-20 Alan Modra <amodra@gmail.com>
+
+ Apply mainline r205060.
+ * config/rs6000/sysv4.h (CC1_ENDIAN_LITTLE_SPEC): Define as empty.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Default
+ to strict alignment on older processors when little-endian.
+ * config/rs6000/linux64.h (PROCESSOR_DEFAULT64): Default to power8
+ for ELFv2.
+
+2013-11-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r205045:
+
+ 2013-11-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/vector.md ("mov<mode>"): Do not call
+ rs6000_emit_le_vsx_move to move into or out of GPRs.
+ * config/rs6000/rs6000.c (rs6000_emit_le_vsx_move): Assert
+ source and destination are not GPR hard regs.
+
+2013-11-18 Peter Bergner <bergner@vnet.ibm.com>
+
+ Merge up to 204974.
+ * REVISION: Update subversion id.
+
+2013-11-17 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204927:
+
+ 2013-11-17 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_move): Use low word of
+ sdmode_stack_slot also in little-endian mode.
+
+2013-11-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204920
+ 2011-11-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_frame_related): Add split_reg
+ parameter and use it in REG_FRAME_RELATED_EXPR note.
+ (emit_frame_save): Call rs6000_frame_related with extra NULL_RTX
+ parameter.
+ (rs6000_emit_prologue): Likewise, but for little endian VSX
+ stores, pass the source register of the store instead.
+
+2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204862
+ 2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (UNSPEC_VPERM_X, UNSPEC_VPERM_UNS_X):
+ Remove.
+ (altivec_vperm_<mode>): Revert earlier little endian change.
+ (*altivec_vperm_<mode>_internal): Remove.
+ (altivec_vperm_<mode>_uns): Revert earlier little endian change.
+ (*altivec_vperm_<mode>_uns_internal): Remove.
+ * config/rs6000/vector.md (vec_realign_load_<mode>): Revise
+ commentary.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204842:
+
+ 2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * doc/invoke.texi (-mabi=elfv1, -mabi=elfv2): Document.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204809:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/sysv4le.h (LINUX64_DEFAULT_ABI_ELFv2): Define.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204808:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.h (RS6000_SAVE_AREA): Handle ABI_ELFv2.
+ (RS6000_SAVE_TOC): Remove.
+ (RS6000_TOC_SAVE_SLOT): New macro.
+ * config/rs6000/rs6000.c (rs6000_parm_offset): New function.
+ (rs6000_parm_start): Use it.
+ (rs6000_function_arg_advance_1): Likewise.
+ (rs6000_emit_prologue): Use RS6000_TOC_SAVE_SLOT.
+ (rs6000_emit_epilogue): Likewise.
+ (rs6000_call_aix): Likewise.
+ (rs6000_output_function_prologue): Do not save/restore r11
+ around calling _mcount for ABI_ELFv2.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000-protos.h (rs6000_reg_parm_stack_space):
+ Add prototype.
+ * config/rs6000/rs6000.h (RS6000_REG_SAVE): Remove.
+ (REG_PARM_STACK_SPACE): Call rs6000_reg_parm_stack_space.
+ * config/rs6000/rs6000.c (rs6000_parm_needs_stack): New function.
+ (rs6000_function_parms_need_stack): Likewise.
+ (rs6000_reg_parm_stack_space): Likewise.
+ (rs6000_function_arg): Do not replace BLKmode by Pmode when
+ returning a register argument.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Michael Gschwind <mkg@us.ibm.com>
+
+ * config/rs6000/rs6000.h (FP_ARG_MAX_RETURN): New macro.
+ (ALTIVEC_ARG_MAX_RETURN): Likewise.
+ (FUNCTION_VALUE_REGNO_P): Use them.
+ * config/rs6000/rs6000.c (TARGET_RETURN_IN_MSB): Define.
+ (rs6000_return_in_msb): New function.
+ (rs6000_return_in_memory): Handle ELFv2 homogeneous aggregates.
+ Handle aggregates of up to 16 bytes for ELFv2.
+ (rs6000_function_value): Handle ELFv2 homogeneous aggregates.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Michael Gschwind <mkg@us.ibm.com>
+
+ * config/rs6000/rs6000.h (AGGR_ARG_NUM_REG): Define.
+ * config/rs6000/rs6000.c (rs6000_aggregate_candidate): New function.
+ (rs6000_discover_homogeneous_aggregate): Likewise.
+ (rs6000_function_arg_boundary): Handle homogeneous aggregates.
+ (rs6000_function_arg_advance_1): Likewise.
+ (rs6000_function_arg): Likewise.
+ (rs6000_arg_partial_bytes): Likewise.
+ (rs6000_psave_function_arg): Handle BLKmode arguments.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Michael Gschwind <mkg@us.ibm.com>
+
+ * config/rs6000/rs6000.h (AGGR_ARG_NUM_REG): Define.
+ * config/rs6000/rs6000.c (rs6000_aggregate_candidate): New function.
+ (rs6000_discover_homogeneous_aggregate): Likewise.
+ (rs6000_function_arg_boundary): Handle homogeneous aggregates.
+ (rs6000_function_arg_advance_1): Likewise.
+ (rs6000_function_arg): Likewise.
+ (rs6000_arg_partial_bytes): Likewise.
+ (rs6000_psave_function_arg): Handle BLKmode arguments.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (machine_function): New member
+ r2_setup_needed.
+ (rs6000_emit_prologue): Set r2_setup_needed if necessary.
+ (rs6000_output_mi_thunk): Set r2_setup_needed.
+ (rs6000_output_function_prologue): Output global entry point
+ prologue and local entry point marker if needed for ABI_ELFv2.
+ Output -mprofile-kernel code here.
+ (output_function_profiler): Do not output -mprofile-kernel
+ code here; moved to rs6000_output_function_prologue.
+ (rs6000_file_start): Output ".abiversion 2" for ABI_ELFv2.
+
+ (rs6000_emit_move): Do not handle dot symbols for ABI_ELFv2.
+ (rs6000_output_function_entry): Likewise.
+ (rs6000_assemble_integer): Likewise.
+ (rs6000_elf_encode_section_info): Likewise.
+ (rs6000_elf_declare_function_name): Do not create dot symbols
+ or .opd section for ABI_ELFv2.
+
+ (rs6000_trampoline_size): Update for ABI_ELFv2 trampolines.
+ (rs6000_trampoline_init): Likewise.
+ (rs6000_elf_file_end): Call file_end_indicate_exec_stack
+ for ABI_ELFv2.
+
+ (rs6000_call_aix): Handle ELFv2 indirect calls. Do not check
+ for function descriptors in ABI_ELFv2.
+
+ * config/rs6000/rs6000.md ("*call_indirect_aix<mode>"): Support
+ on ABI_AIX only, not ABI_ELFv2.
+ ("*call_value_indirect_aix<mode>"): Likewise.
+ ("*call_indirect_elfv2<mode>"): New pattern.
+ ("*call_value_indirect_elfv2<mode>"): Likewise.
+
+ * config/rs6000/predicates.md ("symbol_ref_operand"): Do not
+ check for function descriptors in ABI_ELFv2.
+ ("current_file_function_operand"): Likewise.
+
+ * config/rs6000/ppc-asm.h [__powerpc64__ && _CALL_ELF == 2]:
+ (toc): Undefine.
+ (FUNC_NAME): Define ELFv2 variant.
+ (JUMP_TARGET): Likewise.
+ (FUNC_START): Likewise.
+ (HIDDEN_FUNC): Likewise.
+ (FUNC_END): Likeiwse.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config.gcc [powerpc*-*-* | rs6000-*-*]: Support --with-abi=elfv1
+ and --with-abi=elfv2.
+ * config/rs6000/option-defaults.h (OPTION_DEFAULT_SPECS): Add "abi".
+ * config/rs6000/rs6000.opt (mabi=elfv1): New option.
+ (mabi=elfv2): Likewise.
+ * config/rs6000/rs6000-opts.h (enum rs6000_abi): Add ABI_ELFv2.
+ * config/rs6000/linux64.h (DEFAULT_ABI): Do not hard-code to AIX_ABI
+ if !RS6000_BI_ARCH.
+ (ELFv2_ABI_CHECK): New macro.
+ (SUBSUBTARGET_OVERRIDE_OPTIONS): Use it to decide whether to set
+ rs6000_current_abi to ABI_AIX or ABI_ELFv2.
+ (GLIBC_DYNAMIC_LINKER64): Support ELFv2 ld.so version.
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Predefine
+ _CALL_ELF and __STRUCT_PARM_ALIGN__ if appropriate.
+
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Handle ABI_ELFv2.
+ (debug_stack_info): Likewise.
+ (rs6000_file_start): Treat ABI_ELFv2 the same as ABI_AIX.
+ (rs6000_legitimize_tls_address): Likewise.
+ (rs6000_conditional_register_usage): Likewise.
+ (rs6000_emit_move): Likewise.
+ (init_cumulative_args): Likewise.
+ (rs6000_function_arg_advance_1): Likewise.
+ (rs6000_function_arg): Likewise.
+ (rs6000_arg_partial_bytes): Likewise.
+ (rs6000_output_function_entry): Likewise.
+ (rs6000_assemble_integer): Likewise.
+ (rs6000_savres_strategy): Likewise.
+ (rs6000_stack_info): Likewise.
+ (rs6000_function_ok_for_sibcall): Likewise.
+ (rs6000_emit_load_toc_table): Likewise.
+ (rs6000_savres_routine_name): Likewise.
+ (ptr_regno_for_savres): Likewise.
+ (rs6000_emit_prologue): Likewise.
+ (rs6000_emit_epilogue): Likewise.
+ (rs6000_output_function_epilogue): Likewise.
+ (output_profile_hook): Likewise.
+ (output_function_profiler): Likewise.
+ (rs6000_trampoline_size): Likewise.
+ (rs6000_trampoline_init): Likewise.
+ (rs6000_elf_output_toc_section_asm_op): Likewise.
+ (rs6000_elf_encode_section_info): Likewise.
+ (rs6000_elf_reloc_rw_mask): Likewise.
+ (rs6000_elf_declare_function_name): Likewise.
+ (rs6000_function_arg_boundary): Treat ABI_ELFv2 the same as ABI_AIX,
+ except that rs6000_compat_align_parm is always assumed false.
+ (rs6000_gimplify_va_arg): Likewise.
+ (rs6000_call_aix): Update comment.
+ (rs6000_sibcall_aix): Likewise.
+ * config/rs6000/rs6000.md ("tls_gd_aix<TLSmode:tls_abi_suffix>"):
+ Treat ABI_ELFv2 the same as ABI_AIX.
+ ("*tls_gd_call_aix<TLSmode:tls_abi_suffix>"): Likewise.
+ ("tls_ld_aix<TLSmode:tls_abi_suffix>"): Likewise.
+ ("*tls_ld_call_aix<TLSmode:tls_abi_suffix>"): Likewise.
+ ("load_toc_aix_si"): Likewise.
+ ("load_toc_aix_di"): Likewise.
+ ("call"): Likewise.
+ ("call_value"): Likewise.
+ ("*call_local_aix<mode>"): Likewise.
+ ("*call_value_local_aix<mode>"): Likewise.
+ ("*call_nonlocal_aix<mode>"): Likewise.
+ ("*call_value_nonlocal_aix<mode>"): Likewise.
+ ("*call_indirect_aix<mode>"): Likewise.
+ ("*call_value_indirect_aix<mode>"): Likewise.
+ ("sibcall"): Likewise.
+ ("sibcall_value"): Likewise.
+ ("*sibcall_aix<mode>"): Likewise.
+ ("*sibcall_value_aix<mode>"): Likewise.
+ * config/rs6000/predicates.md ("symbol_ref_operand"): Likewise.
+ ("current_file_function_operand"): Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204807:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_arg_partial_bytes): Simplify logic
+ by making use of the fact that for vector / floating point arguments
+ passed both in VRs/FPRs and in the fixed parameter area, the partial
+ bytes mechanism is in fact not used.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204806:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_psave_function_arg): New function.
+ (rs6000_finish_function_arg): Likewise.
+ (rs6000_function_arg): Use rs6000_psave_function_arg and
+ rs6000_finish_function_arg to handle both vector and floating
+ point arguments that are also passed in GPRs / the stack.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204805:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Remove TYPE argument.
+ (USE_ALTIVEC_FOR_ARG_P): Likewise.
+ (rs6000_darwin64_record_arg_advance_recurse): Update uses.
+ (rs6000_function_arg_advance_1):Likewise.
+ (rs6000_darwin64_record_arg_recurse): Likewise.
+ (rs6000_function_arg): Likewise.
+ (rs6000_arg_partial_bytes): Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204804:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Replace
+ "DEFAULT_ABI != ABI_AIX" test by testing for ABI_V4 or ABI_DARWIN.
+ (rs6000_savres_strategy): Likewise.
+ (rs6000_return_addr): Likewise.
+ (rs6000_emit_load_toc_table): Replace "DEFAULT_ABI != ABI_AIX" by
+ testing for ABI_V4 (since ABI_DARWIN is impossible here).
+ (rs6000_emit_prologue): Likewise.
+ (legitimate_lo_sum_address_p): Simplify DEFAULT_ABI test.
+ (rs6000_elf_declare_function_name): Remove duplicated test.
+ * config/rs6000/rs6000.md ("load_toc_v4_PIC_1"): Explicitly test
+ for ABI_V4 (instead of "DEFAULT_ABI != ABI_AIX" test).
+ ("load_toc_v4_PIC_1_normal"): Likewise.
+ ("load_toc_v4_PIC_1_476"): Likewise.
+ ("load_toc_v4_PIC_1b"): Likewise.
+ ("load_toc_v4_PIC_1b_normal"): Likewise.
+ ("load_toc_v4_PIC_1b_476"): Likewise.
+ ("load_toc_v4_PIC_2"): Likewise.
+ ("load_toc_v4_PIC_3b"): Likewise.
+ ("load_toc_v4_PIC_3c"): Likewise.
+ * config/rs6000/rs6000.h (RS6000_REG_SAVE): Simplify DEFAULT_ABI test.
+ (RS6000_SAVE_AREA): Likewise.
+ (FP_ARG_MAX_REG): Likewise.
+ (RETURN_ADDRESS_OFFSET): Likewise.
+ * config/rs6000/sysv.h (TARGET_TOC): Test for ABI_V4 instead
+ of ABI_AIX.
+ (SUBTARGET_OVERRIDE_OPTIONS): Likewise.
+ (MINIMAL_TOC_SECTION_ASM_OP): Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204803:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_call_indirect_aix): Rename to ...
+ (rs6000_call_aix): ... this. Handle both direct and indirect calls.
+ Create call insn directly instead of via various gen_... routines.
+ Mention special registers used by the call in CALL_INSN_FUNCTION_USAGE.
+ (rs6000_sibcall_aix): New function.
+ * config/rs6000/rs6000.md (TOC_SAVE_OFFSET_32BIT): Remove.
+ (TOC_SAVE_OFFSET_64BIT): Likewise.
+ (AIX_FUNC_DESC_TOC_32BIT): Likewise.
+ (AIX_FUNC_DESC_TOC_64BIT): Likewise.
+ (AIX_FUNC_DESC_SC_32BIT): Likewise.
+ (AIX_FUNC_DESC_SC_64BIT): Likewise.
+ ("call" expander): Call rs6000_call_aix.
+ ("call_value" expander): Likewise.
+ ("call_indirect_aix<ptrsize>"): Replace this pattern ...
+ ("call_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
+ ("*call_indirect_aix<mode>"): ... by this insn pattern.
+ ("call_value_indirect_aix<ptrsize>"): Replace this pattern ...
+ ("call_value_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
+ ("*call_value_indirect_aix<mode>"): ... by this insn pattern.
+ ("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ...
+ ("*call_nonlocal_aix<mode>"): ... this pattern.
+ ("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace
+ ("*call_value_nonlocal_aix<mode>"): ... by this pattern.
+ ("*call_local_aix<mode>"): New insn pattern.
+ ("*call_value_local_aix<mode>"): Likewise.
+ ("sibcall" expander): Call rs6000_sibcall_aix.
+ ("sibcall_value" expander): Likewise. Move earlier in file.
+ ("*sibcall_nonlocal_aix<mode>"): Replace by ...
+ ("*sibcall_aix<mode>"): ... this pattern.
+ ("*sibcall_value_nonlocal_aix<mode>"): Replace by ...
+ ("*sibcall_value_aix<mode>"): ... this pattern.
+ * config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove.
+ (rs6000_call_aix): Add prototype.
+ (rs6000_sibcall_aix): Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204799:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Do not place a
+ RTX_FRAME_RELATED_P marker on the UNSPEC_MOVESI_FROM_CR insn.
+ Instead, add USEs of all modified call-saved CR fields to the
+ insn storing the result to the stack slot, and provide an
+ appropriate REG_FRAME_RELATED_EXPR for that insn.
+ * config/rs6000/rs6000.md ("*crsave"): New insn pattern.
+ * config/rs6000/predicates.md ("crsave_operation"): New predicate.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204798:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+ Alan Modra <amodra@gmail.com>
+
+ * function.c (assign_parms): Use all.reg_parm_stack_space instead
+ of re-evaluating REG_PARM_STACK_SPACE target macro.
+ (locate_and_pad_parm): New parameter REG_PARM_STACK_SPACE. Use it
+ instead of evaluating target macro REG_PARM_STACK_SPACE every time.
+ (assign_parm_find_entry_rtl): Update call.
+ * calls.c (initialize_argument_information): Update call.
+ (emit_library_call_value_1): Likewise.
+ * expr.h (locate_and_pad_parm): Update prototype.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204797:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * calls.c (store_unaligned_arguments_into_pseudos): Skip PARALLEL
+ arguments.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r197003:
+
+ 2013-03-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * calls.c (expand_call): Add missing guard to code handling return
+ of non-BLKmode structures in MSB.
+ * function.c (expand_function_end): Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r201750.
+ Note: Default setting of -mcompat-align-parm inverted!
+
+ 2013-08-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR target/57949
+ * doc/invoke.texi: Add documentation of mcompat-align-parm
+ option.
+ * config/rs6000/rs6000.opt: Add mcompat-align-parm option.
+ * config/rs6000/rs6000.c (rs6000_function_arg_boundary): For AIX
+ and Linux, correct BLKmode alignment when 128-bit alignment is
+ required and compatibility flag is not set.
+ (rs6000_gimplify_va_arg): For AIX and Linux, honor specified
+ alignment for zero-size arguments when compatibility flag is not
+ set.
+
+2013-11-12 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * configure: Regenerate.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204441
+ 2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Remove restriction against use of VSX instructions when generating
+ code for little endian mode.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204440
+ 2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (mulv4si3): Ensure we generate vmulouh
+ for both big and little endian.
+ (mulv8hi3): Swap input operands for merge high and merge low
+ instructions for little endian.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204439
+ 2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_widen_umult_even_v16qi): Change
+ define_insn to define_expand that uses even patterns for big
+ endian and odd patterns for little endian.
+ (vec_widen_smult_even_v16qi): Likewise.
+ (vec_widen_umult_even_v8hi): Likewise.
+ (vec_widen_smult_even_v8hi): Likewise.
+ (vec_widen_umult_odd_v16qi): Likewise.
+ (vec_widen_smult_odd_v16qi): Likewise.
+ (vec_widen_umult_odd_v8hi): Likewise.
+ (vec_widen_smult_odd_v8hi): Likewise.
+ (altivec_vmuleub): New define_insn.
+ (altivec_vmuloub): Likewise.
+ (altivec_vmulesb): Likewise.
+ (altivec_vmulosb): Likewise.
+ (altivec_vmuleuh): Likewise.
+ (altivec_vmulouh): Likewise.
+ (altivec_vmulesh): Likewise.
+ (altivec_vmulosh): Likewise.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204395
+ 2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_pack_sfix_trunc_v2df): Adjust for
+ little endian.
+ (vec_pack_ufix_trunc_v2df): Likewise.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204363
+ 2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_widen_umult_hi_v16qi): Swap
+ arguments to merge instruction for little endian.
+ (vec_widen_umult_lo_v16qi): Likewise.
+ (vec_widen_smult_hi_v16qi): Likewise.
+ (vec_widen_smult_lo_v16qi): Likewise.
+ (vec_widen_umult_hi_v8hi): Likewise.
+ (vec_widen_umult_lo_v8hi): Likewise.
+ (vec_widen_smult_hi_v8hi): Likewise.
+ (vec_widen_smult_lo_v8hi): Likewise.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204350
+ 2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (*vsx_le_perm_store_<mode> for VSX_D):
+ Replace the define_insn_and_split with a define_insn and two
+ define_splits, with the split after reload re-permuting the source
+ register to its original value.
+ (*vsx_le_perm_store_<mode> for VSX_W): Likewise.
+ (*vsx_le_perm_store_v8hi): Likewise.
+ (*vsx_le_perm_store_v16qi): Likewise.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204321
+ 2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_pack_trunc_v2df): Adjust for
+ little endian.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204321
+ 2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_set): Adjust for
+ little endian.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203980
+ 2013-10-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (mulv8hi3): Adjust for little endian.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203930
+ 2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Reverse
+ meaning of merge-high and merge-low masks for little endian; avoid
+ use of vector-pack masks for little endian for mismatched modes.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203877
+ 2013-10-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_unpacku_hi_v16qi): Adjust for
+ little endian.
+ (vec_unpacku_hi_v8hi): Likewise.
+ (vec_unpacku_lo_v16qi): Likewise.
+ (vec_unpacku_lo_v8hi): Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203863
+ 2013-10-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (vspltis_constant): Make sure we check
+ all elements for both endian flavors.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203714
+ 2013-10-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc/config/rs6000/vector.md (vec_unpacks_hi_v4sf): Correct for
+ endianness.
+ (vec_unpacks_lo_v4sf): Likewise.
+ (vec_unpacks_float_hi_v4si): Likewise.
+ (vec_unpacks_float_lo_v4si): Likewise.
+ (vec_unpacku_float_hi_v4si): Likewise.
+ (vec_unpacku_float_lo_v4si): Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203713
+ 2013-10-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_concat_<mode>): Adjust output for LE.
+ (vsx_concat_v2sf): Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203458
+ 2013-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): Generalize to
+ handle vector float as well.
+ (*vsx_le_perm_load_v4si): Likewise.
+ (*vsx_le_perm_store_v2di): Likewise.
+ (*vsx_le_perm_store_v4si): Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203457
+ 2013-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_realign_load<mode>): Generate vperm
+ directly to circumvent subtract from splat{31} workaround.
+ * config/rs6000/rs6000-protos.h (altivec_expand_vec_perm_le): New
+ prototype.
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_le): New.
+ * config/rs6000/altivec.md (define_c_enum "unspec"): Add
+ UNSPEC_VPERM_X and UNSPEC_VPERM_UNS_X.
+ (altivec_vperm_<mode>): Convert to define_insn_and_split to
+ separate big and little endian logic.
+ (*altivec_vperm_<mode>_internal): New define_insn.
+ (altivec_vperm_<mode>_uns): Convert to define_insn_and_split to
+ separate big and little endian logic.
+ (*altivec_vperm_<mode>_uns_internal): New define_insn.
+ (vec_permv16qi): Add little endian logic.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203247
+ 2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const_le): New.
+ (altivec_expand_vec_perm_const): Call it.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203246
+ 2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (mov<mode>): Emit permuted move
+ sequences for LE VSX loads and stores at expand time.
+ * config/rs6000/rs6000-protos.h (rs6000_emit_le_vsx_move): New
+ prototype.
+ * config/rs6000/rs6000.c (rs6000_const_vec): New.
+ (rs6000_gen_le_vsx_permute): New.
+ (rs6000_gen_le_vsx_load): New.
+ (rs6000_gen_le_vsx_store): New.
+ (rs6000_gen_le_vsx_move): New.
+ * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): New.
+ (*vsx_le_perm_load_v4si): New.
+ (*vsx_le_perm_load_v8hi): New.
+ (*vsx_le_perm_load_v16qi): New.
+ (*vsx_le_perm_store_v2di): New.
+ (*vsx_le_perm_store_v4si): New.
+ (*vsx_le_perm_store_v8hi): New.
+ (*vsx_le_perm_store_v16qi): New.
+ (*vsx_xxpermdi2_le_<mode>): New.
+ (*vsx_xxpermdi4_le_<mode>): New.
+ (*vsx_xxpermdi8_le_V8HI): New.
+ (*vsx_xxpermdi16_le_V16QI): New.
+ (*vsx_lxvd2x2_le_<mode>): New.
+ (*vsx_lxvd2x4_le_<mode>): New.
+ (*vsx_lxvd2x8_le_V8HI): New.
+ (*vsx_lxvd2x16_le_V16QI): New.
+ (*vsx_stxvd2x2_le_<mode>): New.
+ (*vsx_stxvd2x4_le_<mode>): New.
+ (*vsx_stxvd2x8_le_V8HI): New.
+ (*vsx_stxvd2x16_le_V16QI): New.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r201235
+ 2013-07-24 Bill Schmidt <wschmidt@linux.ibm.com>
+ Anton Blanchard <anton@au1.ibm.com>
+
+ * config/rs6000/altivec.md (altivec_vpkpx): Handle little endian.
+ (altivec_vpks<VI_char>ss): Likewise.
+ (altivec_vpks<VI_char>us): Likewise.
+ (altivec_vpku<VI_char>us): Likewise.
+ (altivec_vpku<VI_char>um): Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r201208
+ 2013-07-24 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+ Anton Blanchard <anton@au1.ibm.com>
+
+ * config/rs6000/vector.md (vec_realign_load_<mode>): Reorder input
+ operands to vperm for little endian.
+ * config/rs6000/rs6000.c (rs6000_expand_builtin): Use lvsr instead
+ of lvsl to create the control mask for a vperm for little endian.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r201195
+ 2013-07-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+ Anton Blanchard <anton@au1.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Reverse
+ two operands for little-endian.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r201193
+ 2013-07-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+ Anton Blanchard <anton@au1.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Correct
+ selection of field for vector splat in little endian mode.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r201149
+ 2013-07-22 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+ Anton Blanchard <anton@au1.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Fix
+ endianness when selecting field to splat.
+
+2013-10-21 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-04-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR target/56843
+ * config/rs6000/rs6000.c (rs6000_emit_swdiv_high_precision): Remove.
+ (rs6000_emit_swdiv_low_precision): Remove.
+ (rs6000_emit_swdiv): Rewrite to handle between one and four
+ iterations of Newton-Raphson generally; modify required number of
+ iterations for some cases.
+ * config/rs6000/rs6000.h (RS6000_RECIP_HIGH_PRECISION_P): Remove.
+
+2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (enum rs6000_reload_reg_type): Add new
+ fields to the reg_addr array that describes the valid addressing
+ mode for any register, general purpose registers, floating point
+ registers, and Altivec registers.
+ (FIRST_RELOAD_REG_CLASS): Likewise.
+ (LAST_RELOAD_REG_CLASS): Likewise.
+ (struct reload_reg_map_type): Likewise.
+ (reload_reg_map_type): Likewise.
+ (RELOAD_REG_VALID): Likewise.
+ (RELOAD_REG_MULTIPLE): Likewise.
+ (RELOAD_REG_INDEXED): Likewise.
+ (RELOAD_REG_OFFSET): Likewise.
+ (RELOAD_REG_PRE_INCDEC): Likewise.
+ (RELOAD_REG_PRE_MODIFY): Likewise.
+ (reg_addr): Likewise.
+ (mode_supports_pre_incdec_p): New helper functions to say whether
+ a given mode supports PRE_INC, PRE_DEC, and PRE_MODIFY.
+ (mode_supports_pre_modify_p): Likewise.
+ (rs6000_debug_vector_unit): Rearrange the -mdebug=reg output to
+ print the valid address mode bits for each mode.
+ (rs6000_debug_print_mode): Likewise.
+ (rs6000_debug_reg_global): Likewise.
+ (rs6000_setup_reg_addr_masks): New function to set up the address
+ mask bits for each type.
+ (rs6000_init_hard_regno_mode_ok): Use memset to clear arrays.
+ Call rs6000_setup_reg_addr_masks to set up the address mask bits.
+ (rs6000_legitimate_address_p): Use mode_supports_pre_incdec_p and
+ mode_supports_pre_modify_p to determine if PRE_INC, PRE_DEC, and
+ PRE_MODIFY are supported.
+ (rs6000_output_move_128bit): Change to use {src,dest}_vmx_p for altivec
+ registers, instead of {src,dest}_av_p.
+ (rs6000_print_options_internal): Tweak the debug output slightly.
+
+ Backport from mainline
+ 2013-10-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-builtin.def (XSRDPIM): Use floatdf2,
+ ceildf2, btruncdf2, instead of vsx_* name.
+
+ * config/rs6000/vsx.md (vsx_add<mode>3): Change arithmetic
+ iterators to only do V2DF and V4SF here. Move the DF code to
+ rs6000.md where it is combined with SF mode. Replace <VSv> with
+ just 'v' since only vector operations are handled with these insns
+ after moving the DF support to rs6000.md.
+ (vsx_sub<mode>3): Likewise.
+ (vsx_mul<mode>3): Likewise.
+ (vsx_div<mode>3): Likewise.
+ (vsx_fre<mode>2): Likewise.
+ (vsx_neg<mode>2): Likewise.
+ (vsx_abs<mode>2): Likewise.
+ (vsx_nabs<mode>2): Likewise.
+ (vsx_smax<mode>3): Likewise.
+ (vsx_smin<mode>3): Likewise.
+ (vsx_sqrt<mode>2): Likewise.
+ (vsx_rsqrte<mode>2): Likewise.
+ (vsx_fms<mode>4): Likewise.
+ (vsx_nfma<mode>4): Likewise.
+ (vsx_copysign<mode>3): Likewise.
+ (vsx_btrunc<mode>2): Likewise.
+ (vsx_floor<mode>2): Likewise.
+ (vsx_ceil<mode>2): Likewise.
+ (vsx_smaxsf3): Delete scalar ops that were moved to rs6000.md.
+ (vsx_sminsf3): Likewise.
+ (vsx_fmadf4): Likewise.
+ (vsx_fmsdf4): Likewise.
+ (vsx_nfmadf4): Likewise.
+ (vsx_nfmsdf4): Likewise.
+ (vsx_cmpdf_internal1): Likewise.
+
+ * config/rs6000/rs6000.h (TARGET_SF_SPE): Define macros to make it
+ simpler to select whether a target has SPE or traditional floating
+ point support in iterators.
+ (TARGET_DF_SPE): Likewise.
+ (TARGET_SF_FPR): Likewise.
+ (TARGET_DF_FPR): Likewise.
+ (TARGET_SF_INSN): Macros to say whether floating point support
+ exists for a given operation for expanders.
+ (TARGET_DF_INSN): Likewise.
+
+ * config/rs6000/rs6000.c (Ftrad): New mode attributes to allow
+ combining of SF/DF mode operations, using both traditional and VSX
+ registers.
+ (Fvsx): Likewise.
+ (Ff): Likewise.
+ (Fv): Likewise.
+ (Fs): Likewise.
+ (Ffre): Likewise.
+ (FFRE): Likewise.
+ (abs<mode>2): Combine SF/DF modes using traditional floating point
+ instructions. Add support for using the upper DF registers with
+ VSX support, and SF registers with power8-vector support. Update
+ expanders for operations supported by both the SPE and traditional
+ floating point units.
+ (abs<mode>2_fpr): Likewise.
+ (nabs<mode>2): Likewise.
+ (nabs<mode>2_fpr): Likewise.
+ (neg<mode>2): Likewise.
+ (neg<mode>2_fpr): Likewise.
+ (add<mode>3): Likewise.
+ (add<mode>3_fpr): Likewise.
+ (sub<mode>3): Likewise.
+ (sub<mode>3_fpr): Likewise.
+ (mul<mode>3): Likewise.
+ (mul<mode>3_fpr): Likewise.
+ (div<mode>3): Likewise.
+ (div<mode>3_fpr): Likewise.
+ (sqrt<mode>3): Likewise.
+ (sqrt<mode>3_fpr): Likewise.
+ (fre<Fs>): Likewise.
+ (rsqrt<mode>2): Likewise.
+ (cmp<mode>_fpr): Likewise.
+ (smax<mode>3): Likewise.
+ (smin<mode>3): Likewise.
+ (smax<mode>3_vsx): Likewise.
+ (smin<mode>3_vsx): Likewise.
+ (negsf2): Delete SF operations that are merged with DF.
+ (abssf2): Likewise.
+ (addsf3): Likewise.
+ (subsf3): Likewise.
+ (mulsf3): Likewise.
+ (divsf3): Likewise.
+ (fres): Likewise.
+ (fmasf4_fpr): Likewise.
+ (fmssf4_fpr): Likewise.
+ (nfmasf4_fpr): Likewise.
+ (nfmssf4_fpr): Likewise.
+ (sqrtsf2): Likewise.
+ (rsqrtsf_internal1): Likewise.
+ (smaxsf3): Likewise.
+ (sminsf3): Likewise.
+ (cmpsf_internal1): Likewise.
+ (copysign<mode>3_fcpsgn): Add VSX/power8-vector support.
+ (negdf2): Delete DF operations that are merged with SF.
+ (absdf2): Likewise.
+ (nabsdf2): Likewise.
+ (adddf3): Likewise.
+ (subdf3): Likewise.
+ (muldf3): Likewise.
+ (divdf3): Likewise.
+ (fred): Likewise.
+ (rsqrtdf_internal1): Likewise.
+ (fmadf4_fpr): Likewise.
+ (fmsdf4_fpr): Likewise.
+ (nfmadf4_fpr): Likewise.
+ (nfmsdf4_fpr): Likewise.
+ (sqrtdf2): Likewise.
+ (smaxdf3): Likewise.
+ (smindf3): Likewise.
+ (cmpdf_internal1): Likewise.
+ (lrint<mode>di2): Use TARGET_<MODE>_FPR macro.
+ (btrunc<mode>2): Delete separate expander, and combine with the
+ insn and add VSX instruction support. Use TARGET_<MODE>_FPR.
+ (btrunc<mode>2_fpr): Likewise.
+ (ceil<mode>2): Likewise.
+ (ceil<mode>2_fpr): Likewise.
+ (floor<mode>2): Likewise.
+ (floor<mode>2_fpr): Likewise.
+ (fma<mode>4_fpr): Combine SF and DF fused multiply/add support.
+ Add support for using the upper registers with VSX and
+ power8-vector. Move insns to be closer to the define_expands. On
+ VSX systems, prefer the traditional form of FMA over the VSX
+ version, since the traditional form allows the target not to
+ overlap with the inputs.
+ (fms<mode>4_fpr): Likewise.
+ (nfma<mode>4_fpr): Likewise.
+ (nfms<mode>4_fpr): Likewise.
+
+ Backport from mainline
+ 2013-09-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
+ DFmode, DImode, and SFmode in the upper VSX registers based on the
+ -mupper-regs-{df,sf} flags. Fix wu constraint to be ALTIVEC_REGS
+ if -mpower8-vector. Combine -mvsx-timode handling with the rest
+ of the VSX register handling.
+
+ * config/rs6000/rs6000.md (f32_lv): Use %x0 for VSX regsters.
+ (f32_sv): Likewise.
+ (zero_extendsidi2_lfiwzx): Add support for loading into the
+ Altivec registers with -mpower8-vector. Use wu/wv constraints to
+ only do VSX memory options on Altivec registers.
+ (extendsidi2_lfiwax): Likewise.
+ (extendsfdf2_fpr): Likewise.
+ (mov<mode>_hardfloat, SF/SD modes): Likewise.
+ (mov<mode>_hardfloat32, DF/DD modes): Likewise.
+ (mov<mode>_hardfloat64, DF/DD modes): Likewise.
+ (movdi_internal64): Likewise.
+
+ Backport from mainline
+ 2013-09-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_vector_reload): Delete, combine
+ reload helper function arrays into a single array reg_addr.
+ (reload_fpr_gpr): Likewise.
+ (reload_gpr_vsx): Likewise.
+ (reload_vsx_gpr): Likewise.
+ (struct rs6000_reg_addr): Likewise.
+ (reg_addr): Likewise.
+ (rs6000_debug_reg_global): Change rs6000_vector_reload,
+ reload_fpr_gpr, reload_gpr_vsx, reload_vsx_gpr uses to reg_addr.
+ (rs6000_init_hard_regno_mode_ok): Likewise.
+ (rs6000_secondary_reload_direct_move): Likewise.
+ (rs6000_secondary_reload): Likewise.
+
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add new
+ constraints: wu, ww, and wy. Repurpose wv constraint added during
+ power8 changes. Put wg constraint in alphabetical order.
+
+ * config/rs6000/rs6000.opt (-mvsx-scalar-float): New debug switch
+ for future work to add ISA 2.07 VSX single precision support.
+ (-mvsx-scalar-double): Change default from -1 to 1, update
+ documentation comment.
+ (-mvsx-scalar-memory): Rename debug switch to -mupper-regs-df.
+ (-mupper-regs-df): New debug switch to control whether DF values
+ can go in the traditional Altivec registers.
+ (-mupper-regs-sf): New debug switch to control whether SF values
+ can go in the traditional Altivec registers.
+
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print wu, ww,
+ and wy constraints.
+ (rs6000_init_hard_regno_mode_ok): Use ssize_t instead of int for
+ loop variables. Rename -mvsx-scalar-memory to -mupper-regs-df.
+ Add new constraints, wu/ww/wy. Repurpose wv constraint.
+ (rs6000_debug_legitimate_address_p): Print if we are running
+ before, during, or after reload.
+ (rs6000_secondary_reload): Add a comment.
+ (rs6000_opt_masks): Add -mupper-regs-df, -mupper-regs-sf.
+
+ * config/rs6000/constraints.md (wa constraint): Sort w<x>
+ constraints. Update documentation string.
+ (wd constraint): Likewise.
+ (wf constraint): Likewise.
+ (wg constraint): Likewise.
+ (wn constraint): Likewise.
+ (ws constraint): Likewise.
+ (wt constraint): Likewise.
+ (wx constraint): Likewise.
+ (wz constraint): Likewise.
+ (wu constraint): New constraint for ISA 2.07 SFmode scalar
+ instructions.
+ (ww constraint): Likewise.
+ (wy constraint): Likewise.
+ (wv constraint): Repurpose ISA 2.07 constraint that did not use in
+ the previous submissions.
+ * doc/md.texi (PowerPC and IBM RS6000): Likewise.
+
+ Backport from mainline
+ 2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58673
+ * config/rs6000/rs6000.c (rs6000_legitimate_address_p): Only
+ restrict TImode addresses to single indirect registers if both
+ -mquad-memory and -mvsx-timode are used.
+ (rs6000_output_move_128bit): Use quad_load_store_p to determine if
+ we should emit load/store quad. Remove using %y for quad memory
+ addresses.
+
+ * config/rs6000/rs6000.md (mov<mode>_ppc64, TI/PTImode): Add
+ constraints to allow load/store quad on machines where TImode is
+ not allowed in VSX registers. Use 'n' instead of 'F' constraint
+ for TImode to load integer constants.
+
+2013-10-02 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-10-02 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58587
+ * config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Turn off
+ setting -mvsx-timode by default until the underlying problem is
+ fixed.
+ (RS6000_CPU, power7 defaults): Likewise.
+
+2013-08-19 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2013-08-19 Peter Bergner <bergner@vnet.ibm.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * builtins.def (BUILT_IN_FABSD32): New DFP ABS builtin.
+ (BUILT_IN_FABSD64): Likewise.
+ (BUILT_IN_FABSD128): Likewise.
+ * builtins.c (expand_builtin): Add support for
+ new DFP ABS builtins.
+ (fold_builtin_1): Likewise.
+ * config/rs6000/dfp.md
+ (*negtd2_fpr): Handle
+ non-overlapping destination
+ and source operands.
+ (*abstd2_fpr):
+ Likewise.
+ (*nabstd2_fpr):
+ Likewise.
+
2013-08-16 Michael Meissner <meissner@linux.vnet.ibm.com>
Backport from trunk
diff --git a/gcc/ChangeLog.meissner b/gcc/ChangeLog.meissner
index 45e97bec95f..67c7e7eeb91 100644
--- a/gcc/ChangeLog.meissner
+++ b/gcc/ChangeLog.meissner
@@ -1,3 +1,7 @@
+2014-02-21 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Merge up to subversion id 208009.
+
2013-08-16 Michael Meissner <meissner@linux.vnet.ibm.com>
Merge up to subversion id 201796.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 79a747b6775..226d0338a2f 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20130716
+20140116
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index aad927cb9ac..2194dd4c2d1 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3037,7 +3037,7 @@ tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \
$(TM_H) coretypes.h $(GIMPLE_H) \
$(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \
$(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) \
- $(GIMPLE_PRETTY_PRINT_H) langhooks.h
+ $(GIMPLE_PRETTY_PRINT_H) langhooks.h $(OPTABS_H)
tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
$(TM_H) $(FLAGS_H) $(TREE_FLOW_H) $(GIMPLE_H) \
tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h
@@ -3276,12 +3276,12 @@ lra-constraints.o : lra-constraints.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) insn-config.h insn-codes.h $(DF_H) \
$(RECOG_H) output.h addresses.h $(REGS_H) hard-reg-set.h $(FLAGS_H) \
$(FUNCTION_H) $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) \
- ira.h rtl-error.h $(LRA_INT_H)
+ ira.h rtl-error.h $(LRA_INT_H) $(OPTABS_H)
lra-eliminations.o : lra-eliminations.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
$(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
$(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) ira.h \
- rtl-error.h $(LRA_INT_H)
+ rtl-error.h $(LRA_INT_H) $(OPTABS_H)
lra-lives.o : lra-lives.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
$(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
diff --git a/gcc/REVISION b/gcc/REVISION
index 775f8138702..f1b8dccb3d0 100644
--- a/gcc/REVISION
+++ b/gcc/REVISION
@@ -1 +1 @@
-[ibm/gcc-4_8-branch merged from gcc-4_8-branch, revision 200989]
+[ibm/gcc-4_8-branch merged from gcc-4_8-branch, revision 206665]
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index bdb70ddb8c0..5f62d18f315 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,67 @@
+2014-01-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/59772
+ * gcc-interface/cuintp.c (build_cst_from_int): Use 32-bit integer type
+ as intermediate type.
+ (UI_To_gnu): Likewise.
+
+2013-12-12 Eric Botcazou <ebotcazou@adacore.com>
+ Iain Sandoe <iain@codesourcery.com>
+
+ PR ada/55946
+ * gcc-interface/Make-lang.in (ada/doctools/xgnatugn): Use gnatmake.
+ * gcc-interface/Makefile.in (GCC_LINK): Add LDFLAGS.
+ (../../gnatmake): Remove LDFLAGS.
+ (../../gnatlink): Likewise.
+
+2013-12-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/59382
+ * indepsw-darwin.adb: New file.
+
+2013-10-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (scale_by_factor_of): New function.
+ (rest_of_record_type_compilation): Use scale_by_factor_of in order to
+ scale the original offset for both rounding cases; in the second case,
+ take into accout the addend to compute the alignment. Tidy up.
+
+2013-10-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (gnat_set_type_context): New function.
+ (gnat_pushdecl): Use it to set the context of the type.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_param): Remove obsolete comment.
+
+2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/58264
+ * gcc-interface/trans.c (Attribute_to_gnu): Define GNAT_PREFIX local
+ variable and use it throughout.
+ <Attr_Length>: Note whether the prefix is the dereference of a pointer
+ to unconstrained array and, in this case, capture the result for both
+ Attr_First and Attr_Last.
+
+2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gigi): Remove dead code.
+
+2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Subprogram_Body_to_gnu): Pop the stack of
+ return variables for subprograms using the CICO mechanism.
+
+2013-08-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (can_equal_min_or_max_val_p): Be prepared for
+ values outside of the range of the type.
+
2013-06-13 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (DECL_BY_DOUBLE_REF_P): Delete.
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 57f90090dcf..e1d3ed6ebf3 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -625,7 +625,7 @@ ada.tags: force
ada/doctools/xgnatugn$(build_exeext): ada/xgnatugn.adb
-$(MKDIR) ada/doctools
$(CP) $^ ada/doctools
- cd ada/doctools && $(GNATMAKE) -q xgnatugn
+ cd ada/doctools && gnatmake -q xgnatugn
# Note that doc/gnat_ugn.texi and doc/projects.texi do not depend on
# xgnatugn being built so we can distribute a pregenerated doc/gnat_ugn.info
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 0ddde729425..ee610f789bb 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -2397,7 +2397,7 @@ TOOLS_FLAGS_TO_PASS= \
"GNATLINK=$(GNATLINK)" \
"GNATBIND=$(GNATBIND)"
-GCC_LINK=$(CC) $(GCC_LINK_FLAGS) $(ADA_INCLUDES)
+GCC_LINK=$(CC) $(GCC_LINK_FLAGS) $(ADA_INCLUDES) $(LDFLAGS)
# Build directory for the tools. Let's copy the target-dependent
# sources using the same mechanism as for gnatlib. The other sources are
@@ -2519,12 +2519,10 @@ gnatlink-re: ../stamp-tools link.o targext.o gnatmake-re
# Likewise for the tools
../../gnatmake$(exeext): $(P) b_gnatm.o link.o targext.o $(GNATMAKE_OBJS)
- $(GCC_LINK) $(ALL_CFLAGS) $(LDFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) \
- $(TOOLS_LIBS)
+ +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatm.o $(GNATMAKE_OBJS) $(TOOLS_LIBS)
../../gnatlink$(exeext): $(P) b_gnatl.o link.o targext.o $(GNATLINK_OBJS)
- $(GCC_LINK) $(ALL_CFLAGS) $(LDFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) \
- $(TOOLS_LIBS)
+ +$(GCC_LINK) $(ALL_CFLAGS) -o $@ b_gnatl.o $(GNATLINK_OBJS) $(TOOLS_LIBS)
../stamp-gnatlib-$(RTSDIR):
@if [ ! -f stamp-gnatlib-$(RTSDIR) ] ; \
diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c
index e077d9ce009..f4d75eca2eb 100644
--- a/gcc/ada/gcc-interface/cuintp.c
+++ b/gcc/ada/gcc-interface/cuintp.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2012, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2014, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -59,8 +59,8 @@
static tree
build_cst_from_int (tree type, HOST_WIDE_INT low)
{
- if (TREE_CODE (type) == REAL_TYPE)
- return convert (type, build_int_cst (NULL_TREE, low));
+ if (SCALAR_FLOAT_TYPE_P (type))
+ return convert (type, build_int_cst (gnat_type_for_size (32, 0), low));
else
return build_int_cst_type (type, low);
}
@@ -99,19 +99,12 @@ UI_To_gnu (Uint Input, tree type)
gcc_assert (Length > 0);
/* The computations we perform below always require a type at least as
- large as an integer not to overflow. REAL types are always fine, but
+ large as an integer not to overflow. FP types are always fine, but
INTEGER or ENUMERAL types we are handed may be too short. We use a
base integer type node for the computations in this case and will
- convert the final result back to the incoming type later on.
- The base integer precision must be superior than 16. */
-
- if (TREE_CODE (comp_type) != REAL_TYPE
- && TYPE_PRECISION (comp_type)
- < TYPE_PRECISION (long_integer_type_node))
- {
- comp_type = long_integer_type_node;
- gcc_assert (TYPE_PRECISION (comp_type) > 16);
- }
+ convert the final result back to the incoming type later on. */
+ if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32)
+ comp_type = gnat_type_for_size (32, 0);
gnu_base = build_cst_from_int (comp_type, Base);
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 5bdab9ddb49..5a68e8eaec4 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -5763,12 +5763,8 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
ro_param || by_ref || by_component_ptr);
DECL_BY_REF_P (gnu_param) = by_ref;
DECL_BY_COMPONENT_PTR_P (gnu_param) = by_component_ptr;
- DECL_BY_DESCRIPTOR_P (gnu_param) = (mech == By_Descriptor ||
- mech == By_Short_Descriptor);
- /* Note that, in case of a parameter passed by double reference, the
- DECL_POINTS_TO_READONLY_P flag is meant for the second reference.
- The first reference always points to read-only, as it points to
- the second reference, i.e. the reference to the actual parameter. */
+ DECL_BY_DESCRIPTOR_P (gnu_param)
+ = (mech == By_Descriptor || mech == By_Short_Descriptor);
DECL_POINTS_TO_READONLY_P (gnu_param)
= (ro_param && (by_ref || by_component_ptr));
DECL_CAN_NEVER_BE_NULL_P (gnu_param) = Can_Never_Be_Null (gnat_param);
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index cd78bf33a37..779174a68b3 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -286,9 +286,6 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
tree int64_type = gnat_type_for_size (64, 0);
struct elab_info *info;
int i;
-#ifdef ORDINARY_MAP_INSTANCE
- struct line_map *map;
-#endif
max_gnat_nodes = max_gnat_node;
@@ -303,10 +300,6 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
type_annotate_only = (gigi_operating_mode == 1);
- /* ??? Disable the generation of the SCO instance table until after the
- back-end supports instance based debug info discriminators. */
- Generate_SCO_Instance_Table = False;
-
for (i = 0; i < number_file; i++)
{
/* Use the identifier table to make a permanent copy of the filename as
@@ -326,11 +319,6 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
/* We create the line map for a source file at once, with a fixed number
of columns chosen to avoid jumping over the next power of 2. */
linemap_add (line_table, LC_ENTER, 0, filename, 1);
-#ifdef ORDINARY_MAP_INSTANCE
- map = LINEMAPS_ORDINARY_MAP_AT (line_table, i);
- if (flag_debug_instances)
- ORDINARY_MAP_INSTANCE (map) = file_info_ptr[i].Instance;
-#endif
linemap_line_start (line_table, file_info_ptr[i].Num_Source_Lines, 252);
linemap_position_for_column (line_table, 252 - 1);
linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
@@ -1277,6 +1265,7 @@ Pragma_to_gnu (Node_Id gnat_node)
static tree
Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
{
+ const Node_Id gnat_prefix = Prefix (gnat_node);
tree gnu_prefix, gnu_type, gnu_expr;
tree gnu_result_type, gnu_result = error_mark_node;
bool prefix_unused = false;
@@ -1286,13 +1275,13 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
parameter types might be incomplete types coming from a limited with. */
if (Ekind (Etype (gnat_node)) == E_Access_Subprogram_Type
&& Is_Dispatch_Table_Entity (Etype (gnat_node))
- && Nkind (Prefix (gnat_node)) == N_Identifier
- && Is_Subprogram (Entity (Prefix (gnat_node)))
- && Is_Public (Entity (Prefix (gnat_node)))
- && !present_gnu_tree (Entity (Prefix (gnat_node))))
- gnu_prefix = get_minimal_subprog_decl (Entity (Prefix (gnat_node)));
+ && Nkind (gnat_prefix) == N_Identifier
+ && Is_Subprogram (Entity (gnat_prefix))
+ && Is_Public (Entity (gnat_prefix))
+ && !present_gnu_tree (Entity (gnat_prefix)))
+ gnu_prefix = get_minimal_subprog_decl (Entity (gnat_prefix));
else
- gnu_prefix = gnat_to_gnu (Prefix (gnat_node));
+ gnu_prefix = gnat_to_gnu (gnat_prefix);
gnu_type = TREE_TYPE (gnu_prefix);
/* If the input is a NULL_EXPR, make a new one. */
@@ -1435,8 +1424,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
since it can use a special calling convention on some platforms,
which cannot be propagated to the access type. */
else if (attribute == Attr_Access
- && Nkind (Prefix (gnat_node)) == N_Identifier
- && is_cplusplus_method (Entity (Prefix (gnat_node))))
+ && Nkind (gnat_prefix) == N_Identifier
+ && is_cplusplus_method (Entity (gnat_prefix)))
post_error ("access to C++ constructor or member function not allowed",
gnat_node);
@@ -1547,13 +1536,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
/* If this is a dereference and we have a special dynamic constrained
subtype on the prefix, use it to compute the size; otherwise, use
the designated subtype. */
- if (Nkind (Prefix (gnat_node)) == N_Explicit_Dereference)
+ if (Nkind (gnat_prefix) == N_Explicit_Dereference)
{
- Node_Id gnat_deref = Prefix (gnat_node);
Node_Id gnat_actual_subtype
- = Actual_Designated_Subtype (gnat_deref);
+ = Actual_Designated_Subtype (gnat_prefix);
tree gnu_ptr_type
- = TREE_TYPE (gnat_to_gnu (Prefix (gnat_deref)));
+ = TREE_TYPE (gnat_to_gnu (Prefix (gnat_prefix)));
if (TYPE_IS_FAT_OR_THIN_POINTER_P (gnu_ptr_type)
&& Present (gnat_actual_subtype))
@@ -1614,7 +1602,6 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
align = DECL_ALIGN (TREE_OPERAND (gnu_prefix, 1)) / BITS_PER_UNIT;
else
{
- Node_Id gnat_prefix = Prefix (gnat_node);
Entity_Id gnat_type = Etype (gnat_prefix);
unsigned int double_align;
bool is_capped_double, align_clause;
@@ -1686,28 +1673,38 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
: 1), i;
struct parm_attr_d *pa = NULL;
Entity_Id gnat_param = Empty;
+ bool unconstrained_ptr_deref = false;
/* Make sure any implicit dereference gets done. */
gnu_prefix = maybe_implicit_deref (gnu_prefix);
gnu_prefix = maybe_unconstrained_array (gnu_prefix);
- /* We treat unconstrained array In parameters specially. */
- if (!Is_Constrained (Etype (Prefix (gnat_node))))
- {
- Node_Id gnat_prefix = Prefix (gnat_node);
-
- /* This is the direct case. */
- if (Nkind (gnat_prefix) == N_Identifier
- && Ekind (Entity (gnat_prefix)) == E_In_Parameter)
- gnat_param = Entity (gnat_prefix);
-
- /* This is the indirect case. Note that we need to be sure that
- the access value cannot be null as we'll hoist the load. */
- if (Nkind (gnat_prefix) == N_Explicit_Dereference
- && Nkind (Prefix (gnat_prefix)) == N_Identifier
- && Ekind (Entity (Prefix (gnat_prefix))) == E_In_Parameter
- && Can_Never_Be_Null (Entity (Prefix (gnat_prefix))))
- gnat_param = Entity (Prefix (gnat_prefix));
+ /* We treat unconstrained array In parameters specially. We also note
+ whether we are dereferencing a pointer to unconstrained array. */
+ if (!Is_Constrained (Etype (gnat_prefix)))
+ switch (Nkind (gnat_prefix))
+ {
+ case N_Identifier:
+ /* This is the direct case. */
+ if (Ekind (Entity (gnat_prefix)) == E_In_Parameter)
+ gnat_param = Entity (gnat_prefix);
+ break;
+
+ case N_Explicit_Dereference:
+ /* This is the indirect case. Note that we need to be sure that
+ the access value cannot be null as we'll hoist the load. */
+ if (Nkind (Prefix (gnat_prefix)) == N_Identifier
+ && Ekind (Entity (Prefix (gnat_prefix))) == E_In_Parameter)
+ {
+ if (Can_Never_Be_Null (Entity (Prefix (gnat_prefix))))
+ gnat_param = Entity (Prefix (gnat_prefix));
+ }
+ else
+ unconstrained_ptr_deref = true;
+ break;
+
+ default:
+ break;
}
/* If the prefix is the view conversion of a constrained array to an
@@ -1842,22 +1839,54 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
{
gnu_result
= build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
- if (attribute == Attr_First)
- pa->first = gnu_result;
- else if (attribute == Attr_Last)
- pa->last = gnu_result;
- else
- pa->length = gnu_result;
+ switch (attribute)
+ {
+ case Attr_First:
+ pa->first = gnu_result;
+ break;
+
+ case Attr_Last:
+ pa->last = gnu_result;
+ break;
+
+ case Attr_Length:
+ case Attr_Range_Length:
+ pa->length = gnu_result;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
}
- /* Set the source location onto the predicate of the condition in the
- 'Length case but do not do it if the expression is cached to avoid
- messing up the debug info. */
- else if ((attribute == Attr_Range_Length || attribute == Attr_Length)
- && TREE_CODE (gnu_result) == COND_EXPR
- && EXPR_P (TREE_OPERAND (gnu_result, 0)))
- set_expr_location_from_node (TREE_OPERAND (gnu_result, 0),
- gnat_node);
+ /* Otherwise, evaluate it each time it is referenced. */
+ else
+ switch (attribute)
+ {
+ case Attr_First:
+ case Attr_Last:
+ /* If we are dereferencing a pointer to unconstrained array, we
+ need to capture the value because the pointed-to bounds may
+ subsequently be released. */
+ if (unconstrained_ptr_deref)
+ gnu_result
+ = build1 (SAVE_EXPR, TREE_TYPE (gnu_result), gnu_result);
+ break;
+
+ case Attr_Length:
+ case Attr_Range_Length:
+ /* Set the source location onto the predicate of the condition
+ but not if the expression is cached to avoid messing up the
+ debug info. */
+ if (TREE_CODE (gnu_result) == COND_EXPR
+ && EXPR_P (TREE_OPERAND (gnu_result, 0)))
+ set_expr_location_from_node (TREE_OPERAND (gnu_result, 0),
+ gnat_node);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
}
@@ -2030,8 +2059,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
case Attr_Mechanism_Code:
{
+ Entity_Id gnat_obj = Entity (gnat_prefix);
int code;
- Entity_Id gnat_obj = Entity (Prefix (gnat_node));
prefix_unused = true;
gnu_result_type = get_unpadded_type (Etype (gnat_node));
@@ -2066,10 +2095,11 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
it has a side-effect. But don't do it if the prefix is just an entity
name. However, if an access check is needed, we must do it. See second
example in AARM 11.6(5.e). */
- if (prefix_unused && TREE_SIDE_EFFECTS (gnu_prefix)
- && !Is_Entity_Name (Prefix (gnat_node)))
- gnu_result = build_compound_expr (TREE_TYPE (gnu_result), gnu_prefix,
- gnu_result);
+ if (prefix_unused
+ && TREE_SIDE_EFFECTS (gnu_prefix)
+ && !Is_Entity_Name (gnat_prefix))
+ gnu_result
+ = build_compound_expr (TREE_TYPE (gnu_result), gnu_prefix, gnu_result);
*gnu_result_type_p = gnu_result_type;
return gnu_result;
@@ -2267,7 +2297,10 @@ can_equal_min_or_max_val_p (tree val, tree type, bool max)
if (TREE_CODE (val) != INTEGER_CST)
return true;
- return tree_int_cst_equal (val, min_or_max_val) == 1;
+ if (max)
+ return tree_int_cst_lt (val, min_or_max_val) == 0;
+ else
+ return tree_int_cst_lt (min_or_max_val, val) == 0;
}
/* Return true if VAL (of type TYPE) can equal the minimum value of TYPE.
@@ -3476,6 +3509,8 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
{
tree gnu_retval;
+ gnu_return_var_stack->pop ();
+
add_stmt (gnu_result);
add_stmt (build1 (LABEL_EXPR, void_type_node,
gnu_return_label_stack->last ()));
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index c5cee7a0098..ec252829c63 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -232,6 +232,7 @@ static tree compute_related_constant (tree, tree);
static tree split_plus (tree, tree *);
static tree float_type_for_precision (int, enum machine_mode);
static tree convert_to_fat_pointer (tree, tree);
+static unsigned int scale_by_factor_of (tree, unsigned int);
static bool potential_alignment_gap (tree, tree, tree);
static void process_attributes (tree, struct attrib *);
@@ -532,6 +533,22 @@ gnat_zaplevel (void)
free_binding_level = level;
}
+/* Set the context of TYPE and its parallel types (if any) to CONTEXT. */
+
+static void
+gnat_set_type_context (tree type, tree context)
+{
+ tree decl = TYPE_STUB_DECL (type);
+
+ TYPE_CONTEXT (type) = context;
+
+ while (decl && DECL_PARALLEL_TYPE (decl))
+ {
+ TYPE_CONTEXT (DECL_PARALLEL_TYPE (decl)) = context;
+ decl = TYPE_STUB_DECL (DECL_PARALLEL_TYPE (decl));
+ }
+}
+
/* Record DECL as belonging to the current lexical scope and use GNAT_NODE
for location information and flag propagation. */
@@ -613,7 +630,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
if (TREE_CODE (t) == POINTER_TYPE)
TYPE_NEXT_PTR_TO (t) = tt;
TYPE_NAME (tt) = DECL_NAME (decl);
- TYPE_CONTEXT (tt) = DECL_CONTEXT (decl);
+ gnat_set_type_context (tt, DECL_CONTEXT (decl));
TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (t);
DECL_ORIGINAL_TYPE (decl) = tt;
}
@@ -623,7 +640,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
/* We need a variant for the placeholder machinery to work. */
tree tt = build_variant_type_copy (t);
TYPE_NAME (tt) = decl;
- TYPE_CONTEXT (tt) = DECL_CONTEXT (decl);
+ gnat_set_type_context (tt, DECL_CONTEXT (decl));
TREE_USED (tt) = TREE_USED (t);
TREE_TYPE (decl) = tt;
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
@@ -645,7 +662,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
if (!(TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL))
{
TYPE_NAME (t) = decl;
- TYPE_CONTEXT (t) = DECL_CONTEXT (decl);
+ gnat_set_type_context (t, DECL_CONTEXT (decl));
}
}
}
@@ -1692,93 +1709,74 @@ rest_of_record_type_compilation (tree record_type)
TYPE_SIZE_UNIT (new_record_type)
= size_int (TYPE_ALIGN (record_type) / BITS_PER_UNIT);
- /* Now scan all the fields, replacing each field with a new
- field corresponding to the new encoding. */
+ /* Now scan all the fields, replacing each field with a new field
+ corresponding to the new encoding. */
for (old_field = TYPE_FIELDS (record_type); old_field;
old_field = DECL_CHAIN (old_field))
{
tree field_type = TREE_TYPE (old_field);
tree field_name = DECL_NAME (old_field);
- tree new_field;
tree curpos = bit_position (old_field);
+ tree pos, new_field;
bool var = false;
unsigned int align = 0;
- tree pos;
-
- /* See how the position was modified from the last position.
- There are two basic cases we support: a value was added
- to the last position or the last position was rounded to
- a boundary and they something was added. Check for the
- first case first. If not, see if there is any evidence
- of rounding. If so, round the last position and try
- again.
+ /* We're going to do some pattern matching below so remove as many
+ conversions as possible. */
+ curpos = remove_conversions (curpos, true);
- If this is a union, the position can be taken as zero. */
+ /* See how the position was modified from the last position.
- /* Some computations depend on the shape of the position expression,
- so strip conversions to make sure it's exposed. */
- curpos = remove_conversions (curpos, true);
+ There are two basic cases we support: a value was added
+ to the last position or the last position was rounded to
+ a boundary and they something was added. Check for the
+ first case first. If not, see if there is any evidence
+ of rounding. If so, round the last position and retry.
+ If this is a union, the position can be taken as zero. */
if (TREE_CODE (new_record_type) == UNION_TYPE)
- pos = bitsize_zero_node, align = 0;
+ pos = bitsize_zero_node;
else
pos = compute_related_constant (curpos, last_pos);
- if (!pos && TREE_CODE (curpos) == MULT_EXPR
+ if (!pos
+ && TREE_CODE (curpos) == MULT_EXPR
&& host_integerp (TREE_OPERAND (curpos, 1), 1))
{
tree offset = TREE_OPERAND (curpos, 0);
align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
-
- /* An offset which is a bitwise AND with a mask increases the
- alignment according to the number of trailing zeros. */
- offset = remove_conversions (offset, true);
- if (TREE_CODE (offset) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (offset, 1)) == INTEGER_CST)
- {
- unsigned HOST_WIDE_INT mask
- = TREE_INT_CST_LOW (TREE_OPERAND (offset, 1));
- unsigned int i;
-
- for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
- {
- if (mask & 1)
- break;
- mask >>= 1;
- align *= 2;
- }
- }
-
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ align = scale_by_factor_of (offset, align);
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
- else if (!pos && TREE_CODE (curpos) == PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST
+ else if (!pos
+ && TREE_CODE (curpos) == PLUS_EXPR
+ && host_integerp (TREE_OPERAND (curpos, 1), 1)
&& TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
- && host_integerp (TREE_OPERAND
- (TREE_OPERAND (curpos, 0), 1),
- 1))
+ && host_integerp
+ (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1))
{
+ tree offset = TREE_OPERAND (TREE_OPERAND (curpos, 0), 0);
+ unsigned HOST_WIDE_INT addend
+ = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
align
- = tree_low_cst
- (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ = tree_low_cst (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
+ align = scale_by_factor_of (offset, align);
+ align = MIN (align, addend & -addend);
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
- else if (potential_alignment_gap (prev_old_field, old_field,
- pos))
+ else if (potential_alignment_gap (prev_old_field, old_field, pos))
{
align = TYPE_ALIGN (field_type);
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
/* If we can't compute a position, set it to zero.
- ??? We really should abort here, but it's too much work
- to get this correct for all cases. */
-
+ ??? We really should abort here, but it's too much work
+ to get this correct for all cases. */
if (!pos)
pos = bitsize_zero_node;
@@ -2553,6 +2551,32 @@ value_factor_p (tree value, HOST_WIDE_INT factor)
return false;
}
+/* Return VALUE scaled by the biggest power-of-2 factor of EXPR. */
+
+static unsigned int
+scale_by_factor_of (tree expr, unsigned int value)
+{
+ expr = remove_conversions (expr, true);
+
+ /* An expression which is a bitwise AND with a mask has a power-of-2 factor
+ corresponding to the number of trailing zeros of the mask. */
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1));
+ unsigned int i = 0;
+
+ while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT)
+ {
+ mask >>= 1;
+ value *= 2;
+ i++;
+ }
+ }
+
+ return value;
+}
+
/* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true
unless we can prove these 2 fields are laid out in such a way that no gap
exist between the end of PREV_FIELD and the beginning of CURR_FIELD. OFFSET
diff --git a/gcc/ada/indepsw-darwin.adb b/gcc/ada/indepsw-darwin.adb
new file mode 100644
index 00000000000..e25e9049200
--- /dev/null
+++ b/gcc/ada/indepsw-darwin.adb
@@ -0,0 +1,67 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- I N D E P S W --
+-- --
+-- B o d y --
+-- (Darwin version) --
+-- --
+-- Copyright (C) 2013, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This is the Darwin version
+
+package body Indepsw is
+
+ Map_Switch : aliased constant String := "-Wl,-map,";
+
+ -------------
+ -- Convert --
+ -------------
+
+ procedure Convert
+ (Switch : Switch_Kind;
+ Argument : String;
+ To : out String_List_Access)
+ is
+ begin
+ case Switch is
+ when Map_File =>
+ To := new Argument_List'(1 => new String'(Map_Switch & Argument));
+ end case;
+ end Convert;
+
+ ------------------
+ -- Is_Supported --
+ ------------------
+
+ function Is_Supported (Switch : Switch_Kind) return Boolean is
+ begin
+ case Switch is
+ when Map_File =>
+ return True;
+ end case;
+ end Is_Supported;
+
+end Indepsw;
diff --git a/gcc/alias.c b/gcc/alias.c
index 970bdb0ee9a..aa404a7ab49 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -2871,16 +2871,13 @@ init_alias_analysis (void)
/* Wipe the reg_seen array clean. */
bitmap_clear (reg_seen);
- /* Mark all hard registers which may contain an address.
- The stack, frame and argument pointers may contain an address.
- An argument register which can hold a Pmode value may contain
- an address even if it is not in BASE_REGS.
-
- The address expression is VOIDmode for an argument and
- Pmode for other registers. */
-
- memcpy (new_reg_base_value, static_reg_base_value,
- FIRST_PSEUDO_REGISTER * sizeof (rtx));
+ /* Initialize the alias information for this pass. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (static_reg_base_value[i])
+ {
+ new_reg_base_value[i] = static_reg_base_value[i];
+ bitmap_set_bit (reg_seen, i);
+ }
/* Walk the insns adding values to the new_reg_base_value array. */
for (i = 0; i < rpo_cnt; i++)
diff --git a/gcc/asan.c b/gcc/asan.c
index 52a2dbc5dfd..d68579b2e5e 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1675,7 +1675,7 @@ instrument_mem_region_access (tree base, tree len,
access to the last byte of the argument; it uses the result of the
call to deduce the offset of that last byte.
- Upon completion, iff the call has actullay been instrumented, this
+ Upon completion, iff the call has actually been instrumented, this
function returns TRUE and *ITER points to the statement logically
following the built-in strlen function call *ITER was initially
pointing to. Otherwise, the function returns FALSE and *ITER
@@ -1706,10 +1706,10 @@ instrument_strlen_call (gimple_stmt_iterator *iter)
/* Instrument the access to the first byte of str_arg. i.e:
_1 = str_arg; instrument (_1); */
+ tree cptr_type = build_pointer_type (char_type_node);
gimple str_arg_ssa =
gimple_build_assign_with_ops (NOP_EXPR,
- make_ssa_name (build_pointer_type
- (char_type_node), NULL),
+ make_ssa_name (cptr_type, NULL),
str_arg, NULL);
gimple_set_location (str_arg_ssa, loc);
gimple_stmt_iterator gsi = *iter;
@@ -1728,8 +1728,7 @@ instrument_strlen_call (gimple_stmt_iterator *iter)
pointer_plus expr: (_1 + len). */
gimple stmt =
gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
- make_ssa_name (TREE_TYPE (str_arg),
- NULL),
+ make_ssa_name (cptr_type, NULL),
gimple_assign_lhs (str_arg_ssa),
len);
gimple_set_location (stmt, loc);
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e3c32a91c64..85ecdd35587 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1958,6 +1958,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
bool errno_set = false;
+ bool try_widening = false;
tree arg;
if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
@@ -1969,6 +1970,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
{
CASE_FLT_FN (BUILT_IN_SQRT):
errno_set = ! tree_expr_nonnegative_p (arg);
+ try_widening = true;
builtin_optab = sqrt_optab;
break;
CASE_FLT_FN (BUILT_IN_EXP):
@@ -2025,8 +2027,10 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
if (! flag_errno_math || ! HONOR_NANS (mode))
errno_set = false;
- /* Before working hard, check whether the instruction is available. */
- if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
+ /* Before working hard, check whether the instruction is available, but try
+ to widen the mode for specific operations. */
+ if ((optab_handler (builtin_optab, mode) != CODE_FOR_nothing
+ || (try_widening && !excess_precision_type (TREE_TYPE (exp))))
&& (!errno_set || !optimize_insn_for_size_p ()))
{
rtx result = gen_reg_rtx (mode);
@@ -5846,6 +5850,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
switch (fcode)
{
CASE_FLT_FN (BUILT_IN_FABS):
+ case BUILT_IN_FABSD32:
+ case BUILT_IN_FABSD64:
+ case BUILT_IN_FABSD128:
target = expand_builtin_fabs (exp, target, subtarget);
if (target)
return target;
@@ -10298,6 +10305,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
return fold_builtin_strlen (loc, type, arg0);
CASE_FLT_FN (BUILT_IN_FABS):
+ case BUILT_IN_FABSD32:
+ case BUILT_IN_FABSD64:
+ case BUILT_IN_FABSD128:
return fold_builtin_fabs (loc, arg0, type);
case BUILT_IN_ABS:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 4f378fad60b..d5afe0d054e 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -252,6 +252,9 @@ DEF_C99_BUILTIN (BUILT_IN_EXPM1L, "expm1l", BT_FN_LONGDOUBLE_LONGDOUBLE,
DEF_LIB_BUILTIN (BUILT_IN_FABS, "fabs", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSF, "fabsf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSL, "fabsl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
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)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 3acbfe39292..7b783e4f109 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,26 @@
+2013-11-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/59280
+ * c-common.c (get_priority): If TREE_VALUE (args) is IDENTIFIER_NODE,
+ goto invalid. If it is error_mark_node, don't issue further
+ diagnostics.
+
+2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ Backport from mainline
+ 2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58979
+ * c-common.c (invalid_indirection_error): Handle RO_ARROW_STAR case.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-08-09 Arnaud Charlet <charlet@adacore.com>
+
+ * c-ada-spec.c (print_ada_declaration): Prevent accessing null asm name
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 21cbfe94fba..2d6ce14ca48 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -2900,7 +2900,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, " -- ");
dump_sloc (buffer, t);
- if (is_abstract)
+ if (is_abstract || !DECL_ASSEMBLER_NAME (t))
return 1;
newline_and_indent (buffer, spc);
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0d91cc3cfdf..67a57624e4a 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6917,6 +6917,10 @@ get_priority (tree args, bool is_destructor)
}
arg = TREE_VALUE (args);
+ if (TREE_CODE (arg) == IDENTIFIER_NODE)
+ goto invalid;
+ if (arg == error_mark_node)
+ return DEFAULT_INIT_PRIORITY;
arg = default_conversion (arg);
if (!host_integerp (arg, /*pos=*/0)
|| !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
@@ -9763,6 +9767,11 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
"invalid type argument of %<->%> (have %qT)",
type);
break;
+ case RO_ARROW_STAR:
+ error_at (loc,
+ "invalid type argument of %<->*%> (have %qT)",
+ type);
+ break;
case RO_IMPLICIT_CONVERSION:
error_at (loc,
"invalid type argument of implicit conversion (have %qT)",
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 32410a3c3f9..d487a6e6d67 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,22 @@
+2013-12-03 Marek Polacek <polacek@redhat.com>
+
+ Backport from mainline
+ 2013-12-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/59351
+ * c-decl.c (build_compound_literal): Allow compound literals with
+ empty initial value.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/59032
+ * c-typeck.c (build_unary_op): Allow vector increment and decrement.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index d9bbf5c25f9..7e4ba134e44 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -4632,7 +4632,9 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
{
int failure = complete_array_type (&TREE_TYPE (decl),
DECL_INITIAL (decl), true);
- gcc_assert (!failure);
+ /* If complete_array_type returns 3, it means that the
+ initial value of the compound literal is empty. Allow it. */
+ gcc_assert (failure == 0 || failure == 3);
type = TREE_TYPE (decl);
TREE_TYPE (DECL_INITIAL (decl)) = type;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index ddb6d39774f..428fba92da0 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3629,7 +3629,8 @@ build_unary_op (location_t location,
/* Report invalid types. */
if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
- && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
+ && typecode != INTEGER_TYPE && typecode != REAL_TYPE
+ && typecode != VECTOR_TYPE)
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error_at (location, "wrong type argument to increment");
@@ -3694,7 +3695,9 @@ build_unary_op (location_t location,
}
else
{
- inc = integer_one_node;
+ inc = (TREE_CODE (argtype) == VECTOR_TYPE
+ ? build_one_cst (argtype)
+ : integer_one_node);
inc = convert (argtype, inc);
}
diff --git a/gcc/calls.c b/gcc/calls.c
index dd034b40099..bf0ba306b66 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -983,6 +983,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
for (i = 0; i < num_actuals; i++)
if (args[i].reg != 0 && ! args[i].pass_on_stack
+ && GET_CODE (args[i].reg) != PARALLEL
&& args[i].mode == BLKmode
&& MEM_P (args[i].value)
&& (MEM_ALIGN (args[i].value)
@@ -1327,6 +1328,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
#else
args[i].reg != 0,
#endif
+ reg_parm_stack_space,
args[i].pass_on_stack ? 0 : args[i].partial,
fndecl, args_size, &args[i].locate);
#ifdef BLOCK_REG_PADDING
@@ -3171,7 +3173,9 @@ expand_call (tree exp, rtx target, int ignore)
group load/store machinery below. */
if (!structure_value_addr
&& !pcc_struct_value
+ && TYPE_MODE (rettype) != VOIDmode
&& TYPE_MODE (rettype) != BLKmode
+ && REG_P (valreg)
&& targetm.calls.return_in_msb (rettype))
{
if (shift_return_value (TYPE_MODE (rettype), false, valreg))
@@ -3734,7 +3738,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
#else
argvec[count].reg != 0,
#endif
- 0, NULL_TREE, &args_size, &argvec[count].locate);
+ reg_parm_stack_space, 0,
+ NULL_TREE, &args_size, &argvec[count].locate);
if (argvec[count].reg == 0 || argvec[count].partial != 0
|| reg_parm_stack_space > 0)
@@ -3821,7 +3826,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
#else
argvec[count].reg != 0,
#endif
- argvec[count].partial,
+ reg_parm_stack_space, argvec[count].partial,
NULL_TREE, &args_size, &argvec[count].locate);
args_size.constant += argvec[count].locate.size.constant;
gcc_assert (!argvec[count].locate.size.var);
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 471d293f12f..3f930b836c3 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -927,6 +927,24 @@ merge_memattrs (rtx x, rtx y)
set_mem_align (y, MEM_ALIGN (x));
}
}
+ if (code == MEM)
+ {
+ if (MEM_READONLY_P (x) != MEM_READONLY_P (y))
+ {
+ MEM_READONLY_P (x) = 0;
+ MEM_READONLY_P (y) = 0;
+ }
+ if (MEM_NOTRAP_P (x) != MEM_NOTRAP_P (y))
+ {
+ MEM_NOTRAP_P (x) = 0;
+ MEM_NOTRAP_P (y) = 0;
+ }
+ if (MEM_VOLATILE_P (x) != MEM_VOLATILE_P (y))
+ {
+ MEM_VOLATILE_P (x) = 1;
+ MEM_VOLATILE_P (y) = 1;
+ }
+ }
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@@ -1275,7 +1293,6 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2,
{
rtx i1, i2, last1, last2, afterlast1, afterlast2;
int ninsns = 0;
- rtx p1;
enum replace_direction dir, last_dir, afterlast_dir;
bool follow_fallthru, did_fallthru;
@@ -1303,8 +1320,9 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2,
|| (returnjump_p (i2) && !side_effects_p (PATTERN (i2))))
{
last2 = i2;
- /* Count everything except for unconditional jump as insn. */
- if (!simplejump_p (i2) && !returnjump_p (i2) && last1)
+ /* Count everything except for unconditional jump as insn.
+ Don't count any jumps if dir_p is NULL. */
+ if (!simplejump_p (i2) && !returnjump_p (i2) && last1 && dir_p)
ninsns++;
i2 = PREV_INSN (i2);
}
@@ -1355,8 +1373,8 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2,
last1 = i1, last2 = i2;
afterlast_dir = last_dir;
last_dir = dir;
- p1 = PATTERN (i1);
- if (!(GET_CODE (p1) == USE || GET_CODE (p1) == CLOBBER))
+ if (GET_CODE (PATTERN (i1)) != USE
+ && GET_CODE (PATTERN (i1)) != CLOBBER)
ninsns++;
}
@@ -1402,7 +1420,8 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2,
/* Like flow_find_cross_jump, except start looking for a matching sequence from
the head of the two blocks. Do not include jumps at the end.
If STOP_AFTER is nonzero, stop after finding that many matching
- instructions. */
+ instructions. If STOP_AFTER is zero, count all INSN_P insns, if it is
+ non-zero, only count active insns. */
int
flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
@@ -1474,7 +1493,10 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
beforelast1 = last1, beforelast2 = last2;
last1 = i1, last2 = i2;
- ninsns++;
+ if (!stop_after
+ || (GET_CODE (PATTERN (i1)) != USE
+ && GET_CODE (PATTERN (i1)) != CLOBBER))
+ ninsns++;
}
if (i1 == BB_END (bb1) || i2 == BB_END (bb2)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 5acc42d73f5..1321c214d92 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -331,7 +331,7 @@ stack_var_conflict_p (size_t x, size_t y)
enter its partition number into bitmap DATA. */
static bool
-visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+visit_op (gimple, tree op, tree, void *data)
{
bitmap active = (bitmap)data;
op = get_base_address (op);
@@ -351,7 +351,7 @@ visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
from bitmap DATA. */
static bool
-visit_conflict (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+visit_conflict (gimple, tree op, tree, void *data)
{
bitmap active = (bitmap)data;
op = get_base_address (op);
@@ -385,7 +385,7 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)
edge e;
edge_iterator ei;
gimple_stmt_iterator gsi;
- bool (*visit)(gimple, tree, void *);
+ walk_stmt_load_store_addr_fn visit;
bitmap_clear (work);
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -4707,14 +4707,18 @@ gimple_expand_cfg (void)
if (e->insns.r)
{
rebuild_jump_labels_chain (e->insns.r);
- /* Avoid putting insns before parm_birth_insn. */
+ /* Put insns after parm birth, but before
+ NOTE_INSNS_FUNCTION_BEG. */
if (e->src == ENTRY_BLOCK_PTR
- && single_succ_p (ENTRY_BLOCK_PTR)
- && parm_birth_insn)
+ && single_succ_p (ENTRY_BLOCK_PTR))
{
rtx insns = e->insns.r;
e->insns.r = NULL_RTX;
- emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
+ if (NOTE_P (parm_birth_insn)
+ && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
+ emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
+ else
+ emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
}
else
commit_one_edge_insertion (e);
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index ec1ba9ad71c..1d1c6e7d811 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1784,10 +1784,18 @@ commit_one_edge_insertion (edge e)
}
/* If the source has one successor and the edge is not abnormal,
- insert there. Except for the entry block. */
+ insert there. Except for the entry block.
+ Don't do this if the predecessor ends in a jump other than
+ unconditional simple jump. E.g. for asm goto that points all
+ its labels at the fallthru basic block, we can't insert instructions
+ before the asm goto, as the asm goto can have various of side effects,
+ and can't emit instructions after the asm goto, as it must end
+ the basic block. */
else if ((e->flags & EDGE_ABNORMAL) == 0
&& single_succ_p (e->src)
- && e->src != ENTRY_BLOCK_PTR)
+ && e->src != ENTRY_BLOCK_PTR
+ && (!JUMP_P (BB_END (e->src))
+ || simplejump_p (BB_END (e->src))))
{
bb = e->src;
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 8c1efb4c37a..fd3aadee45d 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2596,4 +2596,47 @@ verify_cgraph (void)
FOR_EACH_FUNCTION (node)
verify_cgraph_node (node);
}
+
+/* Create external decl node for DECL.
+ The difference i nbetween cgraph_get_create_node and
+ cgraph_get_create_real_symbol_node is that cgraph_get_create_node
+ may return inline clone, while cgraph_get_create_real_symbol_node
+ will create a new node in this case.
+ FIXME: This function should be removed once clones are put out of decl
+ hash. */
+
+struct cgraph_node *
+cgraph_get_create_real_symbol_node (tree decl)
+{
+ struct cgraph_node *first_clone = cgraph_get_node (decl);
+ struct cgraph_node *node;
+ /* create symbol table node. even if inline clone exists, we can not take
+ it as a target of non-inlined call. */
+ node = cgraph_get_node (decl);
+ if (node && !node->global.inlined_to)
+ return node;
+
+ node = cgraph_create_node (decl);
+
+ /* ok, we previously inlined the function, then removed the offline copy and
+ now we want it back for external call. this can happen when devirtualizing
+ while inlining function called once that happens after extern inlined and
+ virtuals are already removed. in this case introduce the external node
+ and make it available for call. */
+ if (first_clone)
+ {
+ first_clone->clone_of = node;
+ node->clones = first_clone;
+ symtab_prevail_in_asm_name_hash ((symtab_node) node);
+ symtab_insert_node_to_hashtable ((symtab_node) node);
+ if (dump_file)
+ fprintf (dump_file, "Introduced new external node "
+ "(%s/%i) and turned into root of the clone tree.\n",
+ xstrdup (cgraph_node_name (node)), node->uid);
+ }
+ else if (dump_file)
+ fprintf (dump_file, "Introduced new external node "
+ "(%s/%i).\n", xstrdup (cgraph_node_name (node)), node->uid);
+ return node;
+}
#include "gt-cgraph.h"
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 5df7fb478b4..8ab7ae18102 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -575,6 +575,7 @@ struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
struct cgraph_node * cgraph_create_node (tree);
struct cgraph_node * cgraph_create_empty_node (void);
struct cgraph_node * cgraph_get_create_node (tree);
+struct cgraph_node * cgraph_get_create_real_symbol_node (tree);
struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
HOST_WIDE_INT, tree, tree);
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index fb01f24ec07..8869f524db5 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -73,7 +73,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
decl = get_base_var (*tp);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (decl);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl);
if (!ctx->only_vars)
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)ctx->varpool_node,
@@ -143,7 +143,7 @@ record_eh_tables (struct cgraph_node *node, struct function *fun)
{
struct cgraph_node *per_node;
- per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
+ per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL);
cgraph_mark_address_taken_node (per_node);
}
@@ -218,12 +218,12 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb)
/* Mark address taken in STMT. */
static bool
-mark_address (gimple stmt, tree addr, void *data)
+mark_address (gimple stmt, tree addr, tree, void *data)
{
addr = get_base_address (addr);
if (TREE_CODE (addr) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (addr);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr);
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)data,
(symtab_node)node,
@@ -245,14 +245,14 @@ mark_address (gimple stmt, tree addr, void *data)
/* Mark load of T. */
static bool
-mark_load (gimple stmt, tree t, void *data)
+mark_load (gimple stmt, tree t, tree, void *data)
{
t = get_base_address (t);
if (t && TREE_CODE (t) == FUNCTION_DECL)
{
/* ??? This can happen on platforms with descriptors when these are
directly manipulated in the code. Pretend that it's an address. */
- struct cgraph_node *node = cgraph_get_create_node (t);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (t);
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)data,
(symtab_node)node,
@@ -273,7 +273,7 @@ mark_load (gimple stmt, tree t, void *data)
/* Mark store of T. */
static bool
-mark_store (gimple stmt, tree t, void *data)
+mark_store (gimple stmt, tree t, tree, void *data)
{
t = get_base_address (t);
if (t && TREE_CODE (t) == VAR_DECL
@@ -330,7 +330,7 @@ build_cgraph_edges (void)
{
tree fn = gimple_omp_parallel_child_fn (stmt);
ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_node (fn),
+ (symtab_node)cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
@@ -338,12 +338,12 @@ build_cgraph_edges (void)
tree fn = gimple_omp_task_child_fn (stmt);
if (fn)
ipa_record_reference ((symtab_node)node,
- (symtab_node) cgraph_get_create_node (fn),
+ (symtab_node) cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
fn = gimple_omp_task_copy_fn (stmt);
if (fn)
ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_node (fn),
+ (symtab_node)cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
}
diff --git a/gcc/combine.c b/gcc/combine.c
index a589cfadb42..4df47283448 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -5798,8 +5798,15 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest,
return x;
}
- /* If the code changed, return a whole new comparison. */
- if (new_code != code)
+ /* If the code changed, return a whole new comparison.
+ We also need to avoid using SUBST in cases where
+ simplify_comparison has widened a comparison with a CONST_INT,
+ since in that case the wider CONST_INT may fail the sanity
+ checks in do_SUBST. */
+ if (new_code != code
+ || (CONST_INT_P (op1)
+ && GET_MODE (op0) != GET_MODE (XEXP (x, 0))
+ && GET_MODE (op0) != GET_MODE (XEXP (x, 1))))
return gen_rtx_fmt_ee (new_code, mode, op0, op1);
/* Otherwise, keep this operation, but maybe change its operands.
@@ -7991,7 +7998,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
if (code == CALL || code == ASM_OPERANDS || code == CLOBBER)
return x;
- /* We want to perform the operation is its present mode unless we know
+ /* We want to perform the operation in its present mode unless we know
that the operation is valid in MODE, in which case we do the operation
in MODE. */
op_mode = ((GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (x))
@@ -8427,9 +8434,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
GET_MODE (x), GEN_INT (mask),
XEXP (x, 1));
if (temp && CONST_INT_P (temp))
- SUBST (XEXP (x, 0),
- force_to_mode (XEXP (x, 0), GET_MODE (x),
- INTVAL (temp), next_select));
+ x = simplify_gen_binary (code, GET_MODE (x),
+ force_to_mode (XEXP (x, 0), GET_MODE (x),
+ INTVAL (temp), next_select),
+ XEXP (x, 1));
}
break;
@@ -8497,14 +8505,16 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* We have no way of knowing if the IF_THEN_ELSE can itself be
written in a narrower mode. We play it safe and do not do so. */
- SUBST (XEXP (x, 1),
- gen_lowpart_or_truncate (GET_MODE (x),
- force_to_mode (XEXP (x, 1), mode,
- mask, next_select)));
- SUBST (XEXP (x, 2),
- gen_lowpart_or_truncate (GET_MODE (x),
- force_to_mode (XEXP (x, 2), mode,
- mask, next_select)));
+ op0 = gen_lowpart_or_truncate (GET_MODE (x),
+ force_to_mode (XEXP (x, 1), mode,
+ mask, next_select));
+ op1 = gen_lowpart_or_truncate (GET_MODE (x),
+ force_to_mode (XEXP (x, 2), mode,
+ mask, next_select));
+ if (op0 != XEXP (x, 1) || op1 != XEXP (x, 2))
+ x = simplify_gen_ternary (IF_THEN_ELSE, GET_MODE (x),
+ GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+ op0, op1);
break;
default:
diff --git a/gcc/common/config/s390/s390-common.c b/gcc/common/config/s390/s390-common.c
index 1ffe93e8a18..c2031b74b1f 100644
--- a/gcc/common/config/s390/s390-common.c
+++ b/gcc/common/config/s390/s390-common.c
@@ -42,7 +42,7 @@ EXPORTED_CONST int processor_flags_table[] =
/* z196 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
| PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196,
/* zEC12 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
- | PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196 | PF_ZEC12
+ | PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196 | PF_ZEC12 | PF_TX
};
/* Change optimizations to be performed, depending on the
diff --git a/gcc/config.gcc b/gcc/config.gcc
index d2ef48c89ff..a4fb77db746 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -452,6 +452,7 @@ s390*-*-*)
cpu_type=s390
need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
+ extra_headers="s390intrin.h htmintrin.h htmxlintrin.h"
;;
# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
sh[123456789lbe]*-*-* | sh-*-*)
@@ -734,6 +735,7 @@ case ${target} in
yes) thread_file='rtems' ;;
esac
extra_options="${extra_options} rtems.opt"
+ default_use_cxa_atexit=yes
use_gcc_stdint=wrap
;;
*-*-uclinux*)
@@ -1057,7 +1059,6 @@ hppa*64*-*-linux*)
tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h gnu-user.h linux.h \
glibc-stdint.h pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h \
pa/pa64-linux.h"
- tmake_file="${tmake_file} pa/t-linux"
gas=yes gnu_ld=yes
need_64bit_hwint=yes
;;
@@ -1760,6 +1761,14 @@ microblaze*-linux*)
tmake_file="${tmake_file} microblaze/t-microblaze-linux"
;;
microblaze*-*-rtems*)
+ case $target in
+ microblazeel-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=0"
+ ;;
+ microblaze-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ ;;
+ esac
tm_file="${tm_file} dbxelf.h"
tm_file="${tm_file} microblaze/rtems.h rtems.h newlib-stdint.h"
c_target_objs="${c_target_objs} microblaze-c.o"
@@ -2072,7 +2081,7 @@ powerpc*-*-linux*)
tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
case ${target} in
powerpc*le-*-*)
- tm_file="${tm_file} rs6000/sysv4le.h" ;;
+ tm_file="${tm_file} rs6000/sysv4le.h" ;;
esac
maybe_biarch=yes
case ${target} in
@@ -2095,6 +2104,19 @@ powerpc*-*-linux*)
fi
tm_file="rs6000/biarch64.h ${tm_file} rs6000/linux64.h glibc-stdint.h"
tmake_file="$tmake_file rs6000/t-linux64"
+ case ${target} in
+ powerpc*le-*-*)
+ tmake_file="$tmake_file rs6000/t-linux64le"
+ case ${enable_targets} in
+ all | *powerpc64-* | *powerpc-*)
+ tmake_file="$tmake_file rs6000/t-linux64lebe" ;;
+ esac ;;
+ *)
+ case ${enable_targets} in
+ all | *powerpc64le-* | *powerpcle-*)
+ tmake_file="$tmake_file rs6000/t-linux64bele" ;;
+ esac ;;
+ esac
extra_options="${extra_options} rs6000/linux64.opt"
;;
*)
@@ -2962,11 +2984,18 @@ if test x$with_cpu = x ; then
with_cpu=8540
fi
;;
- sparc-leon*-*)
- with_cpu=v8;
- ;;
sparc*-*-*)
- with_cpu="`echo ${target} | sed 's/-.*$//'`"
+ case ${target} in
+ *-leon-*)
+ with_cpu=leon
+ ;;
+ *-leon[3-9]*)
+ with_cpu=leon3
+ ;;
+ *)
+ with_cpu="`echo ${target} | sed 's/-.*$//'`"
+ ;;
+ esac
;;
esac
@@ -3493,7 +3522,7 @@ case "${target}" in
;;
powerpc*-*-* | rs6000-*-*)
- supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64"
+ supported_defaults="abi cpu cpu_32 cpu_64 float tune tune_32 tune_64"
for which in cpu cpu_32 cpu_64 tune tune_32 tune_64; do
eval "val=\$with_$which"
@@ -3530,6 +3559,16 @@ case "${target}" in
;;
esac
done
+
+ case "$with_abi" in
+ "" | elfv1 | elfv2 )
+ #OK
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi"
+ exit 1
+ ;;
+ esac
;;
s390*-*-*)
@@ -3586,7 +3625,7 @@ case "${target}" in
case ${val} in
"" | sparc | sparcv9 | sparc64 \
| v7 | cypress \
- | v8 | supersparc | hypersparc | leon \
+ | v8 | supersparc | hypersparc | leon | leon3 \
| sparclite | f930 | f934 | sparclite86x \
| sparclet | tsc701 \
| v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \
@@ -3744,15 +3783,6 @@ case ${target} in
cxx_target_objs="${cxx_target_objs} sh-c.o"
;;
- sparc-leon*-*)
- if test x$with_tune = x ; then
- with_tune=leon;
- fi
-
- # The SPARC port checks this value at compile-time.
- target_cpu_default2="TARGET_CPU_$with_cpu"
- ;;
-
sparc*-*-*)
# Some standard aliases.
case x$with_cpu in
@@ -3764,6 +3794,17 @@ case ${target} in
;;
esac
+ if test x$with_tune = x ; then
+ case ${target} in
+ *-leon-*)
+ with_tune=leon
+ ;;
+ *-leon[3-9]*)
+ with_tune=leon3
+ ;;
+ esac
+ fi
+
# The SPARC port checks this value at compile-time.
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
diff --git a/gcc/config.in b/gcc/config.in
index 23c741ac80e..9705dd0936e 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -375,6 +375,12 @@
#endif
+/* Define if your assembler supports LEON instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LEON
+#endif
+
+
/* Define if the assembler won't complain about a line such as # 0 "" 2. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_LINE_ZERO
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 1ea55a83eb8..b2901dbcab2 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -1154,6 +1154,7 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
return aarch64_simd_expand_args (target, icode, 1, exp,
SIMD_ARG_COPY_TO_REG, SIMD_ARG_STOP);
+ case AARCH64_SIMD_STORE1:
case AARCH64_SIMD_STORESTRUCT:
return aarch64_simd_expand_args (target, icode, 0, exp,
SIMD_ARG_COPY_TO_REG,
diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h
index e914ed27f1f..83efad447f1 100644
--- a/gcc/config/aarch64/aarch64-linux.h
+++ b/gcc/config/aarch64/aarch64-linux.h
@@ -23,6 +23,8 @@
#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-aarch64.so.1"
+#define CPP_SPEC "%{pthread:-D_REENTRANT}"
+
#define LINUX_TARGET_LINK_SPEC "%{h*} \
%{static:-Bstatic} \
%{shared:-shared} \
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index a6a5e12c7a5..ed73c15d7e9 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -217,8 +217,8 @@
BUILTIN_VSDQ_I_DI (BINOP, cmle)
BUILTIN_VSDQ_I_DI (BINOP, cmlt)
/* Implemented by aarch64_cm<cmp><mode>. */
- BUILTIN_VSDQ_I_DI (BINOP, cmhs)
- BUILTIN_VSDQ_I_DI (BINOP, cmhi)
+ BUILTIN_VSDQ_I_DI (BINOP, cmgeu)
+ BUILTIN_VSDQ_I_DI (BINOP, cmgtu)
BUILTIN_VSDQ_I_DI (BINOP, cmtst)
/* Implemented by aarch64_<fmaxmin><mode>. */
@@ -256,3 +256,10 @@
BUILTIN_VALL (BINOP, uzp2)
BUILTIN_VALL (BINOP, trn1)
BUILTIN_VALL (BINOP, trn2)
+
+ /* Implemented by aarch64_ld1<VALL:mode>. */
+ BUILTIN_VALL (LOAD1, ld1)
+
+ /* Implemented by aarch64_st1<VALL:mode>. */
+ BUILTIN_VALL (STORE1, st1)
+
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 79c30933115..481222cf528 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -21,7 +21,7 @@
; Main data types used by the insntructions
-(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,HI,QI"
+(define_attr "simd_mode" "unknown,none,V8QI,V16QI,V4HI,V8HI,V2SI,V4SI,V2DI,V2SF,V4SF,V2DF,OI,CI,XI,DI,DF,SI,SF,HI,QI"
(const_string "unknown"))
@@ -1548,12 +1548,12 @@
case LTU:
case GEU:
- emit_insn (gen_aarch64_cmhs<mode> (mask, operands[4], operands[5]));
+ emit_insn (gen_aarch64_cmgeu<mode> (mask, operands[4], operands[5]));
break;
case LEU:
case GTU:
- emit_insn (gen_aarch64_cmhi<mode> (mask, operands[4], operands[5]));
+ emit_insn (gen_aarch64_cmgtu<mode> (mask, operands[4], operands[5]));
break;
case NE:
@@ -3034,48 +3034,181 @@
)
-;; cm(eq|ge|le|lt|gt)
+;; cm(eq|ge|gt|lt|le)
+;; Note, we have constraints for Dz and Z as different expanders
+;; have different ideas of what should be passed to this pattern.
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
- (unspec:<V_cmp_result>
- [(match_operand:VSDQ_I_DI 1 "register_operand" "w,w")
- (match_operand:VSDQ_I_DI 2 "aarch64_simd_reg_or_zero" "w,Z")]
- VCMP_S))]
+ (neg:<V_cmp_result>
+ (COMPARISONS:<V_cmp_result>
+ (match_operand:VDQ 1 "register_operand" "w,w")
+ (match_operand:VDQ 2 "aarch64_simd_reg_or_zero" "w,ZDz")
+ )))]
"TARGET_SIMD"
"@
- cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>
- cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
+ cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
+ cm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
[(set_attr "simd_type" "simd_cmp")
(set_attr "simd_mode" "<MODE>")]
)
-;; cm(hs|hi|tst)
+(define_insn_and_split "aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w,w,r")
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w,w,r")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,r")
+ )))]
+ "TARGET_SIMD"
+ "@
+ cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+ cm<optab>\t%d0, %d1, #0
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; cm(hs|hi)
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
- (unspec:<V_cmp_result>
- [(match_operand:VSDQ_I_DI 1 "register_operand" "w")
- (match_operand:VSDQ_I_DI 2 "register_operand" "w")]
- VCMP_U))]
+ (neg:<V_cmp_result>
+ (UCOMPARISONS:<V_cmp_result>
+ (match_operand:VDQ 1 "register_operand" "w")
+ (match_operand:VDQ 2 "register_operand" "w")
+ )))]
"TARGET_SIMD"
- "cm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ "cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
[(set_attr "simd_type" "simd_cmp")
(set_attr "simd_mode" "<MODE>")]
)
-;; fcm(eq|ge|le|lt|gt)
+(define_insn_and_split "aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w,r")
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w,r")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,r")
+ )))]
+ "TARGET_SIMD"
+ "@
+ cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; cmtst
-(define_insn "aarch64_cm<cmp><mode>"
+(define_insn "aarch64_cmtst<mode>"
+ [(set (match_operand:<V_cmp_result> 0 "register_operand" "=w")
+ (neg:<V_cmp_result>
+ (ne:<V_cmp_result>
+ (and:VDQ
+ (match_operand:VDQ 1 "register_operand" "w")
+ (match_operand:VDQ 2 "register_operand" "w"))
+ (vec_duplicate:<V_cmp_result> (const_int 0)))))]
+ "TARGET_SIMD"
+ "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "<MODE>")]
+)
+
+(define_insn_and_split "aarch64_cmtstdi"
+ [(set (match_operand:DI 0 "register_operand" "=w,r")
+ (neg:DI
+ (ne:DI
+ (and:DI
+ (match_operand:DI 1 "register_operand" "w,r")
+ (match_operand:DI 2 "register_operand" "w,r"))
+ (const_int 0))))]
+ "TARGET_SIMD"
+ "@
+ cmtst\t%d0, %d1, %d2
+ #"
+ "reload_completed
+ /* We need to prevent the split from
+ happening in the 'w' constraint cases. */
+ && GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1]))"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:DI (match_dup 1)
+ (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (neg:DI
+ (ne:DI
+ (match_operand 3 "cc_register" "")
+ (const_int 0))))]
+ {
+ rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
+ enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
+ rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
+ rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ [(set_attr "simd_type" "simd_cmp")
+ (set_attr "simd_mode" "DI")]
+)
+
+;; fcm(eq|ge|gt|le|lt)
+
+(define_insn "aarch64_cm<optab><mode>"
[(set (match_operand:<V_cmp_result> 0 "register_operand" "=w,w")
- (unspec:<V_cmp_result>
- [(match_operand:VDQF 1 "register_operand" "w,w")
- (match_operand:VDQF 2 "aarch64_simd_reg_or_zero" "w,Dz")]
- VCMP_S))]
+ (neg:<V_cmp_result>
+ (COMPARISONS:<V_cmp_result>
+ (match_operand:VALLF 1 "register_operand" "w,w")
+ (match_operand:VALLF 2 "aarch64_simd_reg_or_zero" "w,YDz")
+ )))]
"TARGET_SIMD"
"@
- fcm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>
- fcm<cmp>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
+ fcm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
+ fcm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
[(set_attr "simd_type" "simd_fcmp")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3457,6 +3590,17 @@
DONE;
})
+(define_expand "aarch64_ld1<VALL:mode>"
+ [(match_operand:VALL 0 "register_operand")
+ (match_operand:DI 1 "register_operand")]
+ "TARGET_SIMD"
+{
+ enum machine_mode mode = <VALL:MODE>mode;
+ rtx mem = gen_rtx_MEM (mode, operands[1]);
+ emit_move_insn (operands[0], mem);
+ DONE;
+})
+
(define_expand "aarch64_ld<VSTRUCT:nregs><VQ:mode>"
[(match_operand:VSTRUCT 0 "register_operand" "=w")
(match_operand:DI 1 "register_operand" "r")
@@ -3673,6 +3817,17 @@
DONE;
})
+(define_expand "aarch64_st1<VALL:mode>"
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:VALL 1 "register_operand")]
+ "TARGET_SIMD"
+{
+ enum machine_mode mode = <VALL:MODE>mode;
+ rtx mem = gen_rtx_MEM (mode, operands[0]);
+ emit_move_insn (mem, operands[1]);
+ DONE;
+})
+
;; Expander for builtins to insert vector registers into large
;; opaque integer modes.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 5b87b3c37fd..c5cfedb8fa5 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1313,7 +1313,7 @@
)
(define_insn "*add_<shift>_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
(match_operand:GPI 3 "register_operand" "r")))]
@@ -1325,7 +1325,7 @@
;; zero_extend version of above
(define_insn "*add_<shift>_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_si" "n"))
@@ -1337,7 +1337,7 @@
)
(define_insn "*add_mul_imm_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
(match_operand:GPI 3 "register_operand" "r")))]
@@ -1660,7 +1660,7 @@
)
(define_insn "*sub_<shift>_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_operand:GPI 3 "register_operand" "r")
(ASHIFT:GPI
(match_operand:GPI 1 "register_operand" "r")
@@ -1673,7 +1673,7 @@
;; zero_extend version of above
(define_insn "*sub_<shift>_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 3 "register_operand" "r")
(ASHIFT:SI
@@ -1686,7 +1686,7 @@
)
(define_insn "*sub_mul_imm_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_operand:GPI 3 "register_operand" "r")
(mult:GPI
(match_operand:GPI 1 "register_operand" "r")
@@ -1699,7 +1699,7 @@
;; zero_extend version of above
(define_insn "*sub_mul_imm_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 3 "register_operand" "r")
(mult:SI
@@ -2211,7 +2211,7 @@
(set_attr "mode" "SI")]
)
-(define_insn "*cstore<mode>_neg"
+(define_insn "cstore<mode>_neg"
[(set (match_operand:ALLI 0 "register_operand" "=r")
(neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator"
[(match_operand 2 "cc_register" "") (const_int 0)])))]
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 669217e2762..d16711d6e92 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -8518,28 +8518,6 @@ vld1_dup_u64 (const uint64_t * a)
return result;
}
-__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
-vld1_f32 (const float32_t * a)
-{
- float32x2_t result;
- __asm__ ("ld1 {%0.2s}, %1"
- : "=w"(result)
- : "Utv"(({const float32x2_t *_a = (float32x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
-vld1_f64 (const float64_t * a)
-{
- float64x1_t result;
- __asm__ ("ld1 {%0.1d}, %1"
- : "=w"(result)
- : "Utv"(*a)
- : /* No clobbers */);
- return result;
-}
-
#define vld1_lane_f32(a, b, c) \
__extension__ \
({ \
@@ -8696,116 +8674,6 @@ vld1_f64 (const float64_t * a)
result; \
})
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vld1_p8 (const poly8_t * a)
-{
- poly8x8_t result;
- __asm__ ("ld1 {%0.8b}, %1"
- : "=w"(result)
- : "Utv"(({const poly8x8_t *_a = (poly8x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__))
-vld1_p16 (const poly16_t * a)
-{
- poly16x4_t result;
- __asm__ ("ld1 {%0.4h}, %1"
- : "=w"(result)
- : "Utv"(({const poly16x4_t *_a = (poly16x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vld1_s8 (const int8_t * a)
-{
- int8x8_t result;
- __asm__ ("ld1 {%0.8b}, %1"
- : "=w"(result)
- : "Utv"(({const int8x8_t *_a = (int8x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
-vld1_s16 (const int16_t * a)
-{
- int16x4_t result;
- __asm__ ("ld1 {%0.4h}, %1"
- : "=w"(result)
- : "Utv"(({const int16x4_t *_a = (int16x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
-vld1_s32 (const int32_t * a)
-{
- int32x2_t result;
- __asm__ ("ld1 {%0.2s}, %1"
- : "=w"(result)
- : "Utv"(({const int32x2_t *_a = (int32x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
-vld1_s64 (const int64_t * a)
-{
- int64x1_t result;
- __asm__ ("ld1 {%0.1d}, %1"
- : "=w"(result)
- : "Utv"(*a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vld1_u8 (const uint8_t * a)
-{
- uint8x8_t result;
- __asm__ ("ld1 {%0.8b}, %1"
- : "=w"(result)
- : "Utv"(({const uint8x8_t *_a = (uint8x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
-vld1_u16 (const uint16_t * a)
-{
- uint16x4_t result;
- __asm__ ("ld1 {%0.4h}, %1"
- : "=w"(result)
- : "Utv"(({const uint16x4_t *_a = (uint16x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
-vld1_u32 (const uint32_t * a)
-{
- uint32x2_t result;
- __asm__ ("ld1 {%0.2s}, %1"
- : "=w"(result)
- : "Utv"(({const uint32x2_t *_a = (uint32x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
-vld1_u64 (const uint64_t * a)
-{
- uint64x1_t result;
- __asm__ ("ld1 {%0.1d}, %1"
- : "=w"(result)
- : "Utv"(*a)
- : /* No clobbers */);
- return result;
-}
-
__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
vld1q_dup_f32 (const float32_t * a)
{
@@ -8938,28 +8806,6 @@ vld1q_dup_u64 (const uint64_t * a)
return result;
}
-__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
-vld1q_f32 (const float32_t * a)
-{
- float32x4_t result;
- __asm__ ("ld1 {%0.4s}, %1"
- : "=w"(result)
- : "Utv"(({const float32x4_t *_a = (float32x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
-vld1q_f64 (const float64_t * a)
-{
- float64x2_t result;
- __asm__ ("ld1 {%0.2d}, %1"
- : "=w"(result)
- : "Utv"(({const float64x2_t *_a = (float64x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
#define vld1q_lane_f32(a, b, c) \
__extension__ \
({ \
@@ -9116,116 +8962,6 @@ vld1q_f64 (const float64_t * a)
result; \
})
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vld1q_p8 (const poly8_t * a)
-{
- poly8x16_t result;
- __asm__ ("ld1 {%0.16b}, %1"
- : "=w"(result)
- : "Utv"(({const poly8x16_t *_a = (poly8x16_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__))
-vld1q_p16 (const poly16_t * a)
-{
- poly16x8_t result;
- __asm__ ("ld1 {%0.16b}, %1"
- : "=w"(result)
- : "Utv"(({const poly16x8_t *_a = (poly16x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vld1q_s8 (const int8_t * a)
-{
- int8x16_t result;
- __asm__ ("ld1 {%0.16b}, %1"
- : "=w"(result)
- : "Utv"(({const int8x16_t *_a = (int8x16_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
-vld1q_s16 (const int16_t * a)
-{
- int16x8_t result;
- __asm__ ("ld1 {%0.8h}, %1"
- : "=w"(result)
- : "Utv"(({const int16x8_t *_a = (int16x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
-vld1q_s32 (const int32_t * a)
-{
- int32x4_t result;
- __asm__ ("ld1 {%0.4s}, %1"
- : "=w"(result)
- : "Utv"(({const int32x4_t *_a = (int32x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
-vld1q_s64 (const int64_t * a)
-{
- int64x2_t result;
- __asm__ ("ld1 {%0.2d}, %1"
- : "=w"(result)
- : "Utv"(({const int64x2_t *_a = (int64x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vld1q_u8 (const uint8_t * a)
-{
- uint8x16_t result;
- __asm__ ("ld1 {%0.16b}, %1"
- : "=w"(result)
- : "Utv"(({const uint8x16_t *_a = (uint8x16_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
-vld1q_u16 (const uint16_t * a)
-{
- uint16x8_t result;
- __asm__ ("ld1 {%0.8h}, %1"
- : "=w"(result)
- : "Utv"(({const uint16x8_t *_a = (uint16x8_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
-vld1q_u32 (const uint32_t * a)
-{
- uint32x4_t result;
- __asm__ ("ld1 {%0.4s}, %1"
- : "=w"(result)
- : "Utv"(({const uint32x4_t *_a = (uint32x4_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
-vld1q_u64 (const uint64_t * a)
-{
- uint64x2_t result;
- __asm__ ("ld1 {%0.2d}, %1"
- : "=w"(result)
- : "Utv"(({const uint64x2_t *_a = (uint64x2_t *) a; *_a;}))
- : /* No clobbers */);
- return result;
-}
-
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
vmaxnm_f32 (float32x2_t a, float32x2_t b)
{
@@ -16285,24 +16021,6 @@ vrsubhn_u64 (uint64x2_t a, uint64x2_t b)
result; \
})
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_f32 (float32_t * a, float32x2_t b)
-{
- __asm__ ("st1 {%1.2s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_f64 (float64_t * a, float64x1_t b)
-{
- __asm__ ("st1 {%1.1d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
#define vst1_lane_f32(a, b, c) \
__extension__ \
({ \
@@ -16435,113 +16153,6 @@ vst1_f64 (float64_t * a, float64x1_t b)
: "memory"); \
})
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_p8 (poly8_t * a, poly8x8_t b)
-{
- __asm__ ("st1 {%1.8b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_p16 (poly16_t * a, poly16x4_t b)
-{
- __asm__ ("st1 {%1.4h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_s8 (int8_t * a, int8x8_t b)
-{
- __asm__ ("st1 {%1.8b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_s16 (int16_t * a, int16x4_t b)
-{
- __asm__ ("st1 {%1.4h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_s32 (int32_t * a, int32x2_t b)
-{
- __asm__ ("st1 {%1.2s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_s64 (int64_t * a, int64x1_t b)
-{
- __asm__ ("st1 {%1.1d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_u8 (uint8_t * a, uint8x8_t b)
-{
- __asm__ ("st1 {%1.8b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_u16 (uint16_t * a, uint16x4_t b)
-{
- __asm__ ("st1 {%1.4h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_u32 (uint32_t * a, uint32x2_t b)
-{
- __asm__ ("st1 {%1.2s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1_u64 (uint64_t * a, uint64x1_t b)
-{
- __asm__ ("st1 {%1.1d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_f32 (float32_t * a, float32x4_t b)
-{
- __asm__ ("st1 {%1.4s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_f64 (float64_t * a, float64x2_t b)
-{
- __asm__ ("st1 {%1.2d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
#define vst1q_lane_f32(a, b, c) \
__extension__ \
@@ -16675,96 +16286,6 @@ vst1q_f64 (float64_t * a, float64x2_t b)
: "memory"); \
})
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_p8 (poly8_t * a, poly8x16_t b)
-{
- __asm__ ("st1 {%1.16b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_p16 (poly16_t * a, poly16x8_t b)
-{
- __asm__ ("st1 {%1.8h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_s8 (int8_t * a, int8x16_t b)
-{
- __asm__ ("st1 {%1.16b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_s16 (int16_t * a, int16x8_t b)
-{
- __asm__ ("st1 {%1.8h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_s32 (int32_t * a, int32x4_t b)
-{
- __asm__ ("st1 {%1.4s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_s64 (int64_t * a, int64x2_t b)
-{
- __asm__ ("st1 {%1.2d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_u8 (uint8_t * a, uint8x16_t b)
-{
- __asm__ ("st1 {%1.16b},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_u16 (uint16_t * a, uint16x8_t b)
-{
- __asm__ ("st1 {%1.8h},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_u32 (uint32_t * a, uint32x4_t b)
-{
- __asm__ ("st1 {%1.4s},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
-__extension__ static __inline void __attribute__ ((__always_inline__))
-vst1q_u64 (uint64_t * a, uint64x2_t b)
-{
- __asm__ ("st1 {%1.2d},[%0]"
- :
- : "r"(a), "w"(b)
- : "memory");
-}
-
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vsubhn_high_s16 (int8x8_t a, int16x8_t b, int16x8_t c)
{
@@ -19669,7 +19190,7 @@ vtbx1_s8 (int8x8_t r, int8x8_t tab, int8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -19685,7 +19206,7 @@ vtbx1_u8 (uint8x8_t r, uint8x8_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -19701,7 +19222,7 @@ vtbx1_p8 (poly8x8_t r, poly8x8_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -19756,7 +19277,7 @@ vtbx3_s8 (int8x8_t r, int8x8x3_t tab, int8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -19775,7 +19296,7 @@ vtbx3_u8 (uint8x8_t r, uint8x8x3_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -19794,7 +19315,7 @@ vtbx3_p8 (poly8x8_t r, poly8x8x3_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -20030,28 +19551,28 @@ vcge_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vcge_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t) __builtin_aarch64_cmhsv8qi ((int8x8_t) __a,
+ return (uint8x8_t) __builtin_aarch64_cmgeuv8qi ((int8x8_t) __a,
(int8x8_t) __b);
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vcge_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t) __builtin_aarch64_cmhsv4hi ((int16x4_t) __a,
+ return (uint16x4_t) __builtin_aarch64_cmgeuv4hi ((int16x4_t) __a,
(int16x4_t) __b);
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vcge_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t) __builtin_aarch64_cmhsv2si ((int32x2_t) __a,
+ return (uint32x2_t) __builtin_aarch64_cmgeuv2si ((int32x2_t) __a,
(int32x2_t) __b);
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vcge_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __a,
+ return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __a,
(int64x1_t) __b);
}
@@ -20082,28 +19603,28 @@ vcgeq_s64 (int64x2_t __a, int64x2_t __b)
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vcgeq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t) __builtin_aarch64_cmhsv16qi ((int8x16_t) __a,
+ return (uint8x16_t) __builtin_aarch64_cmgeuv16qi ((int8x16_t) __a,
(int8x16_t) __b);
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vcgeq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t) __builtin_aarch64_cmhsv8hi ((int16x8_t) __a,
+ return (uint16x8_t) __builtin_aarch64_cmgeuv8hi ((int16x8_t) __a,
(int16x8_t) __b);
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vcgeq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t) __builtin_aarch64_cmhsv4si ((int32x4_t) __a,
+ return (uint32x4_t) __builtin_aarch64_cmgeuv4si ((int32x4_t) __a,
(int32x4_t) __b);
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vcgeq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t) __builtin_aarch64_cmhsv2di ((int64x2_t) __a,
+ return (uint64x2_t) __builtin_aarch64_cmgeuv2di ((int64x2_t) __a,
(int64x2_t) __b);
}
@@ -20116,7 +19637,7 @@ vcged_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vcged_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __a,
+ return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __a,
(int64x1_t) __b);
}
@@ -20155,28 +19676,28 @@ vcgt_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vcgt_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t) __builtin_aarch64_cmhiv8qi ((int8x8_t) __a,
+ return (uint8x8_t) __builtin_aarch64_cmgtuv8qi ((int8x8_t) __a,
(int8x8_t) __b);
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vcgt_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t) __builtin_aarch64_cmhiv4hi ((int16x4_t) __a,
+ return (uint16x4_t) __builtin_aarch64_cmgtuv4hi ((int16x4_t) __a,
(int16x4_t) __b);
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vcgt_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t) __builtin_aarch64_cmhiv2si ((int32x2_t) __a,
+ return (uint32x2_t) __builtin_aarch64_cmgtuv2si ((int32x2_t) __a,
(int32x2_t) __b);
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vcgt_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __a,
+ return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __a,
(int64x1_t) __b);
}
@@ -20207,28 +19728,28 @@ vcgtq_s64 (int64x2_t __a, int64x2_t __b)
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vcgtq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t) __builtin_aarch64_cmhiv16qi ((int8x16_t) __a,
+ return (uint8x16_t) __builtin_aarch64_cmgtuv16qi ((int8x16_t) __a,
(int8x16_t) __b);
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vcgtq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t) __builtin_aarch64_cmhiv8hi ((int16x8_t) __a,
+ return (uint16x8_t) __builtin_aarch64_cmgtuv8hi ((int16x8_t) __a,
(int16x8_t) __b);
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vcgtq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t) __builtin_aarch64_cmhiv4si ((int32x4_t) __a,
+ return (uint32x4_t) __builtin_aarch64_cmgtuv4si ((int32x4_t) __a,
(int32x4_t) __b);
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vcgtq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t) __builtin_aarch64_cmhiv2di ((int64x2_t) __a,
+ return (uint64x2_t) __builtin_aarch64_cmgtuv2di ((int64x2_t) __a,
(int64x2_t) __b);
}
@@ -20241,7 +19762,7 @@ vcgtd_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vcgtd_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __a,
+ return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __a,
(int64x1_t) __b);
}
@@ -20280,28 +19801,28 @@ vcle_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vcle_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t) __builtin_aarch64_cmhsv8qi ((int8x8_t) __b,
+ return (uint8x8_t) __builtin_aarch64_cmgeuv8qi ((int8x8_t) __b,
(int8x8_t) __a);
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vcle_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t) __builtin_aarch64_cmhsv4hi ((int16x4_t) __b,
+ return (uint16x4_t) __builtin_aarch64_cmgeuv4hi ((int16x4_t) __b,
(int16x4_t) __a);
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vcle_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t) __builtin_aarch64_cmhsv2si ((int32x2_t) __b,
+ return (uint32x2_t) __builtin_aarch64_cmgeuv2si ((int32x2_t) __b,
(int32x2_t) __a);
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vcle_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhsdi ((int64x1_t) __b,
+ return (uint64x1_t) __builtin_aarch64_cmgeudi ((int64x1_t) __b,
(int64x1_t) __a);
}
@@ -20332,28 +19853,28 @@ vcleq_s64 (int64x2_t __a, int64x2_t __b)
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vcleq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t) __builtin_aarch64_cmhsv16qi ((int8x16_t) __b,
+ return (uint8x16_t) __builtin_aarch64_cmgeuv16qi ((int8x16_t) __b,
(int8x16_t) __a);
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vcleq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t) __builtin_aarch64_cmhsv8hi ((int16x8_t) __b,
+ return (uint16x8_t) __builtin_aarch64_cmgeuv8hi ((int16x8_t) __b,
(int16x8_t) __a);
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vcleq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t) __builtin_aarch64_cmhsv4si ((int32x4_t) __b,
+ return (uint32x4_t) __builtin_aarch64_cmgeuv4si ((int32x4_t) __b,
(int32x4_t) __a);
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vcleq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t) __builtin_aarch64_cmhsv2di ((int64x2_t) __b,
+ return (uint64x2_t) __builtin_aarch64_cmgeuv2di ((int64x2_t) __b,
(int64x2_t) __a);
}
@@ -20398,28 +19919,28 @@ vclt_s64 (int64x1_t __a, int64x1_t __b)
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vclt_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t) __builtin_aarch64_cmhiv8qi ((int8x8_t) __b,
+ return (uint8x8_t) __builtin_aarch64_cmgtuv8qi ((int8x8_t) __b,
(int8x8_t) __a);
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vclt_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t) __builtin_aarch64_cmhiv4hi ((int16x4_t) __b,
+ return (uint16x4_t) __builtin_aarch64_cmgtuv4hi ((int16x4_t) __b,
(int16x4_t) __a);
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vclt_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t) __builtin_aarch64_cmhiv2si ((int32x2_t) __b,
+ return (uint32x2_t) __builtin_aarch64_cmgtuv2si ((int32x2_t) __b,
(int32x2_t) __a);
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vclt_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t) __builtin_aarch64_cmhidi ((int64x1_t) __b,
+ return (uint64x1_t) __builtin_aarch64_cmgtudi ((int64x1_t) __b,
(int64x1_t) __a);
}
@@ -20450,28 +19971,28 @@ vcltq_s64 (int64x2_t __a, int64x2_t __b)
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vcltq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t) __builtin_aarch64_cmhiv16qi ((int8x16_t) __b,
+ return (uint8x16_t) __builtin_aarch64_cmgtuv16qi ((int8x16_t) __b,
(int8x16_t) __a);
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vcltq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t) __builtin_aarch64_cmhiv8hi ((int16x8_t) __b,
+ return (uint16x8_t) __builtin_aarch64_cmgtuv8hi ((int16x8_t) __b,
(int16x8_t) __a);
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vcltq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t) __builtin_aarch64_cmhiv4si ((int32x4_t) __b,
+ return (uint32x4_t) __builtin_aarch64_cmgtuv4si ((int32x4_t) __b,
(int32x4_t) __a);
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vcltq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t) __builtin_aarch64_cmhiv2di ((int64x2_t) __b,
+ return (uint64x2_t) __builtin_aarch64_cmgtuv2di ((int64x2_t) __b,
(int64x2_t) __a);
}
@@ -20537,6 +20058,165 @@ vdupd_lane_u64 (uint64x2_t a, int const b)
return (uint64x1_t) __builtin_aarch64_dup_lanedi ((int64x2_t) a, b);
}
+/* vld1 */
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vld1_f32 (const float32_t *a)
+{
+ return __builtin_aarch64_ld1v2sf ((const __builtin_aarch64_simd_sf *) a);
+}
+
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vld1_f64 (const float64_t *a)
+{
+ return *a;
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vld1_p8 (const poly8_t *a)
+{
+ return (poly8x8_t)
+ __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__))
+vld1_p16 (const poly16_t *a)
+{
+ return (poly16x4_t)
+ __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vld1_s8 (const int8_t *a)
+{
+ return __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
+vld1_s16 (const int16_t *a)
+{
+ return __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
+vld1_s32 (const int32_t *a)
+{
+ return __builtin_aarch64_ld1v2si ((const __builtin_aarch64_simd_si *) a);
+}
+
+__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
+vld1_s64 (const int64_t *a)
+{
+ return *a;
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vld1_u8 (const uint8_t *a)
+{
+ return (uint8x8_t)
+ __builtin_aarch64_ld1v8qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
+vld1_u16 (const uint16_t *a)
+{
+ return (uint16x4_t)
+ __builtin_aarch64_ld1v4hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
+vld1_u32 (const uint32_t *a)
+{
+ return (uint32x2_t)
+ __builtin_aarch64_ld1v2si ((const __builtin_aarch64_simd_si *) a);
+}
+
+__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
+vld1_u64 (const uint64_t *a)
+{
+ return *a;
+}
+
+/* vld1q */
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vld1q_f32 (const float32_t *a)
+{
+ return __builtin_aarch64_ld1v4sf ((const __builtin_aarch64_simd_sf *) a);
+}
+
+__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
+vld1q_f64 (const float64_t *a)
+{
+ return __builtin_aarch64_ld1v2df ((const __builtin_aarch64_simd_df *) a);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vld1q_p8 (const poly8_t *a)
+{
+ return (poly8x16_t)
+ __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__))
+vld1q_p16 (const poly16_t *a)
+{
+ return (poly16x8_t)
+ __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vld1q_s8 (const int8_t *a)
+{
+ return __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
+vld1q_s16 (const int16_t *a)
+{
+ return __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
+vld1q_s32 (const int32_t *a)
+{
+ return __builtin_aarch64_ld1v4si ((const __builtin_aarch64_simd_si *) a);
+}
+
+__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
+vld1q_s64 (const int64_t *a)
+{
+ return __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vld1q_u8 (const uint8_t *a)
+{
+ return (uint8x16_t)
+ __builtin_aarch64_ld1v16qi ((const __builtin_aarch64_simd_qi *) a);
+}
+
+__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
+vld1q_u16 (const uint16_t *a)
+{
+ return (uint16x8_t)
+ __builtin_aarch64_ld1v8hi ((const __builtin_aarch64_simd_hi *) a);
+}
+
+__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
+vld1q_u32 (const uint32_t *a)
+{
+ return (uint32x4_t)
+ __builtin_aarch64_ld1v4si ((const __builtin_aarch64_simd_si *) a);
+}
+
+__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
+vld1q_u64 (const uint64_t *a)
+{
+ return (uint64x2_t)
+ __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a);
+}
+
/* vldn */
__extension__ static __inline int64x1x2_t __attribute__ ((__always_inline__))
@@ -24307,6 +23987,165 @@ vsrid_n_u64 (uint64x1_t __a, uint64x1_t __b, const int __c)
return (uint64x1_t) __builtin_aarch64_usri_ndi (__a, __b, __c);
}
+/* vst1 */
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_f32 (float32_t *a, float32x2_t b)
+{
+ __builtin_aarch64_st1v2sf ((__builtin_aarch64_simd_sf *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_f64 (float64_t *a, float64x1_t b)
+{
+ *a = b;
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_p8 (poly8_t *a, poly8x8_t b)
+{
+ __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a,
+ (int8x8_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_p16 (poly16_t *a, poly16x4_t b)
+{
+ __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a,
+ (int16x4_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_s8 (int8_t *a, int8x8_t b)
+{
+ __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_s16 (int16_t *a, int16x4_t b)
+{
+ __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_s32 (int32_t *a, int32x2_t b)
+{
+ __builtin_aarch64_st1v2si ((__builtin_aarch64_simd_si *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_s64 (int64_t *a, int64x1_t b)
+{
+ *a = b;
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_u8 (uint8_t *a, uint8x8_t b)
+{
+ __builtin_aarch64_st1v8qi ((__builtin_aarch64_simd_qi *) a,
+ (int8x8_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_u16 (uint16_t *a, uint16x4_t b)
+{
+ __builtin_aarch64_st1v4hi ((__builtin_aarch64_simd_hi *) a,
+ (int16x4_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_u32 (uint32_t *a, uint32x2_t b)
+{
+ __builtin_aarch64_st1v2si ((__builtin_aarch64_simd_si *) a,
+ (int32x2_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1_u64 (uint64_t *a, uint64x1_t b)
+{
+ *a = b;
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_f32 (float32_t *a, float32x4_t b)
+{
+ __builtin_aarch64_st1v4sf ((__builtin_aarch64_simd_sf *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_f64 (float64_t *a, float64x2_t b)
+{
+ __builtin_aarch64_st1v2df ((__builtin_aarch64_simd_df *) a, b);
+}
+
+/* vst1q */
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_p8 (poly8_t *a, poly8x16_t b)
+{
+ __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a,
+ (int8x16_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_p16 (poly16_t *a, poly16x8_t b)
+{
+ __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a,
+ (int16x8_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_s8 (int8_t *a, int8x16_t b)
+{
+ __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_s16 (int16_t *a, int16x8_t b)
+{
+ __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_s32 (int32_t *a, int32x4_t b)
+{
+ __builtin_aarch64_st1v4si ((__builtin_aarch64_simd_si *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_s64 (int64_t *a, int64x2_t b)
+{
+ __builtin_aarch64_st1v2di ((__builtin_aarch64_simd_di *) a, b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_u8 (uint8_t *a, uint8x16_t b)
+{
+ __builtin_aarch64_st1v16qi ((__builtin_aarch64_simd_qi *) a,
+ (int8x16_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_u16 (uint16_t *a, uint16x8_t b)
+{
+ __builtin_aarch64_st1v8hi ((__builtin_aarch64_simd_hi *) a,
+ (int16x8_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_u32 (uint32_t *a, uint32x4_t b)
+{
+ __builtin_aarch64_st1v4si ((__builtin_aarch64_simd_si *) a,
+ (int32x4_t) b);
+}
+
+__extension__ static __inline void __attribute__ ((__always_inline__))
+vst1q_u64 (uint64_t *a, uint64x2_t b)
+{
+ __builtin_aarch64_st1v2di ((__builtin_aarch64_simd_di *) a,
+ (int64x2_t) b);
+}
+
/* vstn */
__extension__ static __inline void
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index ce81ac5ce87..d19b26a6484 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -83,6 +83,9 @@
;; Vector Float modes.
(define_mode_iterator VDQF [V2SF V4SF V2DF])
+;; All Float modes.
+(define_mode_iterator VALLF [V2SF V4SF V2DF SF DF])
+
;; Vector Float modes with 2 elements.
(define_mode_iterator V2F [V2SF V2DF])
@@ -213,13 +216,6 @@
UNSPEC_URSHL ; Used in aarch64-simd.md.
UNSPEC_SQRSHL ; Used in aarch64-simd.md.
UNSPEC_UQRSHL ; Used in aarch64-simd.md.
- UNSPEC_CMEQ ; Used in aarch64-simd.md.
- UNSPEC_CMLE ; Used in aarch64-simd.md.
- UNSPEC_CMLT ; Used in aarch64-simd.md.
- UNSPEC_CMGE ; Used in aarch64-simd.md.
- UNSPEC_CMGT ; Used in aarch64-simd.md.
- UNSPEC_CMHS ; Used in aarch64-simd.md.
- UNSPEC_CMHI ; Used in aarch64-simd.md.
UNSPEC_SSLI ; Used in aarch64-simd.md.
UNSPEC_USLI ; Used in aarch64-simd.md.
UNSPEC_SSRI ; Used in aarch64-simd.md.
@@ -227,7 +223,6 @@
UNSPEC_SSHLL ; Used in aarch64-simd.md.
UNSPEC_USHLL ; Used in aarch64-simd.md.
UNSPEC_ADDP ; Used in aarch64-simd.md.
- UNSPEC_CMTST ; Used in aarch64-simd.md.
UNSPEC_FMAX ; Used in aarch64-simd.md.
UNSPEC_FMIN ; Used in aarch64-simd.md.
UNSPEC_BSL ; Used in aarch64-simd.md.
@@ -251,6 +246,7 @@
;; For scalar usage of vector/FP registers
(define_mode_attr v [(QI "b") (HI "h") (SI "s") (DI "d")
+ (SF "s") (DF "d")
(V8QI "") (V16QI "")
(V4HI "") (V8HI "")
(V2SI "") (V4SI "")
@@ -305,7 +301,8 @@
(V4SF ".4s") (V2DF ".2d")
(DI "") (SI "")
(HI "") (QI "")
- (TI "")])
+ (TI "") (SF "")
+ (DF "")])
;; Register suffix narrowed modes for VQN.
(define_mode_attr Vmntype [(V8HI ".8b") (V4SI ".4h")
@@ -444,7 +441,8 @@
(V2SI "V2SI") (V4SI "V4SI")
(DI "DI") (V2DI "V2DI")
(V2SF "V2SI") (V4SF "V4SI")
- (V2DF "V2DI")])
+ (V2DF "V2DI") (DF "DI")
+ (SF "SI")])
;; Lower case mode of results of comparison operations.
(define_mode_attr v_cmp_result [(V8QI "v8qi") (V16QI "v16qi")
@@ -452,7 +450,8 @@
(V2SI "v2si") (V4SI "v4si")
(DI "di") (V2DI "v2di")
(V2SF "v2si") (V4SF "v4si")
- (V2DF "v2di")])
+ (V2DF "v2di") (DF "di")
+ (SF "si")])
;; Vm for lane instructions is restricted to FP_LO_REGS.
(define_mode_attr vwx [(V4HI "x") (V8HI "x") (HI "x")
@@ -543,6 +542,12 @@
;; Code iterator for signed variants of vector saturating binary ops.
(define_code_iterator SBINQOPS [ss_plus ss_minus])
+;; Comparison operators for <F>CM.
+(define_code_iterator COMPARISONS [lt le eq ge gt])
+
+;; Unsigned comparison operators.
+(define_code_iterator UCOMPARISONS [ltu leu geu gtu])
+
;; -------------------------------------------------------------------
;; Code Attributes
;; -------------------------------------------------------------------
@@ -571,7 +576,28 @@
(eq "eq")
(ne "ne")
(lt "lt")
- (ge "ge")])
+ (ge "ge")
+ (le "le")
+ (gt "gt")
+ (ltu "ltu")
+ (leu "leu")
+ (geu "geu")
+ (gtu "gtu")])
+
+;; For comparison operators we use the FCM* and CM* instructions.
+;; As there are no CMLE or CMLT instructions which act on 3 vector
+;; operands, we must use CMGE or CMGT and swap the order of the
+;; source operands.
+
+(define_code_attr n_optab [(lt "gt") (le "ge") (eq "eq") (ge "ge") (gt "gt")
+ (ltu "hi") (leu "hs") (geu "hs") (gtu "hi")])
+(define_code_attr cmp_1 [(lt "2") (le "2") (eq "1") (ge "1") (gt "1")
+ (ltu "2") (leu "2") (geu "1") (gtu "1")])
+(define_code_attr cmp_2 [(lt "1") (le "1") (eq "2") (ge "2") (gt "2")
+ (ltu "1") (leu "1") (geu "2") (gtu "2")])
+
+(define_code_attr CMP [(lt "LT") (le "LE") (eq "EQ") (ge "GE") (gt "GT")
+ (ltu "LTU") (leu "LEU") (geu "GEU") (gtu "GTU")])
;; Optab prefix for sign/zero-extending operations
(define_code_attr su_optab [(sign_extend "") (zero_extend "u")
@@ -680,11 +706,6 @@
UNSPEC_SQSHRN UNSPEC_UQSHRN
UNSPEC_SQRSHRN UNSPEC_UQRSHRN])
-(define_int_iterator VCMP_S [UNSPEC_CMEQ UNSPEC_CMGE UNSPEC_CMGT
- UNSPEC_CMLE UNSPEC_CMLT])
-
-(define_int_iterator VCMP_U [UNSPEC_CMHS UNSPEC_CMHI UNSPEC_CMTST])
-
(define_int_iterator PERMUTE [UNSPEC_ZIP1 UNSPEC_ZIP2
UNSPEC_TRN1 UNSPEC_TRN2
UNSPEC_UZP1 UNSPEC_UZP2])
@@ -768,12 +789,6 @@
(UNSPEC_RADDHN2 "add")
(UNSPEC_RSUBHN2 "sub")])
-(define_int_attr cmp [(UNSPEC_CMGE "ge") (UNSPEC_CMGT "gt")
- (UNSPEC_CMLE "le") (UNSPEC_CMLT "lt")
- (UNSPEC_CMEQ "eq")
- (UNSPEC_CMHS "hs") (UNSPEC_CMHI "hi")
- (UNSPEC_CMTST "tst")])
-
(define_int_attr offsetlr [(UNSPEC_SSLI "1") (UNSPEC_USLI "1")
(UNSPEC_SSRI "0") (UNSPEC_USRI "0")])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 8f80b202811..8514e8f8fbd 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -31,6 +31,11 @@
(ior (match_operand 0 "register_operand")
(match_test "op == const0_rtx"))))
+(define_predicate "aarch64_reg_or_fp_zero"
+ (and (match_code "reg,subreg,const_double")
+ (ior (match_operand 0 "register_operand")
+ (match_test "aarch64_float_const_zero_rtx_p (op)"))))
+
(define_predicate "aarch64_reg_zero_or_m1_or_1"
(and (match_code "reg,subreg,const_int")
(ior (match_operand 0 "register_operand")
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 8f95317e083..5bd49f96daa 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -2659,6 +2659,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
cmp_mode = cmp_mode == DImode ? DFmode : DImode;
op0 = gen_lowpart (cmp_mode, tem);
op1 = CONST0_RTX (cmp_mode);
+ cmp = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
local_fast_math = 1;
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index edf850d9bff..46631b6e1a3 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4459,7 +4459,9 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
if (((pcum->aapcs_vfp_regs_free >> regno) & mask) == mask)
{
pcum->aapcs_vfp_reg_alloc = mask << regno;
- if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
+ if (mode == BLKmode
+ || (mode == TImode && ! TARGET_NEON)
+ || ! arm_hard_regno_mode_ok (FIRST_VFP_REGNUM + regno, mode))
{
int i;
int rcount = pcum->aapcs_vfp_rcount;
@@ -5423,7 +5425,8 @@ require_pic_register (void)
if (!crtl->uses_pic_offset_table)
{
gcc_assert (can_create_pseudo_p ());
- if (arm_pic_register != INVALID_REGNUM)
+ if (arm_pic_register != INVALID_REGNUM
+ && !(TARGET_THUMB1 && arm_pic_register > LAST_LO_REGNUM))
{
if (!cfun->machine->pic_reg)
cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
@@ -5449,7 +5452,12 @@ require_pic_register (void)
crtl->uses_pic_offset_table = 1;
start_sequence ();
- arm_load_pic_register (0UL);
+ if (TARGET_THUMB1 && arm_pic_register != INVALID_REGNUM
+ && arm_pic_register > LAST_LO_REGNUM)
+ emit_move_insn (cfun->machine->pic_reg,
+ gen_rtx_REG (Pmode, arm_pic_register));
+ else
+ arm_load_pic_register (0UL);
seq = get_insns ();
end_sequence ();
@@ -5707,6 +5715,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
emit_insn (gen_pic_add_dot_plus_four (pic_reg, pic_reg, labelno));
}
+ else if (arm_pic_register != INVALID_REGNUM
+ && arm_pic_register > LAST_LO_REGNUM
+ && REGNO (pic_reg) <= LAST_LO_REGNUM)
+ {
+ emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno));
+ emit_move_insn (gen_rtx_REG (Pmode, arm_pic_register), pic_reg);
+ emit_use (gen_rtx_REG (Pmode, arm_pic_register));
+ }
else
emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno));
}
@@ -7839,6 +7855,15 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
case PLUS:
case MINUS:
+ /* Thumb-1 needs two instructions to fulfill shiftadd/shiftsub0/shiftsub1
+ defined by RTL expansion, especially for the expansion of
+ multiplication. */
+ if ((GET_CODE (XEXP (x, 0)) == MULT
+ && power_of_two_operand (XEXP (XEXP (x,0),1), SImode))
+ || (GET_CODE (XEXP (x, 1)) == MULT
+ && power_of_two_operand (XEXP (XEXP (x, 1), 1), SImode)))
+ return COSTS_N_INSNS (2);
+ /* On purpose fall through for normal RTX. */
case COMPARE:
case NEG:
case NOT:
@@ -17464,7 +17489,8 @@ arm_expand_prologue (void)
}
}
- if (current_tune->prefer_ldrd_strd
+ if (TARGET_LDRD
+ && current_tune->prefer_ldrd_strd
&& !optimize_function_for_size_p (cfun))
{
if (TARGET_THUMB2)
@@ -21267,7 +21293,11 @@ arm_expand_neon_args (rtx target, int icode, int have_retval,
type_mode);
}
- op[argc] = expand_normal (arg[argc]);
+ /* Use EXPAND_MEMORY for NEON_ARG_MEMORY to ensure a MEM_P
+ be returned. */
+ op[argc] = expand_expr (arg[argc], NULL_RTX, VOIDmode,
+ (thisarg == NEON_ARG_MEMORY
+ ? EXPAND_MEMORY : EXPAND_NORMAL));
switch (thisarg)
{
@@ -21286,6 +21316,9 @@ arm_expand_neon_args (rtx target, int icode, int have_retval,
break;
case NEON_ARG_MEMORY:
+ /* Check if expand failed. */
+ if (op[argc] == const0_rtx)
+ return 0;
gcc_assert (MEM_P (op[argc]));
PUT_MODE (op[argc], mode[argc]);
/* ??? arm_neon.h uses the same built-in functions for signed
@@ -23543,6 +23576,7 @@ arm_expand_epilogue_apcs_frame (bool really_return)
num_regs = bit_count (saved_regs_mask);
if ((offsets->outgoing_args != (1 + num_regs)) || cfun->calls_alloca)
{
+ emit_insn (gen_blockage ());
/* Unwind the stack to just below the saved registers. */
emit_insn (gen_addsi3 (stack_pointer_rtx,
hard_frame_pointer_rtx,
@@ -23571,8 +23605,8 @@ arm_expand_epilogue_apcs_frame (bool really_return)
if (crtl->calls_eh_return)
emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (ARM_EH_STACKADJ_REGNUM)));
+ stack_pointer_rtx,
+ gen_rtx_REG (SImode, ARM_EH_STACKADJ_REGNUM)));
if (IS_STACKALIGN (func_type))
/* Restore the original stack pointer. Before prologue, the stack was
@@ -23778,7 +23812,8 @@ arm_expand_epilogue (bool really_return)
}
else
{
- if (current_tune->prefer_ldrd_strd
+ if (TARGET_LDRD
+ && current_tune->prefer_ldrd_strd
&& !optimize_function_for_size_p (cfun))
{
if (TARGET_THUMB2)
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index b3ad42b376f..df82c061fab 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -493,6 +493,10 @@
(UNSPEC_VRINTA "no") (UNSPEC_VRINTM "no")
(UNSPEC_VRINTR "yes") (UNSPEC_VRINTX "yes")])
+(define_int_attr vrint_conds [(UNSPEC_VRINTZ "nocond") (UNSPEC_VRINTP "unconditional")
+ (UNSPEC_VRINTA "unconditional") (UNSPEC_VRINTM "unconditional")
+ (UNSPEC_VRINTR "nocond") (UNSPEC_VRINTX "nocond")])
+
(define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p")
(UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m")
(UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")])
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 99fb5e89f41..86a5932d7b0 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -244,7 +244,7 @@
[(set (match_operand:VDQX 0 "neon_struct_or_register_operand")
(unspec:VDQX [(match_operand:VDQX 1 "neon_struct_or_register_operand")]
UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
{
/* This pattern is not permitted to fail during expansion: if both arguments
are non-registers (e.g. memory := constant, which can be created by the
@@ -258,7 +258,7 @@
[(set (match_operand:VDX 0 "neon_struct_operand" "=Um")
(unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vst1.<V_sz_elem>\t{%P1}, %A0"
[(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
@@ -266,7 +266,7 @@
[(set (match_operand:VDX 0 "s_register_operand" "=w")
(unspec:VDX [(match_operand:VDX 1 "neon_struct_operand" " Um")]
UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vld1.<V_sz_elem>\t{%P0}, %A1"
[(set_attr "neon_type" "neon_vld1_1_2_regs")])
@@ -274,7 +274,7 @@
[(set (match_operand:VQX 0 "neon_struct_operand" "=Um")
(unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")]
UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vst1.<V_sz_elem>\t{%q1}, %A0"
[(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")])
@@ -282,7 +282,7 @@
[(set (match_operand:VQX 0 "s_register_operand" "=w")
(unspec:VQX [(match_operand:VQX 1 "neon_struct_operand" " Um")]
UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vld1.<V_sz_elem>\t{%q0}, %A1"
[(set_attr "neon_type" "neon_vld1_1_2_regs")])
@@ -1732,6 +1732,7 @@
? 3 : 1;
rtx magic_rtx = GEN_INT (magic_word);
int inverse = 0;
+ int use_zero_form = 0;
int swap_bsl_operands = 0;
rtx mask = gen_reg_rtx (<V_cmp_result>mode);
rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
@@ -1742,12 +1743,16 @@
switch (GET_CODE (operands[3]))
{
case GE:
+ case GT:
case LE:
+ case LT:
case EQ:
- if (!REG_P (operands[5])
- && (operands[5] != CONST0_RTX (<MODE>mode)))
- operands[5] = force_reg (<MODE>mode, operands[5]);
- break;
+ if (operands[5] == CONST0_RTX (<MODE>mode))
+ {
+ use_zero_form = 1;
+ break;
+ }
+ /* Fall through. */
default:
if (!REG_P (operands[5]))
operands[5] = force_reg (<MODE>mode, operands[5]);
@@ -1798,7 +1803,26 @@
a GT b -> a GT b
a LE b -> b GE a
a LT b -> b GT a
- a EQ b -> a EQ b */
+ a EQ b -> a EQ b
+ Note that there also exist direct comparison against 0 forms,
+ so catch those as a special case. */
+ if (use_zero_form)
+ {
+ inverse = 0;
+ switch (GET_CODE (operands[3]))
+ {
+ case LT:
+ base_comparison = gen_neon_vclt<mode>;
+ break;
+ case LE:
+ base_comparison = gen_neon_vcle<mode>;
+ break;
+ default:
+ /* Do nothing, other zero form cases already have the correct
+ base_comparison. */
+ break;
+ }
+ }
if (!inverse)
emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 923624ffc6f..13e151f5ad8 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -1207,18 +1207,18 @@
(set_attr "type" "fcmpd")]
)
-;; Fixed point to floating point conversions.
+;; Fixed point to floating point conversions.
(define_code_iterator FCVT [unsigned_float float])
(define_code_attr FCVTI32typename [(unsigned_float "u32") (float "s32")])
(define_insn "*combine_vcvt_f32_<FCVTI32typename>"
[(set (match_operand:SF 0 "s_register_operand" "=t")
(mult:SF (FCVT:SF (match_operand:SI 1 "s_register_operand" "0"))
- (match_operand 2
+ (match_operand 2
"const_double_vcvt_power_of_two_reciprocal" "Dt")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math"
- "vcvt.f32.<FCVTI32typename>\\t%0, %1, %v2"
- [(set_attr "predicable" "no")
+ "vcvt%?.f32.<FCVTI32typename>\\t%0, %1, %v2"
+ [(set_attr "predicable" "yes")
(set_attr "type" "f_cvt")]
)
@@ -1227,15 +1227,16 @@
(define_insn "*combine_vcvt_f64_<FCVTI32typename>"
[(set (match_operand:DF 0 "s_register_operand" "=x,x,w")
(mult:DF (FCVT:DF (match_operand:SI 1 "s_register_operand" "r,t,r"))
- (match_operand 2
+ (match_operand 2
"const_double_vcvt_power_of_two_reciprocal" "Dt,Dt,Dt")))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP3 && !flag_rounding_math
&& !TARGET_VFP_SINGLE"
"@
- vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
- vmov.f32\\t%0, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2
- vmov.f64\\t%P0, %1, %1\;vcvt.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
- [(set_attr "predicable" "no")
+ vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
+ vmov%?.f32\\t%0, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2
+ vmov%?.f64\\t%P0, %1, %1\;vcvt%?.f64.<FCVTI32typename>\\t%P0, %P0, %v2"
+ [(set_attr "predicable" "yes")
+ (set_attr "ce_count" "2")
(set_attr "type" "f_cvt")
(set_attr "length" "8")]
)
@@ -1263,6 +1264,7 @@
"TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
"vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1"
[(set_attr "predicable" "<vrint_predicable>")
+ (set_attr "conds" "<vrint_conds>")
(set_attr "type" "f_rint<vfp_type>")]
)
@@ -1279,7 +1281,8 @@
(match_operand:SDF 2 "register_operand" "<F_constraint>")))]
"TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
"vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "f_minmax<vfp_type>")]
+ [(set_attr "type" "f_minmax<vfp_type>")
+ (set_attr "conds" "unconditional")]
)
(define_insn "smin<mode>3"
@@ -1288,7 +1291,8 @@
(match_operand:SDF 2 "register_operand" "<F_constraint>")))]
"TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
"vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "f_minmax<vfp_type>")]
+ [(set_attr "type" "f_minmax<vfp_type>")
+ (set_attr "conds" "unconditional")]
)
;; Unimplemented insns:
diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index 7d9b525ef6c..b2f0b9aa144 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -447,49 +447,18 @@
;; "roundqq3_const" "rounduqq3_const"
;; "roundhq3_const" "rounduhq3_const" "roundha3_const" "rounduha3_const"
;; "roundsq3_const" "roundusq3_const" "roundsa3_const" "roundusa3_const"
-(define_expand "round<mode>3_const"
- [(parallel [(match_operand:ALL124QA 0 "register_operand" "")
- (match_operand:ALL124QA 1 "register_operand" "")
- (match_operand:HI 2 "const_int_operand" "")])]
+(define_insn "round<mode>3_const"
+ [(set (match_operand:ALL124QA 0 "register_operand" "=d")
+ (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "n")
+ (const_int 0)]
+ UNSPEC_ROUND))]
""
{
- // The rounding point RP is $2. The smallest fractional
- // bit that is not cleared by the rounding is 2^(-RP).
-
- enum machine_mode imode = int_mode_for_mode (<MODE>mode);
- int fbit = (int) GET_MODE_FBIT (<MODE>mode);
-
- // Add-Saturate 1/2 * 2^(-RP)
-
- double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (operands[2]));
- rtx x_add = const_fixed_from_double_int (i_add, <MODE>mode);
-
- if (SIGNED_FIXED_POINT_MODE_P (<MODE>mode))
- emit_move_insn (operands[0],
- gen_rtx_SS_PLUS (<MODE>mode, operands[1], x_add));
- else
- emit_move_insn (operands[0],
- gen_rtx_US_PLUS (<MODE>mode, operands[1], x_add));
-
- // Keep all bits from RP and higher: ... 2^(-RP)
- // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
- // Rounding point ^^^^^^^
- // Added above ^^^^^^^^^
-
- rtx xreg = simplify_gen_subreg (imode, operands[0], <MODE>mode, 0);
- rtx xmask = immed_double_int_const (-i_add - i_add, imode);
-
- if (SImode == imode)
- emit_insn (gen_andsi3 (xreg, xreg, xmask));
- else if (HImode == imode)
- emit_insn (gen_andhi3 (xreg, xreg, xmask));
- else if (QImode == imode)
- emit_insn (gen_andqi3 (xreg, xreg, xmask));
- else
- gcc_unreachable();
-
- DONE;
- })
+ return avr_out_round (insn, operands);
+ }
+ [(set_attr "cc" "clobber")
+ (set_attr "adjust_len" "round")])
;; "*roundqq3.libgcc" "*rounduqq3.libgcc"
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 5246d063799..21ad26a6f34 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -86,7 +86,8 @@ extern int avr_starting_frame_offset (void);
extern void avr_output_addr_vec_elt (FILE *stream, int value);
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
-extern const char* avr_out_plus (rtx, rtx*, int* =NULL, int* =NULL);
+extern const char* avr_out_plus (rtx, rtx*, int* =NULL, int* =NULL, bool =true);
+extern const char* avr_out_round (rtx, rtx*, int* =NULL);
extern const char* avr_out_addto_sp (rtx*, int*);
extern const char* avr_out_xload (rtx, rtx*, int*);
extern const char* avr_out_movmem (rtx, rtx*, int*);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 86594e7c208..74872aa6c50 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -6232,11 +6232,14 @@ lshrsi3_out (rtx insn, rtx operands[], int *len)
the subtrahend in the original insn, provided it is a compile time constant.
In all other cases, SIGN is 0.
- Return "". */
+ If OUT_LABEL is true, print the final 0: label which is needed for
+ saturated addition / subtraction. The only case where OUT_LABEL = false
+ is useful is for saturated addition / subtraction performed during
+ fixed-point rounding, cf. `avr_out_round'. */
static void
avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
- enum rtx_code code_sat = UNKNOWN, int sign = 0)
+ enum rtx_code code_sat, int sign, bool out_label)
{
/* MODE of the operation. */
enum machine_mode mode = GET_MODE (xop[0]);
@@ -6675,7 +6678,8 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
"mov %r0+5,%0", xop, plen, 4);
}
- avr_asm_len ("0:", op, plen, 0);
+ if (out_label)
+ avr_asm_len ("0:", op, plen, 0);
}
@@ -6713,8 +6717,8 @@ avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
/* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
- INSN is a single_set insn with a binary operation as SET_SRC that is
- one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
+ INSN is a single_set insn or an insn pattern with a binary operation as
+ SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
XOP are the operands of INSN. In the case of 64-bit operations with
constant XOP[] has just one element: The summand/subtrahend in XOP[0].
@@ -6729,19 +6733,22 @@ avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
PLEN and PCC default to NULL.
+ OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
+
Return "" */
const char*
-avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
+avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
{
int cc_plus, cc_minus, cc_dummy;
int len_plus, len_minus;
rtx op[4];
- rtx xdest = SET_DEST (single_set (insn));
+ rtx xpattern = INSN_P (insn) ? single_set (insn) : insn;
+ rtx xdest = SET_DEST (xpattern);
enum machine_mode mode = GET_MODE (xdest);
enum machine_mode imode = int_mode_for_mode (mode);
int n_bytes = GET_MODE_SIZE (mode);
- enum rtx_code code_sat = GET_CODE (SET_SRC (single_set (insn)));
+ enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
enum rtx_code code
= (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
? PLUS : MINUS);
@@ -6756,7 +6763,7 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
if (n_bytes <= 4 && REG_P (xop[2]))
{
- avr_out_plus_1 (xop, plen, code, pcc, code_sat);
+ avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
return "";
}
@@ -6783,7 +6790,8 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
/* Saturations and 64-bit operations don't have a clobber operand.
For the other cases, the caller will provide a proper XOP[3]. */
- op[3] = PARALLEL == GET_CODE (PATTERN (insn)) ? xop[3] : NULL_RTX;
+ xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
+ op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
/* Saturation will need the sign of the original operand. */
@@ -6798,8 +6806,8 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
/* Work out the shortest sequence. */
- avr_out_plus_1 (op, &len_minus, MINUS, &cc_plus, code_sat, sign);
- avr_out_plus_1 (op, &len_plus, PLUS, &cc_minus, code_sat, sign);
+ avr_out_plus_1 (op, &len_minus, MINUS, &cc_plus, code_sat, sign, out_label);
+ avr_out_plus_1 (op, &len_plus, PLUS, &cc_minus, code_sat, sign, out_label);
if (plen)
{
@@ -6807,9 +6815,9 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
*pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
}
else if (len_minus <= len_plus)
- avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign);
+ avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
else
- avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign);
+ avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
return "";
}
@@ -6823,13 +6831,15 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc)
and return "". If PLEN == NULL, print assembler instructions to perform the
operation; otherwise, set *PLEN to the length of the instruction sequence
(in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
- register or SCRATCH if no clobber register is needed for the operation. */
+ register or SCRATCH if no clobber register is needed for the operation.
+ INSN is an INSN_P or a pattern of an insn. */
const char*
avr_out_bitop (rtx insn, rtx *xop, int *plen)
{
/* CODE and MODE of the operation. */
- enum rtx_code code = GET_CODE (SET_SRC (single_set (insn)));
+ rtx xpattern = INSN_P (insn) ? single_set (insn) : insn;
+ enum rtx_code code = GET_CODE (SET_SRC (xpattern));
enum machine_mode mode = GET_MODE (xop[0]);
/* Number of bytes to operate on. */
@@ -7332,6 +7342,67 @@ avr_out_fract (rtx insn, rtx operands[], bool intsigned, int *plen)
}
+/* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
+ XOP[2] is the rounding point, a CONST_INT. The function prints the
+ instruction sequence if PLEN = NULL and computes the length in words
+ of the sequence if PLEN != NULL. Most of this function deals with
+ preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
+
+const char*
+avr_out_round (rtx insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
+{
+ enum machine_mode mode = GET_MODE (xop[0]);
+ enum machine_mode imode = int_mode_for_mode (mode);
+ // The smallest fractional bit not cleared by the rounding is 2^(-RP).
+ int fbit = (int) GET_MODE_FBIT (mode);
+ double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
+ // Lengths of PLUS and AND parts.
+ int len_add = 0, *plen_add = plen ? &len_add : NULL;
+ int len_and = 0, *plen_and = plen ? &len_and : NULL;
+
+ // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
+ // the saturated addition so that we can emit the "rjmp 1f" before the
+ // "0:" below.
+
+ rtx xadd = const_fixed_from_double_int (i_add, mode);
+ rtx xpattern, xsrc, op[4];
+
+ xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
+ ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
+ : gen_rtx_US_PLUS (mode, xop[1], xadd);
+ xpattern = gen_rtx_SET (VOIDmode, xop[0], xsrc);
+
+ op[0] = xop[0];
+ op[1] = xop[1];
+ op[2] = xadd;
+ avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
+
+ avr_asm_len ("rjmp 1f" CR_TAB
+ "0:", NULL, plen_add, 1);
+
+ // Keep all bits from RP and higher: ... 2^(-RP)
+ // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
+ // Rounding point ^^^^^^^
+ // Added above ^^^^^^^^^
+ rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
+ rtx xmask = immed_double_int_const (-i_add - i_add, imode);
+
+ xpattern = gen_rtx_SET (VOIDmode, xreg, gen_rtx_AND (imode, xreg, xmask));
+
+ op[0] = xreg;
+ op[1] = xreg;
+ op[2] = xmask;
+ op[3] = gen_rtx_SCRATCH (QImode);
+ avr_out_bitop (xpattern, op, plen_and);
+ avr_asm_len ("1:", NULL, plen, 0);
+
+ if (plen)
+ *plen = len_add + len_and;
+
+ return "";
+}
+
+
/* Create RTL split patterns for byte sized rotate expressions. This
produces a series of move instructions and considers overlap situations.
Overlapping non-HImode operands need a scratch register. */
@@ -7540,6 +7611,7 @@ avr_adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
+ case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index e9f5d038f1f..f2681233ace 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -140,7 +140,7 @@
"out_bitop, plus, addto_sp,
tsthi, tstpsi, tstsi, compare, compare64, call,
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
- ufract, sfract,
+ ufract, sfract, round,
xload, lpm, movmem,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 8a7f0bfdd70..b3e9f0494b8 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -758,7 +758,7 @@
(match_operand:SI 1 "const_int_operand" ""))
(match_operand:SI 2 "register_operand" ""))])
(match_operand 3 "register_operand" ""))
- (set (match_operand:SI 4 "register_operand" "")
+ (set (match_operand:SI 4 "cris_nonsp_register_operand" "")
(plus:SI (mult:SI (match_dup 0)
(match_dup 1))
(match_dup 2)))])]
@@ -859,7 +859,7 @@
(match_operand:SI 0 "cris_bdap_operand" "")
(match_operand:SI 1 "cris_bdap_operand" ""))])
(match_operand 2 "register_operand" ""))
- (set (match_operand:SI 3 "register_operand" "")
+ (set (match_operand:SI 3 "cris_nonsp_register_operand" "")
(plus:SI (match_dup 0) (match_dup 1)))])]
"reload_completed && reg_overlap_mentioned_p (operands[3], operands[2])"
[(set (match_dup 4) (match_dup 2))
@@ -3960,7 +3960,7 @@
;; up.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
4 "cris_operand_extend_operator"
[(match_operand 1 "register_operand" "")
@@ -3990,7 +3990,7 @@
;; Call this op-extend-split-rx=rz
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
4 "cris_plus_or_bound_operator"
[(match_operand 1 "register_operand" "")
@@ -4018,7 +4018,7 @@
;; Call this op-extend-split-swapped
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
4 "cris_plus_or_bound_operator"
[(match_operator
@@ -4044,7 +4044,7 @@
;; bound. Call this op-extend-split-swapped-rx=rz.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
4 "cris_plus_or_bound_operator"
[(match_operator
@@ -4075,7 +4075,7 @@
;; Call this op-extend.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
3 "cris_orthogonal_operator"
[(match_operand 1 "register_operand" "")
@@ -4099,7 +4099,7 @@
;; Call this op-split-rx=rz
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
3 "cris_commutative_orth_op"
[(match_operand 2 "memory_operand" "")
@@ -4123,7 +4123,7 @@
;; Call this op-split-swapped.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
3 "cris_commutative_orth_op"
[(match_operand 1 "register_operand" "")
@@ -4146,7 +4146,7 @@
;; Call this op-split-swapped-rx=rz.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
3 "cris_orthogonal_operator"
[(match_operand 2 "memory_operand" "")
@@ -4555,10 +4555,11 @@
;; We're not allowed to generate copies of registers with different mode
;; until after reload; copying pseudos upsets reload. CVS as of
;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in
-;; cselib_invalidate_regno.
+;; cselib_invalidate_regno. Also, don't do this for the stack-pointer,
+;; as we don't want it set temporarily to an invalid value.
(define_split ; indir_to_reg_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operand 1 "indirect_operand" ""))]
"reload_completed
&& REG_P (operands[0])
@@ -4574,7 +4575,7 @@
;; As the above, but MOVS and MOVU.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "cris_nonsp_register_operand" "")
(match_operator
4 "cris_extend_operator"
[(match_operand 1 "indirect_operand" "")]))]
diff --git a/gcc/config/cris/predicates.md b/gcc/config/cris/predicates.md
index 040482ba9d1..2acd02f8ad9 100644
--- a/gcc/config/cris/predicates.md
+++ b/gcc/config/cris/predicates.md
@@ -76,6 +76,10 @@
(match_test "cris_simple_address_operand (XEXP (op, 0),
Pmode)"))))
+(define_predicate "cris_nonsp_register_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "op != stack_pointer_rtx")))
+
;; The caller needs to use :SI.
(define_predicate "cris_bdap_sign_extend_operand"
; Disabled until <URL:http://gcc.gnu.org/ml/gcc-patches/2005-10/msg01376.html>
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index 0755e94692a..70b7fb00959 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -25,6 +25,7 @@ extern void machopic_validate_stub_or_non_lazy_ptr (const char *);
extern void machopic_output_function_base_name (FILE *);
extern const char *machopic_indirection_name (rtx, bool);
extern const char *machopic_mcount_stub_name (void);
+extern bool machopic_should_output_picbase_label (void);
#ifdef RTX_CODE
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index a049a5d0796..e07fa4c8324 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -369,14 +369,13 @@ machopic_gen_offset (rtx orig)
static GTY(()) const char * function_base_func_name;
static GTY(()) int current_pic_label_num;
+static GTY(()) int emitted_pic_label_num;
-void
-machopic_output_function_base_name (FILE *file)
+static void
+update_pic_label_number_if_needed (void)
{
const char *current_name;
- /* If dynamic-no-pic is on, we should not get here. */
- gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
/* When we are generating _get_pc thunks within stubs, there is no current
function. */
if (current_function_decl)
@@ -394,7 +393,28 @@ machopic_output_function_base_name (FILE *file)
++current_pic_label_num;
function_base_func_name = "L_machopic_stub_dummy";
}
- fprintf (file, "L%011d$pb", current_pic_label_num);
+}
+
+void
+machopic_output_function_base_name (FILE *file)
+{
+ /* If dynamic-no-pic is on, we should not get here. */
+ gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
+
+ update_pic_label_number_if_needed ();
+ fprintf (file, "L%d$pb", current_pic_label_num);
+}
+
+bool
+machopic_should_output_picbase_label (void)
+{
+ update_pic_label_number_if_needed ();
+
+ if (current_pic_label_num == emitted_pic_label_num)
+ return false;
+
+ emitted_pic_label_num = current_pic_label_num;
+ return true;
}
/* The suffix attached to non-lazy pointer symbols. */
diff --git a/gcc/config/i386/bmiintrin.h b/gcc/config/i386/bmiintrin.h
index 0087f5c06e0..fc7f2ec2212 100644
--- a/gcc/config/i386/bmiintrin.h
+++ b/gcc/config/i386/bmiintrin.h
@@ -38,7 +38,6 @@ __tzcnt_u16 (unsigned short __X)
return __builtin_ctzs (__X);
}
-
extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__andn_u32 (unsigned int __X, unsigned int __Y)
{
@@ -52,23 +51,46 @@ __bextr_u32 (unsigned int __X, unsigned int __Y)
}
extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_bextr_u32 (unsigned int __X, unsigned int __Y, unsigned __Z)
+{
+ return __builtin_ia32_bextr_u32 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsi_u32 (unsigned int __X)
{
return __X & -__X;
}
extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsi_u32 (unsigned int __X)
+{
+ return __blsi_u32 (__X);
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsmsk_u32 (unsigned int __X)
{
return __X ^ (__X - 1);
}
extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsmsk_u32 (unsigned int __X)
+{
+ return __blsmsk_u32 (__X);
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsr_u32 (unsigned int __X)
{
return __X & (__X - 1);
}
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsr_u32 (unsigned int __X)
+{
+ return __blsr_u32 (__X);
+}
extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__tzcnt_u32 (unsigned int __X)
@@ -76,6 +98,12 @@ __tzcnt_u32 (unsigned int __X)
return __builtin_ctz (__X);
}
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_tzcnt_u32 (unsigned int __X)
+{
+ return __builtin_ctz (__X);
+}
+
#ifdef __x86_64__
extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
@@ -91,29 +119,59 @@ __bextr_u64 (unsigned long long __X, unsigned long long __Y)
}
extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_bextr_u64 (unsigned long long __X, unsigned int __Y, unsigned int __Z)
+{
+ return __builtin_ia32_bextr_u64 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsi_u64 (unsigned long long __X)
{
return __X & -__X;
}
extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsi_u64 (unsigned long long __X)
+{
+ return __blsi_u64 (__X);
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsmsk_u64 (unsigned long long __X)
{
return __X ^ (__X - 1);
}
extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsmsk_u64 (unsigned long long __X)
+{
+ return __blsmsk_u64 (__X);
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__blsr_u64 (unsigned long long __X)
{
return __X & (__X - 1);
}
extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_blsr_u64 (unsigned long long __X)
+{
+ return __blsr_u64 (__X);
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__tzcnt_u64 (unsigned long long __X)
{
return __builtin_ctzll (__X);
}
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_tzcnt_u64 (unsigned long long __X)
+{
+ return __builtin_ctzll (__X);
+}
+
#endif /* __x86_64__ */
#endif /* _BMIINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 55c389a16ee..70ad5c9ac3a 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -126,6 +126,18 @@ decode_caches_intel (unsigned reg, bool xeon_mp,
case 0x0c:
level1->sizekb = 16; level1->assoc = 4; level1->line = 32;
break;
+ case 0x0d:
+ level1->sizekb = 16; level1->assoc = 4; level1->line = 64;
+ break;
+ case 0x0e:
+ level1->sizekb = 24; level1->assoc = 6; level1->line = 64;
+ break;
+ case 0x21:
+ level2->sizekb = 256; level2->assoc = 8; level2->line = 64;
+ break;
+ case 0x24:
+ level2->sizekb = 1024; level2->assoc = 16; level2->line = 64;
+ break;
case 0x2c:
level1->sizekb = 32; level1->assoc = 8; level1->line = 64;
break;
@@ -162,6 +174,9 @@ decode_caches_intel (unsigned reg, bool xeon_mp,
case 0x45:
level2->sizekb = 2048; level2->assoc = 4; level2->line = 32;
break;
+ case 0x48:
+ level2->sizekb = 3072; level2->assoc = 12; level2->line = 64;
+ break;
case 0x49:
if (xeon_mp)
break;
@@ -203,6 +218,9 @@ decode_caches_intel (unsigned reg, bool xeon_mp,
case 0x7f:
level2->sizekb = 512; level2->assoc = 2; level2->line = 64;
break;
+ case 0x80:
+ level2->sizekb = 512; level2->assoc = 8; level2->line = 64;
+ break;
case 0x82:
level2->sizekb = 256; level2->assoc = 8; level2->line = 32;
break;
@@ -638,13 +656,18 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Atom. */
cpu = "atom";
break;
+ case 0x0f:
+ /* Merom. */
+ case 0x17:
+ case 0x1d:
+ /* Penryn. */
+ cpu = "core2";
+ break;
case 0x1a:
case 0x1e:
case 0x1f:
case 0x2e:
/* Nehalem. */
- cpu = "corei7";
- break;
case 0x25:
case 0x2c:
case 0x2f:
@@ -656,20 +679,25 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Sandy Bridge. */
cpu = "corei7-avx";
break;
- case 0x17:
- case 0x1d:
- /* Penryn. */
- cpu = "core2";
+ case 0x3a:
+ case 0x3e:
+ /* Ivy Bridge. */
+ cpu = "core-avx-i";
break;
- case 0x0f:
- /* Merom. */
- cpu = "core2";
+ case 0x3c:
+ case 0x45:
+ case 0x46:
+ /* Haswell. */
+ cpu = "core-avx2";
break;
default:
if (arch)
{
/* This is unknown family 0x6 CPU. */
- if (has_avx)
+ if (has_avx2)
+ /* Assume Haswell. */
+ cpu = "core-avx2";
+ else if (has_avx)
/* Assume Sandy Bridge. */
cpu = "corei7-avx";
else if (has_sse4_2)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 858dda3d75d..7ec198faa3b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1378,7 +1378,7 @@ struct processor_costs nocona_cost = {
8, /* MMX or SSE register to integer */
8, /* size of l1 cache. */
1024, /* size of l2 cache. */
- 128, /* size of prefetch block */
+ 64, /* size of prefetch block */
8, /* number of parallel prefetches */
1, /* Branch cost */
COSTS_N_INSNS (6), /* cost of FADD and FSUB insns. */
@@ -1894,10 +1894,10 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_AMDFAM10 | m_BDVER | m_GENERIC,
/* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL */
- m_COREI7 | m_AMDFAM10 | m_BDVER | m_BTVER,
+ m_COREI7 | m_HASWELL | m_AMDFAM10 | m_BDVER | m_BTVER,
/* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL */
- m_COREI7 | m_BDVER,
+ m_COREI7 | m_HASWELL| m_BDVER,
/* X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL */
m_BDVER ,
@@ -2409,6 +2409,7 @@ static tree ix86_veclibabi_acml (enum built_in_function, tree, tree);
/* Processor target table, indexed by processor number */
struct ptt
{
+ const char *const name; /* processor name */
const struct processor_costs *cost; /* Processor costs */
const int align_loop; /* Default alignments. */
const int align_loop_max_skip;
@@ -2417,66 +2418,31 @@ struct ptt
const int align_func;
};
+/* This table must be in sync with enum processor_type in i386.h. */
static const struct ptt processor_target_table[PROCESSOR_max] =
{
- {&i386_cost, 4, 3, 4, 3, 4},
- {&i486_cost, 16, 15, 16, 15, 16},
- {&pentium_cost, 16, 7, 16, 7, 16},
- {&pentiumpro_cost, 16, 15, 16, 10, 16},
- {&geode_cost, 0, 0, 0, 0, 0},
- {&k6_cost, 32, 7, 32, 7, 32},
- {&athlon_cost, 16, 7, 16, 7, 16},
- {&pentium4_cost, 0, 0, 0, 0, 0},
- {&k8_cost, 16, 7, 16, 7, 16},
- {&nocona_cost, 0, 0, 0, 0, 0},
- /* Core 2 */
- {&core_cost, 16, 10, 16, 10, 16},
- /* Core i7 */
- {&core_cost, 16, 10, 16, 10, 16},
- /* Core avx2 */
- {&core_cost, 16, 10, 16, 10, 16},
- {&generic32_cost, 16, 7, 16, 7, 16},
- {&generic64_cost, 16, 10, 16, 10, 16},
- {&amdfam10_cost, 32, 24, 32, 7, 32},
- {&bdver1_cost, 32, 24, 32, 7, 32},
- {&bdver2_cost, 32, 24, 32, 7, 32},
- {&bdver3_cost, 32, 24, 32, 7, 32},
- {&btver1_cost, 32, 24, 32, 7, 32},
- {&btver2_cost, 32, 24, 32, 7, 32},
- {&atom_cost, 16, 15, 16, 7, 16}
-};
-
-static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
-{
- "generic",
- "i386",
- "i486",
- "pentium",
- "pentium-mmx",
- "pentiumpro",
- "pentium2",
- "pentium3",
- "pentium4",
- "pentium-m",
- "prescott",
- "nocona",
- "core2",
- "corei7",
- "core-avx2",
- "atom",
- "geode",
- "k6",
- "k6-2",
- "k6-3",
- "athlon",
- "athlon-4",
- "k8",
- "amdfam10",
- "bdver1",
- "bdver2",
- "bdver3",
- "btver1",
- "btver2"
+ {"generic", &generic32_cost, 16, 7, 16, 7, 16},
+ {"generic", &generic64_cost, 16, 10, 16, 10, 16},
+ {"i386", &i386_cost, 4, 3, 4, 3, 4},
+ {"i486", &i486_cost, 16, 15, 16, 15, 16},
+ {"pentium", &pentium_cost, 16, 7, 16, 7, 16},
+ {"pentiumpro", &pentiumpro_cost, 16, 15, 16, 10, 16},
+ {"pentium4", &pentium4_cost, 0, 0, 0, 0, 0},
+ {"nocona", &nocona_cost, 0, 0, 0, 0, 0},
+ {"core2", &core_cost, 16, 10, 16, 10, 16},
+ {"corei7", &core_cost, 16, 10, 16, 10, 16},
+ {"core-avx2", &core_cost, 16, 10, 16, 10, 16},
+ {"atom", &atom_cost, 16, 15, 16, 7, 16},
+ {"geode", &geode_cost, 0, 0, 0, 0, 0},
+ {"k6", &k6_cost, 32, 7, 32, 7, 32},
+ {"athlon", &athlon_cost, 16, 7, 16, 7, 16},
+ {"k8", &k8_cost, 16, 7, 16, 7, 16},
+ {"amdfam10", &amdfam10_cost, 32, 24, 32, 7, 32},
+ {"bdver1", &bdver1_cost, 16, 10, 16, 7, 11},
+ {"bdver2", &bdver2_cost, 16, 10, 16, 7, 11},
+ {"bdver3", &bdver3_cost, 16, 10, 16, 7, 11},
+ {"btver1", &btver1_cost, 16, 10, 16, 7, 11},
+ {"btver2", &btver2_cost, 16, 10, 16, 7, 11}
};
static bool
@@ -2983,7 +2949,7 @@ ix86_option_override_internal (bool main_args_p)
{"bdver3", PROCESSOR_BDVER3, CPU_BDVER3,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
| PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
| PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE
| PTA_XSAVEOPT},
@@ -3125,7 +3091,8 @@ ix86_option_override_internal (bool main_args_p)
ix86_tune_string = ix86_arch_string;
if (!ix86_tune_string)
{
- ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT];
+ ix86_tune_string
+ = processor_target_table[TARGET_CPU_DEFAULT].name;
ix86_tune_defaulted = 1;
}
@@ -3768,24 +3735,19 @@ ix86_option_override_internal (bool main_args_p)
ix86_gen_leave = gen_leave_rex64;
if (Pmode == DImode)
{
- ix86_gen_monitor = gen_sse3_monitor64_di;
ix86_gen_tls_global_dynamic_64 = gen_tls_global_dynamic_64_di;
ix86_gen_tls_local_dynamic_base_64
= gen_tls_local_dynamic_base_64_di;
}
else
{
- ix86_gen_monitor = gen_sse3_monitor64_si;
ix86_gen_tls_global_dynamic_64 = gen_tls_global_dynamic_64_si;
ix86_gen_tls_local_dynamic_base_64
= gen_tls_local_dynamic_base_64_si;
}
}
else
- {
- ix86_gen_leave = gen_leave;
- ix86_gen_monitor = gen_sse3_monitor;
- }
+ ix86_gen_leave = gen_leave;
if (Pmode == DImode)
{
@@ -3797,6 +3759,7 @@ ix86_option_override_internal (bool main_args_p)
ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_di;
ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probedi;
ix86_gen_probe_stack_range = gen_probe_stack_rangedi;
+ ix86_gen_monitor = gen_sse3_monitor_di;
}
else
{
@@ -3808,6 +3771,7 @@ ix86_option_override_internal (bool main_args_p)
ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_si;
ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probesi;
ix86_gen_probe_stack_range = gen_probe_stack_rangesi;
+ ix86_gen_monitor = gen_sse3_monitor_si;
}
#ifdef USE_IX86_CLD
@@ -4081,19 +4045,15 @@ ix86_function_specific_print (FILE *file, int indent,
= ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_target_flags,
NULL, NULL, ptr->x_ix86_fpmath, false);
+ gcc_assert (ptr->arch < PROCESSOR_max);
fprintf (file, "%*sarch = %d (%s)\n",
indent, "",
- ptr->arch,
- ((ptr->arch < TARGET_CPU_DEFAULT_max)
- ? cpu_names[ptr->arch]
- : "<unknown>"));
+ ptr->arch, processor_target_table[ptr->arch].name);
+ gcc_assert (ptr->tune < PROCESSOR_max);
fprintf (file, "%*stune = %d (%s)\n",
indent, "",
- ptr->tune,
- ((ptr->tune < TARGET_CPU_DEFAULT_max)
- ? cpu_names[ptr->tune]
- : "<unknown>"));
+ ptr->tune, processor_target_table[ptr->tune].name);
fprintf (file, "%*sbranch_cost = %d\n", indent, "", ptr->branch_cost);
@@ -4691,6 +4651,28 @@ x86_64_elf_select_section (tree decl, int reloc,
return default_elf_select_section (decl, reloc, align);
}
+/* Select a set of attributes for section NAME based on the properties
+ of DECL and whether or not RELOC indicates that DECL's initializer
+ might contain runtime relocations. */
+
+static unsigned int ATTRIBUTE_UNUSED
+x86_64_elf_section_type_flags (tree decl, const char *name, int reloc)
+{
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+ if (decl == NULL_TREE
+ && (strcmp (name, ".ldata.rel.ro") == 0
+ || strcmp (name, ".ldata.rel.ro.local") == 0))
+ flags |= SECTION_RELRO;
+
+ if (strcmp (name, ".lbss") == 0
+ || strncmp (name, ".lbss.", 5) == 0
+ || strncmp (name, ".gnu.linkonce.lb.", 16) == 0)
+ flags |= SECTION_BSS;
+
+ return flags;
+}
+
/* Build up a unique section name, expressed as a
STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
RELOC indicates whether the initial value of EXP requires
@@ -5390,6 +5372,17 @@ ix86_legitimate_combined_insn (rtx insn)
bool win;
int j;
+ /* For pre-AVX disallow unaligned loads/stores where the
+ instructions don't support it. */
+ if (!TARGET_AVX
+ && VECTOR_MODE_P (GET_MODE (op))
+ && misaligned_operand (op, GET_MODE (op)))
+ {
+ int min_align = get_attr_ssememalign (insn);
+ if (min_align == 0)
+ return false;
+ }
+
/* A unary operator may be accepted by the predicate, but it
is irrelevant for matching constraints. */
if (UNARY_P (op))
@@ -5811,7 +5804,8 @@ type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum)
}
return TYPE_MODE (type);
}
- else if ((size == 8 || size == 16) && !TARGET_SSE)
+ else if (((size == 8 && TARGET_64BIT) || size == 16)
+ && !TARGET_SSE)
{
static bool warnedsse;
@@ -5823,10 +5817,21 @@ type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum)
warning (0, "SSE vector argument without SSE "
"enabled changes the ABI");
}
- return mode;
}
- else
- return mode;
+ else if ((size == 8 && !TARGET_64BIT) && !TARGET_MMX)
+ {
+ static bool warnedmmx;
+
+ if (cum
+ && !warnedmmx
+ && cum->warn_mmx)
+ {
+ warnedmmx = true;
+ warning (0, "MMX vector argument without MMX "
+ "enabled changes the ABI");
+ }
+ }
+ return mode;
}
gcc_unreachable ();
@@ -7216,9 +7221,15 @@ ix86_function_value_regno_p (const unsigned int regno)
switch (regno)
{
case AX_REG:
+ case DX_REG:
return true;
+ case DI_REG:
+ case SI_REG:
+ return TARGET_64BIT && ix86_abi != MS_ABI;
- case FIRST_FLOAT_REG:
+ /* Complex values are returned in %st(0)/%st(1) pair. */
+ case ST0_REG:
+ case ST1_REG:
/* TODO: The function should depend on current function ABI but
builtins.c would need updating then. Therefore we use the
default ABI. */
@@ -7226,10 +7237,12 @@ ix86_function_value_regno_p (const unsigned int regno)
return false;
return TARGET_FLOAT_RETURNS_IN_80387;
- case FIRST_SSE_REG:
+ /* Complex values are returned in %xmm0/%xmm1 pair. */
+ case XMM0_REG:
+ case XMM1_REG:
return TARGET_SSE;
- case FIRST_MMX_REG:
+ case MM0_REG:
if (TARGET_MACHO || TARGET_64BIT)
return false;
return TARGET_MMX;
@@ -8721,17 +8734,12 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
if (!flag_pic)
{
- xops[2] = gen_rtx_LABEL_REF (Pmode, label ? label : gen_label_rtx ());
+ if (TARGET_MACHO)
+ /* We don't need a pic base, we're not producing pic. */
+ gcc_unreachable ();
+ xops[2] = gen_rtx_LABEL_REF (Pmode, label ? label : gen_label_rtx ());
output_asm_insn ("mov%z0\t{%2, %0|%0, %2}", xops);
-
-#if TARGET_MACHO
- /* Output the Mach-O "canonical" label name ("Lxx$pb") here too. This
- is what will be referenced by the Mach-O PIC subsystem. */
- if (!label)
- ASM_OUTPUT_LABEL (asm_out_file, MACHOPIC_FUNCTION_BASE_NAME);
-#endif
-
targetm.asm_out.internal_label (asm_out_file, "L",
CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
}
@@ -8744,12 +8752,18 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
xops[2] = gen_rtx_MEM (QImode, xops[2]);
output_asm_insn ("call\t%X2", xops);
- /* Output the Mach-O "canonical" label name ("Lxx$pb") here too. This
- is what will be referenced by the Mach-O PIC subsystem. */
+
#if TARGET_MACHO
- if (!label)
+ /* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here.
+ This is what will be referenced by the Mach-O PIC subsystem. */
+ if (machopic_should_output_picbase_label () || !label)
ASM_OUTPUT_LABEL (asm_out_file, MACHOPIC_FUNCTION_BASE_NAME);
- else
+
+ /* When we are restoring the pic base at the site of a nonlocal label,
+ and we decided to emit the pic base above, we will still output a
+ local label used for calculating the correction offset (even though
+ the offset will be 0 in that case). */
+ if (label)
targetm.asm_out.internal_label (asm_out_file, "L",
CODE_LABEL_NUMBER (label));
#endif
@@ -8831,7 +8845,8 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return)
&& (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM)
|| crtl->profile
|| crtl->calls_eh_return
- || crtl->uses_const_pool))
+ || crtl->uses_const_pool
+ || cfun->has_nonlocal_label))
return ix86_select_alt_pic_regnum () == INVALID_REGNUM;
if (crtl->calls_eh_return && maybe_eh_return)
@@ -10539,18 +10554,21 @@ ix86_expand_prologue (void)
}
m->fs.sp_offset += allocate;
+ /* Use stack_pointer_rtx for relative addressing so that code
+ works for realigned stack, too. */
if (r10_live && eax_live)
{
- t = choose_baseaddr (m->fs.sp_offset - allocate);
+ t = plus_constant (Pmode, stack_pointer_rtx, allocate);
emit_move_insn (gen_rtx_REG (word_mode, R10_REG),
gen_frame_mem (word_mode, t));
- t = choose_baseaddr (m->fs.sp_offset - allocate - UNITS_PER_WORD);
+ t = plus_constant (Pmode, stack_pointer_rtx,
+ allocate - UNITS_PER_WORD);
emit_move_insn (gen_rtx_REG (word_mode, AX_REG),
gen_frame_mem (word_mode, t));
}
else if (eax_live || r10_live)
{
- t = choose_baseaddr (m->fs.sp_offset - allocate);
+ t = plus_constant (Pmode, stack_pointer_rtx, allocate);
emit_move_insn (gen_rtx_REG (word_mode,
(eax_live ? AX_REG : R10_REG)),
gen_frame_mem (word_mode, t));
@@ -11540,30 +11558,6 @@ ix86_live_on_entry (bitmap regs)
}
}
-/* Determine if op is suitable SUBREG RTX for address. */
-
-static bool
-ix86_address_subreg_operand (rtx op)
-{
- enum machine_mode mode;
-
- if (!REG_P (op))
- return false;
-
- mode = GET_MODE (op);
-
- if (GET_MODE_CLASS (mode) != MODE_INT)
- return false;
-
- /* Don't allow SUBREGs that span more than a word. It can lead to spill
- failures when the register is one word out of a two word structure. */
- if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
- return false;
-
- /* Allow only SUBREGs of non-eliminable hard registers. */
- return register_no_elim_operand (op, mode);
-}
-
/* Extract the parts of an RTL expression that is a valid memory address
for an instruction. Return 0 if the structure of the address is
grossly off. Return -1 if the address contains ASHIFT, so it is not
@@ -11620,7 +11614,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
base = addr;
else if (GET_CODE (addr) == SUBREG)
{
- if (ix86_address_subreg_operand (SUBREG_REG (addr)))
+ if (REG_P (SUBREG_REG (addr)))
base = addr;
else
return 0;
@@ -11684,7 +11678,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
break;
case SUBREG:
- if (!ix86_address_subreg_operand (SUBREG_REG (op)))
+ if (!REG_P (SUBREG_REG (op)))
return 0;
/* FALLTHRU */
@@ -11729,19 +11723,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
scale = 1 << scale;
retval = -1;
}
- else if (CONST_INT_P (addr))
- {
- if (!x86_64_immediate_operand (addr, VOIDmode))
- return 0;
-
- /* Constant addresses are sign extended to 64bit, we have to
- prevent addresses from 0x80000000 to 0xffffffff in x32 mode. */
- if (TARGET_X32
- && val_signbit_known_set_p (SImode, INTVAL (addr)))
- return 0;
-
- disp = addr;
- }
else
disp = addr; /* displacement */
@@ -11750,18 +11731,12 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
if (REG_P (index))
;
else if (GET_CODE (index) == SUBREG
- && ix86_address_subreg_operand (SUBREG_REG (index)))
+ && REG_P (SUBREG_REG (index)))
;
else
return 0;
}
-/* Address override works only on the (%reg) part of %fs:(%reg). */
- if (seg != SEG_DEFAULT
- && ((base && GET_MODE (base) != word_mode)
- || (index && GET_MODE (index) != word_mode)))
- return 0;
-
/* Extract the integral value of scale. */
if (scale_rtx)
{
@@ -12237,6 +12212,45 @@ ix86_legitimize_reload_address (rtx x,
return false;
}
+/* Determine if op is suitable RTX for an address register.
+ Return naked register if a register or a register subreg is
+ found, otherwise return NULL_RTX. */
+
+static rtx
+ix86_validate_address_register (rtx op)
+{
+ enum machine_mode mode = GET_MODE (op);
+
+ /* Only SImode or DImode registers can form the address. */
+ if (mode != SImode && mode != DImode)
+ return NULL_RTX;
+
+ if (REG_P (op))
+ return op;
+ else if (GET_CODE (op) == SUBREG)
+ {
+ rtx reg = SUBREG_REG (op);
+
+ if (!REG_P (reg))
+ return NULL_RTX;
+
+ mode = GET_MODE (reg);
+
+ /* Don't allow SUBREGs that span more than a word. It can
+ lead to spill failures when the register is one word out
+ of a two word structure. */
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ return NULL_RTX;
+
+ /* Allow only SUBREGs of non-eliminable hard registers. */
+ if (register_no_elim_operand (reg, mode))
+ return reg;
+ }
+
+ /* Op is not a register. */
+ return NULL_RTX;
+}
+
/* Recognizes RTL expressions that are valid memory addresses for an
instruction. The MODE argument is the machine mode for the MEM
expression that wants to use this address.
@@ -12252,6 +12266,7 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
struct ix86_address parts;
rtx base, index, disp;
HOST_WIDE_INT scale;
+ enum ix86_address_seg seg;
if (ix86_decompose_address (addr, &parts) <= 0)
/* Decomposition failed. */
@@ -12261,21 +12276,14 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
index = parts.index;
disp = parts.disp;
scale = parts.scale;
+ seg = parts.seg;
/* Validate base register. */
if (base)
{
- rtx reg;
-
- if (REG_P (base))
- reg = base;
- else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base)))
- reg = SUBREG_REG (base);
- else
- /* Base is not a register. */
- return false;
+ rtx reg = ix86_validate_address_register (base);
- if (GET_MODE (base) != SImode && GET_MODE (base) != DImode)
+ if (reg == NULL_RTX)
return false;
if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
@@ -12287,17 +12295,9 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
/* Validate index register. */
if (index)
{
- rtx reg;
+ rtx reg = ix86_validate_address_register (index);
- if (REG_P (index))
- reg = index;
- else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index)))
- reg = SUBREG_REG (index);
- else
- /* Index is not a register. */
- return false;
-
- if (GET_MODE (index) != SImode && GET_MODE (index) != DImode)
+ if (reg == NULL_RTX)
return false;
if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
@@ -12311,6 +12311,12 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
&& GET_MODE (base) != GET_MODE (index))
return false;
+ /* Address override works only on the (%reg) part of %fs:(%reg). */
+ if (seg != SEG_DEFAULT
+ && ((base && GET_MODE (base) != word_mode)
+ || (index && GET_MODE (index) != word_mode)))
+ return false;
+
/* Validate scale factor. */
if (scale != 1)
{
@@ -12432,6 +12438,12 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
&& !x86_64_immediate_operand (disp, VOIDmode))
/* Displacement is out of range. */
return false;
+ /* In x32 mode, constant addresses are sign extended to 64bit, so
+ we have to prevent addresses from 0x80000000 to 0xffffffff. */
+ else if (TARGET_X32 && !(index || base)
+ && CONST_INT_P (disp)
+ && val_signbit_known_set_p (SImode, INTVAL (disp)))
+ return false;
}
/* Everything looks valid. */
@@ -13596,21 +13608,29 @@ ix86_delegitimize_address (rtx x)
x = replace_equiv_address_nv (orig_x, x);
return x;
}
- if (GET_CODE (x) != CONST
- || GET_CODE (XEXP (x, 0)) != UNSPEC
- || (XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
- && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL)
- || (!MEM_P (orig_x) && XINT (XEXP (x, 0), 1) != UNSPEC_PCREL))
- return ix86_delegitimize_tls_address (orig_x);
- x = XVECEXP (XEXP (x, 0), 0, 0);
- if (GET_MODE (orig_x) != GET_MODE (x) && MEM_P (orig_x))
+
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == UNSPEC
+ && (XINT (XEXP (x, 0), 1) == UNSPEC_GOTPCREL
+ || XINT (XEXP (x, 0), 1) == UNSPEC_PCREL)
+ && (MEM_P (orig_x) || XINT (XEXP (x, 0), 1) == UNSPEC_PCREL))
{
- x = simplify_gen_subreg (GET_MODE (orig_x), x,
- GET_MODE (x), 0);
- if (x == NULL_RTX)
- return orig_x;
+ x = XVECEXP (XEXP (x, 0), 0, 0);
+ if (GET_MODE (orig_x) != GET_MODE (x) && MEM_P (orig_x))
+ {
+ x = simplify_gen_subreg (GET_MODE (orig_x), x,
+ GET_MODE (x), 0);
+ if (x == NULL_RTX)
+ return orig_x;
+ }
+ return x;
}
- return x;
+
+ if (ix86_cmodel != CM_MEDIUM_PIC && ix86_cmodel != CM_LARGE_PIC)
+ return ix86_delegitimize_tls_address (orig_x);
+
+ /* Fall thru into the code shared with -m32 for -mcmodel=large -fpic
+ and -mcmodel=medium -fpic. */
}
if (GET_CODE (x) != PLUS
@@ -13647,10 +13667,12 @@ ix86_delegitimize_address (rtx x)
if (GET_CODE (x) == UNSPEC
&& ((XINT (x, 1) == UNSPEC_GOT && MEM_P (orig_x) && !addend)
- || (XINT (x, 1) == UNSPEC_GOTOFF && !MEM_P (orig_x))))
+ || (XINT (x, 1) == UNSPEC_GOTOFF && !MEM_P (orig_x))
+ || (XINT (x, 1) == UNSPEC_PLTOFF && ix86_cmodel == CM_LARGE_PIC
+ && !MEM_P (orig_x) && !addend)))
result = XVECEXP (x, 0, 0);
- if (TARGET_MACHO && darwin_local_data_pic (x)
+ if (!TARGET_64BIT && TARGET_MACHO && darwin_local_data_pic (x)
&& !MEM_P (orig_x))
result = XVECEXP (x, 0, 0);
@@ -13786,8 +13808,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
Those same assemblers have the same but opposite lossage on cmov. */
if (mode == CCmode)
suffix = fp ? "nbe" : "a";
- else if (mode == CCCmode)
- suffix = "b";
else
gcc_unreachable ();
break;
@@ -13809,8 +13829,12 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
}
break;
case LTU:
- gcc_assert (mode == CCmode || mode == CCCmode);
- suffix = "b";
+ if (mode == CCmode)
+ suffix = "b";
+ else if (mode == CCCmode)
+ suffix = "c";
+ else
+ gcc_unreachable ();
break;
case GE:
switch (mode)
@@ -13830,20 +13854,20 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
}
break;
case GEU:
- /* ??? As above. */
- gcc_assert (mode == CCmode || mode == CCCmode);
- suffix = fp ? "nb" : "ae";
+ if (mode == CCmode)
+ suffix = fp ? "nb" : "ae";
+ else if (mode == CCCmode)
+ suffix = "nc";
+ else
+ gcc_unreachable ();
break;
case LE:
gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode);
suffix = "le";
break;
case LEU:
- /* ??? As above. */
if (mode == CCmode)
suffix = "be";
- else if (mode == CCCmode)
- suffix = fp ? "nb" : "ae";
else
gcc_unreachable ();
break;
@@ -15309,7 +15333,7 @@ ix86_avx_u128_mode_needed (rtx insn)
rtx arg = XEXP (XEXP (link, 0), 0);
if (ix86_check_avx256_register (&arg, NULL))
- return AVX_U128_ANY;
+ return AVX_U128_DIRTY;
}
}
@@ -15429,8 +15453,8 @@ ix86_avx_u128_mode_after (int mode, rtx insn)
{
bool avx_reg256_found = false;
note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found);
- if (!avx_reg256_found)
- return AVX_U128_CLEAN;
+
+ return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
}
/* Otherwise, return current mode. Remember that if insn
@@ -18455,12 +18479,7 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
return CCmode;
case GTU: /* CF=0 & ZF=0 */
case LEU: /* CF=1 | ZF=1 */
- /* Detect overflow checks. They need just the carry flag. */
- if (GET_CODE (op0) == MINUS
- && rtx_equal_p (op1, XEXP (op0, 0)))
- return CCCmode;
- else
- return CCmode;
+ return CCmode;
/* Codes possibly doable only with sign flag when
comparing against zero. */
case GE: /* SF=OF or SF=0 */
@@ -21709,6 +21728,21 @@ counter_mode (rtx count_exp)
return SImode;
}
+/* Copy the address to a Pmode register. This is used for x32 to
+ truncate DImode TLS address to a SImode register. */
+
+static rtx
+ix86_copy_addr_to_reg (rtx addr)
+{
+ if (GET_MODE (addr) == Pmode)
+ return copy_addr_to_reg (addr);
+ else
+ {
+ gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
+ return gen_rtx_SUBREG (SImode, copy_to_mode_reg (DImode, addr), 0);
+ }
+}
+
/* When SRCPTR is non-NULL, output simple loop to move memory
pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
@@ -22697,8 +22731,8 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
gcc_assert (alg != no_stringop);
if (!count)
count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
- destreg = copy_addr_to_reg (XEXP (dst, 0));
- srcreg = copy_addr_to_reg (XEXP (src, 0));
+ destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
+ srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
switch (alg)
{
case libcall:
@@ -23088,7 +23122,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
gcc_assert (alg != no_stringop);
if (!count)
count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp);
- destreg = copy_addr_to_reg (XEXP (dst, 0));
+ destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
switch (alg)
{
case libcall:
@@ -24957,7 +24991,8 @@ ix86_constant_alignment (tree exp, int align)
int
ix86_data_alignment (tree type, int align)
{
- int max_align = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT);
+ int max_align
+ = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT);
if (AGGREGATE_TYPE_P (type)
&& TYPE_SIZE (type)
@@ -27953,8 +27988,8 @@ static const struct builtin_description bdesc_multi_arg[] =
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv8hi3, "__builtin_ia32_vpshlw", IX86_BUILTIN_VPSHLW, UNKNOWN, (int)MULTI_ARG_2_HI },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv16qi3, "__builtin_ia32_vpshlb", IX86_BUILTIN_VPSHLB, UNKNOWN, (int)MULTI_ARG_2_QI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_2_SF },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_2_DF },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_1_SF },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_1_DF },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv4sf2, "__builtin_ia32_vfrczps", IX86_BUILTIN_VFRCZPS, UNKNOWN, (int)MULTI_ARG_1_SF },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv2df2, "__builtin_ia32_vfrczpd", IX86_BUILTIN_VFRCZPD, UNKNOWN, (int)MULTI_ARG_1_DF },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv8sf2, "__builtin_ia32_vfrczps256", IX86_BUILTIN_VFRCZPS256, UNKNOWN, (int)MULTI_ARG_1_SF2 },
@@ -28935,10 +28970,11 @@ dispatch_function_versions (tree dispatch_decl,
if (predicate_chain == NULL_TREE)
continue;
+ function_version_info [actual_versions].version_decl = version_decl;
+ function_version_info [actual_versions].predicate_chain
+ = predicate_chain;
+ function_version_info [actual_versions].dispatch_priority = priority;
actual_versions++;
- function_version_info [ix - 1].version_decl = version_decl;
- function_version_info [ix - 1].predicate_chain = predicate_chain;
- function_version_info [ix - 1].dispatch_priority = priority;
}
/* Sort the versions according to descending order of dispatch priority. The
@@ -31213,11 +31249,12 @@ ix86_expand_args_builtin (const struct builtin_description *d,
static rtx
ix86_expand_special_args_builtin (const struct builtin_description *d,
- tree exp, rtx target)
+ tree exp, rtx target)
{
tree arg;
rtx pat, op;
unsigned int i, nargs, arg_adjust, memory;
+ bool aligned_mem = false;
struct
{
rtx op;
@@ -31263,6 +31300,15 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
nargs = 1;
klass = load;
memory = 0;
+ switch (icode)
+ {
+ case CODE_FOR_sse4_1_movntdqa:
+ case CODE_FOR_avx2_movntdqa:
+ aligned_mem = true;
+ break;
+ default:
+ break;
+ }
break;
case VOID_FTYPE_PV2SF_V4SF:
case VOID_FTYPE_PV4DI_V4DI:
@@ -31280,6 +31326,26 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
klass = store;
/* Reserve memory operand for target. */
memory = ARRAY_SIZE (args);
+ switch (icode)
+ {
+ /* These builtins and instructions require the memory
+ to be properly aligned. */
+ case CODE_FOR_avx_movntv4di:
+ case CODE_FOR_sse2_movntv2di:
+ case CODE_FOR_avx_movntv8sf:
+ case CODE_FOR_sse_movntv4sf:
+ case CODE_FOR_sse4a_vmmovntv4sf:
+ case CODE_FOR_avx_movntv4df:
+ case CODE_FOR_sse2_movntv2df:
+ case CODE_FOR_sse4a_vmmovntv2df:
+ case CODE_FOR_sse2_movntidi:
+ case CODE_FOR_sse_movntq:
+ case CODE_FOR_sse2_movntisi:
+ aligned_mem = true;
+ break;
+ default:
+ break;
+ }
break;
case V4SF_FTYPE_V4SF_PCV2SF:
case V2DF_FTYPE_V2DF_PCDOUBLE:
@@ -31336,6 +31402,17 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
{
op = force_reg (Pmode, convert_to_mode (Pmode, op, 1));
target = gen_rtx_MEM (tmode, op);
+ /* target at this point has just BITS_PER_UNIT MEM_ALIGN
+ on it. Try to improve it using get_pointer_alignment,
+ and if the special builtin is one that requires strict
+ mode alignment, also from it's GET_MODE_ALIGNMENT.
+ Failure to do so could lead to ix86_legitimate_combined_insn
+ rejecting all changes to such insns. */
+ unsigned int align = get_pointer_alignment (arg);
+ if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
+ align = GET_MODE_ALIGNMENT (tmode);
+ if (MEM_ALIGN (target) < align)
+ set_mem_align (target, align);
}
else
target = force_reg (tmode, op);
@@ -31381,8 +31458,17 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
/* This must be the memory operand. */
op = force_reg (Pmode, convert_to_mode (Pmode, op, 1));
op = gen_rtx_MEM (mode, op);
- gcc_assert (GET_MODE (op) == mode
- || GET_MODE (op) == VOIDmode);
+ /* op at this point has just BITS_PER_UNIT MEM_ALIGN
+ on it. Try to improve it using get_pointer_alignment,
+ and if the special builtin is one that requires strict
+ mode alignment, also from it's GET_MODE_ALIGNMENT.
+ Failure to do so could lead to ix86_legitimate_combined_insn
+ rejecting all changes to such insns. */
+ unsigned int align = get_pointer_alignment (arg);
+ if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
+ align = GET_MODE_ALIGNMENT (mode);
+ if (MEM_ALIGN (op) < align)
+ set_mem_align (op, align);
}
else
{
@@ -33847,10 +33933,10 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
{
/* We implement the move patterns for all vector modes into and
out of SSE registers, even when no operation instructions
- are available. OImode move is available only when AVX is
- enabled. */
- return ((TARGET_AVX && mode == OImode)
- || VALID_AVX256_REG_MODE (mode)
+ are available. OImode and AVX modes are available only when
+ AVX is enabled. */
+ return ((TARGET_AVX
+ && VALID_AVX256_REG_OR_OI_MODE (mode))
|| VALID_SSE_REG_MODE (mode)
|| VALID_SSE2_REG_MODE (mode)
|| VALID_MMX_REG_MODE (mode)
@@ -35200,7 +35286,10 @@ ix86_avoid_jump_mispredicts (void)
The smallest offset in the page INSN can start is the case where START
ends on the offset 0. Offset of INSN is then NBYTES - sizeof (INSN).
We add p2align to 16byte window with maxskip 15 - NBYTES + sizeof (INSN).
- */
+
+ Don't consider asm goto as jump, while it can contain a jump, it doesn't
+ have to, control transfer to label(s) can be performed through other
+ means, and also we estimate minimum length of all asm stmts as 0. */
for (insn = start; insn; insn = NEXT_INSN (insn))
{
int min_size;
@@ -35228,6 +35317,7 @@ ix86_avoid_jump_mispredicts (void)
{
start = NEXT_INSN (start);
if ((JUMP_P (start)
+ && asm_noperands (PATTERN (start)) < 0
&& GET_CODE (PATTERN (start)) != ADDR_VEC
&& GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC)
|| CALL_P (start))
@@ -35246,6 +35336,7 @@ ix86_avoid_jump_mispredicts (void)
fprintf (dump_file, "Insn %i estimated to %i bytes\n",
INSN_UID (insn), min_size);
if ((JUMP_P (insn)
+ && asm_noperands (PATTERN (insn)) < 0
&& GET_CODE (PATTERN (insn)) != ADDR_VEC
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
|| CALL_P (insn))
@@ -35257,6 +35348,7 @@ ix86_avoid_jump_mispredicts (void)
{
start = NEXT_INSN (start);
if ((JUMP_P (start)
+ && asm_noperands (PATTERN (start)) < 0
&& GET_CODE (PATTERN (start)) != ADDR_VEC
&& GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC)
|| CALL_P (start))
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index a69862c549f..335cf611d79 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -197,10 +197,10 @@ extern const struct processor_costs ix86_size_cost;
/* Macros used in the machine description to test the flags. */
-/* configure can arrange to make this 2, to force a 486. */
+/* configure can arrange to change it. */
#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT TARGET_CPU_DEFAULT_generic
+#define TARGET_CPU_DEFAULT PROCESSOR_GENERIC32
#endif
#ifndef TARGET_FPMATH_DEFAULT
@@ -591,43 +591,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* Target Pragmas. */
#define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
-enum target_cpu_default
-{
- TARGET_CPU_DEFAULT_generic = 0,
-
- TARGET_CPU_DEFAULT_i386,
- TARGET_CPU_DEFAULT_i486,
- TARGET_CPU_DEFAULT_pentium,
- TARGET_CPU_DEFAULT_pentium_mmx,
- TARGET_CPU_DEFAULT_pentiumpro,
- TARGET_CPU_DEFAULT_pentium2,
- TARGET_CPU_DEFAULT_pentium3,
- TARGET_CPU_DEFAULT_pentium4,
- TARGET_CPU_DEFAULT_pentium_m,
- TARGET_CPU_DEFAULT_prescott,
- TARGET_CPU_DEFAULT_nocona,
- TARGET_CPU_DEFAULT_core2,
- TARGET_CPU_DEFAULT_corei7,
- TARGET_CPU_DEFAULT_haswell,
- TARGET_CPU_DEFAULT_atom,
-
- TARGET_CPU_DEFAULT_geode,
- TARGET_CPU_DEFAULT_k6,
- TARGET_CPU_DEFAULT_k6_2,
- TARGET_CPU_DEFAULT_k6_3,
- TARGET_CPU_DEFAULT_athlon,
- TARGET_CPU_DEFAULT_athlon_sse,
- TARGET_CPU_DEFAULT_k8,
- TARGET_CPU_DEFAULT_amdfam10,
- TARGET_CPU_DEFAULT_bdver1,
- TARGET_CPU_DEFAULT_bdver2,
- TARGET_CPU_DEFAULT_bdver3,
- TARGET_CPU_DEFAULT_btver1,
- TARGET_CPU_DEFAULT_btver2,
-
- TARGET_CPU_DEFAULT_max
-};
-
#ifndef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu) "
#endif
@@ -2089,32 +2052,33 @@ do { \
with x86-64 medium memory model */
#define DEFAULT_LARGE_SECTION_THRESHOLD 65536
-/* Which processor to tune code generation for. */
+/* Which processor to tune code generation for. These must be in sync
+ with processor_target_table in i386.c. */
enum processor_type
{
- PROCESSOR_I386 = 0, /* 80386 */
+ PROCESSOR_GENERIC32 = 0,
+ PROCESSOR_GENERIC64,
+ PROCESSOR_I386, /* 80386 */
PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
PROCESSOR_PENTIUM,
PROCESSOR_PENTIUMPRO,
- PROCESSOR_GEODE,
- PROCESSOR_K6,
- PROCESSOR_ATHLON,
PROCESSOR_PENTIUM4,
- PROCESSOR_K8,
PROCESSOR_NOCONA,
PROCESSOR_CORE2,
PROCESSOR_COREI7,
PROCESSOR_HASWELL,
- PROCESSOR_GENERIC32,
- PROCESSOR_GENERIC64,
+ PROCESSOR_ATOM,
+ PROCESSOR_GEODE,
+ PROCESSOR_K6,
+ PROCESSOR_ATHLON,
+ PROCESSOR_K8,
PROCESSOR_AMDFAM10,
PROCESSOR_BDVER1,
PROCESSOR_BDVER2,
PROCESSOR_BDVER3,
PROCESSOR_BTVER1,
PROCESSOR_BTVER2,
- PROCESSOR_ATOM,
PROCESSOR_max
};
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 047076fc917..ebfa0bbccff 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -222,6 +222,8 @@
UNSPECV_XEND
UNSPECV_XABORT
UNSPECV_XTEST
+
+ UNSPECV_NLGR
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -361,6 +363,13 @@
(const_string "unknown")]
(const_string "integer")))
+;; The minimum required alignment of vector mode memory operands of the SSE
+;; (non-VEX/EVEX) instruction in bits, if it is different from
+;; GET_MODE_ALIGNMENT of the operand, otherwise 0. If an instruction has
+;; multiple alternatives, this should be conservative maximum of those minimum
+;; required alignments.
+(define_attr "ssememalign" "" (const_int 0))
+
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
(cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
@@ -1568,7 +1577,7 @@
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
@@ -1585,7 +1594,7 @@
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
@@ -2314,7 +2323,7 @@
"TARGET_LP64 && ix86_check_movabs (insn, 0)"
"@
movabs{<imodesuffix>}\t{%1, %P0|[%P0], %1}
- mov{<imodesuffix>}\t{%1, %a0|%a0, %1}"
+ mov{<imodesuffix>}\t{%1, %a0|<iptrsize> PTR %a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
@@ -2328,7 +2337,7 @@
"TARGET_LP64 && ix86_check_movabs (insn, 1)"
"@
movabs{<imodesuffix>}\t{%P1, %0|%0, [%P1]}
- mov{<imodesuffix>}\t{%a1, %0|%0, %a1}"
+ mov{<imodesuffix>}\t{%a1, %0|%0, <iptrsize> PTR %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
@@ -6587,7 +6596,7 @@
(set_attr "use_carry" "1")
(set_attr "mode" "<MODE>")])
-;; Overflow setting add and subtract instructions
+;; Overflow setting add instructions
(define_insn "*add<mode>3_cconly_overflow"
[(set (reg:CCC FLAGS_REG)
@@ -6602,43 +6611,31 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*sub<mode>3_cconly_overflow"
+(define_insn "*add<mode>3_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (minus:SWI
- (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
- (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
- (match_dup 0)))]
- ""
- "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*<plusminus_insn><mode>3_cc_overflow"
- [(set (reg:CCC FLAGS_REG)
- (compare:CCC
- (plusminus:SWI
- (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
+ (plus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
(match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))
(match_dup 1)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
- (plusminus:SWI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+ (plus:SWI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+ "add{<imodesuffix>}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*<plusminus_insn>si3_zext_cc_overflow"
+(define_insn "*addsi3_zext_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plusminus:SI
- (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
+ (plus:SI
+ (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "x86_64_general_operand" "rme"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
- "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
- "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}"
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
+ "add{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
@@ -8010,7 +8007,18 @@
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
(and:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+ "TARGET_64BIT
+ && ix86_match_ccmode
+ (insn,
+ /* If we are going to emit andl instead of andq, and the operands[2]
+ constant might have the SImode sign bit set, make sure the sign
+ flag isn't tested, because the instruction will set the sign flag
+ based on bit 31 rather than bit 63. If it isn't CONST_INT,
+ conservatively assume it might have bit 31 set. */
+ (satisfies_constraint_Z (operands[2])
+ && (!CONST_INT_P (operands[2])
+ || val_signbit_known_set_p (SImode, INTVAL (operands[2]))))
+ ? CCZmode : CCNOmode)
&& ix86_binary_operator_ok (AND, DImode, operands)"
"@
and{l}\t{%k2, %k0|%k0, %k2}
@@ -16646,7 +16654,37 @@
emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
-
+
+(define_insn_and_split "nonlocal_goto_receiver"
+ [(unspec_volatile [(const_int 0)] UNSPECV_NLGR)]
+ "TARGET_MACHO && !TARGET_64BIT && flag_pic"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ if (crtl->uses_pic_offset_table)
+ {
+ rtx xops[3];
+ rtx label_rtx = gen_label_rtx ();
+ rtx tmp;
+
+ /* Get a new pic base. */
+ emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
+ /* Correct this with the offset from the new to the old. */
+ xops[0] = xops[1] = pic_offset_table_rtx;
+ label_rtx = gen_rtx_LABEL_REF (SImode, label_rtx);
+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, label_rtx),
+ UNSPEC_MACHOPIC_OFFSET);
+ xops[2] = gen_rtx_CONST (Pmode, tmp);
+ ix86_expand_binary_operator (MINUS, SImode, xops);
+ }
+ else
+ /* No pic reg restore needed. */
+ emit_note (NOTE_INSN_DELETED);
+
+ DONE;
+})
+
;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
(define_split
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 4f9bd658e2d..565163704e1 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -605,6 +605,7 @@
}
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "ssememalign" "8")
(set_attr "prefix" "maybe_vex")
(set (attr "mode")
(cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
@@ -634,6 +635,7 @@
}
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "ssememalign" "8")
(set_attr "prefix" "maybe_vex")
(set (attr "mode")
(cond [(ior (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
@@ -663,6 +665,7 @@
}
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "ssememalign" "8")
(set (attr "prefix_data16")
(if_then_else
(match_test "TARGET_AVX")
@@ -696,6 +699,7 @@
}
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "ssememalign" "8")
(set (attr "prefix_data16")
(if_then_else
(match_test "TARGET_AVX")
@@ -721,6 +725,7 @@
"%vlddqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "ssememalign" "8")
(set (attr "prefix_data16")
(if_then_else
(match_test "TARGET_AVX")
@@ -1001,6 +1006,7 @@
vrcpss\t{%1, %2, %0|%0, %2, %1}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse")
+ (set_attr "ssememalign" "32")
(set_attr "atom_sse_attr" "rcp")
(set_attr "btver2_sse_attr" "rcp")
(set_attr "prefix" "orig,vex")
@@ -1089,6 +1095,7 @@
vrsqrtss\t{%1, %2, %0|%0, %2, %1}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse")
+ (set_attr "ssememalign" "32")
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
@@ -2844,6 +2851,7 @@
"%vcvtdq2pd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssecvt")
(set_attr "prefix" "maybe_vex")
+ (set_attr "ssememalign" "64")
(set_attr "mode" "V2DF")])
(define_insn "avx_cvtpd2dq256"
@@ -3572,6 +3580,7 @@
%vmovhps\t{%2, %0|%0, %2}"
[(set_attr "isa" "noavx,avx,noavx,avx,*")
(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
@@ -3617,6 +3626,7 @@
%vmovlps\t{%2, %H0|%H0, %2}"
[(set_attr "isa" "noavx,avx,noavx,avx,*")
(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
@@ -3941,6 +3951,7 @@
%vmovhlps\t{%1, %d0|%d0, %1}
%vmovlps\t{%H1, %d0|%d0, %H1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V2SF,V4SF,V2SF")])
@@ -3980,6 +3991,7 @@
%vmovlps\t{%2, %H0|%H0, %2}"
[(set_attr "isa" "noavx,avx,noavx,avx,*")
(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
(set_attr "mode" "V2SF,V2SF,V4SF,V4SF,V2SF")])
@@ -4033,6 +4045,7 @@
%vmovlps\t{%2, %0|%0, %2}"
[(set_attr "isa" "noavx,avx,noavx,avx,*")
(set_attr "type" "sseshuf,sseshuf,ssemov,ssemov,ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "length_immediate" "1,1,*,*,*")
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
@@ -4642,7 +4655,8 @@
vmovlpd\t{%H1, %2, %0|%0, %2, %H1}
%vmovhpd\t{%1, %0|%0, %1}"
[(set_attr "isa" "noavx,avx,sse3,noavx,avx,*")
- (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+ (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_data16" "*,*,*,1,*,1")
(set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex")
(set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")])
@@ -4744,6 +4758,7 @@
%vmovlpd\t{%2, %H0|%H0, %2}"
[(set_attr "isa" "noavx,avx,sse3,noavx,avx,*")
(set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_data16" "*,*,*,1,*,1")
(set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex")
(set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")])
@@ -4982,6 +4997,7 @@
movhlps\t{%1, %0|%0, %1}
movlps\t{%H1, %0|%0, %H1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "mode" "V2SF,V4SF,V2SF")])
;; Avoid combining registers from different units in a single alternative,
@@ -5077,6 +5093,7 @@
#"
[(set_attr "isa" "noavx,avx,noavx,avx,*,*,*")
(set_attr "type" "ssemov,ssemov,sselog,sselog,ssemov,fmov,imov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_data16" "1,*,*,*,*,*,*")
(set_attr "prefix" "orig,vex,orig,vex,*,*,*")
(set_attr "mode" "V1DF,V1DF,V2DF,V2DF,DF,DF,DF")])
@@ -5145,6 +5162,7 @@
(const_string "imov")
]
(const_string "ssemov")))
+ (set_attr "ssememalign" "64")
(set_attr "prefix_data16" "*,1,*,*,*,*,1,*,*,*,*")
(set_attr "length_immediate" "*,*,*,*,*,1,*,*,*,*,*")
(set_attr "prefix" "maybe_vex,orig,vex,orig,vex,orig,orig,vex,*,*,*")
@@ -5189,6 +5207,7 @@
(const_string "1")
(const_string "*")))
(set_attr "length_immediate" "*,*,*,*,*,1,*,*,*")
+ (set_attr "ssememalign" "64")
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex,orig,orig,vex,maybe_vex")
(set_attr "mode" "DF,DF,V1DF,V1DF,V1DF,V2DF,V1DF,V1DF,V1DF")])
@@ -7758,9 +7777,17 @@
(mem:V16QI (match_dup 0))]
UNSPEC_MASKMOV))]
"TARGET_SSE2"
- "%vmaskmovdqu\t{%2, %1|%1, %2}"
+{
+ /* We can't use %^ here due to ASM_OUTPUT_OPCODE processing
+ that requires %v to be at the beginning of the opcode name. */
+ if (Pmode != word_mode)
+ fputs ("\taddr32", asm_out_file);
+ return "%vmaskmovdqu\t{%2, %1|%1, %2}";
+}
[(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
+ (set (attr "length_address")
+ (symbol_ref ("Pmode != word_mode")))
;; The implicit %rdi operand confuses default length_vex computation.
(set (attr "length_vex")
(symbol_ref ("3 + REX_SSE_REGNO_P (REGNO (operands[2]))")))
@@ -7808,26 +7835,18 @@
"mwait"
[(set_attr "length" "3")])
-(define_insn "sse3_monitor"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
- (match_operand:SI 1 "register_operand" "c")
- (match_operand:SI 2 "register_operand" "d")]
- UNSPECV_MONITOR)]
- "TARGET_SSE3 && !TARGET_64BIT"
- "monitor\t%0, %1, %2"
- [(set_attr "length" "3")])
-
-(define_insn "sse3_monitor64_<mode>"
+(define_insn "sse3_monitor_<mode>"
[(unspec_volatile [(match_operand:P 0 "register_operand" "a")
(match_operand:SI 1 "register_operand" "c")
(match_operand:SI 2 "register_operand" "d")]
UNSPECV_MONITOR)]
- "TARGET_SSE3 && TARGET_64BIT"
+ "TARGET_SSE3"
;; 64bit version is "monitor %rax,%rcx,%rdx". But only lower 32bits in
;; RCX and RDX are used. Since 32bit register operands are implicitly
;; zero extended to 64bit, we only need to set up 32bit registers.
- "monitor"
- [(set_attr "length" "3")])
+ "%^monitor"
+ [(set (attr "length")
+ (symbol_ref ("(Pmode != word_mode) + 3")))])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -8736,6 +8755,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>bw\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -8766,6 +8786,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>bd\t{%1, %0|%0, %k1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "32")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -8791,6 +8812,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>wd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -8818,6 +8840,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>bq\t{%1, %0|%0, %w1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "16")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -8845,6 +8868,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>wq\t{%1, %0|%0, %k1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "32")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -8868,6 +8892,7 @@
"TARGET_SSE4_1"
"%vpmov<extsuffix>dq\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
+ (set_attr "ssememalign" "64")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -9151,6 +9176,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9213,6 +9239,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "load")
(set_attr "mode" "TI")])
@@ -9240,6 +9267,7 @@
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "btver2_decode" "vector")
(set_attr "memory" "none,load")
@@ -9267,6 +9295,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "btver2_decode" "vector")
@@ -9293,6 +9322,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "none,load,none,load")
(set_attr "btver2_decode" "vector,vector,vector,vector")
@@ -9346,6 +9376,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9399,6 +9430,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "load")
(set_attr "mode" "TI")])
@@ -9421,6 +9453,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "none,load")
@@ -9445,6 +9478,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "none,load")
@@ -9469,6 +9503,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "ssememalign" "8")
(set_attr "length_immediate" "1")
(set_attr "memory" "none,load,none,load")
(set_attr "prefix" "maybe_vex")
@@ -10213,7 +10248,6 @@
[(set_attr "type" "ssecvt1")
(set_attr "mode" "<MODE>")])
-;; scalar insns
(define_expand "xop_vmfrcz<mode>2"
[(set (match_operand:VF_128 0 "register_operand")
(vec_merge:VF_128
@@ -10223,11 +10257,9 @@
(match_dup 3)
(const_int 1)))]
"TARGET_XOP"
-{
- operands[3] = CONST0_RTX (<MODE>mode);
-})
+ "operands[3] = CONST0_RTX (<MODE>mode);")
-(define_insn "*xop_vmfrcz_<mode>"
+(define_insn "*xop_vmfrcz<mode>2"
[(set (match_operand:VF_128 0 "register_operand" "=x")
(vec_merge:VF_128
(unspec:VF_128
diff --git a/gcc/config/i386/t-rtems b/gcc/config/i386/t-rtems
index 6161ec10090..fef4c22e9c1 100644
--- a/gcc/config/i386/t-rtems
+++ b/gcc/config/i386/t-rtems
@@ -17,11 +17,10 @@
# <http://www.gnu.org/licenses/>.
#
-MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro \
-msoft-float
+MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro msoft-float
MULTILIB_DIRNAMES= m486 mpentium mpentiumpro soft-float
-MULTILIB_MATCHES = msoft-float=mno-m80387
-MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?mathlon
+MULTILIB_MATCHES = msoft-float=mno-80387
+MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?athlon
MULTILIB_EXCEPTIONS = \
mtune=pentium/*msoft-float* \
mtune=pentiumpro/*msoft-float*
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 7e7c1555a40..1e49a461a10 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -547,8 +547,9 @@ i386_pe_asm_named_section (const char *name, unsigned int flags,
sets 'discard' characteristic, rather than telling linker
to warn of size or content mismatch, so do the same. */
bool discard = (flags & SECTION_CODE)
- || lookup_attribute ("selectany",
- DECL_ATTRIBUTES (decl));
+ || (TREE_CODE (decl) != IDENTIFIER_NODE
+ && lookup_attribute ("selectany",
+ DECL_ATTRIBUTES (decl)));
fprintf (asm_out_file, "\t.linkonce %s\n",
(discard ? "discard" : "same_size"));
}
diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h
index c103c5865a3..66f96d98e2e 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -103,3 +103,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#undef TARGET_ASM_UNIQUE_SECTION
#define TARGET_ASM_UNIQUE_SECTION x86_64_elf_unique_section
+
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS x86_64_elf_section_type_flags
diff --git a/gcc/config/i386/xopintrin.h b/gcc/config/i386/xopintrin.h
index 66b0f0de5c9..d2a99a1674a 100644
--- a/gcc/config/i386/xopintrin.h
+++ b/gcc/config/i386/xopintrin.h
@@ -745,13 +745,17 @@ _mm_frcz_pd (__m128d __A)
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_frcz_ss (__m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfrczss ((__v4sf)__A, (__v4sf)__B);
+ return (__m128) __builtin_ia32_movss ((__v4sf)__A,
+ (__v4sf)
+ __builtin_ia32_vfrczss ((__v4sf)__B));
}
extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_frcz_sd (__m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfrczsd ((__v2df)__A, (__v2df)__B);
+ return (__m128d) __builtin_ia32_movsd ((__v2df)__A,
+ (__v2df)
+ __builtin_ia32_vfrczsd ((__v2df)__B));
}
extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 5e3236fa8de..a662bed81b5 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -3325,12 +3325,12 @@ handle_move_double (rtx operands[2],
latehalf[1] = adjust_address (operands[1], SImode, 0);
}
- /* If insn is effectively movd N(sp),-(sp) then we will do the
- high word first. We should use the adjusted operand 1 (which is N+4(sp))
- for the low word as well, to compensate for the first decrement of sp. */
+ /* If insn is effectively movd N(REG),-(REG) then we will do the high
+ word first. We should use the adjusted operand 1 (which is N+4(REG))
+ for the low word as well, to compensate for the first decrement of
+ REG. */
if (optype0 == PUSHOP
- && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
- && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+ && reg_overlap_mentioned_p (XEXP (XEXP (operands[0], 0), 0), operands[1]))
operands[1] = middlehalf[1] = latehalf[1];
/* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
diff --git a/gcc/config/mips/driver-native.c b/gcc/config/mips/driver-native.c
index 8b7ed5b5530..758efa9a4a6 100644
--- a/gcc/config/mips/driver-native.c
+++ b/gcc/config/mips/driver-native.c
@@ -58,11 +58,17 @@ host_detect_local_cpu (int argc, const char **argv)
if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0)
{
if (strstr (buf, "Godson2 V0.2") != NULL
- || strstr (buf, "Loongson-2 V0.2") != NULL)
+ || strstr (buf, "Loongson-2 V0.2") != NULL
+ || strstr (buf, "Loongson-2E") != NULL)
cpu = "loongson2e";
else if (strstr (buf, "Godson2 V0.3") != NULL
- || strstr (buf, "Loongson-2 V0.3") != NULL)
+ || strstr (buf, "Loongson-2 V0.3") != NULL
+ || strstr (buf, "Loongson-2F") != NULL)
cpu = "loongson2f";
+ else if (strstr (buf, "Godson3 V0.5") != NULL
+ || strstr (buf, "Loongson-3 V0.5") != NULL
+ || strstr (buf, "Loongson-3A") != NULL)
+ cpu = "loongson3a";
else if (strstr (buf, "SiByte SB1") != NULL)
cpu = "sb1";
else if (strstr (buf, "R5000") != NULL)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 252e828480e..e5f72e475eb 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3560,17 +3560,6 @@ mips_set_reg_reg_cost (enum machine_mode mode)
}
}
-/* Return the cost of an operand X that can be trucated for free.
- SPEED says whether we're optimizing for size or speed. */
-
-static int
-mips_truncated_op_cost (rtx x, bool speed)
-{
- if (GET_CODE (x) == TRUNCATE)
- x = XEXP (x, 0);
- return set_src_cost (x, speed);
-}
-
/* Implement TARGET_RTX_COSTS. */
static bool
@@ -3951,13 +3940,12 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
case ZERO_EXTEND:
if (outer_code == SET
&& ISA_HAS_BADDU
+ && (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ || GET_CODE (XEXP (x, 0)) == SUBREG)
&& GET_MODE (XEXP (x, 0)) == QImode
- && GET_CODE (XEXP (x, 0)) == PLUS)
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
{
- rtx plus = XEXP (x, 0);
- *total = (COSTS_N_INSNS (1)
- + mips_truncated_op_cost (XEXP (plus, 0), speed)
- + mips_truncated_op_cost (XEXP (plus, 1), speed));
+ *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed);
return true;
}
*total = mips_zero_extend_cost (mode, XEXP (x, 0));
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 0acce14bd8c..d6e721d30f5 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -949,6 +949,11 @@ struct mips_cpu_info {
|| TARGET_SMARTMIPS) \
&& !TARGET_MIPS16)
+/* ISA has the WSBH (word swap bytes within halfwords) instruction.
+ 64-bit targets also provide DSBH and DSHD. */
+#define ISA_HAS_WSBH ((ISA_MIPS32R2 || ISA_MIPS64R2) \
+ && !TARGET_MIPS16)
+
/* ISA has data prefetch instructions. This controls use of 'pref'. */
#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
|| TARGET_LOONGSON_2EF \
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 7aa461dbd69..2a0c695c807 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -73,6 +73,11 @@
UNSPEC_STORE_LEFT
UNSPEC_STORE_RIGHT
+ ;; Integer operations that are too cumbersome to describe directly.
+ UNSPEC_WSBH
+ UNSPEC_DSBH
+ UNSPEC_DSHD
+
;; Floating-point moves.
UNSPEC_LOAD_LOW
UNSPEC_LOAD_HIGH
@@ -1294,20 +1299,32 @@
;; Combiner patterns for unsigned byte-add.
-(define_insn "*baddu_si"
+(define_insn "*baddu_si_eb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI
+ (subreg:QI
+ (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")) 3)))]
+ "ISA_HAS_BADDU && BYTES_BIG_ENDIAN"
+ "baddu\\t%0,%1,%2"
+ [(set_attr "alu_type" "add")])
+
+(define_insn "*baddu_si_el"
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI
- (plus:QI (match_operand:QI 1 "register_operand" "d")
- (match_operand:QI 2 "register_operand" "d"))))]
- "ISA_HAS_BADDU"
+ (subreg:QI
+ (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")) 0)))]
+ "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN"
"baddu\\t%0,%1,%2"
[(set_attr "alu_type" "add")])
(define_insn "*baddu_di<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(zero_extend:GPR
- (plus:QI (truncate:QI (match_operand:DI 1 "register_operand" "d"))
- (truncate:QI (match_operand:DI 2 "register_operand" "d")))))]
+ (truncate:QI
+ (plus:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))))]
"ISA_HAS_BADDU && TARGET_64BIT"
"baddu\\t%0,%1,%2"
[(set_attr "alu_type" "add")])
@@ -5367,6 +5384,56 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
+
+(define_insn "bswaphi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (bswap:HI (match_operand:HI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn_and_split "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (bswap:SI (match_operand:SI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH && ISA_HAS_ROR"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_WSBH))
+ (set (match_dup 0) (rotatert:SI (match_dup 0) (const_int 16)))]
+ ""
+ [(set_attr "length" "8")])
+
+(define_insn_and_split "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (bswap:DI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_DSBH))
+ (set (match_dup 0) (unspec:DI [(match_dup 0)] UNSPEC_DSHD))]
+ ""
+ [(set_attr "length" "8")])
+
+(define_insn "wsbh"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")] UNSPEC_WSBH))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dsbh"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSBH))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dshd"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSHD))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dshd\t%0,%1"
+ [(set_attr "type" "shift")])
;;
;; ....................
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index dc6f2e42bcf..779243da221 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -513,6 +513,12 @@ pa_option_override (void)
write_symbols = NO_DEBUG;
}
+#ifdef AUTO_INC_DEC
+ /* FIXME: Disable auto increment and decrement processing until reload
+ is completed. See PR middle-end 56791. */
+ flag_auto_inc_dec = reload_completed;
+#endif
+
/* We only support the "big PIC" model now. And we always generate PIC
code when in 64bit mode. */
if (flag_pic == 1 || TARGET_64BIT)
@@ -4038,7 +4044,8 @@ pa_expand_prologue (void)
|| (! TARGET_64BIT && df_regs_ever_live_p (i + 1)))
{
rtx addr, insn, reg;
- addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
+ addr = gen_rtx_MEM (DFmode,
+ gen_rtx_POST_INC (word_mode, tmpreg));
reg = gen_rtx_REG (DFmode, i);
insn = emit_move_insn (addr, reg);
if (DO_FRAME_NOTES)
@@ -4331,7 +4338,8 @@ pa_expand_epilogue (void)
if (df_regs_ever_live_p (i)
|| (! TARGET_64BIT && df_regs_ever_live_p (i + 1)))
{
- rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
+ rtx src = gen_rtx_MEM (DFmode,
+ gen_rtx_POST_INC (word_mode, tmpreg));
rtx dest = gen_rtx_REG (DFmode, i);
emit_move_insn (dest, src);
}
@@ -10514,13 +10522,13 @@ pa_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
/* When INT14_OK_STRICT is false, a secondary reload is needed
to adjust the displacement of SImode and DImode floating point
- instructions. So, we return false when STRICT is true. We
+ instructions but this may fail when the register also needs
+ reloading. So, we return false when STRICT is true. We
also reject long displacements for float mode addresses since
the majority of accesses will use floating point instructions
that don't support 14-bit offsets. */
if (!INT14_OK_STRICT
- && reload_in_progress
- && strict
+ && (strict || !(reload_in_progress || reload_completed))
&& mode != QImode
&& mode != HImode)
return false;
@@ -10580,8 +10588,7 @@ pa_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
return true;
if (!INT14_OK_STRICT
- && reload_in_progress
- && strict
+ && (strict || !(reload_in_progress || reload_completed))
&& mode != QImode
&& mode != HImode)
return false;
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 5e6d5652e71..af24886cd59 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -833,46 +833,46 @@
(define_insn "scc"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")]))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")]))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi 1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn "iorscc"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")])
(match_operator:SI 6 "comparison_operator"
- [(match_operand:SI 4 "register_operand" "r")
+ [(match_operand:SI 4 "reg_or_0_operand" "rM")
(match_operand:SI 5 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%S3 %2,%1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%4,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%S3 %2,%r1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(ior:DI (match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")])
(match_operator:DI 6 "comparison_operator"
- [(match_operand:DI 4 "register_operand" "r")
+ [(match_operand:DI 4 "reg_or_0_operand" "rM")
(match_operand:DI 5 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%S3 %2,%1,%%r0\;cmp%I5clr,*%B6 %5,%4,%0\;ldi 1,%0"
+ "cmp%I2clr,*%S3 %2,%r1,%%r0\;cmp%I5clr,*%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
@@ -881,20 +881,20 @@
(define_insn "negscc"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operator:SI 3 "comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
+ [(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi -1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operator:DI 3 "comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
+ [(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi -1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index db2e93a168a..c0767a57603 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -46,6 +46,7 @@
UNSPEC_VPACK_SIGN_UNS_SAT
UNSPEC_VPACK_UNS_UNS_SAT
UNSPEC_VPACK_UNS_UNS_MOD
+ UNSPEC_VPACK_UNS_UNS_MOD_DIRECT
UNSPEC_VSLV4SI
UNSPEC_VSLO
UNSPEC_VSR
@@ -69,6 +70,8 @@
UNSPEC_VLSDOI
UNSPEC_VUNPACK_HI_SIGN
UNSPEC_VUNPACK_LO_SIGN
+ UNSPEC_VUNPACK_HI_SIGN_DIRECT
+ UNSPEC_VUNPACK_LO_SIGN_DIRECT
UNSPEC_VUPKHPX
UNSPEC_VUPKLPX
UNSPEC_DST
@@ -129,6 +132,10 @@
UNSPEC_VUPKHU_V4SF
UNSPEC_VUPKLU_V4SF
UNSPEC_VGBBD
+ UNSPEC_VMRGH_DIRECT
+ UNSPEC_VMRGL_DIRECT
+ UNSPEC_VSPLT_DIRECT
+ UNSPEC_VSUMSWS_DIRECT
])
(define_c_enum "unspecv"
@@ -649,7 +656,7 @@
convert_move (small_swap, swap, 0);
low_product = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_umult_odd_v8hi (low_product, one, two));
+ emit_insn (gen_altivec_vmulouh (low_product, one, two));
high_product = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
@@ -673,13 +680,22 @@
rtx high = gen_reg_rtx (V4SImode);
rtx low = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_smult_even_v8hi (even, operands[1], operands[2]));
- emit_insn (gen_vec_widen_smult_odd_v8hi (odd, operands[1], operands[2]));
-
- emit_insn (gen_altivec_vmrghw (high, even, odd));
- emit_insn (gen_altivec_vmrglw (low, even, odd));
-
- emit_insn (gen_altivec_vpkuwum (operands[0], high, low));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmulesh (even, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulosh (odd, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (high, even, odd));
+ emit_insn (gen_altivec_vmrglw_direct (low, even, odd));
+ emit_insn (gen_altivec_vpkuwum_direct (operands[0], high, low));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulosh (even, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulesh (odd, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (high, odd, even));
+ emit_insn (gen_altivec_vmrglw_direct (low, odd, even));
+ emit_insn (gen_altivec_vpkuwum_direct (operands[0], low, high));
+ }
DONE;
}")
@@ -830,9 +846,41 @@
"vmladduhm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
-(define_insn "altivec_vmrghb"
+(define_expand "altivec_vmrghb"
+ [(use (match_operand:V16QI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25),
+ GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27),
+ GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29),
+ GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31));
+ x = gen_rtx_VEC_CONCAT (V32QImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17),
+ GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19),
+ GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21),
+ GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23));
+ x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrghb_internal"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_select:V16QI
+ (vec_select:V16QI
(vec_concat:V32QI
(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v"))
@@ -845,12 +893,54 @@
(const_int 6) (const_int 22)
(const_int 7) (const_int 23)])))]
"TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrghb %0,%1,%2";
+ else
+ return "vmrglb %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghb_direct"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMRGH_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrghb %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrghh"
+(define_expand "altivec_vmrghh"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13),
+ GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15));
+ x = gen_rtx_VEC_CONCAT (V16HImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9),
+ GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11));
+ x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrghh_internal"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_select:V8HI
+ (vec_select:V8HI
(vec_concat:V16HI
(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v"))
@@ -859,10 +949,50 @@
(const_int 2) (const_int 10)
(const_int 3) (const_int 11)])))]
"TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrghh %0,%1,%2";
+ else
+ return "vmrglh %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghh_direct"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMRGH_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrghw"
+(define_expand "altivec_vmrghw"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V4SI 1 "register_operand" ""))
+ (use (match_operand:V4SI 2 "register_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7));
+ x = gen_rtx_VEC_CONCAT (V8SImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5));
+ x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrghw_internal"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(vec_select:V4SI
(vec_concat:V8SI
@@ -871,6 +1001,20 @@
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrghw %0,%1,%2";
+ else
+ return "vmrglw %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghw_direct"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMRGH_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -883,10 +1027,47 @@
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
- "vmrghw %0,%1,%2"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrghw %0,%1,%2";
+ else
+ return "vmrglw %0,%2,%1";
+}
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrglb"
+(define_expand "altivec_vmrglb"
+ [(use (match_operand:V16QI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17),
+ GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19),
+ GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21),
+ GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23));
+ x = gen_rtx_VEC_CONCAT (V32QImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25),
+ GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27),
+ GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29),
+ GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31));
+ x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrglb_internal"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_select:V16QI
(vec_concat:V32QI
@@ -901,10 +1082,52 @@
(const_int 14) (const_int 30)
(const_int 15) (const_int 31)])))]
"TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrglb %0,%1,%2";
+ else
+ return "vmrghb %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglb_direct"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMRGL_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrglb %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrglh"
+(define_expand "altivec_vmrglh"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9),
+ GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11));
+ x = gen_rtx_VEC_CONCAT (V16HImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13),
+ GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15));
+ x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrglh_internal"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_select:V8HI
(vec_concat:V16HI
@@ -915,10 +1138,50 @@
(const_int 6) (const_int 14)
(const_int 7) (const_int 15)])))]
"TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrglh %0,%1,%2";
+ else
+ return "vmrghh %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglh_direct"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMRGL_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vmrglw"
+(define_expand "altivec_vmrglw"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V4SI 1 "register_operand" ""))
+ (use (match_operand:V4SI 2 "register_operand" ""))]
+ "VECTOR_MEM_ALTIVEC_P (V4SImode)"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5));
+ x = gen_rtx_VEC_CONCAT (V8SImode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7));
+ x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vmrglw_internal"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(vec_select:V4SI
(vec_concat:V8SI
@@ -927,6 +1190,20 @@
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"VECTOR_MEM_ALTIVEC_P (V4SImode)"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrglw %0,%1,%2";
+ else
+ return "vmrghw %0,%2,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglw_direct"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VMRGL_DIRECT))]
+ "TARGET_ALTIVEC"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -939,7 +1216,12 @@
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"VECTOR_MEM_ALTIVEC_P (V4SFmode)"
- "vmrglw %0,%1,%2"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrglw %0,%1,%2";
+ else
+ return "vmrghw %0,%2,%1";
+}
[(set_attr "type" "vecperm")])
;; Power8 vector merge even/odd
@@ -952,7 +1234,12 @@
(parallel [(const_int 0) (const_int 4)
(const_int 2) (const_int 6)])))]
"TARGET_P8_VECTOR"
- "vmrgew %0,%1,%2"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrgew %0,%1,%2";
+ else
+ return "vmrgow %0,%2,%1";
+}
[(set_attr "type" "vecperm")])
(define_insn "p8_vmrgow"
@@ -964,10 +1251,119 @@
(parallel [(const_int 1) (const_int 5)
(const_int 3) (const_int 7)])))]
"TARGET_P8_VECTOR"
- "vmrgow %0,%1,%2"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "vmrgow %0,%1,%2";
+ else
+ return "vmrgew %0,%2,%1";
+}
[(set_attr "type" "vecperm")])
-(define_insn "vec_widen_umult_even_v16qi"
+(define_expand "vec_widen_umult_even_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_even_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_umult_even_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_even_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulosh (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" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_odd_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_umult_odd_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_odd_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulesh (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")
(match_operand:V16QI 2 "register_operand" "v")]
@@ -976,43 +1372,25 @@
"vmuleub %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_even_v16qi"
+(define_insn "altivec_vmuloub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VMULESB))]
- "TARGET_ALTIVEC"
- "vmulesb %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "vec_widen_umult_even_v8hi"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VMULEUH))]
- "TARGET_ALTIVEC"
- "vmuleuh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "vec_widen_smult_even_v8hi"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VMULESH))]
+ UNSPEC_VMULOUB))]
"TARGET_ALTIVEC"
- "vmulesh %0,%1,%2"
+ "vmuloub %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_umult_odd_v16qi"
+(define_insn "altivec_vmulesb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VMULOUB))]
+ UNSPEC_VMULESB))]
"TARGET_ALTIVEC"
- "vmuloub %0,%1,%2"
+ "vmulesb %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_odd_v16qi"
+(define_insn "altivec_vmulosb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
@@ -1021,7 +1399,16 @@
"vmulosb %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_umult_odd_v8hi"
+(define_insn "altivec_vmuleuh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULEUH))]
+ "TARGET_ALTIVEC"
+ "vmuleuh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulouh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
@@ -1030,7 +1417,16 @@
"vmulouh %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_odd_v8hi"
+(define_insn "altivec_vmulesh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULESH))]
+ "TARGET_ALTIVEC"
+ "vmulesh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulosh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
@@ -1047,7 +1443,13 @@
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VPKPX))]
"TARGET_ALTIVEC"
- "vpkpx %0,%1,%2"
+ "*
+ {
+ if (VECTOR_ELT_ORDER_BIG)
+ return \"vpkpx %0,%1,%2\";
+ else
+ return \"vpkpx %0,%2,%1\";
+ }"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpks<VI_char>ss"
@@ -1056,7 +1458,13 @@
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_SIGN_SIGN_SAT))]
"<VI_unit>"
- "vpks<VI_char>ss %0,%1,%2"
+ "*
+ {
+ if (VECTOR_ELT_ORDER_BIG)
+ return \"vpks<VI_char>ss %0,%1,%2\";
+ else
+ return \"vpks<VI_char>ss %0,%2,%1\";
+ }"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpks<VI_char>us"
@@ -1065,7 +1473,13 @@
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_SIGN_UNS_SAT))]
"<VI_unit>"
- "vpks<VI_char>us %0,%1,%2"
+ "*
+ {
+ if (VECTOR_ELT_ORDER_BIG)
+ return \"vpks<VI_char>us %0,%1,%2\";
+ else
+ return \"vpks<VI_char>us %0,%2,%1\";
+ }"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpku<VI_char>us"
@@ -1074,7 +1488,13 @@
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_UNS_UNS_SAT))]
"<VI_unit>"
- "vpku<VI_char>us %0,%1,%2"
+ "*
+ {
+ if (VECTOR_ELT_ORDER_BIG)
+ return \"vpku<VI_char>us %0,%1,%2\";
+ else
+ return \"vpku<VI_char>us %0,%2,%1\";
+ }"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vpku<VI_char>um"
@@ -1083,7 +1503,28 @@
(match_operand:VP 2 "register_operand" "v")]
UNSPEC_VPACK_UNS_UNS_MOD))]
"<VI_unit>"
- "vpku<VI_char>um %0,%1,%2"
+ "*
+ {
+ if (VECTOR_ELT_ORDER_BIG)
+ return \"vpku<VI_char>um %0,%1,%2\";
+ else
+ return \"vpku<VI_char>um %0,%2,%1\";
+ }"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpku<VI_char>um_direct"
+ [(set (match_operand:<VP_small> 0 "register_operand" "=v")
+ (unspec:<VP_small> [(match_operand:VP 1 "register_operand" "v")
+ (match_operand:VP 2 "register_operand" "v")]
+ UNSPEC_VPACK_UNS_UNS_MOD_DIRECT))]
+ "<VI_unit>"
+ "*
+ {
+ if (BYTES_BIG_ENDIAN)
+ return \"vpku<VI_char>um %0,%1,%2\";
+ else
+ return \"vpku<VI_char>um %0,%2,%1\";
+ }"
[(set_attr "type" "vecperm")])
(define_insn "*altivec_vrl<VI_char>"
@@ -1174,64 +1615,242 @@
"vsum4s<VI_char>s %0,%1,%2"
[(set_attr "type" "veccomplex")])
+;; FIXME: For the following two patterns, the scratch should only be
+;; allocated for !VECTOR_ELT_ORDER_BIG, and the instructions should
+;; be emitted separately.
(define_insn "altivec_vsum2sws"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUM2SWS))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))
+ (clobber (match_scratch:V4SI 3 "=v"))]
"TARGET_ALTIVEC"
- "vsum2sws %0,%1,%2"
- [(set_attr "type" "veccomplex")])
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vsum2sws %0,%1,%2";
+ else
+ return "vsldoi %3,%2,%2,12\n\tvsum2sws %3,%1,%3\n\tvsldoi %0,%3,%3,4";
+}
+ [(set_attr "type" "veccomplex")
+ (set (attr "length")
+ (if_then_else
+ (match_test "VECTOR_ELT_ORDER_BIG")
+ (const_string "4")
+ (const_string "12")))])
(define_insn "altivec_vsumsws"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")]
UNSPEC_VSUMSWS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))
+ (clobber (match_scratch:V4SI 3 "=v"))]
+ "TARGET_ALTIVEC"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vsumsws %0,%1,%2";
+ else
+ return "vspltw %3,%2,0\n\tvsumsws %3,%1,%3\n\tvspltw %0,%3,3";
+}
+ [(set_attr "type" "veccomplex")
+ (set (attr "length")
+ (if_then_else
+ (match_test "(VECTOR_ELT_ORDER_BIG)")
+ (const_string "4")
+ (const_string "12")))])
+
+(define_insn "altivec_vsumsws_direct"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUMSWS_DIRECT))
(set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsumsws %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "altivec_vspltb"
+(define_expand "altivec_vspltb"
+ [(use (match_operand:V16QI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. We have to reflect
+ the actual selected index for the splat in the RTL. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ operands[2] = GEN_INT (15 - INTVAL (operands[2]));
+
+ v = gen_rtvec (1, operands[2]);
+ x = gen_rtx_VEC_SELECT (QImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
+ x = gen_rtx_VEC_DUPLICATE (V16QImode, x);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vspltb_internal"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_duplicate:V16QI
(vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
"TARGET_ALTIVEC"
+{
+ /* For true LE, this adjusts the selected index. For LE with
+ -maltivec=be, this reverses what was done in the define_expand
+ because the instruction already has big-endian bias. */
+ if (!BYTES_BIG_ENDIAN)
+ operands[2] = GEN_INT (15 - INTVAL (operands[2]));
+
+ return "vspltb %0,%1,%2";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vspltb_direct"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:QI 2 "u5bit_cint_operand" "i")]
+ UNSPEC_VSPLT_DIRECT))]
+ "TARGET_ALTIVEC"
"vspltb %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsplth"
+(define_expand "altivec_vsplth"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. We have to reflect
+ the actual selected index for the splat in the RTL. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
+
+ v = gen_rtvec (1, operands[2]);
+ x = gen_rtx_VEC_SELECT (HImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
+ x = gen_rtx_VEC_DUPLICATE (V8HImode, x);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vsplth_internal"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_duplicate:V8HI
(vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
"TARGET_ALTIVEC"
+{
+ /* For true LE, this adjusts the selected index. For LE with
+ -maltivec=be, this reverses what was done in the define_expand
+ because the instruction already has big-endian bias. */
+ if (!BYTES_BIG_ENDIAN)
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
+
+ return "vsplth %0,%1,%2";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsplth_direct"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:QI 2 "u5bit_cint_operand" "i")]
+ UNSPEC_VSPLT_DIRECT))]
+ "TARGET_ALTIVEC"
"vsplth %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vspltw"
+(define_expand "altivec_vspltw"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V4SI 1 "register_operand" ""))
+ (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. We have to reflect
+ the actual selected index for the splat in the RTL. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ operands[2] = GEN_INT (3 - INTVAL (operands[2]));
+
+ v = gen_rtvec (1, operands[2]);
+ x = gen_rtx_VEC_SELECT (SImode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
+ x = gen_rtx_VEC_DUPLICATE (V4SImode, x);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vspltw_internal"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(vec_duplicate:V4SI
(vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
"TARGET_ALTIVEC"
+{
+ /* For true LE, this adjusts the selected index. For LE with
+ -maltivec=be, this reverses what was done in the define_expand
+ because the instruction already has big-endian bias. */
+ if (!BYTES_BIG_ENDIAN)
+ operands[2] = GEN_INT (3 - INTVAL (operands[2]));
+
+ return "vspltw %0,%1,%2";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vspltw_direct"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:QI 2 "u5bit_cint_operand" "i")]
+ UNSPEC_VSPLT_DIRECT))]
+ "TARGET_ALTIVEC"
"vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vspltsf"
+(define_expand "altivec_vspltsf"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))
+ (use (match_operand:QI 2 "u5bit_cint_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. We have to reflect
+ the actual selected index for the splat in the RTL. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ operands[2] = GEN_INT (3 - INTVAL (operands[2]));
+
+ v = gen_rtvec (1, operands[2]);
+ x = gen_rtx_VEC_SELECT (SFmode, operands[1], gen_rtx_PARALLEL (VOIDmode, v));
+ x = gen_rtx_VEC_DUPLICATE (V4SFmode, x);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*altivec_vspltsf_internal"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_duplicate:V4SF
(vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
"VECTOR_UNIT_ALTIVEC_P (V4SFmode)"
- "vspltw %0,%1,%2"
+{
+ /* For true LE, this adjusts the selected index. For LE with
+ -maltivec=be, this reverses what was done in the define_expand
+ because the instruction already has big-endian bias. */
+ if (!BYTES_BIG_ENDIAN)
+ operands[2] = GEN_INT (3 - INTVAL (operands[2]));
+
+ return "vspltw %0,%1,%2";
+}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltis<VI_char>"
@@ -1249,7 +1868,22 @@
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
-(define_insn "altivec_vperm_<mode>"
+(define_expand "altivec_vperm_<mode>"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+{
+ if (!VECTOR_ELT_ORDER_BIG)
+ {
+ altivec_expand_vec_perm_le (operands);
+ DONE;
+ }
+})
+
+(define_insn "*altivec_vperm_<mode>_internal"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
(match_operand:VM 2 "register_operand" "v")
@@ -1259,7 +1893,22 @@
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vperm_<mode>_uns"
+(define_expand "altivec_vperm_<mode>_uns"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM_UNS))]
+ "TARGET_ALTIVEC"
+{
+ if (!VECTOR_ELT_ORDER_BIG)
+ {
+ altivec_expand_vec_perm_le (operands);
+ DONE;
+ }
+})
+
+(define_insn "*altivec_vperm_<mode>_uns_internal"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
(match_operand:VM 2 "register_operand" "v")
@@ -1276,7 +1925,12 @@
(match_operand:V16QI 3 "register_operand" "")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
- "")
+{
+ if (!BYTES_BIG_ENDIAN) {
+ altivec_expand_vec_perm_le (operands);
+ DONE;
+ }
+})
(define_expand "vec_perm_constv16qi"
[(match_operand:V16QI 0 "register_operand" "")
@@ -1422,6 +2076,19 @@
(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
UNSPEC_VUNPACK_HI_SIGN))]
"<VI_unit>"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vupkhs<VU_char> %0,%1";
+ else
+ return "vupkls<VU_char> %0,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*altivec_vupkhs<VU_char>_direct"
+ [(set (match_operand:VP 0 "register_operand" "=v")
+ (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
+ UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
+ "<VI_unit>"
"vupkhs<VU_char> %0,%1"
[(set_attr "type" "vecperm")])
@@ -1430,6 +2097,19 @@
(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
UNSPEC_VUNPACK_LO_SIGN))]
"<VI_unit>"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vupkls<VU_char> %0,%1";
+ else
+ return "vupkhs<VU_char> %0,%1";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*altivec_vupkls<VU_char>_direct"
+ [(set (match_operand:VP 0 "register_operand" "=v")
+ (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
+ UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
+ "<VI_unit>"
"vupkls<VU_char> %0,%1"
[(set_attr "type" "vecperm")])
@@ -1438,7 +2118,12 @@
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKHPX))]
"TARGET_ALTIVEC"
- "vupkhpx %0,%1"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vupkhpx %0,%1";
+ else
+ return "vupklpx %0,%1";
+}
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupklpx"
@@ -1446,7 +2131,12 @@
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
UNSPEC_VUPKLPX))]
"TARGET_ALTIVEC"
- "vupklpx %0,%1"
+{
+ if (VECTOR_ELT_ORDER_BIG)
+ return "vupklpx %0,%1";
+ else
+ return "vupkhpx %0,%1";
+}
[(set_attr "type" "vecperm")])
;; Compare vectors producing a vector result and a predicate, setting CR6 to
@@ -1777,7 +2467,7 @@
emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
emit_insn (gen_altivec_vsum4s<VI_char>s (vtmp1, operands[1], vzero));
- emit_insn (gen_altivec_vsumsws (dest, vtmp1, vzero));
+ emit_insn (gen_altivec_vsumsws_direct (dest, vtmp1, vzero));
DONE;
})
@@ -1886,14 +2576,14 @@
(define_expand "vec_unpacks_hi_<VP_small_lc>"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
- UNSPEC_VUNPACK_HI_SIGN))]
+ UNSPEC_VUNPACK_HI_SIGN_DIRECT))]
"<VI_unit>"
"")
(define_expand "vec_unpacks_lo_<VP_small_lc>"
[(set (match_operand:VP 0 "register_operand" "=v")
(unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")]
- UNSPEC_VUNPACK_LO_SIGN))]
+ UNSPEC_VUNPACK_LO_SIGN_DIRECT))]
"<VI_unit>"
"")
@@ -1928,25 +2618,26 @@
rtx vzero = gen_reg_rtx (V8HImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 7);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 0 : 16);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 6);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 2 : 16);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 4);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 4 : 16);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 2);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 6 : 16);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 0);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
@@ -1963,25 +2654,26 @@
rtx vzero = gen_reg_rtx (V4SImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 7);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 6);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 0 : 17);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 4);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 2 : 17);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 2);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 4 : 17);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 0);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 6 : 17);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
@@ -1998,25 +2690,26 @@
rtx vzero = gen_reg_rtx (V8HImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 15);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 8 : 16);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 8);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
@@ -2033,25 +2726,26 @@
rtx vzero = gen_reg_rtx (V4SImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 15);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 8 : 17);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 8);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
@@ -2069,9 +2763,18 @@
rtx ve = gen_reg_rtx (V8HImode);
rtx vo = gen_reg_rtx (V8HImode);
- emit_insn (gen_vec_widen_umult_even_v16qi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_umult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2086,9 +2789,18 @@
rtx ve = gen_reg_rtx (V8HImode);
rtx vo = gen_reg_rtx (V8HImode);
- emit_insn (gen_vec_widen_umult_even_v16qi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_umult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2103,9 +2815,18 @@
rtx ve = gen_reg_rtx (V8HImode);
rtx vo = gen_reg_rtx (V8HImode);
- emit_insn (gen_vec_widen_smult_even_v16qi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_smult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2120,9 +2841,18 @@
rtx ve = gen_reg_rtx (V8HImode);
rtx vo = gen_reg_rtx (V8HImode);
- emit_insn (gen_vec_widen_smult_even_v16qi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_smult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2137,9 +2867,18 @@
rtx ve = gen_reg_rtx (V4SImode);
rtx vo = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2154,9 +2893,18 @@
rtx ve = gen_reg_rtx (V4SImode);
rtx vo = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2171,9 +2919,18 @@
rtx ve = gen_reg_rtx (V4SImode);
rtx vo = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve));
+ }
DONE;
}")
@@ -2188,9 +2945,18 @@
rtx ve = gen_reg_rtx (V4SImode);
rtx vo = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
- emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2]));
+ emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve));
+ }
DONE;
}")
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index fa53cbb9de7..4467b9e3d8b 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -52,29 +52,18 @@
"@internal")
;; Use w as a prefix to add VSX modes
-;; vector double (V2DF)
+;; any VSX register
+(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
+ "Any VSX register if the -mvsx option was used or NO_REGS.")
+
(define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
- "@internal")
+ "VSX vector register to hold vector double data or NO_REGS.")
-;; vector float (V4SF)
(define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
- "@internal")
-
-;; scalar double (DF)
-(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
- "@internal")
-
-;; TImode in VSX registers
-(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
- "@internal")
-
-;; any VSX register
-(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
- "@internal")
+ "VSX vector register to hold vector float data or NO_REGS.")
-;; Register constraints to simplify move patterns
(define_register_constraint "wg" "rs6000_constraints[RS6000_CONSTRAINT_wg]"
- "Floating point register if -mmfpgpr is used, or NO_REGS.")
+ "If -mmfpgpr was used, a floating point register or NO_REGS.")
(define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]"
"Floating point register if the LFIWAX instruction is enabled or NO_REGS.")
@@ -82,23 +71,38 @@
(define_register_constraint "wm" "rs6000_constraints[RS6000_CONSTRAINT_wm]"
"VSX register if direct move instructions are enabled, or NO_REGS.")
+;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use
+;; direct move directly, and movsf can't to move between the register sets.
+;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
+(define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).")
+
(define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]"
"General purpose register if 64-bit instructions are enabled or NO_REGS.")
+(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
+ "VSX vector register to hold scalar double values or NO_REGS.")
+
+(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
+ "VSX vector register to hold 128 bit integer or NO_REGS.")
+
+(define_register_constraint "wu" "rs6000_constraints[RS6000_CONSTRAINT_wu]"
+ "Altivec register to use for float/32-bit int loads/stores or NO_REGS.")
+
(define_register_constraint "wv" "rs6000_constraints[RS6000_CONSTRAINT_wv]"
- "Altivec register if -mpower8-vector is used or NO_REGS.")
+ "Altivec register to use for double loads/stores or NO_REGS.")
+
+(define_register_constraint "ww" "rs6000_constraints[RS6000_CONSTRAINT_ww]"
+ "FP or VSX register to perform float operations under -mvsx or NO_REGS.")
(define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]"
"Floating point register if the STFIWX instruction is enabled or NO_REGS.")
+(define_register_constraint "wy" "rs6000_constraints[RS6000_CONSTRAINT_wy]"
+ "VSX vector register to hold scalar float values or NO_REGS.")
+
(define_register_constraint "wz" "rs6000_constraints[RS6000_CONSTRAINT_wz]"
"Floating point register if the LFIWZX instruction is enabled or NO_REGS.")
-;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use
-;; direct move directly, and movsf can't to move between the register sets.
-;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
-(define_register_constraint "wn" "NO_REGS")
-
;; Lq/stq validates the address for load/store quad
(define_memory_constraint "wQ"
"Memory operand suitable for the load/store quad instructions"
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 052ac482e0f..9a846239b04 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -132,11 +132,14 @@
"")
(define_insn "*negtd2_fpr"
- [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
- (neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
+ (neg:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
+ "@
+ fneg %0,%1
+ fneg %0,%1\;fmr %L0,%L1"
+ [(set_attr "type" "fp")
+ (set_attr "length" "4,8")])
(define_expand "abstd2"
[(set (match_operand:TD 0 "gpc_reg_operand" "")
@@ -145,18 +148,24 @@
"")
(define_insn "*abstd2_fpr"
- [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
- (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))]
+ [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
+ (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
+ "@
+ fabs %0,%1
+ fabs %0,%1\;fmr %L0,%L1"
+ [(set_attr "type" "fp")
+ (set_attr "length" "4,8")])
(define_insn "*nabstd2_fpr"
- [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
- (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d"))))]
+ [(set (match_operand:TD 0 "gpc_reg_operand" "=d,d")
+ (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "0,d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
+ "@
+ fnabs %0,%1
+ fnabs %0,%1\;fmr %L0,%L1"
+ [(set_attr "type" "fp")
+ (set_attr "length" "4,8")])
;; Hardware support for decimal floating point operations.
diff --git a/gcc/config/rs6000/htmintrin.h b/gcc/config/rs6000/htmintrin.h
index 10f3e2e40a2..212cc92f851 100644
--- a/gcc/config/rs6000/htmintrin.h
+++ b/gcc/config/rs6000/htmintrin.h
@@ -99,9 +99,9 @@ typedef uintptr_t tfhar_t;
#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \
_TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1)
-#define _TEXASR_INSRUCTION_FETCH_CONFLICT(TEXASR) \
+#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \
_TEXASR_EXTRACT_BITS(TEXASR, 16, 1)
-#define _TEXASRU_INSRUCTION_FETCH_CONFLICT(TEXASRU) \
+#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \
_TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1)
#define _TEXASR_ABORT(TEXASR) \
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 9425bdaf0c3..19a33a1a358 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -25,9 +25,6 @@
#ifndef RS6000_BI_ARCH
-#undef DEFAULT_ABI
-#define DEFAULT_ABI ABI_AIX
-
#undef TARGET_64BIT
#define TARGET_64BIT 1
@@ -74,7 +71,11 @@ extern int dot_symbols;
#undef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_POWER7
#undef PROCESSOR_DEFAULT64
+#ifdef LINUX64_DEFAULT_ABI_ELFv2
+#define PROCESSOR_DEFAULT64 PROCESSOR_POWER8
+#else
#define PROCESSOR_DEFAULT64 PROCESSOR_POWER7
+#endif
/* We don't need to generate entries in .fixup, except when
-mrelocatable or -mrelocatable-lib is given. */
@@ -88,6 +89,12 @@ extern int dot_symbols;
#define INVALID_64BIT "-m%s not supported in this configuration"
#define INVALID_32BIT INVALID_64BIT
+#ifdef LINUX64_DEFAULT_ABI_ELFv2
+#define ELFv2_ABI_CHECK (rs6000_elf_abi != 1)
+#else
+#define ELFv2_ABI_CHECK (rs6000_elf_abi == 2)
+#endif
+
#undef SUBSUBTARGET_OVERRIDE_OPTIONS
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
do \
@@ -102,6 +109,12 @@ extern int dot_symbols;
error (INVALID_64BIT, "call"); \
} \
dot_symbols = !strcmp (rs6000_abi_name, "aixdesc"); \
+ if (ELFv2_ABI_CHECK) \
+ { \
+ rs6000_current_abi = ABI_ELFv2; \
+ if (dot_symbols) \
+ error ("-mcall-aixdesc incompatible with -mabi=elfv2"); \
+ } \
if (rs6000_isa_flags & OPTION_MASK_RELOCATABLE) \
{ \
rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE; \
@@ -355,7 +368,11 @@ extern int dot_symbols;
#define GLIBC_DYNAMIC_LINKER64 "%:find-dynamic-linker(/lib64/ld64.so.1)"
#else
#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld64.so.1"
+#ifdef LINUX64_DEFAULT_ABI_ELFv2
+#define GLIBC_DYNAMIC_LINKER64 "%{mabi=elfv1:/lib64/ld64.so.1;:/lib64/ld64.so.2}"
+#else
+#define GLIBC_DYNAMIC_LINKER64 "%{mabi=elfv2:/lib64/ld64.so.2;:/lib64/ld64.so.1}"
+#endif
#endif
#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
diff --git a/gcc/config/rs6000/option-defaults.h b/gcc/config/rs6000/option-defaults.h
index 2d7e36a6137..0d7ba1ea3ac 100644
--- a/gcc/config/rs6000/option-defaults.h
+++ b/gcc/config/rs6000/option-defaults.h
@@ -54,6 +54,7 @@
--with-float is ignored if -mhard-float or -msoft-float are
specified. */
#define OPTION_DEFAULT_SPECS \
+ {"abi", "%{!mabi=elfv*:-mabi=%(VALUE)}" }, \
{"tune", "%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}" }, \
{"tune_32", "%{" OPT_ARCH32 ":%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}}" }, \
{"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}}" }, \
diff --git a/gcc/config/rs6000/ppc-asm.h b/gcc/config/rs6000/ppc-asm.h
index db490b6c9b8..8108efd07f5 100644
--- a/gcc/config/rs6000/ppc-asm.h
+++ b/gcc/config/rs6000/ppc-asm.h
@@ -256,7 +256,30 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
* the real function with one or two leading periods respectively.
*/
-#if defined (__powerpc64__)
+#if defined(__powerpc64__) && _CALL_ELF == 2
+
+/* Defining "toc" above breaks @toc in assembler code. */
+#undef toc
+
+#define FUNC_NAME(name) GLUE(__USER_LABEL_PREFIX__,name)
+#define JUMP_TARGET(name) FUNC_NAME(name)
+#define FUNC_START(name) \
+ .type FUNC_NAME(name),@function; \
+ .globl FUNC_NAME(name); \
+FUNC_NAME(name): \
+0: addis 2,12,(.TOC.-0b)@ha; \
+ addi 2,2,(.TOC.-0b)@l; \
+ .localentry FUNC_NAME(name),.-FUNC_NAME(name)
+
+#define HIDDEN_FUNC(name) \
+ FUNC_START(name) \
+ .hidden FUNC_NAME(name);
+
+#define FUNC_END(name) \
+ .size FUNC_NAME(name),.-FUNC_NAME(name)
+
+#elif defined (__powerpc64__)
+
#define FUNC_NAME(name) GLUE(.,name)
#define JUMP_TARGET(name) FUNC_NAME(name)
#define FUNC_START(name) \
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 9534bd2b2cb..3ffdde8fa65 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -270,7 +270,7 @@
{
HOST_WIDE_INT r;
- if (!TARGET_QUAD_MEMORY)
+ if (!TARGET_QUAD_MEMORY && !TARGET_QUAD_MEMORY_ATOMIC)
return 0;
if (GET_CODE (op) == SUBREG)
@@ -376,14 +376,18 @@
(ior (match_code "const_int")
(match_operand 0 "gpc_reg_operand")))
+;; Return 1 if op is a constant integer valid for addition with addis, addi.
+(define_predicate "add_cint_operand"
+ (and (match_code "const_int")
+ (match_test "(unsigned HOST_WIDE_INT)
+ (INTVAL (op) + (mode == SImode ? 0x80000000 : 0x80008000))
+ < (unsigned HOST_WIDE_INT) 0x100000000ll")))
+
;; Return 1 if op is a constant integer valid for addition
;; or non-special register.
(define_predicate "reg_or_add_cint_operand"
(if_then_else (match_code "const_int")
- (match_test "(HOST_BITS_PER_WIDE_INT == 32
- && (mode == SImode || INTVAL (op) < 0x7fff8000))
- || ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
- < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "add_cint_operand")
(match_operand 0 "gpc_reg_operand")))
;; Return 1 if op is a constant integer valid for subtraction
@@ -629,6 +633,7 @@
(match_test "offsettable_nonstrict_memref_p (op)")))
;; Return 1 if the operand is suitable for load/store quad memory.
+;; This predicate only checks for non-atomic loads/stores.
(define_predicate "quad_memory_operand"
(match_code "mem")
{
@@ -1073,7 +1078,8 @@
(and (match_code "symbol_ref")
(match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
&& ((SYMBOL_REF_LOCAL_P (op)
- && (DEFAULT_ABI != ABI_AIX
+ && ((DEFAULT_ABI != ABI_AIX
+ && DEFAULT_ABI != ABI_ELFv2)
|| !SYMBOL_REF_EXTERNAL_P (op)))
|| (op == XEXP (DECL_RTL (current_function_decl),
0)))")))
@@ -1554,6 +1560,26 @@
return 1;
})
+;; Return 1 if OP is valid for crsave insn, known to be a PARALLEL.
+(define_predicate "crsave_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int i;
+
+ for (i = 1; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+
+ if (GET_CODE (exp) != USE
+ || GET_CODE (XEXP (exp, 0)) != REG
+ || GET_MODE (XEXP (exp, 0)) != CCmode
+ || ! CR_REGNO_P (REGNO (XEXP (exp, 0))))
+ return 0;
+ }
+ return 1;
+})
+
;; Return 1 if OP is valid for lmw insn, known to be a PARALLEL.
(define_predicate "lmw_operation"
(match_code "parallel")
@@ -1719,7 +1745,7 @@
(define_predicate "small_toc_ref"
(match_code "unspec,plus")
{
- if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
+ if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), mode))
op = XEXP (op, 0);
return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 672604406d5..18cf48bd9c8 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1209,9 +1209,9 @@ BU_VSX_1 (XVRSPIZ, "xvrspiz", CONST, vsx_btruncv4sf2)
BU_VSX_1 (XSRDPI, "xsrdpi", CONST, vsx_xsrdpi)
BU_VSX_1 (XSRDPIC, "xsrdpic", CONST, vsx_xsrdpic)
-BU_VSX_1 (XSRDPIM, "xsrdpim", CONST, vsx_floordf2)
-BU_VSX_1 (XSRDPIP, "xsrdpip", CONST, vsx_ceildf2)
-BU_VSX_1 (XSRDPIZ, "xsrdpiz", CONST, vsx_btruncdf2)
+BU_VSX_1 (XSRDPIM, "xsrdpim", CONST, floordf2)
+BU_VSX_1 (XSRDPIP, "xsrdpip", CONST, ceildf2)
+BU_VSX_1 (XSRDPIZ, "xsrdpiz", CONST, btruncdf2)
/* VSX predicate functions. */
BU_VSX_P (XVCMPEQSP_P, "xvcmpeqsp_p", CONST, vector_eq_v4sf_p)
@@ -1318,7 +1318,7 @@ BU_P8V_AV_2 (VMRGOW, "vmrgow", CONST, p8_vmrgow)
BU_P8V_AV_2 (VPKUDUM, "vpkudum", CONST, altivec_vpkudum)
BU_P8V_AV_2 (VPKSDSS, "vpksdss", CONST, altivec_vpksdss)
BU_P8V_AV_2 (VPKUDUS, "vpkudus", CONST, altivec_vpkudus)
-BU_P8V_AV_2 (VPKSDUS, "vpksdus", CONST, altivec_vpkswus)
+BU_P8V_AV_2 (VPKSDUS, "vpksdus", CONST, altivec_vpksdus)
BU_P8V_AV_2 (VRLD, "vrld", CONST, vrotlv2di3)
BU_P8V_AV_2 (VSLD, "vsld", CONST, vashlv2di3)
BU_P8V_AV_2 (VSRD, "vsrd", CONST, vlshrv2di3)
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index a75b0bfbf95..240466254ac 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -337,6 +337,10 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
rs6000_define_or_undefine_macro (define_p, "__HTM__");
if ((flags & OPTION_MASK_P8_VECTOR) != 0)
rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__");
+ if ((flags & OPTION_MASK_QUAD_MEMORY) != 0)
+ rs6000_define_or_undefine_macro (define_p, "__QUAD_MEMORY__");
+ if ((flags & OPTION_MASK_QUAD_MEMORY_ATOMIC) != 0)
+ rs6000_define_or_undefine_macro (define_p, "__QUAD_MEMORY_ATOMIC__");
if ((flags & OPTION_MASK_CRYPTO) != 0)
rs6000_define_or_undefine_macro (define_p, "__CRYPTO__");
@@ -461,6 +465,10 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
case ABI_AIX:
builtin_define ("_CALL_AIXDESC");
builtin_define ("_CALL_AIX");
+ builtin_define ("_CALL_ELF=1");
+ break;
+ case ABI_ELFv2:
+ builtin_define ("_CALL_ELF=2");
break;
case ABI_DARWIN:
builtin_define ("_CALL_DARWIN");
@@ -473,6 +481,13 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
builtin_define ("__NO_FPRS__");
+ /* Whether aggregates passed by value are aligned to a 16 byte boundary
+ if their alignment is 16 bytes or larger. */
+ if ((TARGET_MACHO && rs6000_darwin64_abi)
+ || DEFAULT_ABI == ABI_ELFv2
+ || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
+ builtin_define ("__STRUCT_PARM_ALIGN__=16");
+
/* Generate defines for Xilinx FPU. */
if (rs6000_xilinx_fpu)
{
@@ -597,10 +612,6 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_VUPKHSH, ALTIVEC_BUILTIN_VUPKHSH,
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V8HI, 0, 0 },
- { ALTIVEC_BUILTIN_VEC_UNPACKH, P8V_BUILTIN_VUPKHSW,
- RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 },
- { ALTIVEC_BUILTIN_VEC_UNPACKH, P8V_BUILTIN_VUPKHSW,
- RS6000_BTI_bool_V2DI, RS6000_BTI_bool_V4SI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_VUPKHSH, P8V_BUILTIN_VUPKHSW,
RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 },
{ ALTIVEC_BUILTIN_VEC_VUPKHSH, P8V_BUILTIN_VUPKHSW,
@@ -4163,7 +4174,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return build_constructor (type, vec);
}
- /* For now use pointer tricks to do the extaction, unless we are on VSX
+ /* For now use pointer tricks to do the extraction, unless we are on VSX
extracting a double from a constant offset. */
if (fcode == ALTIVEC_BUILTIN_VEC_EXTRACT)
{
@@ -4191,6 +4202,17 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
goto bad;
+ /* If we are targeting little-endian, but -maltivec=be has been
+ specified to override the element order, adjust the element
+ number accordingly. */
+ if (!BYTES_BIG_ENDIAN && rs6000_altivec_element_order == 2)
+ {
+ unsigned int last_elem = TYPE_VECTOR_SUBPARTS (arg1_type) - 1;
+ arg2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg2),
+ build_int_cstu (TREE_TYPE (arg2), last_elem),
+ arg2);
+ }
+
/* If we can use the VSX xxpermdi instruction, use that for extract. */
mode = TYPE_MODE (arg1_type);
if ((mode == V2DFmode || mode == V2DImode) && VECTOR_MEM_VSX_P (mode)
@@ -4238,7 +4260,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
return stmt;
}
- /* For now use pointer tricks to do the insertation, unless we are on VSX
+ /* For now use pointer tricks to do the insertion, unless we are on VSX
inserting a double to a constant offset.. */
if (fcode == ALTIVEC_BUILTIN_VEC_INSERT)
{
@@ -4268,6 +4290,17 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
if (!INTEGRAL_TYPE_P (TREE_TYPE (arg2)))
goto bad;
+ /* If we are targeting little-endian, but -maltivec=be has been
+ specified to override the element order, adjust the element
+ number accordingly. */
+ if (!BYTES_BIG_ENDIAN && rs6000_altivec_element_order == 2)
+ {
+ unsigned int last_elem = TYPE_VECTOR_SUBPARTS (arg1_type) - 1;
+ arg2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg2),
+ build_int_cstu (TREE_TYPE (arg2), last_elem),
+ arg2);
+ }
+
/* If we can use the VSX xxpermdi instruction, use that for insert. */
mode = TYPE_MODE (arg1_type);
if ((mode == V2DFmode || mode == V2DImode) && VECTOR_UNIT_VSX_P (mode)
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index c177512ddfd..089c98d723c 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -38,12 +38,13 @@
/* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
altivec is a win so enable it. */
+ /* OPTION_MASK_VSX_TIMODE should be set, but disable it for now until
+ PR 58587 is fixed. */
#define ISA_2_6_MASKS_EMBEDDED (ISA_2_5_MASKS_EMBEDDED | OPTION_MASK_POPCNTD)
#define ISA_2_6_MASKS_SERVER (ISA_2_5_MASKS_SERVER \
| OPTION_MASK_POPCNTD \
| OPTION_MASK_ALTIVEC \
- | OPTION_MASK_VSX \
- | OPTION_MASK_VSX_TIMODE)
+ | 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 \
@@ -52,7 +53,8 @@
| OPTION_MASK_CRYPTO \
| OPTION_MASK_DIRECT_MOVE \
| OPTION_MASK_HTM \
- | OPTION_MASK_QUAD_MEMORY)
+ | OPTION_MASK_QUAD_MEMORY \
+ | OPTION_MASK_QUAD_MEMORY_ATOMIC)
#define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
@@ -182,7 +184,7 @@ RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
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 | MASK_VSX_TIMODE)
+ | MASK_VSX | MASK_RECIP_PRECISION)
RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index e143a4ca203..52fb5896516 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -101,7 +101,8 @@ enum group_termination
/* Enumeration to give which calling sequence to use. */
enum rs6000_abi {
ABI_NONE,
- ABI_AIX, /* IBM's AIX */
+ ABI_AIX, /* IBM's AIX, or Linux ELFv1 */
+ ABI_ELFv2, /* Linux ELFv2 ABI */
ABI_V4, /* System V.4/eabi */
ABI_DARWIN /* Apple's Darwin (OS X kernel) */
};
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 5c315470f34..604a968f703 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -56,6 +56,7 @@ extern void paired_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, int);
extern void rs6000_expand_vector_extract (rtx, rtx, int);
extern bool altivec_expand_vec_perm_const (rtx op[4]);
+extern void altivec_expand_vec_perm_le (rtx op[4]);
extern bool rs6000_expand_vec_perm_const (rtx op[4]);
extern void rs6000_expand_extract_even (rtx, rtx, rtx);
extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
@@ -122,6 +123,7 @@ 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_move (rtx, rtx, enum machine_mode);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode,
@@ -153,6 +155,7 @@ extern tree altivec_resolve_overloaded_builtin (location_t, tree, void *);
extern rtx rs6000_libcall_value (enum machine_mode);
extern rtx rs6000_va_arg (tree, tree);
extern int function_ok_for_sibcall (tree);
+extern int rs6000_reg_parm_stack_space (tree);
extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
extern bool rs6000_elf_in_small_data_p (const_tree);
#ifdef ARGS_SIZE_RTX
@@ -177,7 +180,8 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *);
-extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
+extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
+extern void rs6000_sibcall_aix (rtx, rtx, rtx, rtx);
extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void get_ppc476_thunk_name (char name[32]);
extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 44681fc8580..63a60724c93 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on IBM RS/6000.
- Copyright (C) 1991-2013 Free Software Foundation, Inc.
+ Copyright (C) 1991-2014 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -56,6 +56,7 @@
#include "intl.h"
#include "params.h"
#include "tm-constrs.h"
+#include "ira.h"
#include "opts.h"
#include "tree-vectorizer.h"
#include "dumpfile.h"
@@ -96,6 +97,7 @@ typedef struct rs6000_stack {
int spe_gp_save_offset; /* offset to save spe 64-bit gprs */
int varargs_save_offset; /* offset to save the varargs registers */
int ehrd_offset; /* offset to EH return data */
+ int ehcr_offset; /* offset to EH CR field data */
int reg_size; /* register size (4 or 8) */
HOST_WIDE_INT vars_size; /* variable save area size */
int parm_size; /* outgoing parameter size */
@@ -139,6 +141,8 @@ typedef struct GTY(()) machine_function
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;
+ /* Flag if r2 setup is needed with ELFv2 ABI. */
+ bool r2_setup_needed;
} machine_function;
/* Support targetm.vectorize.builtin_mask_for_load. */
@@ -189,9 +193,6 @@ unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
/* Map register number to register class. */
enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
-/* Reload functions based on the type and the vector unit. */
-static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
-
static int dbg_cost_ctrl;
/* Built in types. */
@@ -284,9 +285,6 @@ static struct
{ "rsqrtd", (RECIP_DF_RSQRT | RECIP_V2DF_RSQRT) },
};
-/* 2 argument gen function typedef. */
-typedef rtx (*gen_2arg_fn_t) (rtx, rtx, rtx);
-
/* Pointer to function (in rs6000-c.c) that can define or undefine target
macros that have changed. Languages that don't support the preprocessor
don't link in rs6000-c.c, so we can't call it directly. */
@@ -319,11 +317,77 @@ static enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
-/* Direct moves to/from vsx/gpr registers that need an additional register to
- do the move. */
-static enum insn_code reload_fpr_gpr[NUM_MACHINE_MODES];
-static enum insn_code reload_gpr_vsx[NUM_MACHINE_MODES];
-static enum insn_code reload_vsx_gpr[NUM_MACHINE_MODES];
+
+/* Register classes we care about in secondary reload or go if legitimate
+ address. We only need to worry about GPR, FPR, and Altivec registers here,
+ along an ANY field that is the OR of the 3 register classes. */
+
+enum rs6000_reload_reg_type {
+ RELOAD_REG_GPR, /* General purpose registers. */
+ RELOAD_REG_FPR, /* Traditional floating point regs. */
+ RELOAD_REG_VMX, /* Altivec (VMX) registers. */
+ RELOAD_REG_ANY, /* OR of GPR, FPR, Altivec masks. */
+ N_RELOAD_REG
+};
+
+/* For setting up register classes, loop through the 3 register classes mapping
+ into real registers, and skip the ANY class, which is just an OR of the
+ bits. */
+#define FIRST_RELOAD_REG_CLASS RELOAD_REG_GPR
+#define LAST_RELOAD_REG_CLASS RELOAD_REG_VMX
+
+/* Map reload register type to a register in the register class. */
+struct reload_reg_map_type {
+ const char *name; /* Register class name. */
+ int reg; /* Register in the register class. */
+};
+
+static const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
+ { "Gpr", FIRST_GPR_REGNO }, /* RELOAD_REG_GPR. */
+ { "Fpr", FIRST_FPR_REGNO }, /* RELOAD_REG_FPR. */
+ { "VMX", FIRST_ALTIVEC_REGNO }, /* RELOAD_REG_VMX. */
+ { "Any", -1 }, /* RELOAD_REG_ANY. */
+};
+
+/* Mask bits for each register class, indexed per mode. Historically the
+ compiler has been more restrictive which types can do PRE_MODIFY instead of
+ PRE_INC and PRE_DEC, so keep track of sepaate bits for these two. */
+typedef unsigned char addr_mask_type;
+
+#define RELOAD_REG_VALID 0x01 /* Mode valid in register.. */
+#define RELOAD_REG_MULTIPLE 0x02 /* Mode takes multiple registers. */
+#define RELOAD_REG_INDEXED 0x04 /* Reg+reg addressing. */
+#define RELOAD_REG_OFFSET 0x08 /* Reg+offset addressing. */
+#define RELOAD_REG_PRE_INCDEC 0x10 /* PRE_INC/PRE_DEC valid. */
+#define RELOAD_REG_PRE_MODIFY 0x20 /* PRE_MODIFY valid. */
+
+/* Register type masks based on the type, of valid addressing modes. */
+struct rs6000_reg_addr {
+ enum insn_code reload_load; /* INSN to reload for loading. */
+ enum insn_code reload_store; /* INSN to reload for storing. */
+ enum insn_code reload_fpr_gpr; /* INSN to move from FPR to GPR. */
+ enum insn_code reload_gpr_vsx; /* INSN to move from GPR to VSX. */
+ enum insn_code reload_vsx_gpr; /* INSN to move from VSX to GPR. */
+ addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks. */
+};
+
+static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
+
+/* Helper function to say whether a mode supports PRE_INC or PRE_DEC. */
+static inline bool
+mode_supports_pre_incdec_p (enum machine_mode mode)
+{
+ return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
+ != 0);
+}
+
+/* Helper function to say whether a mode supports PRE_MODIFY. */
+static inline bool
+mode_supports_pre_modify_p (enum machine_mode mode)
+{
+ return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
+ != 0);
+}
/* Target cpu costs. */
@@ -1388,6 +1452,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB rs6000_return_in_msb
+
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
@@ -1497,6 +1564,9 @@ 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_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE rs6000_can_eliminate
@@ -1630,19 +1700,28 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
/* VSX registers that overlap the FPR registers are larger than for non-VSX
implementations. Don't allow an item to be split between a FP register
- and an Altivec register. */
- if (VECTOR_MEM_VSX_P (mode))
+ and an Altivec register. Allow TImode in all VSX registers if the user
+ asked for it. */
+ if (TARGET_VSX && VSX_REGNO_P (regno)
+ && (VECTOR_MEM_VSX_P (mode)
+ || (TARGET_VSX_SCALAR_FLOAT && mode == SFmode)
+ || (TARGET_VSX_SCALAR_DOUBLE && (mode == DFmode || mode == DImode))
+ || (TARGET_VSX_TIMODE && mode == TImode)))
{
if (FP_REGNO_P (regno))
return FP_REGNO_P (last_regno);
if (ALTIVEC_REGNO_P (regno))
- return ALTIVEC_REGNO_P (last_regno);
- }
+ {
+ if (mode == SFmode && !TARGET_UPPER_REGS_SF)
+ return 0;
- /* Allow TImode in all VSX registers if the user asked for it. */
- if (mode == TImode && TARGET_VSX_TIMODE && VSX_REGNO_P (regno))
- return 1;
+ if ((mode == DFmode || mode == DImode) && !TARGET_UPPER_REGS_DF)
+ return 0;
+
+ return ALTIVEC_REGNO_P (last_regno);
+ }
+ }
/* The GPRs can hold any mode, but values bigger than one register
cannot go past R31. */
@@ -1772,6 +1851,63 @@ rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
}
}
+static const char *
+rs6000_debug_vector_unit (enum rs6000_vector v)
+{
+ const char *ret;
+
+ switch (v)
+ {
+ case VECTOR_NONE: ret = "none"; break;
+ case VECTOR_ALTIVEC: ret = "altivec"; break;
+ case VECTOR_VSX: ret = "vsx"; break;
+ case VECTOR_P8_VECTOR: ret = "p8_vector"; break;
+ case VECTOR_PAIRED: ret = "paired"; break;
+ case VECTOR_SPE: ret = "spe"; break;
+ case VECTOR_OTHER: ret = "other"; break;
+ default: ret = "unknown"; break;
+ }
+
+ return ret;
+}
+
+/* Print the address masks in a human readble fashion. */
+DEBUG_FUNCTION void
+rs6000_debug_print_mode (ssize_t m)
+{
+ ssize_t rc;
+
+ fprintf (stderr, "Mode: %-5s", GET_MODE_NAME (m));
+ for (rc = 0; rc < N_RELOAD_REG; rc++)
+ {
+ addr_mask_type mask = reg_addr[m].addr_mask[rc];
+ fprintf (stderr,
+ " %s: %c%c%c%c%c%c",
+ reload_reg_map[rc].name,
+ (mask & RELOAD_REG_VALID) != 0 ? 'v' : ' ',
+ (mask & RELOAD_REG_MULTIPLE) != 0 ? 'm' : ' ',
+ (mask & RELOAD_REG_INDEXED) != 0 ? 'i' : ' ',
+ (mask & RELOAD_REG_OFFSET) != 0 ? 'o' : ' ',
+ (mask & RELOAD_REG_PRE_INCDEC) != 0 ? '+' : ' ',
+ (mask & RELOAD_REG_PRE_MODIFY) != 0 ? '+' : ' ');
+ }
+
+ if (rs6000_vector_unit[m] != VECTOR_NONE
+ || rs6000_vector_mem[m] != VECTOR_NONE
+ || (reg_addr[m].reload_store != CODE_FOR_nothing)
+ || (reg_addr[m].reload_load != CODE_FOR_nothing))
+ {
+ fprintf (stderr,
+ " Vector-arith=%-10s Vector-mem=%-10s Reload=%c%c",
+ rs6000_debug_vector_unit (rs6000_vector_unit[m]),
+ rs6000_debug_vector_unit (rs6000_vector_mem[m]),
+ (reg_addr[m].reload_store != CODE_FOR_nothing) ? 's' : '*',
+ (reg_addr[m].reload_load != CODE_FOR_nothing) ? 'l' : '*');
+ }
+
+ fputs ("\n", stderr);
+}
+
#define DEBUG_FMT_ID "%-32s= "
#define DEBUG_FMT_D DEBUG_FMT_ID "%d\n"
#define DEBUG_FMT_WX DEBUG_FMT_ID "%#.12" HOST_WIDE_INT_PRINT "x: "
@@ -1795,17 +1931,6 @@ rs6000_debug_reg_global (void)
const char *cmodel_str;
struct cl_target_option cl_opts;
- /* Map enum rs6000_vector to string. */
- static const char *rs6000_debug_vector_unit[] = {
- "none",
- "altivec",
- "vsx",
- "p8_vector",
- "paired",
- "spe",
- "other"
- };
-
/* Modes we want tieable information on. */
static const enum machine_mode print_tieable_modes[] = {
QImode,
@@ -1897,8 +2022,11 @@ rs6000_debug_reg_global (void)
"wr reg_class = %s\n"
"ws reg_class = %s\n"
"wt reg_class = %s\n"
+ "wu reg_class = %s\n"
"wv reg_class = %s\n"
+ "ww reg_class = %s\n"
"wx reg_class = %s\n"
+ "wy reg_class = %s\n"
"wz reg_class = %s\n"
"\n",
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
@@ -1913,28 +2041,18 @@ rs6000_debug_reg_global (void)
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wu]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wv]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ww]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wy]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]]);
+ nl = "\n";
for (m = 0; m < NUM_MACHINE_MODES; ++m)
- if (rs6000_vector_unit[m] || rs6000_vector_mem[m]
- || (rs6000_vector_reload[m][0] != CODE_FOR_nothing)
- || (rs6000_vector_reload[m][1] != CODE_FOR_nothing))
- {
- nl = "\n";
- fprintf (stderr,
- "Vector mode: %-5s arithmetic: %-10s move: %-10s "
- "reload-out: %c reload-in: %c\n",
- GET_MODE_NAME (m),
- rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
- rs6000_debug_vector_unit[ rs6000_vector_mem[m] ],
- (rs6000_vector_reload[m][0] != CODE_FOR_nothing) ? 'y' : 'n',
- (rs6000_vector_reload[m][1] != CODE_FOR_nothing) ? 'y' : 'n');
- }
+ rs6000_debug_print_mode (m);
- if (nl)
- fputs (nl, stderr);
+ fputs ("\n", stderr);
for (m1 = 0; m1 < ARRAY_SIZE (print_tieable_modes); m1++)
{
@@ -2122,6 +2240,7 @@ rs6000_debug_reg_global (void)
{
case ABI_NONE: abi_str = "none"; break;
case ABI_AIX: abi_str = "aix"; break;
+ case ABI_ELFv2: abi_str = "ELFv2"; break;
case ABI_V4: abi_str = "V4"; break;
case ABI_DARWIN: abi_str = "darwin"; break;
default: abi_str = "unknown"; break;
@@ -2170,11 +2289,106 @@ rs6000_debug_reg_global (void)
(int)RS6000_BUILTIN_COUNT);
}
+
+/* Update the addr mask bits in reg_addr to help secondary reload and go if
+ legitimate address support to figure out the appropriate addressing to
+ use. */
+
+static void
+rs6000_setup_reg_addr_masks (void)
+{
+ ssize_t rc, reg, m, nregs;
+ addr_mask_type any_addr_mask, addr_mask;
+
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ {
+ /* SDmode is special in that we want to access it only via REG+REG
+ addressing on power7 and above, since we want to use the LFIWZX and
+ STFIWZX instructions to load it. */
+ bool indexed_only_p = (m == SDmode && TARGET_NO_SDMODE_STACK);
+
+ any_addr_mask = 0;
+ for (rc = FIRST_RELOAD_REG_CLASS; rc <= LAST_RELOAD_REG_CLASS; rc++)
+ {
+ addr_mask = 0;
+ reg = reload_reg_map[rc].reg;
+
+ /* Can mode values go in the GPR/FPR/Altivec registers? */
+ if (reg >= 0 && rs6000_hard_regno_mode_ok_p[m][reg])
+ {
+ nregs = rs6000_hard_regno_nregs[m][reg];
+ addr_mask |= RELOAD_REG_VALID;
+
+ /* Indicate if the mode takes more than 1 physical register. If
+ it takes a single register, indicate it can do REG+REG
+ addressing. */
+ if (nregs > 1 || m == BLKmode)
+ addr_mask |= RELOAD_REG_MULTIPLE;
+ else
+ addr_mask |= RELOAD_REG_INDEXED;
+
+ /* Figure out if we can do PRE_INC, PRE_DEC, or PRE_MODIFY
+ addressing. Restrict addressing on SPE for 64-bit types
+ because of the SUBREG hackery used to address 64-bit floats in
+ '32-bit' GPRs. To simplify secondary reload, don't allow
+ update forms on scalar floating point types that can go in the
+ upper registers. */
+
+ if (TARGET_UPDATE
+ && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
+ && GET_MODE_SIZE (m) <= 8
+ && !VECTOR_MODE_P (m)
+ && !COMPLEX_MODE_P (m)
+ && !indexed_only_p
+ && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m) == 8)
+ && !(m == DFmode && TARGET_UPPER_REGS_DF)
+ && !(m == SFmode && TARGET_UPPER_REGS_SF))
+ {
+ addr_mask |= RELOAD_REG_PRE_INCDEC;
+
+ /* PRE_MODIFY is more restricted than PRE_INC/PRE_DEC in that
+ we don't allow PRE_MODIFY for some multi-register
+ operations. */
+ switch (m)
+ {
+ default:
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+
+ case DImode:
+ if (TARGET_POWERPC64)
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+
+ case DFmode:
+ case DDmode:
+ if (TARGET_DF_INSN)
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+ }
+ }
+ }
+
+ /* GPR and FPR registers can do REG+OFFSET addressing, except
+ possibly for SDmode. */
+ if ((addr_mask != 0) && !indexed_only_p
+ && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR))
+ addr_mask |= RELOAD_REG_OFFSET;
+
+ reg_addr[m].addr_mask[rc] = addr_mask;
+ any_addr_mask |= addr_mask;
+ }
+
+ reg_addr[m].addr_mask[RELOAD_REG_ANY] = any_addr_mask;
+ }
+}
+
+
/* Initialize the various global tables that are based on register size. */
static void
rs6000_init_hard_regno_mode_ok (bool global_init_p)
{
- int r, m, c;
+ ssize_t r, m, c;
int align64;
int align32;
@@ -2239,17 +2453,18 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_class_to_reg_type[(int)ALTIVEC_REGS] = ALTIVEC_REG_TYPE;
}
- /* Precalculate vector information, this must be set up before the
- rs6000_hard_regno_nregs_internal below. */
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- {
- rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
- rs6000_vector_reload[m][0] = CODE_FOR_nothing;
- rs6000_vector_reload[m][1] = CODE_FOR_nothing;
- }
+ /* Precalculate the valid memory formats as well as the vector information,
+ this must be set up before the rs6000_hard_regno_nregs_internal calls
+ below. */
+ gcc_assert ((int)VECTOR_NONE == 0);
+ memset ((void *) &rs6000_vector_unit[0], '\0', sizeof (rs6000_vector_unit));
+ memset ((void *) &rs6000_vector_mem[0], '\0', sizeof (rs6000_vector_unit));
+
+ gcc_assert ((int)CODE_FOR_nothing == 0);
+ memset ((void *) &reg_addr[0], '\0', sizeof (reg_addr));
- for (c = 0; c < (int)(int)RS6000_CONSTRAINT_MAX; c++)
- rs6000_constraints[c] = NO_REGS;
+ gcc_assert ((int)NO_REGS == 0);
+ memset ((void *) &rs6000_constraints[0], '\0', sizeof (rs6000_constraints));
/* The VSX hardware allows native alignment for vectors, but control whether the compiler
believes it can use native alignment or still uses 128-bit alignment. */
@@ -2326,7 +2541,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
{
rs6000_vector_unit[DFmode] = VECTOR_VSX;
rs6000_vector_mem[DFmode]
- = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
+ = (TARGET_UPPER_REGS_DF ? VECTOR_VSX : VECTOR_NONE);
rs6000_vector_align[DFmode] = align64;
}
@@ -2340,7 +2555,34 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
/* TODO add SPE and paired floating point vector support. */
/* Register class constraints for the constraints that depend on compile
- switches. */
+ switches. When the VSX code was added, different constraints were added
+ based on the type (DFmode, V2DFmode, V4SFmode). For the vector types, all
+ of the VSX registers are used. The register classes for scalar floating
+ point types is set, based on whether we allow that type into the upper
+ (Altivec) registers. GCC has register classes to target the Altivec
+ registers for load/store operations, to select using a VSX memory
+ operation instead of the traditional floating point operation. The
+ constraints are:
+
+ d - Register class to use with traditional DFmode instructions.
+ f - Register class to use with traditional SFmode instructions.
+ v - Altivec register.
+ wa - Any VSX register.
+ wd - Preferred register class for V2DFmode.
+ wf - Preferred register class for V4SFmode.
+ wg - Float register for power6x move insns.
+ wl - Float register if we can do 32-bit signed int loads.
+ wm - VSX register for ISA 2.07 direct move operations.
+ wr - GPR if 64-bit mode is permitted.
+ ws - Register class to do ISA 2.06 DF operations.
+ wu - Altivec register for ISA 2.07 VSX SF/SI load/stores.
+ wv - Altivec register for ISA 2.06 VSX DF/DI load/stores.
+ wt - VSX register for TImode in VSX registers.
+ ww - Register class to do SF conversions in with VSX operations.
+ wx - Float register if we can do 32-bit int stores.
+ wy - Register class to do ISA 2.07 SF operations.
+ wz - Float register if we can do 32-bit unsigned int loads. */
+
if (TARGET_HARD_FLOAT && TARGET_FPRS)
rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS;
@@ -2349,19 +2591,20 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_VSX)
{
- /* At present, we just use VSX_REGS, but we have different constraints
- based on the use, in case we want to fine tune the default register
- class used. wa = any VSX register, wf = register class to use for
- V4SF, wd = register class to use for V2DF, and ws = register classs to
- use for DF scalars. */
rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_ws] = (TARGET_VSX_SCALAR_MEMORY
- ? VSX_REGS
- : FLOAT_REGS);
+ rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
+
if (TARGET_VSX_TIMODE)
rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS;
+
+ if (TARGET_UPPER_REGS_DF)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
+ }
+ else
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = FLOAT_REGS;
}
/* Add conditional constraints based on various options, to allow us to
@@ -2381,8 +2624,19 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_POWERPC64)
rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
- if (TARGET_P8_VECTOR)
- rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
+ if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = VSX_REGS;
+ }
+ else if (TARGET_P8_VECTOR)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wy] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
+ }
+ else if (TARGET_VSX)
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
if (TARGET_STFIWX)
rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS;
@@ -2390,112 +2644,104 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_LFIWZX)
rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;
- /* Setup the direct move combinations. */
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- {
- reload_fpr_gpr[m] = CODE_FOR_nothing;
- reload_gpr_vsx[m] = CODE_FOR_nothing;
- reload_vsx_gpr[m] = CODE_FOR_nothing;
- }
-
/* Set up the reload helper and direct move functions. */
if (TARGET_VSX || TARGET_ALTIVEC)
{
if (TARGET_64BIT)
{
- rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_di_store;
- rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_di_load;
- rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_di_store;
- rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_di_load;
- rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_di_store;
- rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_di_load;
- rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_di_store;
- rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_di_load;
- rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_di_store;
- rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load;
- rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store;
- rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load;
- if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ reg_addr[V16QImode].reload_store = CODE_FOR_reload_v16qi_di_store;
+ reg_addr[V16QImode].reload_load = CODE_FOR_reload_v16qi_di_load;
+ reg_addr[V8HImode].reload_store = CODE_FOR_reload_v8hi_di_store;
+ reg_addr[V8HImode].reload_load = CODE_FOR_reload_v8hi_di_load;
+ reg_addr[V4SImode].reload_store = CODE_FOR_reload_v4si_di_store;
+ reg_addr[V4SImode].reload_load = CODE_FOR_reload_v4si_di_load;
+ reg_addr[V2DImode].reload_store = CODE_FOR_reload_v2di_di_store;
+ reg_addr[V2DImode].reload_load = CODE_FOR_reload_v2di_di_load;
+ reg_addr[V4SFmode].reload_store = CODE_FOR_reload_v4sf_di_store;
+ reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_di_load;
+ reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_di_store;
+ reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_di_load;
+ if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_di_store;
- rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_di_load;
- rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_di_store;
- rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_di_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_di_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_di_load;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_di_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_di_load;
}
if (TARGET_P8_VECTOR)
{
- rs6000_vector_reload[SFmode][0] = CODE_FOR_reload_sf_di_store;
- rs6000_vector_reload[SFmode][1] = CODE_FOR_reload_sf_di_load;
- rs6000_vector_reload[SDmode][0] = CODE_FOR_reload_sd_di_store;
- rs6000_vector_reload[SDmode][1] = CODE_FOR_reload_sd_di_load;
+ reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_di_store;
+ reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_di_load;
+ reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_di_store;
+ reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_di_load;
}
if (TARGET_VSX_TIMODE)
{
- rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_di_store;
- rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_di_load;
+ reg_addr[TImode].reload_store = CODE_FOR_reload_ti_di_store;
+ reg_addr[TImode].reload_load = CODE_FOR_reload_ti_di_load;
}
if (TARGET_DIRECT_MOVE)
{
if (TARGET_POWERPC64)
{
- reload_gpr_vsx[TImode] = CODE_FOR_reload_gpr_from_vsxti;
- reload_gpr_vsx[V2DFmode] = CODE_FOR_reload_gpr_from_vsxv2df;
- reload_gpr_vsx[V2DImode] = CODE_FOR_reload_gpr_from_vsxv2di;
- reload_gpr_vsx[V4SFmode] = CODE_FOR_reload_gpr_from_vsxv4sf;
- reload_gpr_vsx[V4SImode] = CODE_FOR_reload_gpr_from_vsxv4si;
- reload_gpr_vsx[V8HImode] = CODE_FOR_reload_gpr_from_vsxv8hi;
- reload_gpr_vsx[V16QImode] = CODE_FOR_reload_gpr_from_vsxv16qi;
- reload_gpr_vsx[SFmode] = CODE_FOR_reload_gpr_from_vsxsf;
-
- reload_vsx_gpr[TImode] = CODE_FOR_reload_vsx_from_gprti;
- reload_vsx_gpr[V2DFmode] = CODE_FOR_reload_vsx_from_gprv2df;
- reload_vsx_gpr[V2DImode] = CODE_FOR_reload_vsx_from_gprv2di;
- reload_vsx_gpr[V4SFmode] = CODE_FOR_reload_vsx_from_gprv4sf;
- reload_vsx_gpr[V4SImode] = CODE_FOR_reload_vsx_from_gprv4si;
- reload_vsx_gpr[V8HImode] = CODE_FOR_reload_vsx_from_gprv8hi;
- reload_vsx_gpr[V16QImode] = CODE_FOR_reload_vsx_from_gprv16qi;
- reload_vsx_gpr[SFmode] = CODE_FOR_reload_vsx_from_gprsf;
+ reg_addr[TImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxti;
+ reg_addr[V2DFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv2df;
+ reg_addr[V2DImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv2di;
+ reg_addr[V4SFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv4sf;
+ reg_addr[V4SImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv4si;
+ reg_addr[V8HImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv8hi;
+ reg_addr[V16QImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv16qi;
+ reg_addr[SFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxsf;
+
+ reg_addr[TImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprti;
+ reg_addr[V2DFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv2df;
+ reg_addr[V2DImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv2di;
+ reg_addr[V4SFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv4sf;
+ reg_addr[V4SImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv4si;
+ reg_addr[V8HImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv8hi;
+ reg_addr[V16QImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv16qi;
+ reg_addr[SFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprsf;
}
else
{
- reload_fpr_gpr[DImode] = CODE_FOR_reload_fpr_from_gprdi;
- reload_fpr_gpr[DDmode] = CODE_FOR_reload_fpr_from_gprdd;
- reload_fpr_gpr[DFmode] = CODE_FOR_reload_fpr_from_gprdf;
+ reg_addr[DImode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdi;
+ reg_addr[DDmode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdd;
+ reg_addr[DFmode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdf;
}
}
}
else
{
- rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_si_store;
- rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_si_load;
- rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_si_store;
- rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_si_load;
- rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_si_store;
- rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_si_load;
- rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_si_store;
- rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_si_load;
- rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_si_store;
- rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load;
- rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store;
- rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load;
- if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ reg_addr[V16QImode].reload_store = CODE_FOR_reload_v16qi_si_store;
+ reg_addr[V16QImode].reload_load = CODE_FOR_reload_v16qi_si_load;
+ reg_addr[V8HImode].reload_store = CODE_FOR_reload_v8hi_si_store;
+ reg_addr[V8HImode].reload_load = CODE_FOR_reload_v8hi_si_load;
+ reg_addr[V4SImode].reload_store = CODE_FOR_reload_v4si_si_store;
+ reg_addr[V4SImode].reload_load = CODE_FOR_reload_v4si_si_load;
+ reg_addr[V2DImode].reload_store = CODE_FOR_reload_v2di_si_store;
+ reg_addr[V2DImode].reload_load = CODE_FOR_reload_v2di_si_load;
+ reg_addr[V4SFmode].reload_store = CODE_FOR_reload_v4sf_si_store;
+ reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_si_load;
+ reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_si_store;
+ reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_si_load;
+ if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_si_store;
- rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_si_load;
- rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_si_store;
- rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_si_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_si_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_si_load;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_si_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_si_load;
}
if (TARGET_P8_VECTOR)
{
- rs6000_vector_reload[SFmode][0] = CODE_FOR_reload_sf_si_store;
- rs6000_vector_reload[SFmode][1] = CODE_FOR_reload_sf_si_load;
- rs6000_vector_reload[SDmode][0] = CODE_FOR_reload_sd_si_store;
- rs6000_vector_reload[SDmode][1] = CODE_FOR_reload_sd_si_load;
+ reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_si_store;
+ reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_si_load;
+ reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_si_store;
+ reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_si_load;
}
if (TARGET_VSX_TIMODE)
{
- rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_si_store;
- rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_si_load;
+ reg_addr[TImode].reload_store = CODE_FOR_reload_ti_si_store;
+ reg_addr[TImode].reload_load = CODE_FOR_reload_ti_si_load;
}
}
}
@@ -2614,6 +2860,11 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
}
}
+ /* Update the addr mask bits in reg_addr to help secondary reload and go if
+ legitimate address support to figure out the appropriate addressing to
+ use. */
+ rs6000_setup_reg_addr_masks ();
+
if (global_init_p || TARGET_DEBUG_TARGET)
{
if (TARGET_DEBUG_REG)
@@ -2959,6 +3210,24 @@ rs6000_option_override_internal (bool global_init_p)
}
}
+ /* If little-endian, default to -mstrict-align on older processors.
+ Testing for htm matches power8 and later. */
+ if (!BYTES_BIG_ENDIAN
+ && !(processor_target_table[tune_index].target_enable & OPTION_MASK_HTM))
+ rs6000_isa_flags |= ~rs6000_isa_flags_explicit & OPTION_MASK_STRICT_ALIGN;
+
+ /* -maltivec={le,be} implies -maltivec. */
+ if (rs6000_altivec_element_order != 0)
+ rs6000_isa_flags |= OPTION_MASK_ALTIVEC;
+
+ /* Disallow -maltivec=le in big endian mode for now. This is not
+ known to be useful for anyone. */
+ if (BYTES_BIG_ENDIAN && rs6000_altivec_element_order == 1)
+ {
+ warning (0, N_("-maltivec=le not allowed for big-endian targets"));
+ rs6000_altivec_element_order = 0;
+ }
+
/* Add some warnings for VSX. */
if (TARGET_VSX)
{
@@ -2976,11 +3245,6 @@ rs6000_option_override_internal (bool global_init_p)
}
else if (TARGET_PAIRED_FLOAT)
msg = N_("-mvsx and -mpaired are incompatible");
- /* The hardware will allow VSX and little endian, but until we make sure
- things like vector select, etc. work don't allow VSX on little endian
- systems at this point. */
- else if (!BYTES_BIG_ENDIAN)
- msg = N_("-mvsx used with little endian code");
else if (TARGET_AVOID_XFORM > 0)
msg = N_("-mvsx needs indexed addressing");
else if (!TARGET_ALTIVEC && (rs6000_isa_flags_explicit
@@ -3069,14 +3333,37 @@ rs6000_option_override_internal (bool global_init_p)
/* 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_POWERPC64)
+ if ((TARGET_QUAD_MEMORY || TARGET_QUAD_MEMORY_ATOMIC) && !TARGET_POWERPC64)
{
if ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY) != 0)
warning (0, N_("-mquad-memory requires 64-bit mode"));
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY_ATOMIC) != 0)
+ warning (0, N_("-mquad-memory-atomic requires 64-bit mode"));
+
+ rs6000_isa_flags &= ~(OPTION_MASK_QUAD_MEMORY
+ | OPTION_MASK_QUAD_MEMORY_ATOMIC);
+ }
+
+ /* Non-atomic quad memory load/store are disabled for little endian, since
+ the words are reversed, but atomic operations can still be done by
+ swapping the words. */
+ if (TARGET_QUAD_MEMORY && !WORDS_BIG_ENDIAN)
+ {
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY) != 0)
+ warning (0, N_("-mquad-memory is not available in little endian mode"));
+
rs6000_isa_flags &= ~OPTION_MASK_QUAD_MEMORY;
}
+ /* Assume if the user asked for normal quad memory instructions, they want
+ the atomic versions as well, unless they explicity told us not to use quad
+ word atomic instructions. */
+ if (TARGET_QUAD_MEMORY
+ && !TARGET_QUAD_MEMORY_ATOMIC
+ && ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY_ATOMIC) == 0))
+ rs6000_isa_flags |= OPTION_MASK_QUAD_MEMORY_ATOMIC;
+
/* Enable power8 fusion if we are tuning for power8, even if we aren't
generating power8 instructions. */
if (!(rs6000_isa_flags_explicit & OPTION_MASK_P8_FUSION))
@@ -3428,7 +3715,7 @@ rs6000_option_override_internal (bool global_init_p)
/* We should always be splitting complex arguments, but we can't break
Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */
- if (DEFAULT_ABI != ABI_AIX)
+ if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN)
targetm.calls.split_complex_arg = NULL;
}
@@ -4520,7 +4807,11 @@ rs6000_file_start (void)
putc ('\n', file);
}
- if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
+ if (DEFAULT_ABI == ABI_ELFv2)
+ fprintf (file, "\t.abiversion 2\n");
+
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2
+ || (TARGET_ELF && flag_pic == 2))
{
switch_to_section (toc_section);
switch_to_section (text_section);
@@ -4716,7 +5007,7 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
val = const_vector_elt_as_int (op, BYTES_BIG_ENDIAN ? nunits - 1 : 0);
splat_val = val;
- msb_val = val > 0 ? 0 : -1;
+ msb_val = val >= 0 ? 0 : -1;
/* Construct the value to be splatted, if possible. If not, return 0. */
for (i = 2; i <= copies; i *= 2)
@@ -4751,15 +5042,16 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
/* Check if VAL is present in every STEP-th element, and the
other elements are filled with its most significant bit. */
- for (i = 0; i < nunits - 1; ++i)
+ for (i = 1; i < nunits; ++i)
{
HOST_WIDE_INT desired_val;
- if (((BYTES_BIG_ENDIAN ? i + 1 : i) & (step - 1)) == 0)
+ unsigned elt = BYTES_BIG_ENDIAN ? nunits - 1 - i : i;
+ if ((i & (step - 1)) == 0)
desired_val = val;
else
desired_val = msb_val;
- if (desired_val != const_vector_elt_as_int (op, i))
+ if (desired_val != const_vector_elt_as_int (op, elt))
return false;
}
@@ -5180,7 +5472,7 @@ rs6000_expand_vector_init (rtx target, rtx vals)
: gen_vsx_xscvdpsp_scalar (freg, sreg));
emit_insn (cvt);
- emit_insn (gen_vsx_xxspltw_v4sf (target, freg, const0_rtx));
+ emit_insn (gen_vsx_xxspltw_v4sf_direct (target, freg, const0_rtx));
}
else
{
@@ -5291,10 +5583,27 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
XVECEXP (mask, 0, elt*width + i)
= GEN_INT (i + 0x10);
x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
- x = gen_rtx_UNSPEC (mode,
- gen_rtvec (3, target, reg,
- force_reg (V16QImode, x)),
- UNSPEC_VPERM);
+
+ if (BYTES_BIG_ENDIAN)
+ x = gen_rtx_UNSPEC (mode,
+ gen_rtvec (3, target, reg,
+ force_reg (V16QImode, x)),
+ UNSPEC_VPERM);
+ else
+ {
+ /* Invert selector. */
+ rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, splat);
+ x = gen_rtx_MINUS (V16QImode, tmp, force_reg (V16QImode, x));
+ emit_move_insn (tmp, x);
+
+ /* Permute with operands reversed and adjusted selector. */
+ x = gen_rtx_UNSPEC (mode, gen_rtvec (3, reg, target, tmp),
+ UNSPEC_VPERM);
+ }
+
emit_insn (gen_rtx_SET (VOIDmode, target, x));
}
@@ -5602,7 +5911,8 @@ direct_move_p (rtx op0, rtx op1)
return false;
}
-/* Return true if this is a load or store quad operation. */
+/* Return true if this is a load or store quad operation. This function does
+ not handle the atomic quad memory instructions. */
bool
quad_load_store_p (rtx op0, rtx op1)
@@ -5893,7 +6203,7 @@ toc_relative_expr_p (const_rtx op, bool strict)
tocrel_base = op;
tocrel_offset = const0_rtx;
- if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
+ if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), GET_MODE (op)))
{
tocrel_base = XEXP (op, 0);
tocrel_offset = XEXP (op, 1);
@@ -5945,7 +6255,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
return false;
if (!reg_offset_addressing_ok_p (mode))
return virtual_stack_registers_memory_p (x);
- if (legitimate_constant_pool_address_p (x, mode, strict))
+ if (legitimate_constant_pool_address_p (x, mode, strict || lra_in_progress))
return true;
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
@@ -5986,13 +6296,14 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
break;
case TFmode:
- case TDmode:
- case TImode:
- case PTImode:
if (TARGET_E500_DOUBLE)
return (SPE_CONST_OFFSET_OK (offset)
&& SPE_CONST_OFFSET_OK (offset + 8));
+ /* fall through */
+ case TDmode:
+ case TImode:
+ case PTImode:
extra = 8;
if (!worst_case)
break;
@@ -6085,9 +6396,21 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
if (TARGET_ELF || TARGET_MACHO)
{
- if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
+ bool large_toc_ok;
+
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
return false;
- if (TARGET_TOC)
+ /* LRA don't use LEGITIMIZE_RELOAD_ADDRESS as it usually calls
+ push_reload from reload pass code. LEGITIMIZE_RELOAD_ADDRESS
+ recognizes some LO_SUM addresses as valid although this
+ function says opposite. In most cases, LRA through different
+ transformations can generate correct code for address reloads.
+ It can not manage only some LO_SUM cases. So we need to add
+ code analogous to one in rs6000_legitimize_reload_address for
+ LOW_SUM here saying that some addresses are still valid. */
+ large_toc_ok = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL
+ && small_toc_ref (x, VOIDmode));
+ if (TARGET_TOC && ! large_toc_ok)
return false;
if (GET_MODE_NUNITS (mode) != 1)
return false;
@@ -6097,7 +6420,7 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
&& (mode == DFmode || mode == DDmode)))
return false;
- return CONSTANT_P (x);
+ return CONSTANT_P (x) || large_toc_ok;
}
return false;
@@ -6662,10 +6985,13 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
1, const0_rtx, Pmode);
r3 = gen_rtx_REG (Pmode, 3);
- if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
- insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
- else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
- insn = gen_tls_gd_aix32 (r3, got, addr, tga, const0_rtx);
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ if (TARGET_64BIT)
+ insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
+ else
+ insn = gen_tls_gd_aix32 (r3, got, addr, tga, const0_rtx);
+ }
else if (DEFAULT_ABI == ABI_V4)
insn = gen_tls_gd_sysvsi (r3, got, addr, tga, const0_rtx);
else
@@ -6684,10 +7010,13 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
1, const0_rtx, Pmode);
r3 = gen_rtx_REG (Pmode, 3);
- if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
- insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
- else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
- insn = gen_tls_ld_aix32 (r3, got, tga, const0_rtx);
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ if (TARGET_64BIT)
+ insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
+ else
+ insn = gen_tls_ld_aix32 (r3, got, tga, const0_rtx);
+ }
else if (DEFAULT_ABI == ABI_V4)
insn = gen_tls_ld_sysvsi (r3, got, tga, const0_rtx);
else
@@ -6802,7 +7131,6 @@ use_toc_relative_ref (rtx sym)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
get_pool_mode (sym)))
|| (TARGET_CMODEL == CMODEL_MEDIUM
- && !CONSTANT_POOL_ADDRESS_P (sym)
&& SYMBOL_REF_LOCAL_P (sym)));
}
@@ -7080,17 +7408,9 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
return 0;
if (legitimate_indirect_address_p (x, reg_ok_strict))
return 1;
- if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
- && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
- && !SPE_VECTOR_MODE (mode)
- && mode != TFmode
- && mode != TDmode
- && mode != TImode
- && mode != PTImode
- /* Restrict addressing for DI because of our SUBREG hackery. */
- && !(TARGET_E500_DOUBLE
- && (mode == DFmode || mode == DDmode || mode == DImode))
- && TARGET_UPDATE
+ if (TARGET_UPDATE
+ && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && mode_supports_pre_incdec_p (mode)
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
if (virtual_stack_registers_memory_p (x))
@@ -7098,14 +7418,15 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
if (reg_offset_p && legitimate_small_data_p (mode, x))
return 1;
if (reg_offset_p
- && legitimate_constant_pool_address_p (x, mode, reg_ok_strict))
+ && legitimate_constant_pool_address_p (x, mode,
+ reg_ok_strict || lra_in_progress))
return 1;
- /* For TImode, if we have load/store quad, only allow register indirect
- addresses. This will allow the values to go in either GPRs or VSX
- registers without reloading. The vector types would tend to go into VSX
- registers, so we allow REG+REG, while TImode seems somewhat split, in that
- some uses are GPR based, and some VSX based. */
- if (mode == TImode && TARGET_QUAD_MEMORY)
+ /* For TImode, if we have load/store quad and TImode in VSX registers, only
+ allow register indirect addresses. This will allow the values to go in
+ either GPRs or VSX registers without reloading. The vector types would
+ tend to go into VSX registers, so we allow REG+REG, while TImode seems
+ somewhat split, in that some uses are GPR based, and some VSX based. */
+ if (mode == TImode && TARGET_QUAD_MEMORY && TARGET_VSX_TIMODE)
return 0;
/* If not REG_OK_STRICT (before reload) let pass any stack offset. */
if (! reg_ok_strict
@@ -7130,21 +7451,8 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
&& !avoiding_indexed_address_p (mode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
- if (GET_CODE (x) == PRE_MODIFY
- && mode != TImode
- && mode != PTImode
- && mode != TFmode
- && mode != TDmode
- && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
- || TARGET_POWERPC64
- || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
- && (TARGET_POWERPC64 || mode != DImode)
- && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
- && !SPE_VECTOR_MODE (mode)
- /* Restrict addressing for DI because of our SUBREG hackery. */
- && !(TARGET_E500_DOUBLE
- && (mode == DFmode || mode == DDmode || mode == DImode))
- && TARGET_UPDATE
+ if (TARGET_UPDATE && GET_CODE (x) == PRE_MODIFY
+ && mode_supports_pre_modify_p (mode)
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
&& (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1),
reg_ok_strict, false)
@@ -7165,10 +7473,13 @@ rs6000_debug_legitimate_address_p (enum machine_mode mode, rtx x,
bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
fprintf (stderr,
"\nrs6000_legitimate_address_p: return = %s, mode = %s, "
- "strict = %d, code = %s\n",
+ "strict = %d, reload = %s, code = %s\n",
ret ? "true" : "false",
GET_MODE_NAME (mode),
reg_ok_strict,
+ (reload_completed
+ ? "after"
+ : (reload_in_progress ? "progress" : "before")),
GET_RTX_NAME (GET_CODE (x)));
debug_rtx (x);
@@ -7334,7 +7645,7 @@ rs6000_conditional_register_usage (void)
/* The TOC register is not killed across calls in a way that is
visible to the compiler. */
- if (DEFAULT_ABI == ABI_AIX)
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
call_really_used_regs[2] = 0;
if (DEFAULT_ABI == ABI_V4
@@ -7394,6 +7705,7 @@ rs6000_conditional_register_usage (void)
fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
}
}
+
/* Try to output insns to set TARGET equal to the constant C if it can
be done in less than N insns. Do all computations in MODE.
@@ -7607,6 +7919,107 @@ rs6000_eliminate_indexed_memrefs (rtx operands[2])
copy_addr_to_reg (XEXP (operands[1], 0)));
}
+/* Generate a vector of constants to permute MODE for a little-endian
+ storage operation by swapping the two halves of a vector. */
+static rtvec
+rs6000_const_vec (enum machine_mode mode)
+{
+ int i, subparts;
+ rtvec v;
+
+ switch (mode)
+ {
+ case V2DFmode:
+ case V2DImode:
+ subparts = 2;
+ break;
+ case V4SFmode:
+ case V4SImode:
+ subparts = 4;
+ break;
+ case V8HImode:
+ subparts = 8;
+ break;
+ case V16QImode:
+ subparts = 16;
+ break;
+ default:
+ gcc_unreachable();
+ }
+
+ v = rtvec_alloc (subparts);
+
+ for (i = 0; i < subparts / 2; ++i)
+ RTVEC_ELT (v, i) = gen_rtx_CONST_INT (DImode, i + subparts / 2);
+ for (i = subparts / 2; i < subparts; ++i)
+ RTVEC_ELT (v, i) = gen_rtx_CONST_INT (DImode, i - subparts / 2);
+
+ 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, enum machine_mode mode)
+{
+ rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+ return gen_rtx_VEC_SELECT (mode, source, par);
+}
+
+/* Emit a little-endian load from vector memory location SOURCE to VSX
+ register DEST in mode MODE. The load is done with two permuting
+ insn's that represent an lxvd2x and xxpermdi. */
+void
+rs6000_emit_le_vsx_load (rtx dest, rtx source, enum machine_mode mode)
+{
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (dest) : dest;
+ rtx permute_mem = rs6000_gen_le_vsx_permute (source, mode);
+ rtx permute_reg = rs6000_gen_le_vsx_permute (tmp, mode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, permute_mem));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, permute_reg));
+}
+
+/* Emit a little-endian store to vector memory location DEST from VSX
+ register SOURCE in mode MODE. The store is done with two permuting
+ insn's that represent an xxpermdi and an stxvd2x. */
+void
+rs6000_emit_le_vsx_store (rtx dest, rtx source, enum machine_mode mode)
+{
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (source) : source;
+ rtx permute_src = rs6000_gen_le_vsx_permute (source, mode);
+ rtx permute_tmp = rs6000_gen_le_vsx_permute (tmp, mode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, permute_src));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, permute_tmp));
+}
+
+/* Emit a sequence representing a little-endian VSX load or store,
+ moving data from SOURCE to DEST in mode MODE. This is done
+ separately from rs6000_emit_move to ensure it is called only
+ during expand. LE VSX loads and stores introduced later are
+ handled with a split. The expand-time RTL generation allows
+ us to optimize away redundant pairs of register-permutes. */
+void
+rs6000_emit_le_vsx_move (rtx dest, rtx source, enum machine_mode mode)
+{
+ gcc_assert (!BYTES_BIG_ENDIAN
+ && VECTOR_MEM_VSX_P (mode)
+ && mode != TImode
+ && !gpr_or_gpr_p (dest, source)
+ && (MEM_P (source) ^ MEM_P (dest)));
+
+ if (MEM_P (source))
+ {
+ gcc_assert (REG_P (dest));
+ rs6000_emit_le_vsx_load (dest, source, mode);
+ }
+ else
+ {
+ if (!REG_P (source))
+ source = force_reg (mode, source);
+ rs6000_emit_le_vsx_store (dest, source, mode);
+ }
+}
+
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
@@ -7725,6 +8138,68 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
cfun->machine->sdmode_stack_slot =
eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
+
+ if (lra_in_progress
+ && mode == SDmode
+ && REG_P (operands[0]) && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER
+ && reg_preferred_class (REGNO (operands[0])) == NO_REGS
+ && (REG_P (operands[1])
+ || (GET_CODE (operands[1]) == SUBREG
+ && REG_P (SUBREG_REG (operands[1])))))
+ {
+ int regno = REGNO (GET_CODE (operands[1]) == SUBREG
+ ? SUBREG_REG (operands[1]) : operands[1]);
+ enum reg_class cl;
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ cl = reg_preferred_class (regno);
+ gcc_assert (cl != NO_REGS);
+ regno = ira_class_hard_regs[cl][0];
+ }
+ if (FP_REGNO_P (regno))
+ {
+ if (GET_MODE (operands[0]) != DDmode)
+ operands[0] = gen_rtx_SUBREG (DDmode, operands[0], 0);
+ emit_insn (gen_movsd_store (operands[0], operands[1]));
+ }
+ else if (INT_REGNO_P (regno))
+ emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+ else
+ gcc_unreachable();
+ return;
+ }
+ if (lra_in_progress
+ && mode == SDmode
+ && (REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && REG_P (SUBREG_REG (operands[0]))))
+ && REG_P (operands[1]) && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER
+ && reg_preferred_class (REGNO (operands[1])) == NO_REGS)
+ {
+ int regno = REGNO (GET_CODE (operands[0]) == SUBREG
+ ? SUBREG_REG (operands[0]) : operands[0]);
+ enum reg_class cl;
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ cl = reg_preferred_class (regno);
+ gcc_assert (cl != NO_REGS);
+ regno = ira_class_hard_regs[cl][0];
+ }
+ if (FP_REGNO_P (regno))
+ {
+ if (GET_MODE (operands[1]) != DDmode)
+ operands[1] = gen_rtx_SUBREG (DDmode, operands[1], 0);
+ emit_insn (gen_movsd_load (operands[0], operands[1]));
+ }
+ else if (INT_REGNO_P (regno))
+ emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+ else
+ gcc_unreachable();
+ return;
+ }
+
if (reload_in_progress
&& mode == SDmode
&& cfun->machine->sdmode_stack_slot != NULL_RTX
@@ -7740,7 +8215,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
}
else if (INT_REGNO_P (REGNO (operands[1])))
{
- rtx mem = adjust_address_nv (operands[0], mode, 4);
+ 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]));
}
@@ -7763,7 +8240,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
}
else if (INT_REGNO_P (REGNO (operands[0])))
{
- rtx mem = adjust_address_nv (operands[1], mode, 4);
+ 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));
}
@@ -8009,18 +8488,231 @@ rs6000_member_type_forces_blk (const_tree field, enum machine_mode mode)
}
/* Nonzero if we can use a floating-point register to pass this arg. */
-#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
+#define USE_FP_FOR_ARG_P(CUM,MODE) \
(SCALAR_FLOAT_MODE_P (MODE) \
&& (CUM)->fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
/* Nonzero if we can use an AltiVec register to pass this arg. */
-#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
+#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,NAMED) \
(ALTIVEC_OR_VSX_VECTOR_MODE (MODE) \
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI \
&& (NAMED))
+/* Walk down the type tree of TYPE counting consecutive base elements.
+ If *MODEP is VOIDmode, then set it to the first valid floating point
+ or vector type. If a non-floating point or vector type is found, or
+ if a floating point or vector type that doesn't match a non-VOIDmode
+ *MODEP is found, then return -1, otherwise return the count in the
+ sub-tree. */
+
+static int
+rs6000_aggregate_candidate (const_tree type, enum machine_mode *modep)
+{
+ enum machine_mode mode;
+ HOST_WIDE_INT size;
+
+ switch (TREE_CODE (type))
+ {
+ case REAL_TYPE:
+ mode = TYPE_MODE (type);
+ if (!SCALAR_FLOAT_MODE_P (mode))
+ return -1;
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ if (*modep == mode)
+ return 1;
+
+ break;
+
+ case COMPLEX_TYPE:
+ mode = TYPE_MODE (TREE_TYPE (type));
+ if (!SCALAR_FLOAT_MODE_P (mode))
+ return -1;
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ if (*modep == mode)
+ return 2;
+
+ break;
+
+ case VECTOR_TYPE:
+ if (!TARGET_ALTIVEC_ABI || !TARGET_ALTIVEC)
+ return -1;
+
+ /* Use V4SImode as representative of all 128-bit vector types. */
+ size = int_size_in_bytes (type);
+ switch (size)
+ {
+ case 16:
+ mode = V4SImode;
+ break;
+ default:
+ return -1;
+ }
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ /* Vector modes are considered to be opaque: two vectors are
+ equivalent for the purposes of being homogeneous aggregates
+ if they are the same size. */
+ if (*modep == mode)
+ return 1;
+
+ break;
+
+ case ARRAY_TYPE:
+ {
+ int count;
+ tree index = TYPE_DOMAIN (type);
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P (type))
+ return -1;
+
+ count = rs6000_aggregate_candidate (TREE_TYPE (type), modep);
+ if (count == -1
+ || !index
+ || !TYPE_MAX_VALUE (index)
+ || !host_integerp (TYPE_MAX_VALUE (index), 1)
+ || !TYPE_MIN_VALUE (index)
+ || !host_integerp (TYPE_MIN_VALUE (index), 1)
+ || count < 0)
+ return -1;
+
+ count *= (1 + tree_low_cst (TYPE_MAX_VALUE (index), 1)
+ - tree_low_cst (TYPE_MIN_VALUE (index), 1));
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ case RECORD_TYPE:
+ {
+ int count = 0;
+ int sub_count;
+ tree field;
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P (type))
+ return -1;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep);
+ if (sub_count < 0)
+ return -1;
+ count += sub_count;
+ }
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ /* These aren't very interesting except in a degenerate case. */
+ int count = 0;
+ int sub_count;
+ tree field;
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P (type))
+ return -1;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep);
+ if (sub_count < 0)
+ return -1;
+ count = count > sub_count ? count : sub_count;
+ }
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/* If an argument, whose type is described by TYPE and MODE, is a homogeneous
+ float or vector aggregate that shall be passed in FP/vector registers
+ according to the ELFv2 ABI, return the homogeneous element mode in
+ *ELT_MODE and the number of elements in *N_ELTS, and return TRUE.
+
+ Otherwise, set *ELT_MODE to MODE and *N_ELTS to 1, and return FALSE. */
+
+static bool
+rs6000_discover_homogeneous_aggregate (enum machine_mode mode, const_tree type,
+ enum machine_mode *elt_mode,
+ int *n_elts)
+{
+ /* Note that we do not accept complex types at the top level as
+ homogeneous aggregates; these types are handled via the
+ targetm.calls.split_complex_arg mechanism. Complex types
+ can be elements of homogeneous aggregates, however. */
+ if (DEFAULT_ABI == ABI_ELFv2 && type && AGGREGATE_TYPE_P (type))
+ {
+ enum machine_mode field_mode = VOIDmode;
+ int field_count = rs6000_aggregate_candidate (type, &field_mode);
+
+ if (field_count > 0)
+ {
+ int n_regs = (SCALAR_FLOAT_MODE_P (field_mode)?
+ (GET_MODE_SIZE (field_mode) + 7) >> 3 : 1);
+
+ /* The ELFv2 ABI allows homogeneous aggregates to occupy
+ up to AGGR_ARG_NUM_REG registers. */
+ if (field_count * n_regs <= AGGR_ARG_NUM_REG)
+ {
+ if (elt_mode)
+ *elt_mode = field_mode;
+ if (n_elts)
+ *n_elts = field_count;
+ return true;
+ }
+ }
+ }
+
+ if (elt_mode)
+ *elt_mode = mode;
+ if (n_elts)
+ *n_elts = 1;
+ return false;
+}
+
/* Return a nonzero value to say to return the function value in
memory, just as large structures are always returned. TYPE will be
the data type of the value, and FNTYPE will be the type of the
@@ -8073,6 +8765,16 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
/* Otherwise fall through to more conventional ABI rules. */
}
+ /* The ELFv2 ABI returns homogeneous VFP aggregates in registers */
+ if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (type), type,
+ NULL, NULL))
+ return false;
+
+ /* The ELFv2 ABI returns aggregates up to 16B in registers */
+ if (DEFAULT_ABI == ABI_ELFv2 && AGGREGATE_TYPE_P (type)
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) <= 16)
+ return false;
+
if (AGGREGATE_TYPE_P (type)
&& (aix_struct_return
|| (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
@@ -8104,6 +8806,19 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
return false;
}
+/* Specify whether values returned in registers should be at the most
+ significant end of a register. We want aggregates returned by
+ value to match the way aggregates are passed to functions. */
+
+static bool
+rs6000_return_in_msb (const_tree valtype)
+{
+ return (DEFAULT_ABI == ABI_ELFv2
+ && BYTES_BIG_ENDIAN
+ && AGGREGATE_TYPE_P (valtype)
+ && FUNCTION_ARG_PADDING (TYPE_MODE (valtype), valtype) == upward);
+}
+
#ifdef HAVE_AS_GNU_ATTRIBUTE
/* Return TRUE if a call to function FNDECL may be one that
potentially affects the function calling ABI of the object file. */
@@ -8240,7 +8955,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
static bool
rs6000_must_pass_in_stack (enum machine_mode mode, const_tree type)
{
- if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT)
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT)
return must_pass_in_stack_var_size (mode, type);
else
return must_pass_in_stack_var_size_or_pad (mode, type);
@@ -8321,6 +9036,11 @@ function_arg_padding (enum machine_mode mode, const_tree type)
static unsigned int
rs6000_function_arg_boundary (enum machine_mode mode, const_tree type)
{
+ enum machine_mode elt_mode;
+ int n_elts;
+
+ rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+
if (DEFAULT_ABI == ABI_V4
&& (GET_MODE_SIZE (mode) == 8
|| (TARGET_HARD_FLOAT
@@ -8332,12 +9052,13 @@ rs6000_function_arg_boundary (enum machine_mode mode, const_tree type)
&& int_size_in_bytes (type) >= 8
&& int_size_in_bytes (type) < 16))
return 64;
- else if (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) >= 16))
return 128;
- else if (TARGET_MACHO
- && rs6000_darwin64_abi
+ else if (((TARGET_MACHO && rs6000_darwin64_abi)
+ || DEFAULT_ABI == ABI_ELFv2
+ || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
&& mode == BLKmode
&& type && TYPE_ALIGN (type) > 64)
return 128;
@@ -8345,6 +9066,16 @@ rs6000_function_arg_boundary (enum machine_mode mode, const_tree type)
return PARM_BOUNDARY;
}
+/* The offset in words to the start of the parameter save area. */
+
+static unsigned int
+rs6000_parm_offset (void)
+{
+ return (DEFAULT_ABI == ABI_V4 ? 2
+ : DEFAULT_ABI == ABI_ELFv2 ? 4
+ : 6);
+}
+
/* For a function parm of MODE and TYPE, return the starting word in
the parameter area. NWORDS of the parameter area are already used. */
@@ -8353,11 +9084,9 @@ rs6000_parm_start (enum machine_mode mode, const_tree type,
unsigned int nwords)
{
unsigned int align;
- unsigned int parm_offset;
align = rs6000_function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
- parm_offset = DEFAULT_ABI == ABI_V4 ? 2 : 6;
- return nwords + (-(parm_offset + nwords) & align);
+ return nwords + (-(rs6000_parm_offset () + nwords) & align);
}
/* Compute the size (in words) of a function argument. */
@@ -8464,7 +9193,7 @@ rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum,
if (TREE_CODE (ftype) == RECORD_TYPE)
rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos);
- else if (USE_FP_FOR_ARG_P (cum, mode, ftype))
+ else if (USE_FP_FOR_ARG_P (cum, mode))
{
unsigned n_fpregs = (GET_MODE_SIZE (mode) + 7) >> 3;
rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0);
@@ -8505,7 +9234,7 @@ rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum,
else
cum->words += n_fpregs;
}
- else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, 1))
+ else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, 1))
{
rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0);
cum->vregno++;
@@ -8542,6 +9271,11 @@ static void
rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
const_tree type, bool named, int depth)
{
+ enum machine_mode elt_mode;
+ int n_elts;
+
+ rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+
/* Only tick off an argument if we're not recursing. */
if (depth == 0)
cum->nargs_prototype--;
@@ -8562,15 +9296,16 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
#endif
if (TARGET_ALTIVEC_ABI
- && (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
+ && (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) == 16)))
{
bool stack = false;
- if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
+ if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
{
- cum->vregno++;
+ cum->vregno += n_elts;
+
if (!TARGET_ALTIVEC)
error ("cannot pass argument in vector register because"
" altivec instructions are disabled, use -maltivec"
@@ -8579,7 +9314,8 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
/* PowerPC64 Linux and AIX allocate GPRs for a vector argument
even if it is going to be passed in a vector register.
Darwin does the same for variable-argument functions. */
- if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
+ if (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && TARGET_64BIT)
|| (cum->stdarg && DEFAULT_ABI != ABI_V4))
stack = true;
}
@@ -8590,15 +9326,13 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
{
int align;
- /* Vector parameters must be 16-byte aligned. This places
- them at 2 mod 4 in terms of words in 32-bit mode, since
- the parameter save area starts at offset 24 from the
- stack. In 64-bit mode, they just have to start on an
- even word, since the parameter save area is 16-byte
- aligned. Space for GPRs is reserved even if the argument
- will be passed in memory. */
+ /* Vector parameters must be 16-byte aligned. In 32-bit
+ mode this means we need to take into account the offset
+ to the parameter save area. In 64-bit mode, they just
+ have to start on an even word, since the parameter save
+ area is 16-byte aligned. */
if (TARGET_32BIT)
- align = (2 - cum->words) & 3;
+ align = -(rs6000_parm_offset () + cum->words) & 3;
else
align = cum->words & 1;
cum->words += align + rs6000_arg_size (mode, type);
@@ -8723,15 +9457,15 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->words = align_words + n_words;
- if (SCALAR_FLOAT_MODE_P (mode)
+ if (SCALAR_FLOAT_MODE_P (elt_mode)
&& TARGET_HARD_FLOAT && TARGET_FPRS)
{
/* _Decimal128 must be passed in an even/odd float register pair.
This assumes that the register number is odd when fregno is
odd. */
- if (mode == TDmode && (cum->fregno % 2) == 1)
+ if (elt_mode == TDmode && (cum->fregno % 2) == 1)
cum->fregno++;
- cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
+ cum->fregno += n_elts * ((GET_MODE_SIZE (elt_mode) + 7) >> 3);
}
if (TARGET_DEBUG_ARG)
@@ -8941,7 +9675,7 @@ rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, const_tree type,
if (TREE_CODE (ftype) == RECORD_TYPE)
rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k);
- else if (cum->named && USE_FP_FOR_ARG_P (cum, mode, ftype))
+ else if (cum->named && USE_FP_FOR_ARG_P (cum, mode))
{
unsigned n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
#if 0
@@ -8969,7 +9703,7 @@ rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, const_tree type,
if (mode == TFmode || mode == TDmode)
cum->fregno++;
}
- else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, ftype, 1))
+ else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1))
{
rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
rvec[(*k)++]
@@ -9086,6 +9820,84 @@ rs6000_mixed_function_arg (enum machine_mode mode, const_tree type,
return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
}
+/* We have an argument of MODE and TYPE that goes into FPRs or VRs,
+ but must also be copied into the parameter save area starting at
+ offset ALIGN_WORDS. Fill in RVEC with the elements corresponding
+ to the GPRs and/or memory. Return the number of elements used. */
+
+static int
+rs6000_psave_function_arg (enum machine_mode mode, const_tree type,
+ int align_words, rtx *rvec)
+{
+ int k = 0;
+
+ if (align_words < GP_ARG_NUM_REG)
+ {
+ int n_words = rs6000_arg_size (mode, type);
+
+ if (align_words + n_words > GP_ARG_NUM_REG
+ || mode == BLKmode
+ || (TARGET_32BIT && TARGET_POWERPC64))
+ {
+ /* If this is partially on the stack, then we only
+ include the portion actually in registers here. */
+ enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
+ int i = 0;
+
+ if (align_words + n_words > GP_ARG_NUM_REG)
+ {
+ /* Not all of the arg fits in gprs. Say that it goes in memory
+ too, using a magic NULL_RTX component. Also see comment in
+ rs6000_mixed_function_arg for why the normal
+ function_arg_partial_nregs scheme doesn't work in this case. */
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
+ }
+
+ do
+ {
+ rtx r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words);
+ rtx off = GEN_INT (i++ * GET_MODE_SIZE (rmode));
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
+ }
+ while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
+ }
+ else
+ {
+ /* The whole arg fits in gprs. */
+ rtx r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
+ }
+ }
+ else
+ {
+ /* It's entirely in memory. */
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
+ }
+
+ return k;
+}
+
+/* RVEC is a vector of K components of an argument of mode MODE.
+ Construct the final function_arg return value from it. */
+
+static rtx
+rs6000_finish_function_arg (enum machine_mode mode, rtx *rvec, int k)
+{
+ gcc_assert (k >= 1);
+
+ /* Avoid returning a PARALLEL in the trivial cases. */
+ if (k == 1)
+ {
+ if (XEXP (rvec[0], 0) == NULL_RTX)
+ return NULL_RTX;
+
+ if (GET_MODE (XEXP (rvec[0], 0)) == mode)
+ return XEXP (rvec[0], 0);
+ }
+
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
+}
+
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -9120,6 +9932,8 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
enum rs6000_abi abi = DEFAULT_ABI;
+ enum machine_mode elt_mode;
+ int n_elts;
/* Return a marker to indicate whether CR1 needs to set or clear the
bit that V.4 uses to say fp args were passed in registers.
@@ -9146,6 +9960,8 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
return GEN_INT (cum->call_cookie & ~CALL_LIBCALL);
}
+ rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+
if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
{
rtx rslt = rs6000_darwin64_record_arg (cum, type, named, /*retval= */false);
@@ -9154,33 +9970,30 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
/* Else fall through to usual handling. */
}
- if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
- if (TARGET_64BIT && ! cum->prototype)
- {
- /* Vector parameters get passed in vector register
- and also in GPRs or memory, in absence of prototype. */
- int align_words;
- rtx slot;
- align_words = (cum->words + 1) & ~1;
+ if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
+ {
+ rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1];
+ rtx r, off;
+ int i, k = 0;
- if (align_words >= GP_ARG_NUM_REG)
- {
- slot = NULL_RTX;
- }
- else
- {
- slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
- }
- return gen_rtx_PARALLEL (mode,
- gen_rtvec (2,
- gen_rtx_EXPR_LIST (VOIDmode,
- slot, const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (mode, cum->vregno),
- const0_rtx)));
- }
- else
- return gen_rtx_REG (mode, cum->vregno);
+ /* Do we also need to pass this argument in the parameter
+ save area? */
+ if (TARGET_64BIT && ! cum->prototype)
+ {
+ int align_words = (cum->words + 1) & ~1;
+ k = rs6000_psave_function_arg (mode, type, align_words, rvec);
+ }
+
+ /* Describe where this argument goes in the vector registers. */
+ for (i = 0; i < n_elts && cum->vregno + i <= ALTIVEC_ARG_MAX_REG; i++)
+ {
+ r = gen_rtx_REG (elt_mode, cum->vregno + i);
+ off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
+ }
+
+ return rs6000_finish_function_arg (mode, rvec, k);
+ }
else if (TARGET_ALTIVEC_ABI
&& (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
@@ -9195,13 +10008,13 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
int align, align_words, n_words;
enum machine_mode part_mode;
- /* Vector parameters must be 16-byte aligned. This places them at
- 2 mod 4 in terms of words in 32-bit mode, since the parameter
- save area starts at offset 24 from the stack. In 64-bit mode,
- they just have to start on an even word, since the parameter
- save area is 16-byte aligned. */
+ /* Vector parameters must be 16-byte aligned. In 32-bit
+ mode this means we need to take into account the offset
+ to the parameter save area. In 64-bit mode, they just
+ have to start on an even word, since the parameter save
+ area is 16-byte aligned. */
if (TARGET_32BIT)
- align = (2 - cum->words) & 3;
+ align = -(rs6000_parm_offset () + cum->words) & 3;
else
align = cum->words & 1;
align_words = cum->words + align;
@@ -9279,101 +10092,50 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
/* _Decimal128 must be passed in an even/odd float register pair.
This assumes that the register number is odd when fregno is odd. */
- if (mode == TDmode && (cum->fregno % 2) == 1)
+ if (elt_mode == TDmode && (cum->fregno % 2) == 1)
cum->fregno++;
- if (USE_FP_FOR_ARG_P (cum, mode, type))
+ if (USE_FP_FOR_ARG_P (cum, elt_mode))
{
- rtx rvec[GP_ARG_NUM_REG + 1];
- rtx r;
- int k;
- bool needs_psave;
- enum machine_mode fmode = mode;
- unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
-
- if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
- {
- /* Currently, we only ever need one reg here because complex
- doubles are split. */
- gcc_assert (cum->fregno == FP_ARG_MAX_REG
- && (fmode == TFmode || fmode == TDmode));
-
- /* Long double or _Decimal128 split over regs and memory. */
- fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode;
- }
-
- /* Do we also need to pass this arg in the parameter save
- area? */
- needs_psave = (type
- && (cum->nargs_prototype <= 0
- || (DEFAULT_ABI == ABI_AIX
- && TARGET_XL_COMPAT
- && align_words >= GP_ARG_NUM_REG)));
+ rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1];
+ rtx r, off;
+ int i, k = 0;
+ unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
- if (!needs_psave && mode == fmode)
- return gen_rtx_REG (fmode, cum->fregno);
+ /* Do we also need to pass this argument in the parameter
+ save area? */
+ if (type && (cum->nargs_prototype <= 0
+ || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && TARGET_XL_COMPAT
+ && align_words >= GP_ARG_NUM_REG)))
+ k = rs6000_psave_function_arg (mode, type, align_words, rvec);
- k = 0;
- if (needs_psave)
+ /* Describe where this argument goes in the fprs. */
+ for (i = 0; i < n_elts
+ && cum->fregno + i * n_fpreg <= FP_ARG_MAX_REG; i++)
{
- /* Describe the part that goes in gprs or the stack.
- This piece must come first, before the fprs. */
- if (align_words < GP_ARG_NUM_REG)
+ /* Check if the argument is split over registers and memory.
+ This can only ever happen for long double or _Decimal128;
+ complex types are handled via split_complex_arg. */
+ enum machine_mode fmode = elt_mode;
+ if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1)
{
- unsigned long n_words = rs6000_arg_size (mode, type);
-
- if (align_words + n_words > GP_ARG_NUM_REG
- || (TARGET_32BIT && TARGET_POWERPC64))
- {
- /* If this is partially on the stack, then we only
- include the portion actually in registers here. */
- enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
- rtx off;
- int i = 0;
- if (align_words + n_words > GP_ARG_NUM_REG)
- /* Not all of the arg fits in gprs. Say that it
- goes in memory too, using a magic NULL_RTX
- component. Also see comment in
- rs6000_mixed_function_arg for why the normal
- function_arg_partial_nregs scheme doesn't work
- in this case. */
- rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX,
- const0_rtx);
- do
- {
- r = gen_rtx_REG (rmode,
- GP_ARG_MIN_REG + align_words);
- off = GEN_INT (i++ * GET_MODE_SIZE (rmode));
- rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
- }
- while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
- }
- else
- {
- /* The whole arg fits in gprs. */
- r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
- rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
- }
+ gcc_assert (fmode == TFmode || fmode == TDmode);
+ fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode;
}
- else
- /* It's entirely in memory. */
- rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
- }
- /* Describe where this piece goes in the fprs. */
- r = gen_rtx_REG (fmode, cum->fregno);
- rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
+ r = gen_rtx_REG (fmode, cum->fregno + i * n_fpreg);
+ off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
+ }
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
+ return rs6000_finish_function_arg (mode, rvec, k);
}
else if (align_words < GP_ARG_NUM_REG)
{
if (TARGET_32BIT && TARGET_POWERPC64)
return rs6000_mixed_function_arg (mode, type, align_words);
- if (mode == BLKmode)
- mode = Pmode;
-
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
}
else
@@ -9392,15 +10154,31 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
tree type, bool named)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ bool passed_in_gprs = true;
int ret = 0;
int align_words;
+ enum machine_mode elt_mode;
+ int n_elts;
+
+ rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
if (DEFAULT_ABI == ABI_V4)
return 0;
- if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named)
- && cum->nargs_prototype >= 0)
- return 0;
+ if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
+ {
+ /* If we are passing this arg in the fixed parameter save area
+ (gprs or memory) as well as VRs, we do not use the partial
+ bytes mechanism; instead, rs6000_function_arg will return a
+ PARALLEL including a memory element as necessary. */
+ if (TARGET_64BIT && ! cum->prototype)
+ return 0;
+
+ /* Otherwise, we pass in VRs only. Check for partial copies. */
+ passed_in_gprs = false;
+ if (cum->vregno + n_elts > ALTIVEC_ARG_MAX_REG + 1)
+ ret = (ALTIVEC_ARG_MAX_REG + 1 - cum->vregno) * 16;
+ }
/* In this complicated case we just disable the partial_nregs code. */
if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
@@ -9408,26 +10186,30 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
align_words = rs6000_parm_start (mode, type, cum->words);
- if (USE_FP_FOR_ARG_P (cum, mode, type))
+ if (USE_FP_FOR_ARG_P (cum, elt_mode))
{
+ unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
+
/* If we are passing this arg in the fixed parameter save area
- (gprs or memory) as well as fprs, then this function should
- return the number of partial bytes passed in the parameter
- save area rather than partial bytes passed in fprs. */
+ (gprs or memory) as well as FPRs, we do not use the partial
+ bytes mechanism; instead, rs6000_function_arg will return a
+ PARALLEL including a memory element as necessary. */
if (type
&& (cum->nargs_prototype <= 0
- || (DEFAULT_ABI == ABI_AIX
+ || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& TARGET_XL_COMPAT
&& align_words >= GP_ARG_NUM_REG)))
return 0;
- else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3)
- > FP_ARG_MAX_REG + 1)
- ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8;
- else if (cum->nargs_prototype >= 0)
- return 0;
+
+ /* Otherwise, we pass in FPRs only. Check for partial copies. */
+ passed_in_gprs = false;
+ if (cum->fregno + n_elts * n_fpreg > FP_ARG_MAX_REG + 1)
+ ret = ((FP_ARG_MAX_REG + 1 - cum->fregno)
+ * MIN (8, GET_MODE_SIZE (elt_mode)));
}
- if (align_words < GP_ARG_NUM_REG
+ if (passed_in_gprs
+ && align_words < GP_ARG_NUM_REG
&& GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8);
@@ -9508,6 +10290,139 @@ rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
return 0;
}
+/* Process parameter of type TYPE after ARGS_SO_FAR parameters were
+ already processes. Return true if the parameter must be passed
+ (fully or partially) on the stack. */
+
+static bool
+rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
+{
+ enum machine_mode mode;
+ int unsignedp;
+ rtx entry_parm;
+
+ /* Catch errors. */
+ if (type == NULL || type == error_mark_node)
+ return true;
+
+ /* Handle types with no storage requirement. */
+ if (TYPE_MODE (type) == VOIDmode)
+ return false;
+
+ /* Handle complex types. */
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ return (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type))
+ || rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type)));
+
+ /* Handle transparent aggregates. */
+ if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE)
+ && TYPE_TRANSPARENT_AGGR (type))
+ type = TREE_TYPE (first_field (type));
+
+ /* See if this arg was passed by invisible reference. */
+ if (pass_by_reference (get_cumulative_args (args_so_far),
+ TYPE_MODE (type), type, true))
+ type = build_pointer_type (type);
+
+ /* Find mode as it is passed by the ABI. */
+ unsignedp = TYPE_UNSIGNED (type);
+ mode = promote_mode (type, TYPE_MODE (type), &unsignedp);
+
+ /* If we must pass in stack, we need a stack. */
+ if (rs6000_must_pass_in_stack (mode, type))
+ return true;
+
+ /* If there is no incoming register, we need a stack. */
+ entry_parm = rs6000_function_arg (args_so_far, mode, type, true);
+ if (entry_parm == NULL)
+ return true;
+
+ /* Likewise if we need to pass both in registers and on the stack. */
+ if (GET_CODE (entry_parm) == PARALLEL
+ && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
+ return true;
+
+ /* Also true if we're partially in registers and partially not. */
+ if (rs6000_arg_partial_bytes (args_so_far, mode, type, true) != 0)
+ return true;
+
+ /* Update info on where next arg arrives in registers. */
+ rs6000_function_arg_advance (args_so_far, mode, type, true);
+ return false;
+}
+
+/* Return true if FUN has no prototype, has a variable argument
+ list, or passes any parameter in memory. */
+
+static bool
+rs6000_function_parms_need_stack (tree fun)
+{
+ function_args_iterator args_iter;
+ tree arg_type;
+ CUMULATIVE_ARGS args_so_far_v;
+ cumulative_args_t args_so_far;
+
+ if (!fun)
+ /* Must be a libcall, all of which only use reg parms. */
+ return false;
+ if (!TYPE_P (fun))
+ fun = TREE_TYPE (fun);
+
+ /* Varargs functions need the parameter save area. */
+ if (!prototype_p (fun) || stdarg_p (fun))
+ return true;
+
+ INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fun, NULL_RTX);
+ args_so_far = pack_cumulative_args (&args_so_far_v);
+
+ if (aggregate_value_p (TREE_TYPE (fun), fun))
+ {
+ tree type = build_pointer_type (TREE_TYPE (fun));
+ rs6000_parm_needs_stack (args_so_far, type);
+ }
+
+ FOREACH_FUNCTION_ARGS (fun, arg_type, args_iter)
+ if (rs6000_parm_needs_stack (args_so_far, arg_type))
+ return true;
+
+ return false;
+}
+
+/* Return the size of the REG_PARM_STACK_SPACE are for FUN. This is
+ usually a constant depending on the ABI. However, in the ELFv2 ABI
+ the register parameter area is optional when calling a function that
+ has a prototype is scope, has no variable argument list, and passes
+ all parameters in registers. */
+
+int
+rs6000_reg_parm_stack_space (tree fun)
+{
+ int reg_parm_stack_space;
+
+ switch (DEFAULT_ABI)
+ {
+ default:
+ reg_parm_stack_space = 0;
+ break;
+
+ case ABI_AIX:
+ case ABI_DARWIN:
+ reg_parm_stack_space = TARGET_64BIT ? 64 : 32;
+ break;
+
+ case ABI_ELFv2:
+ /* ??? Recomputing this every time is a bit expensive. Is there
+ a place to cache this information? */
+ if (rs6000_function_parms_need_stack (fun))
+ reg_parm_stack_space = TARGET_64BIT ? 64 : 32;
+ else
+ reg_parm_stack_space = 0;
+ break;
+ }
+
+ return reg_parm_stack_space;
+}
+
static void
rs6000_move_block_from_reg (int regno, rtx x, int nregs)
{
@@ -9889,8 +10804,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
We don't need to check for pass-by-reference because of the test above.
We can return a simplifed answer, since we know there's no offset to add. */
- if (TARGET_MACHO
- && rs6000_darwin64_abi
+ if (((TARGET_MACHO
+ && rs6000_darwin64_abi)
+ || DEFAULT_ABI == ABI_ELFv2
+ || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
&& integer_zerop (TYPE_SIZE (type)))
{
unsigned HOST_WIDE_INT align, boundary;
@@ -12362,7 +13279,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case ALTIVEC_BUILTIN_MASK_FOR_LOAD:
case ALTIVEC_BUILTIN_MASK_FOR_STORE:
{
- int icode = (int) CODE_FOR_altivec_lvsr;
+ int icode = (BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr
+ : (int) CODE_FOR_altivec_lvsl);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode = insn_data[icode].operand[1].mode;
tree arg;
@@ -14671,6 +15589,17 @@ rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
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. */
+enum machine_mode
+rs6000_secondary_memory_needed_mode (enum machine_mode mode)
+{
+ if (mode == SDmode)
+ return DDmode;
+ return mode;
+}
+
static tree
rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
@@ -14704,7 +15633,7 @@ rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
/* 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
- was choosen. */
+ was chosen. */
static enum rs6000_reg_type
register_to_reg_type (rtx reg, bool *is_altivec)
@@ -14801,7 +15730,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 3; /* 2 mtvsrd's, 1 xxpermdi. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
/* Handle moving 128-bit values from VSX point registers to GPRs on
@@ -14810,7 +15739,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
else if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* 2 mfvsrd's, 1 xxpermdi. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
}
@@ -14819,13 +15748,13 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* xscvdpspn, mfvsrd, and. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
else if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 2; /* mtvsrz, xscvspdpn. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
}
}
@@ -14838,7 +15767,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 3; /* 2 mtvsrd's, 1 xxpermdi. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
/* Handle moving 128-bit values from VSX point registers to GPRs on
@@ -14847,7 +15776,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
else if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* 2 mfvsrd's, 1 xxpermdi. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
}
@@ -14863,7 +15792,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE && !altivec_p)
{
cost = 3; /* 2 mtvsrwz's, 1 fmrgow. */
- icode = reload_fpr_gpr[(int)mode];
+ icode = reg_addr[mode].reload_fpr_gpr;
}
}
@@ -14946,7 +15875,9 @@ rs6000_secondary_reload (bool in_p,
bool default_p = false;
sri->icode = CODE_FOR_nothing;
- icode = rs6000_vector_reload[mode][in_p != false];
+ icode = ((in_p)
+ ? reg_addr[mode].reload_load
+ : reg_addr[mode].reload_store);
if (REG_P (x) || register_operand (x, mode))
{
@@ -14961,6 +15892,7 @@ rs6000_secondary_reload (bool in_p,
from_type = exchange;
}
+ /* Can we do a direct move of some sort? */
if (rs6000_secondary_reload_move (to_type, from_type, mode, sri,
altivec_p))
{
@@ -15483,7 +16415,7 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
/* Adjust the address if it changed. */
if (addr != XEXP (mem, 0))
{
- mem = change_address (mem, mode, addr);
+ mem = replace_equiv_address_nv (mem, addr);
if (TARGET_DEBUG_ADDR)
fprintf (stderr, "\nrs6000_secondary_reload_inner, mem adjusted.\n");
}
@@ -15561,6 +16493,10 @@ rs6000_alloc_sdmode_stack_slot (void)
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;
@@ -15782,7 +16718,7 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
/* Constants, memory, and FP registers can go into FP registers. */
if ((regno == -1 || FP_REGNO_P (regno))
&& (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
- return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+ return (mode != SDmode || lra_in_progress) ? NO_REGS : GENERAL_REGS;
/* Memory, and FP/altivec registers can go into fp/altivec registers under
VSX. However, for scalar variables, use the traditional floating point
@@ -15856,6 +16792,13 @@ rs6000_cannot_change_mode_class (enum machine_mode from,
if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
return true;
+ /* TDmode in floating-mode registers must always go into a register
+ pair with the most significant word in the even-numbered register
+ to match ISA requirements. In little-endian mode, this does not
+ match subreg numbering, so we cannot allow subregs. */
+ if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
+ return true;
+
if (from_size < 8 || to_size < 8)
return true;
@@ -15934,21 +16877,21 @@ rs6000_output_move_128bit (rtx operands[])
enum machine_mode mode = GET_MODE (dest);
int dest_regno;
int src_regno;
- bool dest_gpr_p, dest_fp_p, dest_av_p, dest_vsx_p;
- bool src_gpr_p, src_fp_p, src_av_p, src_vsx_p;
+ bool dest_gpr_p, dest_fp_p, dest_vmx_p, dest_vsx_p;
+ bool src_gpr_p, src_fp_p, src_vmx_p, src_vsx_p;
if (REG_P (dest))
{
dest_regno = REGNO (dest);
dest_gpr_p = INT_REGNO_P (dest_regno);
dest_fp_p = FP_REGNO_P (dest_regno);
- dest_av_p = ALTIVEC_REGNO_P (dest_regno);
- dest_vsx_p = dest_fp_p | dest_av_p;
+ dest_vmx_p = ALTIVEC_REGNO_P (dest_regno);
+ dest_vsx_p = dest_fp_p | dest_vmx_p;
}
else
{
dest_regno = -1;
- dest_gpr_p = dest_fp_p = dest_av_p = dest_vsx_p = false;
+ dest_gpr_p = dest_fp_p = dest_vmx_p = dest_vsx_p = false;
}
if (REG_P (src))
@@ -15956,13 +16899,13 @@ rs6000_output_move_128bit (rtx operands[])
src_regno = REGNO (src);
src_gpr_p = INT_REGNO_P (src_regno);
src_fp_p = FP_REGNO_P (src_regno);
- src_av_p = ALTIVEC_REGNO_P (src_regno);
- src_vsx_p = src_fp_p | src_av_p;
+ src_vmx_p = ALTIVEC_REGNO_P (src_regno);
+ src_vsx_p = src_fp_p | src_vmx_p;
}
else
{
src_regno = -1;
- src_gpr_p = src_fp_p = src_av_p = src_vsx_p = false;
+ src_gpr_p = src_fp_p = src_vmx_p = src_vsx_p = false;
}
/* Register moves. */
@@ -15986,7 +16929,7 @@ rs6000_output_move_128bit (rtx operands[])
return "#";
}
- else if (TARGET_ALTIVEC && dest_av_p && src_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p && src_vmx_p)
return "vor %0,%1,%1";
else if (dest_fp_p && src_fp_p)
@@ -15998,18 +16941,13 @@ rs6000_output_move_128bit (rtx operands[])
{
if (dest_gpr_p)
{
- if (TARGET_QUAD_MEMORY && (dest_regno & 1) == 0
- && quad_memory_operand (src, mode)
- && !reg_overlap_mentioned_p (dest, src))
- {
- /* lq/stq only has DQ-form, so avoid X-form that %y produces. */
- return REG_P (XEXP (src, 0)) ? "lq %0,%1" : "lq %0,%y1";
- }
+ if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src))
+ return "lq %0,%1";
else
return "#";
}
- else if (TARGET_ALTIVEC && dest_av_p
+ else if (TARGET_ALTIVEC && dest_vmx_p
&& altivec_indexed_or_indirect_operand (src, mode))
return "lvx %0,%y1";
@@ -16021,7 +16959,7 @@ rs6000_output_move_128bit (rtx operands[])
return "lxvd2x %x0,%y1";
}
- else if (TARGET_ALTIVEC && dest_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p)
return "lvx %0,%y1";
else if (dest_fp_p)
@@ -16033,17 +16971,13 @@ rs6000_output_move_128bit (rtx operands[])
{
if (src_gpr_p)
{
- if (TARGET_QUAD_MEMORY && (src_regno & 1) == 0
- && quad_memory_operand (dest, mode))
- {
- /* lq/stq only has DQ-form, so avoid X-form that %y produces. */
- return REG_P (XEXP (dest, 0)) ? "stq %1,%0" : "stq %1,%y0";
- }
+ if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src))
+ return "stq %1,%0";
else
return "#";
}
- else if (TARGET_ALTIVEC && src_av_p
+ else if (TARGET_ALTIVEC && src_vmx_p
&& altivec_indexed_or_indirect_operand (src, mode))
return "stvx %1,%y0";
@@ -16055,7 +16989,7 @@ rs6000_output_move_128bit (rtx operands[])
return "stxvd2x %x1,%y0";
}
- else if (TARGET_ALTIVEC && src_av_p)
+ else if (TARGET_ALTIVEC && src_vmx_p)
return "stvx %1,%y0";
else if (src_fp_p)
@@ -16074,7 +17008,7 @@ rs6000_output_move_128bit (rtx operands[])
else if (TARGET_VSX && dest_vsx_p && zero_constant (src, mode))
return "xxlxor %x0,%x0,%x0";
- else if (TARGET_ALTIVEC && dest_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p)
return output_vec_const_move (operands);
}
@@ -16313,6 +17247,7 @@ rs6000_output_function_entry (FILE *file, const char *fname)
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "L.");
break;
+ case ABI_ELFv2:
case ABI_V4:
case ABI_DARWIN:
break;
@@ -18811,6 +19746,39 @@ rs6000_split_multireg_move (rtx dst, rtx src)
gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
+ /* TDmode residing in FP registers is special, since the ISA requires that
+ the lower-numbered word of a register pair is always the most significant
+ word, even in little-endian mode. This does not match the usual subreg
+ semantics, so we cannnot use simplify_gen_subreg in those cases. Access
+ the appropriate constituent registers "by hand" in little-endian mode.
+
+ Note we do not need to check for destructive overlap here since TDmode
+ can only reside in even/odd register pairs. */
+ if (FP_REGNO_P (reg) && DECIMAL_FLOAT_MODE_P (mode) && !BYTES_BIG_ENDIAN)
+ {
+ rtx p_src, p_dst;
+ int i;
+
+ for (i = 0; i < nregs; i++)
+ {
+ if (REG_P (src) && FP_REGNO_P (REGNO (src)))
+ p_src = gen_rtx_REG (reg_mode, REGNO (src) + nregs - 1 - i);
+ else
+ p_src = simplify_gen_subreg (reg_mode, src, mode,
+ i * reg_mode_size);
+
+ if (REG_P (dst) && FP_REGNO_P (REGNO (dst)))
+ p_dst = gen_rtx_REG (reg_mode, REGNO (dst) + nregs - 1 - i);
+ else
+ p_dst = simplify_gen_subreg (reg_mode, dst, mode,
+ i * reg_mode_size);
+
+ emit_insn (gen_rtx_SET (VOIDmode, p_dst, p_src));
+ }
+
+ return;
+ }
+
if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
{
/* Move register range backwards, if we might have destructive
@@ -19265,7 +20233,7 @@ rs6000_savres_strategy (rs6000_stack_t *info,
}
else
{
- gcc_checking_assert (DEFAULT_ABI == ABI_AIX);
+ gcc_checking_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
if (info->first_fp_reg_save > 61)
strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
@@ -19276,7 +20244,8 @@ rs6000_savres_strategy (rs6000_stack_t *info,
by the static chain. It would require too much fiddling and the
static chain is rarely used anyway. FPRs are saved w.r.t the stack
pointer on Darwin, and AIX uses r1 or r12. */
- if (using_static_chain_p && DEFAULT_ABI != ABI_AIX)
+ if (using_static_chain_p
+ && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN))
strategy |= ((DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
| SAVE_INLINE_GPRS
| SAVE_INLINE_VRS | REST_INLINE_VRS);
@@ -19409,6 +20378,34 @@ rs6000_savres_strategy (rs6000_stack_t *info,
The required alignment for AIX configurations is two words (i.e., 8
or 16 bytes).
+ The ELFv2 ABI is a variant of the AIX ABI. Stack frames look like:
+
+ SP----> +---------------------------------------+
+ | Back chain to caller | 0
+ +---------------------------------------+
+ | Save area for CR | 8
+ +---------------------------------------+
+ | Saved LR | 16
+ +---------------------------------------+
+ | Saved TOC pointer | 24
+ +---------------------------------------+
+ | Parameter save area (P) | 32
+ +---------------------------------------+
+ | Alloca space (A) | 32+P
+ +---------------------------------------+
+ | Local variable space (L) | 32+P+A
+ +---------------------------------------+
+ | Save area for AltiVec registers (W) | 32+P+A+L
+ +---------------------------------------+
+ | AltiVec alignment padding (Y) | 32+P+A+L+W
+ +---------------------------------------+
+ | Save area for GP registers (G) | 32+P+A+L+W+Y
+ +---------------------------------------+
+ | Save area for FP registers (F) | 32+P+A+L+W+Y+G
+ +---------------------------------------+
+ old SP->| back chain to caller's caller | 32+P+A+L+W+Y+G+F
+ +---------------------------------------+
+
V.4 stack frames look like:
@@ -19469,6 +20466,7 @@ rs6000_stack_info (void)
rs6000_stack_t *info_ptr = &stack_info;
int reg_size = TARGET_32BIT ? 4 : 8;
int ehrd_size;
+ int ehcr_size;
int save_align;
int first_gp;
HOST_WIDE_INT non_fixed_size;
@@ -19562,6 +20560,18 @@ rs6000_stack_info (void)
else
ehrd_size = 0;
+ /* In the ELFv2 ABI, we also need to allocate space for separate
+ CR field save areas if the function calls __builtin_eh_return. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ /* This hard-codes that we have three call-saved CR fields. */
+ ehcr_size = 3 * reg_size;
+ /* We do *not* use the regular CR save mechanism. */
+ info_ptr->cr_save_p = 0;
+ }
+ else
+ ehcr_size = 0;
+
/* Determine various sizes. */
info_ptr->reg_size = reg_size;
info_ptr->fixed_size = RS6000_SAVE_AREA;
@@ -19601,6 +20611,7 @@ rs6000_stack_info (void)
gcc_unreachable ();
case ABI_AIX:
+ case ABI_ELFv2:
case ABI_DARWIN:
info_ptr->fp_save_offset = - info_ptr->fp_size;
info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
@@ -19630,6 +20641,8 @@ rs6000_stack_info (void)
}
else
info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
+
+ info_ptr->ehcr_offset = info_ptr->ehrd_offset - ehcr_size;
info_ptr->cr_save_offset = reg_size; /* first word when 64-bit. */
info_ptr->lr_save_offset = 2*reg_size;
break;
@@ -19692,6 +20705,7 @@ rs6000_stack_info (void)
+ info_ptr->spe_gp_size
+ info_ptr->spe_padding_size
+ ehrd_size
+ + ehcr_size
+ info_ptr->cr_size
+ info_ptr->vrsave_size,
save_align);
@@ -19705,7 +20719,7 @@ rs6000_stack_info (void)
/* Determine if we need to save the link register. */
if (info_ptr->calls_p
- || (DEFAULT_ABI == ABI_AIX
+ || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& crtl->profile
&& !TARGET_PROFILE_KERNEL)
|| (DEFAULT_ABI == ABI_V4 && cfun->calls_alloca)
@@ -19851,6 +20865,7 @@ debug_stack_info (rs6000_stack_t *info)
default: abi_string = "Unknown"; break;
case ABI_NONE: abi_string = "NONE"; break;
case ABI_AIX: abi_string = "AIX"; break;
+ case ABI_ELFv2: abi_string = "ELFv2"; break;
case ABI_DARWIN: abi_string = "Darwin"; break;
case ABI_V4: abi_string = "V.4"; break;
}
@@ -19972,7 +20987,8 @@ rs6000_return_addr (int count, rtx frame)
/* Currently we don't optimize very well between prolog and body
code and for PIC code the code can be actually quite bad, so
don't try to be too clever here. */
- if (count != 0 || (DEFAULT_ABI != ABI_AIX && flag_pic))
+ if (count != 0
+ || ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN) && flag_pic))
{
cfun->machine->ra_needs_full_frame = 1;
@@ -20031,13 +21047,13 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp)
return false;
}
- /* Under the AIX ABI we can't allow calls to non-local functions,
- because the callee may have a different TOC pointer to the
- caller and there's no way to ensure we restore the TOC when we
- return. With the secure-plt SYSV ABI we can't make non-local
+ /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
+ functions, because the callee may have a different TOC pointer to
+ the caller and there's no way to ensure we restore the TOC when
+ we return. With the secure-plt SYSV ABI we can't make non-local
calls when -fpic/PIC because the plt call stubs use r30. */
if (DEFAULT_ABI == ABI_DARWIN
- || (DEFAULT_ABI == ABI_AIX
+ || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& decl
&& !DECL_EXTERNAL (decl)
&& (*targetm.binds_local_p) (decl))
@@ -20138,7 +21154,7 @@ rs6000_emit_load_toc_table (int fromprolog)
rtx dest;
dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
- if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic)
+ if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic)
{
char buf[30];
rtx lab, tmp1, tmp2, got;
@@ -20166,7 +21182,7 @@ rs6000_emit_load_toc_table (int fromprolog)
emit_insn (gen_load_toc_v4_pic_si ());
emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
}
- else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
+ else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2)
{
char buf[30];
rtx temp0 = (fromprolog
@@ -20214,7 +21230,7 @@ rs6000_emit_load_toc_table (int fromprolog)
}
else
{
- gcc_assert (DEFAULT_ABI == ABI_AIX);
+ gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
if (TARGET_32BIT)
emit_insn (gen_load_toc_aix_si (dest));
@@ -20619,7 +21635,7 @@ output_probe_stack_range (rtx reg1, rtx reg2)
static rtx
rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
- rtx reg2, rtx rreg)
+ rtx reg2, rtx rreg, rtx split_reg)
{
rtx real, temp;
@@ -20710,6 +21726,11 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
}
}
+ /* If a store insn has been split into multiple insns, the
+ true source register is given by split_reg. */
+ if (split_reg != NULL_RTX)
+ real = gen_rtx_SET (VOIDmode, SET_DEST (real), split_reg);
+
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
@@ -20817,7 +21838,7 @@ emit_frame_save (rtx frame_reg, enum machine_mode mode,
reg = gen_rtx_REG (mode, regno);
insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
}
/* Emit an offset memory reference suitable for a frame store, while
@@ -20933,7 +21954,7 @@ rs6000_savres_routine_name (rs6000_stack_t *info, int regno, int sel)
if ((sel & SAVRES_LR))
suffix = "_x";
}
- else if (DEFAULT_ABI == ABI_AIX)
+ else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
{
#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
/* No out-of-line save/restore routines for GPRs on AIX. */
@@ -21074,7 +22095,7 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
static inline unsigned
ptr_regno_for_savres (int sel)
{
- if (DEFAULT_ABI == ABI_AIX)
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
return (sel & SAVRES_REG) == SAVRES_FPR || (sel & SAVRES_LR) ? 1 : 12;
return DEFAULT_ABI == ABI_DARWIN && (sel & SAVRES_REG) == SAVRES_FPR ? 1 : 11;
}
@@ -21159,6 +22180,43 @@ rs6000_emit_savres_rtx (rs6000_stack_t *info,
return insn;
}
+/* Emit code to store CR fields that need to be saved into REG. */
+
+static void
+rs6000_emit_move_from_cr (rtx reg)
+{
+ /* Only the ELFv2 ABI allows storing only selected fields. */
+ if (DEFAULT_ABI == ABI_ELFv2 && TARGET_MFCRF)
+ {
+ int i, cr_reg[8], count = 0;
+
+ /* Collect CR fields that must be saved. */
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ cr_reg[count++] = i;
+
+ /* If it's just a single one, use mfcrf. */
+ if (count == 1)
+ {
+ rtvec p = rtvec_alloc (1);
+ rtvec r = rtvec_alloc (2);
+ RTVEC_ELT (r, 0) = gen_rtx_REG (CCmode, CR0_REGNO + cr_reg[0]);
+ RTVEC_ELT (r, 1) = GEN_INT (1 << (7 - cr_reg[0]));
+ RTVEC_ELT (p, 0)
+ = gen_rtx_SET (VOIDmode, reg,
+ gen_rtx_UNSPEC (SImode, r, UNSPEC_MOVESI_FROM_CR));
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ return;
+ }
+
+ /* ??? It might be better to handle count == 2 / 3 cases here
+ as well, using logical operations to combine the values. */
+ }
+
+ emit_insn (gen_movesi_from_cr (reg));
+}
+
/* Determine whether the gp REG is really used. */
static bool
@@ -21224,6 +22282,17 @@ rs6000_emit_prologue (void)
#define NOT_INUSE(R) do {} while (0)
#endif
+ if (DEFAULT_ABI == ABI_ELFv2)
+ {
+ cfun->machine->r2_setup_needed = df_regs_ever_live_p (TOC_REGNUM);
+
+ /* With -mminimal-toc we may generate an extra use of r2 below. */
+ if (!TARGET_SINGLE_PIC_BASE
+ && TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
+ cfun->machine->r2_setup_needed = true;
+ }
+
+
if (flag_stack_usage_info)
current_function_static_stack_size = info->total_size;
@@ -21338,7 +22407,7 @@ rs6000_emit_prologue (void)
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- treg, GEN_INT (-info->total_size));
+ treg, GEN_INT (-info->total_size), NULL_RTX);
sp_off = frame_off = info->total_size;
}
@@ -21423,14 +22492,14 @@ rs6000_emit_prologue (void)
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
END_USE (0);
}
}
/* If we need to save CR, put it into r12 or r11. Choose r12 except when
r12 will be needed by out-of-line gpr restore. */
- cr_save_regno = (DEFAULT_ABI == ABI_AIX
+ cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& !(strategy & (SAVE_INLINE_GPRS
| SAVE_NOINLINE_GPRS_SAVES_LR))
? 11 : 12);
@@ -21439,21 +22508,9 @@ rs6000_emit_prologue (void)
&& REGNO (frame_reg_rtx) != cr_save_regno
&& !(using_static_chain_p && cr_save_regno == 11))
{
- rtx set;
-
cr_save_rtx = gen_rtx_REG (SImode, cr_save_regno);
START_USE (cr_save_regno);
- insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
- RTX_FRAME_RELATED_P (insn) = 1;
- /* Now, there's no way that dwarf2out_frame_debug_expr is going
- to understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)'.
- But that's OK. All we have to do is specify that _one_ condition
- code register is saved in this stack slot. The thrower's epilogue
- will then restore all the call-saved registers.
- We use CR2_REGNO (70) to be compatible with gcc-2.95 on Linux. */
- set = gen_rtx_SET (VOIDmode, cr_save_rtx,
- gen_rtx_REG (SImode, CR2_REGNO));
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
+ rs6000_emit_move_from_cr (cr_save_rtx);
}
/* Do any required saving of fpr's. If only one or two to save, do
@@ -21491,7 +22548,7 @@ rs6000_emit_prologue (void)
info->lr_save_offset,
DFmode, sel);
rs6000_frame_related (insn, ptr_reg, sp_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
if (lr)
END_USE (0);
}
@@ -21529,8 +22586,7 @@ rs6000_emit_prologue (void)
HOST_WIDE_INT offset;
if (!(strategy & SAVE_INLINE_GPRS))
- ool_adjust = 8 * (info->first_gp_reg_save
- - (FIRST_SAVRES_REGISTER + 1));
+ ool_adjust = 8 * (info->first_gp_reg_save - FIRST_SAVED_GP_REGNO);
offset = info->spe_gp_save_offset + frame_off - ool_adjust;
spe_save_area_ptr = gen_rtx_REG (Pmode, 11);
save_off = frame_off - offset;
@@ -21571,7 +22627,7 @@ rs6000_emit_prologue (void)
SAVRES_SAVE | SAVRES_GPR);
rs6000_frame_related (insn, spe_save_area_ptr, sp_off - save_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
}
/* Move the static chain pointer back. */
@@ -21621,7 +22677,7 @@ rs6000_emit_prologue (void)
info->lr_save_offset + ptr_off,
reg_mode, sel);
rs6000_frame_related (insn, ptr_reg, sp_off - ptr_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
if (lr)
END_USE (0);
}
@@ -21637,7 +22693,7 @@ rs6000_emit_prologue (void)
info->gp_save_offset + frame_off + reg_size * i);
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
}
else if (!WORLD_SAVE_P (info))
{
@@ -21706,7 +22762,8 @@ rs6000_emit_prologue (void)
be updated if we arrived at this function via a plt call or
toc adjusting stub. */
emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
- toc_restore_insn = TARGET_32BIT ? 0x80410014 : 0xE8410028;
+ toc_restore_insn = ((TARGET_32BIT ? 0x80410000 : 0xE8410000)
+ + RS6000_TOC_SAVE_SLOT);
hi = gen_int_mode (toc_restore_insn & ~0xffff, SImode);
emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si, hi));
compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
@@ -21725,7 +22782,7 @@ rs6000_emit_prologue (void)
LABEL_NUSES (toc_save_done) += 1;
save_insn = emit_frame_save (frame_reg_rtx, reg_mode,
- TOC_REGNUM, frame_off + 5 * reg_size,
+ TOC_REGNUM, frame_off + RS6000_TOC_SAVE_SLOT,
sp_off - frame_off);
emit_label (toc_save_done);
@@ -21765,26 +22822,121 @@ rs6000_emit_prologue (void)
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->cr_save_offset + frame_off));
rtx mem = gen_frame_mem (SImode, addr);
- /* See the large comment above about why CR2_REGNO is used. */
- rtx magic_eh_cr_reg = gen_rtx_REG (SImode, CR2_REGNO);
/* If we didn't copy cr before, do so now using r0. */
if (cr_save_rtx == NULL_RTX)
{
- rtx set;
-
START_USE (0);
cr_save_rtx = gen_rtx_REG (SImode, 0);
- insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
- RTX_FRAME_RELATED_P (insn) = 1;
- set = gen_rtx_SET (VOIDmode, cr_save_rtx, magic_eh_cr_reg);
+ rs6000_emit_move_from_cr (cr_save_rtx);
+ }
+
+ /* Saving CR requires a two-instruction sequence: one instruction
+ to move the CR to a general-purpose register, and a second
+ instruction that stores the GPR to memory.
+
+ We do not emit any DWARF CFI records for the first of these,
+ because we cannot properly represent the fact that CR is saved in
+ a register. One reason is that we cannot express that multiple
+ CR fields are saved; another reason is that on 64-bit, the size
+ of the CR register in DWARF (4 bytes) differs from the size of
+ a general-purpose register.
+
+ This means if any intervening instruction were to clobber one of
+ the call-saved CR fields, we'd have incorrect CFI. To prevent
+ this from happening, we mark the store to memory as a use of
+ those CR fields, which prevents any such instruction from being
+ scheduled in between the two instructions. */
+ rtx crsave_v[9];
+ int n_crsave = 0;
+ int i;
+
+ crsave_v[n_crsave++] = gen_rtx_SET (VOIDmode, mem, cr_save_rtx);
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ crsave_v[n_crsave++]
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec_v (n_crsave, crsave_v)));
+ END_USE (REGNO (cr_save_rtx));
+
+ /* Now, there's no way that dwarf2out_frame_debug_expr is going to
+ understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)',
+ so we need to construct a frame expression manually. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Update address to be stack-pointer relative, like
+ rs6000_frame_related would do. */
+ addr = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
+ GEN_INT (info->cr_save_offset + sp_off));
+ mem = gen_frame_mem (SImode, addr);
+
+ if (DEFAULT_ABI == ABI_ELFv2)
+ {
+ /* In the ELFv2 ABI we generate separate CFI records for each
+ CR field that was actually saved. They all point to the
+ same 32-bit stack slot. */
+ rtx crframe[8];
+ int n_crframe = 0;
+
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ crframe[n_crframe]
+ = gen_rtx_SET (VOIDmode, mem,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (crframe[n_crframe]) = 1;
+ n_crframe++;
+ }
+
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec_v (n_crframe, crframe)));
+ }
+ else
+ {
+ /* In other ABIs, by convention, we use a single CR regnum to
+ represent the fact that all call-saved CR fields are saved.
+ We use CR2_REGNO to be compatible with gcc-2.95 on Linux. */
+ rtx set = gen_rtx_SET (VOIDmode, mem,
+ gen_rtx_REG (SImode, CR2_REGNO));
add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
}
- insn = emit_move_insn (mem, cr_save_rtx);
- END_USE (REGNO (cr_save_rtx));
+ }
- rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- NULL_RTX, NULL_RTX);
+ /* In the ELFv2 ABI we need to save all call-saved CR fields into
+ *separate* slots if the routine calls __builtin_eh_return, so
+ that they can be independently restored by the unwinder. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ int i, cr_off = info->ehcr_offset;
+ rtx crsave;
+
+ /* ??? We might get better performance by using multiple mfocrf
+ instructions. */
+ crsave = gen_rtx_REG (SImode, 0);
+ emit_insn (gen_movesi_from_cr (crsave));
+
+ for (i = 0; i < 8; i++)
+ if (!call_used_regs[CR0_REGNO + i])
+ {
+ rtvec p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0)
+ = gen_frame_store (crsave, frame_reg_rtx, cr_off + frame_off);
+ RTVEC_ELT (p, 1)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_frame_store (gen_rtx_REG (SImode, CR0_REGNO + i),
+ sp_reg_rtx, cr_off + sp_off));
+
+ cr_off += reg_size;
+ }
}
/* Update stack and set back pointer unless this is V.4,
@@ -21864,7 +23016,7 @@ rs6000_emit_prologue (void)
info->altivec_save_offset + ptr_off,
0, V4SImode, SAVRES_SAVE | SAVRES_VR);
rs6000_frame_related (insn, scratch_reg, sp_off - ptr_off,
- NULL_RTX, NULL_RTX);
+ NULL_RTX, NULL_RTX, NULL_RTX);
if (REGNO (frame_reg_rtx) == REGNO (scratch_reg))
{
/* The oddity mentioned above clobbered our frame reg. */
@@ -21880,7 +23032,7 @@ rs6000_emit_prologue (void)
for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
{
- rtx areg, savereg, mem;
+ rtx areg, savereg, mem, split_reg;
int offset;
offset = (info->altivec_save_offset + frame_off
@@ -21898,8 +23050,18 @@ rs6000_emit_prologue (void)
insn = emit_move_insn (mem, savereg);
+ /* When we split a VSX store into two insns, we need to make
+ sure the DWARF info knows which register we are storing.
+ Pass it in to be used on the appropriate note. */
+ if (!BYTES_BIG_ENDIAN
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_SRC (PATTERN (insn))) == VEC_SELECT)
+ split_reg = savereg;
+ else
+ split_reg = NULL_RTX;
+
rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- areg, GEN_INT (offset));
+ areg, GEN_INT (offset), split_reg);
}
}
@@ -21923,7 +23085,8 @@ rs6000_emit_prologue (void)
be using r12 as frame_reg_rtx and r11 as the static chain
pointer for nested functions. */
save_regno = 12;
- if (DEFAULT_ABI == ABI_AIX && !using_static_chain_p)
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && !using_static_chain_p)
save_regno = 11;
else if (REGNO (frame_reg_rtx) == 12)
{
@@ -21962,7 +23125,7 @@ rs6000_emit_prologue (void)
can use register 0. This allows us to use a plain 'blr' to return
from the procedure more often. */
int save_LR_around_toc_setup = (TARGET_ELF
- && DEFAULT_ABI != ABI_AIX
+ && DEFAULT_ABI == ABI_V4
&& flag_pic
&& ! info->lr_save_p
&& EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0);
@@ -22024,7 +23187,7 @@ rs6000_emit_prologue (void)
if (rs6000_save_toc_in_prologue_p ())
{
rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
- emit_insn (gen_frame_store (reg, sp_reg_rtx, 5 * reg_size));
+ emit_insn (gen_frame_store (reg, sp_reg_rtx, RS6000_TOC_SAVE_SLOT));
}
}
@@ -22065,6 +23228,49 @@ rs6000_output_function_prologue (FILE *file,
}
}
+ /* ELFv2 ABI r2 setup code and local entry point. This must follow
+ immediately after the global entry point label. */
+ if (DEFAULT_ABI == ABI_ELFv2 && cfun->machine->r2_setup_needed)
+ {
+ const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+
+ fprintf (file, "0:\taddis 2,12,.TOC.-0b@ha\n");
+ fprintf (file, "\taddi 2,2,.TOC.-0b@l\n");
+
+ fputs ("\t.localentry\t", file);
+ assemble_name (file, name);
+ fputs (",.-", file);
+ assemble_name (file, name);
+ fputs ("\n", file);
+ }
+
+ /* Output -mprofile-kernel code. This needs to be done here instead of
+ in output_function_profile since it must go after the ELFv2 ABI
+ local entry point. */
+ if (TARGET_PROFILE_KERNEL)
+ {
+ gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
+ gcc_assert (!TARGET_32BIT);
+
+ asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
+ asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
+
+ /* In the ELFv2 ABI we have no compiler stack word. It must be
+ the resposibility of _mcount to preserve the static chain
+ register if required. */
+ if (DEFAULT_ABI != ABI_ELFv2
+ && cfun->static_chain_decl != NULL)
+ {
+ asm_fprintf (file, "\tstd %s,24(%s)\n",
+ reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+ fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+ asm_fprintf (file, "\tld %s,24(%s)\n",
+ reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+ }
+ else
+ fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+ }
+
rs6000_pic_labelno++;
}
@@ -22117,6 +23323,7 @@ restore_saved_cr (rtx reg, int using_mfcr_multiple, bool exit_func)
if (using_mfcr_multiple && count > 1)
{
+ rtx insn;
rtvec p;
int ndx;
@@ -22134,16 +23341,43 @@ restore_saved_cr (rtx reg, int using_mfcr_multiple, bool exit_func)
gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
ndx++;
}
- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
gcc_assert (ndx == count);
+
+ /* For the ELFv2 ABI we generate a CFA_RESTORE for each
+ CR field separately. */
+ if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
+ {
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
else
for (i = 0; i < 8; i++)
if (save_reg_p (CR0_REGNO + i))
- emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, CR0_REGNO + i),
- reg));
+ {
+ rtx insn = emit_insn (gen_movsi_to_cr_one
+ (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
- if (!exit_func && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap))
+ /* For the ELFv2 ABI we generate a CFA_RESTORE for each
+ CR field separately, attached to the insn that in fact
+ restores this particular CR field. */
+ if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+
+ /* For other ABIs, we just generate a single CFA_RESTORE for CR2. */
+ if (!exit_func && DEFAULT_ABI != ABI_ELFv2
+ && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap))
{
rtx insn = get_last_insn ();
rtx cr = gen_rtx_REG (SImode, CR2_REGNO);
@@ -22184,10 +23418,22 @@ restore_saved_lr (int regno, bool exit_func)
static rtx
add_crlr_cfa_restore (const rs6000_stack_t *info, rtx cfa_restores)
{
- if (info->cr_save_p)
+ if (DEFAULT_ABI == ABI_ELFv2)
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ rtx cr = gen_rtx_REG (SImode, CR0_REGNO + i);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, cr,
+ cfa_restores);
+ }
+ }
+ else if (info->cr_save_p)
cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
gen_rtx_REG (SImode, CR2_REGNO),
cfa_restores);
+
if (info->lr_save_p)
cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
gen_rtx_REG (Pmode, LR_REGNO),
@@ -22685,6 +23931,35 @@ rs6000_emit_epilogue (int sibcall)
|| (!restoring_GPRs_inline
&& info->first_fp_reg_save == 64));
+ /* In the ELFv2 ABI we need to restore all call-saved CR fields from
+ *separate* slots if the routine calls __builtin_eh_return, so
+ that they can be independently restored by the unwinder. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ int i, cr_off = info->ehcr_offset;
+
+ for (i = 0; i < 8; i++)
+ if (!call_used_regs[CR0_REGNO + i])
+ {
+ rtx reg = gen_rtx_REG (SImode, 0);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx,
+ cr_off + frame_off));
+
+ insn = emit_insn (gen_movsi_to_cr_one
+ (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
+
+ if (!exit_func && flag_shrink_wrap)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ cr_off += reg_size;
+ }
+ }
+
/* Get the old lr if we saved it. If we are restoring registers
out-of-line, then the out-of-line routines can do this for us. */
if (restore_lr && restoring_GPRs_inline)
@@ -22728,7 +24003,7 @@ rs6000_emit_epilogue (int sibcall)
{
rtx reg = gen_rtx_REG (reg_mode, 2);
emit_insn (gen_frame_load (reg, frame_reg_rtx,
- frame_off + 5 * reg_size));
+ frame_off + RS6000_TOC_SAVE_SLOT));
}
for (i = 0; ; ++i)
@@ -22772,8 +24047,7 @@ rs6000_emit_epilogue (int sibcall)
anew to every function. */
if (!restoring_GPRs_inline)
- ool_adjust = 8 * (info->first_gp_reg_save
- - (FIRST_SAVRES_REGISTER + 1));
+ ool_adjust = 8 * (info->first_gp_reg_save - FIRST_SAVED_GP_REGNO);
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
emit_insn (gen_addsi3 (frame_reg_rtx, old_frame_reg_rtx,
GEN_INT (info->spe_gp_save_offset
@@ -23015,6 +24289,7 @@ rs6000_emit_epilogue (int sibcall)
if (! restoring_FPRs_inline)
{
int i;
+ int reg;
rtx sym;
if (flag_shrink_wrap)
@@ -23023,10 +24298,9 @@ rs6000_emit_epilogue (int sibcall)
sym = rs6000_savres_routine_sym (info,
SAVRES_FPR | (lr ? SAVRES_LR : 0));
RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
- RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode,
- DEFAULT_ABI == ABI_AIX
- ? 1 : 11));
+ reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
+ RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
+
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
@@ -23104,7 +24378,8 @@ rs6000_output_function_epilogue (FILE *file,
System V.4 Powerpc's (and the embedded ABI derived from it) use a
different traceback table. */
- if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && ! flag_inhibit_size_directive
&& rs6000_traceback != traceback_none && !cfun->is_thunk)
{
const char *fname = NULL;
@@ -23432,6 +24707,12 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
SIBLING_CALL_P (insn) = 1;
emit_barrier ();
+ /* Ensure we have a global entry point for the thunk. ??? We could
+ avoid that if the target routine doesn't need a global entry point,
+ but we do not know whether this is the case at this point. */
+ if (DEFAULT_ABI == ABI_ELFv2)
+ cfun->machine->r2_setup_needed = true;
+
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
instruction scheduling worth while. Note that use_thunk calls
@@ -24128,7 +25409,7 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED)
if (TARGET_PROFILE_KERNEL)
return;
- if (DEFAULT_ABI == ABI_AIX)
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
{
#ifndef NO_PROFILE_COUNTERS
# define NO_PROFILE_COUNTERS 0
@@ -24272,29 +25553,9 @@ output_function_profiler (FILE *file, int labelno)
break;
case ABI_AIX:
+ case ABI_ELFv2:
case ABI_DARWIN:
- if (!TARGET_PROFILE_KERNEL)
- {
- /* Don't do anything, done in output_profile_hook (). */
- }
- else
- {
- gcc_assert (!TARGET_32BIT);
-
- asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
- asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
-
- if (cfun->static_chain_decl != NULL)
- {
- asm_fprintf (file, "\tstd %s,24(%s)\n",
- reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
- fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
- asm_fprintf (file, "\tld %s,24(%s)\n",
- reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
- }
- else
- fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
- }
+ /* Don't do anything, done in output_profile_hook (). */
break;
}
}
@@ -26230,6 +27491,11 @@ rs6000_trampoline_size (void)
ret = (TARGET_32BIT) ? 12 : 24;
break;
+ case ABI_ELFv2:
+ gcc_assert (!TARGET_32BIT);
+ ret = 32;
+ break;
+
case ABI_DARWIN:
case ABI_V4:
ret = (TARGET_32BIT) ? 40 : 48;
@@ -26285,6 +27551,7 @@ rs6000_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
break;
/* Under V.4/eabi/darwin, __trampoline_setup does the real work. */
+ case ABI_ELFv2:
case ABI_DARWIN:
case ABI_V4:
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
@@ -26579,7 +27846,7 @@ rs6000_ms_bitfield_layout_p (const_tree record_type)
static void
rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
{
- if (DEFAULT_ABI == ABI_AIX
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& TARGET_MINIMAL_TOC
&& !TARGET_RELOCATABLE)
{
@@ -26600,7 +27867,8 @@ rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
else
fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
}
- else if (DEFAULT_ABI == ABI_AIX && !TARGET_RELOCATABLE)
+ else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && !TARGET_RELOCATABLE)
fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
else
{
@@ -27150,7 +28418,7 @@ rs6000_elf_reloc_rw_mask (void)
{
if (flag_pic)
return 3;
- else if (DEFAULT_ABI == ABI_AIX)
+ else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
return 2;
else
return 0;
@@ -27226,7 +28494,7 @@ rs6000_elf_asm_out_destructor (rtx symbol, int priority)
void
rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
{
- if (TARGET_64BIT)
+ if (TARGET_64BIT && DEFAULT_ABI != ABI_ELFv2)
{
fputs ("\t.section\t\".opd\",\"aw\"\n\t.align 3\n", file);
ASM_OUTPUT_LABEL (file, name);
@@ -27292,8 +28560,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
fprintf (file, "%s:\n", desc_name);
fprintf (file, "\t.long %s\n", orig_name);
fputs ("\t.long _GLOBAL_OFFSET_TABLE_\n", file);
- if (DEFAULT_ABI == ABI_AIX)
- fputs ("\t.long 0\n", file);
+ fputs ("\t.long 0\n", file);
fprintf (file, "\t.previous\n");
}
ASM_OUTPUT_LABEL (file, name);
@@ -27322,7 +28589,7 @@ rs6000_elf_file_end (void)
}
#endif
#if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD)
- if (TARGET_32BIT)
+ if (TARGET_32BIT || DEFAULT_ABI == ABI_ELFv2)
file_end_indicate_exec_stack ();
#endif
}
@@ -28277,56 +29544,28 @@ rs6000_emit_nmsub (rtx dst, rtx m1, rtx m2, rtx a)
emit_insn (gen_rtx_SET (VOIDmode, dst, r));
}
-/* Newton-Raphson approximation of floating point divide with just 2 passes
- (either single precision floating point, or newer machines with higher
- accuracy estimates). Support both scalar and vector divide. Assumes no
- trapping math and finite arguments. */
+/* Newton-Raphson approximation of floating point divide DST = N/D. If NOTE_P,
+ add a reg_note saying that this was a division. Support both scalar and
+ vector divide. Assumes no trapping math and finite arguments. */
-static void
-rs6000_emit_swdiv_high_precision (rtx dst, rtx n, rtx d)
+void
+rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p)
{
enum machine_mode mode = GET_MODE (dst);
- rtx x0, e0, e1, y1, u0, v0;
- enum insn_code code = optab_handler (smul_optab, mode);
- gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
- rtx one = rs6000_load_constant_and_splat (mode, dconst1);
-
- gcc_assert (code != CODE_FOR_nothing);
-
- /* x0 = 1./d estimate */
- x0 = gen_reg_rtx (mode);
- emit_insn (gen_rtx_SET (VOIDmode, x0,
- gen_rtx_UNSPEC (mode, gen_rtvec (1, d),
- UNSPEC_FRES)));
-
- e0 = gen_reg_rtx (mode);
- rs6000_emit_nmsub (e0, d, x0, one); /* e0 = 1. - (d * x0) */
-
- e1 = gen_reg_rtx (mode);
- rs6000_emit_madd (e1, e0, e0, e0); /* e1 = (e0 * e0) + e0 */
-
- y1 = gen_reg_rtx (mode);
- rs6000_emit_madd (y1, e1, x0, x0); /* y1 = (e1 * x0) + x0 */
-
- u0 = gen_reg_rtx (mode);
- emit_insn (gen_mul (u0, n, y1)); /* u0 = n * y1 */
-
- v0 = gen_reg_rtx (mode);
- rs6000_emit_nmsub (v0, d, u0, n); /* v0 = n - (d * u0) */
-
- rs6000_emit_madd (dst, v0, y1, u0); /* dst = (v0 * y1) + u0 */
-}
+ rtx one, x0, e0, x1, xprev, eprev, xnext, enext, u, v;
+ int i;
-/* Newton-Raphson approximation of floating point divide that has a low
- precision estimate. Assumes no trapping math and finite arguments. */
+ /* Low precision estimates guarantee 5 bits of accuracy. High
+ precision estimates guarantee 14 bits of accuracy. SFmode
+ requires 23 bits of accuracy. DFmode requires 52 bits of
+ accuracy. Each pass at least doubles the accuracy, leading
+ to the following. */
+ int passes = (TARGET_RECIP_PRECISION) ? 1 : 3;
+ if (mode == DFmode || mode == V2DFmode)
+ passes++;
-static void
-rs6000_emit_swdiv_low_precision (rtx dst, rtx n, rtx d)
-{
- enum machine_mode mode = GET_MODE (dst);
- rtx x0, e0, e1, e2, y1, y2, y3, u0, v0, one;
enum insn_code code = optab_handler (smul_optab, mode);
- gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+ insn_gen_fn gen_mul = GEN_FCN (code);
gcc_assert (code != CODE_FOR_nothing);
@@ -28338,46 +29577,44 @@ rs6000_emit_swdiv_low_precision (rtx dst, rtx n, rtx d)
gen_rtx_UNSPEC (mode, gen_rtvec (1, d),
UNSPEC_FRES)));
- e0 = gen_reg_rtx (mode);
- rs6000_emit_nmsub (e0, d, x0, one); /* e0 = 1. - d * x0 */
-
- y1 = gen_reg_rtx (mode);
- rs6000_emit_madd (y1, e0, x0, x0); /* y1 = x0 + e0 * x0 */
+ /* Each iteration but the last calculates x_(i+1) = x_i * (2 - d * x_i). */
+ if (passes > 1) {
- e1 = gen_reg_rtx (mode);
- emit_insn (gen_mul (e1, e0, e0)); /* e1 = e0 * e0 */
+ /* e0 = 1. - d * x0 */
+ e0 = gen_reg_rtx (mode);
+ rs6000_emit_nmsub (e0, d, x0, one);
- y2 = gen_reg_rtx (mode);
- rs6000_emit_madd (y2, e1, y1, y1); /* y2 = y1 + e1 * y1 */
+ /* x1 = x0 + e0 * x0 */
+ x1 = gen_reg_rtx (mode);
+ rs6000_emit_madd (x1, e0, x0, x0);
- e2 = gen_reg_rtx (mode);
- emit_insn (gen_mul (e2, e1, e1)); /* e2 = e1 * e1 */
-
- y3 = gen_reg_rtx (mode);
- rs6000_emit_madd (y3, e2, y2, y2); /* y3 = y2 + e2 * y2 */
+ for (i = 0, xprev = x1, eprev = e0; i < passes - 2;
+ ++i, xprev = xnext, eprev = enext) {
+
+ /* enext = eprev * eprev */
+ enext = gen_reg_rtx (mode);
+ emit_insn (gen_mul (enext, eprev, eprev));
- u0 = gen_reg_rtx (mode);
- emit_insn (gen_mul (u0, n, y3)); /* u0 = n * y3 */
+ /* xnext = xprev + enext * xprev */
+ xnext = gen_reg_rtx (mode);
+ rs6000_emit_madd (xnext, enext, xprev, xprev);
+ }
- v0 = gen_reg_rtx (mode);
- rs6000_emit_nmsub (v0, d, u0, n); /* v0 = n - d * u0 */
+ } else
+ xprev = x0;
- rs6000_emit_madd (dst, v0, y3, u0); /* dst = u0 + v0 * y3 */
-}
+ /* The last iteration calculates x_(i+1) = n * x_i * (2 - d * x_i). */
-/* Newton-Raphson approximation of floating point divide DST = N/D. If NOTE_P,
- add a reg_note saying that this was a division. Support both scalar and
- vector divide. Assumes no trapping math and finite arguments. */
+ /* u = n * xprev */
+ u = gen_reg_rtx (mode);
+ emit_insn (gen_mul (u, n, xprev));
-void
-rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p)
-{
- enum machine_mode mode = GET_MODE (dst);
+ /* v = n - (d * u) */
+ v = gen_reg_rtx (mode);
+ rs6000_emit_nmsub (v, d, u, n);
- if (RS6000_RECIP_HIGH_PRECISION_P (mode))
- rs6000_emit_swdiv_high_precision (dst, n, d);
- else
- rs6000_emit_swdiv_low_precision (dst, n, d);
+ /* dst = (v * xprev) + u */
+ rs6000_emit_madd (dst, v, xprev, u);
if (note_p)
add_reg_note (get_last_insn (), REG_EQUAL, gen_rtx_DIV (mode, n, d));
@@ -28392,12 +29629,21 @@ rs6000_emit_swrsqrt (rtx dst, rtx src)
enum machine_mode mode = GET_MODE (src);
rtx x0 = gen_reg_rtx (mode);
rtx y = gen_reg_rtx (mode);
- int passes = (TARGET_RECIP_PRECISION) ? 2 : 3;
+
+ /* Low precision estimates guarantee 5 bits of accuracy. High
+ precision estimates guarantee 14 bits of accuracy. SFmode
+ requires 23 bits of accuracy. DFmode requires 52 bits of
+ accuracy. Each pass at least doubles the accuracy, leading
+ to the following. */
+ int passes = (TARGET_RECIP_PRECISION) ? 1 : 3;
+ if (mode == DFmode || mode == V2DFmode)
+ passes++;
+
REAL_VALUE_TYPE dconst3_2;
int i;
rtx halfthree;
enum insn_code code = optab_handler (smul_optab, mode);
- gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+ insn_gen_fn gen_mul = GEN_FCN (code);
gcc_assert (code != CODE_FOR_nothing);
@@ -28554,6 +29800,137 @@ rs6000_emit_parity (rtx dst, rtx src)
}
}
+/* Expand an Altivec constant permutation for little endian mode.
+ There are two issues: First, the two input operands must be
+ swapped so that together they form a double-wide array in LE
+ order. Second, the vperm instruction has surprising behavior
+ in LE mode: it interprets the elements of the source vectors
+ in BE mode ("left to right") and interprets the elements of
+ the destination vector in LE mode ("right to left"). To
+ correct for this, we must subtract each element of the permute
+ control vector from 31.
+
+ For example, suppose we want to concatenate vr10 = {0, 1, 2, 3}
+ with vr11 = {4, 5, 6, 7} and extract {0, 2, 4, 6} using a vperm.
+ We place {0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27} in vr12 to
+ serve as the permute control vector. Then, in BE mode,
+
+ vperm 9,10,11,12
+
+ places the desired result in vr9. However, in LE mode the
+ vector contents will be
+
+ vr10 = 00000003 00000002 00000001 00000000
+ vr11 = 00000007 00000006 00000005 00000004
+
+ The result of the vperm using the same permute control vector is
+
+ vr9 = 05000000 07000000 01000000 03000000
+
+ That is, the leftmost 4 bytes of vr10 are interpreted as the
+ source for the rightmost 4 bytes of vr9, and so on.
+
+ If we change the permute control vector to
+
+ vr12 = {31,20,29,28,23,22,21,20,15,14,13,12,7,6,5,4}
+
+ and issue
+
+ vperm 9,11,10,12
+
+ we get the desired
+
+ vr9 = 00000006 00000004 00000002 00000000. */
+
+void
+altivec_expand_vec_perm_const_le (rtx operands[4])
+{
+ unsigned int i;
+ rtx perm[16];
+ rtx constv, unspec;
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx sel = operands[3];
+
+ /* Unpack and adjust the constant selector. */
+ for (i = 0; i < 16; ++i)
+ {
+ rtx e = XVECEXP (sel, 0, i);
+ unsigned int elt = 31 - (INTVAL (e) & 31);
+ perm[i] = GEN_INT (elt);
+ }
+
+ /* Expand to a permute, swapping the inputs and using the
+ adjusted selector. */
+ if (!REG_P (op0))
+ op0 = force_reg (V16QImode, op0);
+ if (!REG_P (op1))
+ op1 = force_reg (V16QImode, op1);
+
+ constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
+ constv = force_reg (V16QImode, constv);
+ unspec = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, op1, op0, constv),
+ UNSPEC_VPERM);
+ if (!REG_P (target))
+ {
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, unspec);
+ unspec = tmp;
+ }
+
+ emit_move_insn (target, unspec);
+}
+
+/* Similarly to altivec_expand_vec_perm_const_le, we must adjust the
+ permute control vector. But here it's not a constant, so we must
+ generate a vector splat/subtract to do the adjustment. */
+
+void
+altivec_expand_vec_perm_le (rtx operands[4])
+{
+ rtx splat, unspec;
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx sel = operands[3];
+ rtx tmp = target;
+ rtx splatreg = gen_reg_rtx (V16QImode);
+ enum machine_mode mode = GET_MODE (target);
+
+ /* Get everything in regs so the pattern matches. */
+ if (!REG_P (op0))
+ op0 = force_reg (mode, op0);
+ if (!REG_P (op1))
+ op1 = force_reg (mode, op1);
+ if (!REG_P (sel))
+ sel = force_reg (V16QImode, sel);
+ if (!REG_P (target))
+ tmp = gen_reg_rtx (mode);
+
+ /* SEL = splat(31) - SEL. */
+ /* We want to subtract from 31, but we can't vspltisb 31 since
+ it's out of range. -1 works as well because only the low-order
+ five bits of the permute control vector elements are used. */
+ splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ emit_move_insn (splatreg, splat);
+ sel = gen_rtx_MINUS (V16QImode, splatreg, sel);
+ emit_move_insn (splatreg, sel);
+
+ /* Permute with operands reversed and adjusted selector. */
+ unspec = gen_rtx_UNSPEC (mode, gen_rtvec (3, op1, op0, splatreg), UNSPEC_VPERM);
+
+ /* Copy into target, possibly by way of a register. */
+ if (!REG_P (target))
+ {
+ emit_move_insn (tmp, unspec);
+ unspec = tmp;
+ }
+
+ emit_move_insn (target, unspec);
+}
+
/* Expand an Altivec constant permutation. Return true if we match
an efficient implementation; false to fall back to VPERM. */
@@ -28566,21 +29943,33 @@ altivec_expand_vec_perm_const (rtx operands[4])
unsigned char perm[16];
};
static const struct altivec_perm_insn patterns[] = {
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum,
+ { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum_direct,
{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum,
+ { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum_direct,
{ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghb,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct
+ : CODE_FOR_altivec_vmrglb_direct),
{ 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghh,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct
+ : CODE_FOR_altivec_vmrglh_direct),
{ 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghw,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct
+ : CODE_FOR_altivec_vmrglw_direct),
{ 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglb,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct
+ : CODE_FOR_altivec_vmrghb_direct),
{ 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglh,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct
+ : CODE_FOR_altivec_vmrghh_direct),
{ 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglw,
+ { OPTION_MASK_ALTIVEC,
+ (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct
+ : CODE_FOR_altivec_vmrghw_direct),
{ 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } },
{ OPTION_MASK_P8_VECTOR, CODE_FOR_p8_vmrgew,
{ 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27 } },
@@ -28642,7 +30031,9 @@ altivec_expand_vec_perm_const (rtx operands[4])
break;
if (i == 16)
{
- emit_insn (gen_altivec_vspltb (target, op0, GEN_INT (elt)));
+ if (!BYTES_BIG_ENDIAN)
+ elt = 15 - elt;
+ emit_insn (gen_altivec_vspltb_direct (target, op0, GEN_INT (elt)));
return true;
}
@@ -28653,9 +30044,10 @@ altivec_expand_vec_perm_const (rtx operands[4])
break;
if (i == 16)
{
+ int field = BYTES_BIG_ENDIAN ? elt / 2 : 7 - elt / 2;
x = gen_reg_rtx (V8HImode);
- emit_insn (gen_altivec_vsplth (x, gen_lowpart (V8HImode, op0),
- GEN_INT (elt / 2)));
+ emit_insn (gen_altivec_vsplth_direct (x, gen_lowpart (V8HImode, op0),
+ GEN_INT (field)));
emit_move_insn (target, gen_lowpart (V16QImode, x));
return true;
}
@@ -28671,9 +30063,10 @@ altivec_expand_vec_perm_const (rtx operands[4])
break;
if (i == 16)
{
+ int field = BYTES_BIG_ENDIAN ? elt / 4 : 3 - elt / 4;
x = gen_reg_rtx (V4SImode);
- emit_insn (gen_altivec_vspltw (x, gen_lowpart (V4SImode, op0),
- GEN_INT (elt / 4)));
+ emit_insn (gen_altivec_vspltw_direct (x, gen_lowpart (V4SImode, op0),
+ GEN_INT (field)));
emit_move_insn (target, gen_lowpart (V16QImode, x));
return true;
}
@@ -28711,7 +30104,30 @@ altivec_expand_vec_perm_const (rtx operands[4])
enum machine_mode omode = insn_data[icode].operand[0].mode;
enum machine_mode imode = insn_data[icode].operand[1].mode;
- if (swapped)
+ /* For little-endian, don't use vpkuwum and vpkuhum if the
+ underlying vector type is not V4SI and V8HI, respectively.
+ For example, using vpkuwum with a V8HI picks up the even
+ halfwords (BE numbering) when the even halfwords (LE
+ numbering) are what we need. */
+ if (!BYTES_BIG_ENDIAN
+ && icode == CODE_FOR_altivec_vpkuwum_direct
+ && ((GET_CODE (op0) == REG
+ && GET_MODE (op0) != V4SImode)
+ || (GET_CODE (op0) == SUBREG
+ && GET_MODE (XEXP (op0, 0)) != V4SImode)))
+ continue;
+ if (!BYTES_BIG_ENDIAN
+ && icode == CODE_FOR_altivec_vpkuhum_direct
+ && ((GET_CODE (op0) == REG
+ && GET_MODE (op0) != V8HImode)
+ || (GET_CODE (op0) == SUBREG
+ && GET_MODE (XEXP (op0, 0)) != V8HImode)))
+ continue;
+
+ /* For little-endian, the two input operands must be swapped
+ (or swapped back) to ensure proper right-to-left numbering
+ from 0 to 2N-1. */
+ if (swapped ^ !BYTES_BIG_ENDIAN)
x = op0, op0 = op1, op1 = x;
if (imode != V16QImode)
{
@@ -28729,6 +30145,12 @@ altivec_expand_vec_perm_const (rtx operands[4])
}
}
+ if (!BYTES_BIG_ENDIAN)
+ {
+ altivec_expand_vec_perm_const_le (operands);
+ return true;
+ }
+
return false;
}
@@ -28777,7 +30199,6 @@ rs6000_expand_vec_perm_const_1 (rtx target, rtx op0, rtx op1,
vmode = GET_MODE (target);
gcc_assert (GET_MODE_NUNITS (vmode) == 2);
dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
-
x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
@@ -28873,7 +30294,7 @@ rs6000_expand_interleave (rtx target, rtx op0, rtx op1, bool highp)
unsigned i, high, nelt = GET_MODE_NUNITS (vmode);
rtx perm[16];
- high = (highp == BYTES_BIG_ENDIAN ? 0 : nelt / 2);
+ high = (highp ? 0 : nelt / 2);
for (i = 0; i < nelt / 2; i++)
{
perm[i * 2] = GEN_INT (i + high);
@@ -28928,6 +30349,8 @@ rs6000_function_value (const_tree valtype,
{
enum machine_mode mode;
unsigned int regno;
+ enum machine_mode elt_mode;
+ int n_elts;
/* Special handling for structs in darwin64. */
if (TARGET_MACHO
@@ -28947,6 +30370,36 @@ rs6000_function_value (const_tree valtype,
/* Otherwise fall through to standard ABI rules. */
}
+ /* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */
+ if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (valtype), valtype,
+ &elt_mode, &n_elts))
+ {
+ int first_reg, n_regs, i;
+ rtx par;
+
+ if (SCALAR_FLOAT_MODE_P (elt_mode))
+ {
+ /* _Decimal128 must use even/odd register pairs. */
+ first_reg = (elt_mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
+ n_regs = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
+ }
+ else
+ {
+ first_reg = ALTIVEC_ARG_RETURN;
+ n_regs = 1;
+ }
+
+ par = gen_rtx_PARALLEL (TYPE_MODE (valtype), rtvec_alloc (n_elts));
+ for (i = 0; i < n_elts; i++)
+ {
+ rtx r = gen_rtx_REG (elt_mode, first_reg + i * n_regs);
+ rtx off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
+ XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, r, off);
+ }
+
+ return par;
+ }
+
if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
{
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */
@@ -29059,6 +30512,13 @@ rs6000_libcall_value (enum machine_mode mode)
}
+/* Return true if we use LRA instead of reload pass. */
+static bool
+rs6000_lra_p (void)
+{
+ return rs6000_lra_flag;
+}
+
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.
@@ -29340,9 +30800,12 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "powerpc-gfxopt", OPTION_MASK_PPC_GFXOPT, false, true },
{ "powerpc-gpopt", OPTION_MASK_PPC_GPOPT, false, true },
{ "quad-memory", OPTION_MASK_QUAD_MEMORY, false, true },
+ { "quad-memory-atomic", OPTION_MASK_QUAD_MEMORY_ATOMIC, false, true },
{ "recip-precision", OPTION_MASK_RECIP_PRECISION, false, true },
{ "string", OPTION_MASK_STRING, false, true },
{ "update", OPTION_MASK_NO_UPDATE, true , true },
+ { "upper-regs-df", OPTION_MASK_UPPER_REGS_DF, false, false },
+ { "upper-regs-sf", OPTION_MASK_UPPER_REGS_SF, false, false },
{ "vsx", OPTION_MASK_VSX, false, true },
{ "vsx-timode", OPTION_MASK_VSX_TIMODE, false, true },
#ifdef OPTION_MASK_64BIT
@@ -29903,7 +31366,6 @@ rs6000_print_options_internal (FILE *file,
size_t cur_column;
size_t max_column = 76;
const char *comma = "";
- const char *nl = "\n";
if (indent)
start_column += fprintf (file, "%*s", indent, "");
@@ -29934,7 +31396,6 @@ rs6000_print_options_internal (FILE *file,
fprintf (stderr, ", \\\n%*s", (int)start_column, "");
cur_column = start_column + len;
comma = "";
- nl = "\n\n";
}
fprintf (file, "%s%s%s%s", comma, prefix, no_str,
@@ -29944,7 +31405,7 @@ rs6000_print_options_internal (FILE *file,
}
}
- fputs (nl, file);
+ fputs ("\n", file);
}
/* Helper function to print the current isa options on a line. */
@@ -30120,118 +31581,149 @@ rs6000_legitimate_constant_p (enum machine_mode mode, rtx x)
}
-/* A function pointer under AIX is a pointer to a data area whose first word
- contains the actual address of the function, whose second word contains a
- pointer to its TOC, and whose third word contains a value to place in the
- static chain register (r11). Note that if we load the static chain, our
- "trampoline" need not have any executable code. */
+
+/* Expand code to perform a call under the AIX or ELFv2 ABI. */
void
-rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
+rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
{
+ rtx toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
+ rtx toc_load = NULL_RTX;
+ rtx toc_restore = NULL_RTX;
rtx func_addr;
- rtx toc_reg;
- rtx sc_reg;
- rtx stack_ptr;
- rtx stack_toc_offset;
- rtx stack_toc_mem;
- rtx func_toc_offset;
- rtx func_toc_mem;
- rtx func_sc_offset;
- rtx func_sc_mem;
+ rtx abi_reg = NULL_RTX;
+ rtx call[4];
+ int n_call;
rtx insn;
- rtx (*call_func) (rtx, rtx, rtx, rtx);
- rtx (*call_value_func) (rtx, rtx, rtx, rtx, rtx);
-
- stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
- /* Load up address of the actual function. */
- func_desc = force_reg (Pmode, func_desc);
- func_addr = gen_reg_rtx (Pmode);
- emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
-
- if (TARGET_32BIT)
- {
+ /* Handle longcall attributes. */
+ if (INTVAL (cookie) & CALL_LONG)
+ func_desc = rs6000_longcall_ref (func_desc);
+
+ /* Handle indirect calls. */
+ if (GET_CODE (func_desc) != SYMBOL_REF
+ || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func_desc)))
+ {
+ /* Save the TOC into its reserved slot before the call,
+ and prepare to restore it after the call. */
+ rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
+ rtx stack_toc_mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_ptr,
+ stack_toc_offset));
+ toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_mem);
+
+ /* Can we optimize saving the TOC in the prologue or
+ do we need to do it at every call? */
+ if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
+ cfun->machine->save_toc_in_prologue = true;
+ else
+ {
+ MEM_VOLATILE_P (stack_toc_mem) = 1;
+ emit_move_insn (stack_toc_mem, toc_reg);
+ }
- stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT);
- func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT);
- func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT);
- if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ if (DEFAULT_ABI == ABI_ELFv2)
{
- call_func = gen_call_indirect_aix32bit;
- call_value_func = gen_call_value_indirect_aix32bit;
+ /* A function pointer in the ELFv2 ABI is just a plain address, but
+ the ABI requires it to be loaded into r12 before the call. */
+ func_addr = gen_rtx_REG (Pmode, 12);
+ emit_move_insn (func_addr, func_desc);
+ abi_reg = func_addr;
}
else
{
- call_func = gen_call_indirect_aix32bit_nor11;
- call_value_func = gen_call_value_indirect_aix32bit_nor11;
+ /* A function pointer under AIX is a pointer to a data area whose
+ first word contains the actual address of the function, whose
+ second word contains a pointer to its TOC, and whose third word
+ contains a value to place in the static chain register (r11).
+ Note that if we load the static chain, our "trampoline" need
+ not have any executable code. */
+
+ /* Load up address of the actual function. */
+ func_desc = force_reg (Pmode, func_desc);
+ func_addr = gen_reg_rtx (Pmode);
+ emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
+
+ /* Prepare to load the TOC of the called function. Note that the
+ TOC load must happen immediately before the actual call so
+ that unwinding the TOC registers works correctly. See the
+ comment in frob_update_context. */
+ rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode));
+ rtx func_toc_mem = gen_rtx_MEM (Pmode,
+ gen_rtx_PLUS (Pmode, func_desc,
+ func_toc_offset));
+ toc_load = gen_rtx_USE (VOIDmode, func_toc_mem);
+
+ /* If we have a static chain, load it up. */
+ if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ {
+ rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+ rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode));
+ rtx func_sc_mem = gen_rtx_MEM (Pmode,
+ gen_rtx_PLUS (Pmode, func_desc,
+ func_sc_offset));
+ emit_move_insn (sc_reg, func_sc_mem);
+ abi_reg = sc_reg;
+ }
}
}
else
{
- stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_64BIT);
- func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_64BIT);
- func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_64BIT);
- if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
- {
- call_func = gen_call_indirect_aix64bit;
- call_value_func = gen_call_value_indirect_aix64bit;
- }
- else
- {
- call_func = gen_call_indirect_aix64bit_nor11;
- call_value_func = gen_call_value_indirect_aix64bit_nor11;
- }
+ /* Direct calls use the TOC: for local calls, the callee will
+ assume the TOC register is set; for non-local calls, the
+ PLT stub needs the TOC register. */
+ abi_reg = toc_reg;
+ func_addr = func_desc;
}
- /* Reserved spot to store the TOC. */
- stack_toc_mem = gen_frame_mem (Pmode,
- gen_rtx_PLUS (Pmode,
- stack_ptr,
- stack_toc_offset));
+ /* Create the call. */
+ call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), flag);
+ if (value != NULL_RTX)
+ call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
+ n_call = 1;
- gcc_assert (cfun);
- gcc_assert (cfun->machine);
+ if (toc_load)
+ call[n_call++] = toc_load;
+ if (toc_restore)
+ call[n_call++] = toc_restore;
- /* Can we optimize saving the TOC in the prologue or do we need to do it at
- every call? */
- if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
- cfun->machine->save_toc_in_prologue = true;
+ call[n_call++] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
- else
- {
- MEM_VOLATILE_P (stack_toc_mem) = 1;
- emit_move_insn (stack_toc_mem, toc_reg);
- }
+ insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n_call, call));
+ insn = emit_call_insn (insn);
- /* Calculate the address to load the TOC of the called function. We don't
- actually load this until the split after reload. */
- func_toc_mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode,
- func_desc,
- func_toc_offset));
+ /* Mention all registers defined by the ABI to hold information
+ as uses in CALL_INSN_FUNCTION_USAGE. */
+ if (abi_reg)
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg);
+}
- /* If we have a static chain, load it up. */
- if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
- {
- func_sc_mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode,
- func_desc,
- func_sc_offset));
+/* Expand code to perform a sibling call under the AIX or ELFv2 ABI. */
- sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
- emit_move_insn (sc_reg, func_sc_mem);
- }
+void
+rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
+{
+ rtx call[2];
+ rtx insn;
+
+ gcc_assert (INTVAL (cookie) == 0);
/* Create the call. */
- if (value)
- insn = call_value_func (value, func_addr, flag, func_toc_mem,
- stack_toc_mem);
- else
- insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
+ call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_desc), flag);
+ if (value != NULL_RTX)
+ call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
+
+ call[1] = simple_return_rtx;
+
+ insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (2, call));
+ insn = emit_call_insn (insn);
- emit_call_insn (insn);
+ /* Note use of the TOC register. */
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
+ /* We need to also mark a use of the link register since the function we
+ sibling-call to will use it to return to our caller. */
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO));
}
/* Return whether we need to always update the saved TOC pointer when we update
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 0be30d6d726..208480280a7 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -474,6 +474,15 @@ extern int rs6000_vector_align[];
? rs6000_vector_align[(MODE)] \
: (int)GET_MODE_BITSIZE ((MODE)))
+/* Determine the element order to use for vector instructions. By
+ default we use big-endian element order when targeting big-endian,
+ and little-endian element order when targeting little-endian. For
+ programs being ported from BE Power to LE Power, it can sometimes
+ be useful to use big-endian element order when targeting little-endian.
+ This is set via -maltivec=be, for example. */
+#define VECTOR_ELT_ORDER_BIG \
+ (BYTES_BIG_ENDIAN || (rs6000_altivec_element_order == 2))
+
/* Alignment options for fields in structures for sub-targets following
AIX-like ABI.
ALIGN_POWER word-aligns FP doubles (default AIX ABI).
@@ -530,8 +539,11 @@ extern int rs6000_vector_align[];
/* Byte/char syncs were added as phased in for ISA 2.06B, but are not present
in power7, so conditionalize them on p8 features. TImode syncs need quad
memory support. */
-#define TARGET_SYNC_HI_QI (TARGET_QUAD_MEMORY || TARGET_DIRECT_MOVE)
-#define TARGET_SYNC_TI TARGET_QUAD_MEMORY
+#define TARGET_SYNC_HI_QI (TARGET_QUAD_MEMORY \
+ || TARGET_QUAD_MEMORY_ATOMIC \
+ || TARGET_DIRECT_MOVE)
+
+#define TARGET_SYNC_TI TARGET_QUAD_MEMORY_ATOMIC
/* Power7 has both 32-bit load and store integer for the FPRs, so we don't need
to allocate the SDmode stack slot to get the value into the proper location
@@ -623,6 +635,25 @@ extern int rs6000_vector_align[];
|| rs6000_cpu == PROCESSOR_PPC8548)
+/* Whether SF/DF operations are supported on the E500. */
+#define TARGET_SF_SPE (TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT \
+ && !TARGET_FPRS)
+
+#define TARGET_DF_SPE (TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT \
+ && !TARGET_FPRS && TARGET_E500_DOUBLE)
+
+/* Whether SF/DF operations are supported by by the normal floating point unit
+ (or the vector/scalar unit). */
+#define TARGET_SF_FPR (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_SINGLE_FLOAT)
+
+#define TARGET_DF_FPR (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_DOUBLE_FLOAT)
+
+/* Whether SF/DF operations are supported by any hardware. */
+#define TARGET_SF_INSN (TARGET_SF_FPR || TARGET_SF_SPE)
+#define TARGET_DF_INSN (TARGET_DF_FPR || TARGET_DF_SPE)
+
/* Which machine supports the various reciprocal estimate instructions. */
#define TARGET_FRES (TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT \
&& TARGET_FPRS && TARGET_SINGLE_FLOAT)
@@ -660,9 +691,6 @@ extern unsigned char rs6000_recip_bits[];
#define RS6000_RECIP_AUTO_RSQRTE_P(MODE) \
(rs6000_recip_bits[(int)(MODE)] & RS6000_RECIP_MASK_AUTO_RSQRTE)
-#define RS6000_RECIP_HIGH_PRECISION_P(MODE) \
- ((MODE) == SFmode || (MODE) == V4SFmode || TARGET_RECIP_PRECISION)
-
/* The default CPU for TARGET_OPTION_OVERRIDE. */
#define OPTION_TARGET_CPU_DEFAULT TARGET_CPU_DEFAULT
@@ -1418,15 +1446,18 @@ enum r6000_reg_class_enum {
RS6000_CONSTRAINT_v, /* Altivec registers */
RS6000_CONSTRAINT_wa, /* Any VSX register */
RS6000_CONSTRAINT_wd, /* VSX register for V2DF */
- RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */
RS6000_CONSTRAINT_wf, /* VSX register for V4SF */
+ RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */
RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */
RS6000_CONSTRAINT_wm, /* VSX register for direct move */
RS6000_CONSTRAINT_wr, /* GPR register if 64-bit */
RS6000_CONSTRAINT_ws, /* VSX register for DF */
RS6000_CONSTRAINT_wt, /* VSX register for TImode */
- RS6000_CONSTRAINT_wv, /* Altivec register for power8 vector */
+ RS6000_CONSTRAINT_wu, /* Altivec register for float load/stores. */
+ RS6000_CONSTRAINT_wv, /* Altivec register for double load/stores. */
+ RS6000_CONSTRAINT_ww, /* FP or VSX register for vsx float ops. */
RS6000_CONSTRAINT_wx, /* FPR register for STFIWX */
+ RS6000_CONSTRAINT_wy, /* VSX register for SF */
RS6000_CONSTRAINT_wz, /* FPR register for LFIWZX */
RS6000_CONSTRAINT_MAX
};
@@ -1515,21 +1546,14 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
arguments. */
#define FRAME_GROWS_DOWNWARD (flag_stack_protect != 0 || flag_asan != 0)
-/* Size of the outgoing register save area */
-#define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX \
- || DEFAULT_ABI == ABI_DARWIN) \
- ? (TARGET_64BIT ? 64 : 32) \
- : 0)
-
/* Size of the fixed area on the stack */
#define RS6000_SAVE_AREA \
- (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) ? 24 : 8) \
+ ((DEFAULT_ABI == ABI_V4 ? 8 : DEFAULT_ABI == ABI_ELFv2 ? 16 : 24) \
<< (TARGET_64BIT ? 1 : 0))
-/* MEM representing address to save the TOC register */
-#define RS6000_SAVE_TOC gen_rtx_MEM (Pmode, \
- plus_constant (Pmode, stack_pointer_rtx, \
- (TARGET_32BIT ? 20 : 40)))
+/* Stack offset for toc save slot. */
+#define RS6000_TOC_SAVE_SLOT \
+ ((DEFAULT_ABI == ABI_ELFv2 ? 12 : 20) << (TARGET_64BIT ? 1 : 0))
/* Align an address */
#define RS6000_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
@@ -1579,7 +1603,7 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
/* Define this if stack space is still allocated for a parameter passed
in a register. The value is the number of bytes allocated to this
area. */
-#define REG_PARM_STACK_SPACE(FNDECL) RS6000_REG_SAVE
+#define REG_PARM_STACK_SPACE(FNDECL) rs6000_reg_parm_stack_space((FNDECL))
/* Define this if the above stack space is to be considered part of the
space allocated by the caller. */
@@ -1623,9 +1647,8 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define FP_ARG_MIN_REG 33
#define FP_ARG_AIX_MAX_REG 45
#define FP_ARG_V4_MAX_REG 40
-#define FP_ARG_MAX_REG ((DEFAULT_ABI == ABI_AIX \
- || DEFAULT_ABI == ABI_DARWIN) \
- ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
+#define FP_ARG_MAX_REG (DEFAULT_ABI == ABI_V4 \
+ ? FP_ARG_V4_MAX_REG : FP_ARG_AIX_MAX_REG)
#define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
/* Minimum and maximum AltiVec registers used to hold arguments. */
@@ -1633,10 +1656,17 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define ALTIVEC_ARG_MAX_REG (ALTIVEC_ARG_MIN_REG + 11)
#define ALTIVEC_ARG_NUM_REG (ALTIVEC_ARG_MAX_REG - ALTIVEC_ARG_MIN_REG + 1)
+/* Maximum number of registers per ELFv2 homogeneous aggregate argument. */
+#define AGGR_ARG_NUM_REG 8
+
/* Return registers */
#define GP_ARG_RETURN GP_ARG_MIN_REG
#define FP_ARG_RETURN FP_ARG_MIN_REG
#define ALTIVEC_ARG_RETURN (FIRST_ALTIVEC_REGNO + 2)
+#define FP_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? FP_ARG_RETURN \
+ : (FP_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
+#define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? ALTIVEC_ARG_RETURN \
+ : (ALTIVEC_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
/* Flags for the call/call_value rtl operations set up by function_arg */
#define CALL_NORMAL 0x00000000 /* no special processing */
@@ -1656,8 +1686,10 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
On RS/6000, this is r3, fp1, and v2 (for AltiVec). */
#define FUNCTION_VALUE_REGNO_P(N) \
((N) == GP_ARG_RETURN \
- || ((N) == FP_ARG_RETURN && TARGET_HARD_FLOAT && TARGET_FPRS) \
- || ((N) == ALTIVEC_ARG_RETURN && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI))
+ || ((N) >= FP_ARG_RETURN && (N) <= FP_ARG_MAX_RETURN \
+ && TARGET_HARD_FLOAT && TARGET_FPRS) \
+ || ((N) >= ALTIVEC_ARG_RETURN && (N) <= ALTIVEC_ARG_MAX_RETURN \
+ && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI))
/* 1 if N is a possible register number for function argument passing.
On RS/6000, these are r3-r10 and fp1-fp13.
@@ -1781,11 +1813,8 @@ typedef struct rs6000_args
/* Number of bytes into the frame return addresses can be found. See
rs6000_stack_info in rs6000.c for more information on how the different
abi's store the return address. */
-#define RETURN_ADDRESS_OFFSET \
- ((DEFAULT_ABI == ABI_AIX \
- || DEFAULT_ABI == ABI_DARWIN) ? (TARGET_32BIT ? 8 : 16) : \
- (DEFAULT_ABI == ABI_V4) ? 4 : \
- (internal_error ("RETURN_ADDRESS_OFFSET not supported"), 0))
+#define RETURN_ADDRESS_OFFSET \
+ ((DEFAULT_ABI == ABI_V4 ? 4 : 8) << (TARGET_64BIT ? 1 : 0))
/* The current return address is in link register (65). The return address
of anything farther back is accessed normally at an offset of 8 from the
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 47852c432a0..bb1e8764038 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -56,18 +56,6 @@
(TFHAR_REGNO 114)
(TFIAR_REGNO 115)
(TEXASR_REGNO 116)
-
- ; ABI defined stack offsets for storing the TOC pointer with AIX calls.
- (TOC_SAVE_OFFSET_32BIT 20)
- (TOC_SAVE_OFFSET_64BIT 40)
-
- ; Function TOC offset in the AIX function descriptor.
- (AIX_FUNC_DESC_TOC_32BIT 4)
- (AIX_FUNC_DESC_TOC_64BIT 8)
-
- ; Static chain offset in the AIX function descriptor.
- (AIX_FUNC_DESC_SC_32BIT 8)
- (AIX_FUNC_DESC_SC_64BIT 16)
])
;;
@@ -309,13 +297,13 @@
(define_mode_attr f32_lr [(SF "f") (SD "wz")])
(define_mode_attr f32_lm [(SF "m") (SD "Z")])
(define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
-(define_mode_attr f32_lv [(SF "lxsspx %0,%y1") (SD "lxsiwzx %0,%y1")])
+(define_mode_attr f32_lv [(SF "lxsspx %x0,%y1") (SD "lxsiwzx %x0,%y1")])
; Definitions for store from 32-bit fpr register
(define_mode_attr f32_sr [(SF "f") (SD "wx")])
(define_mode_attr f32_sm [(SF "m") (SD "Z")])
(define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
-(define_mode_attr f32_sv [(SF "stxsspx %1,%y0") (SD "stxsiwzx %1,%y0")])
+(define_mode_attr f32_sv [(SF "stxsspx %x1,%y0") (SD "stxsiwzx %x1,%y0")])
; Definitions for 32-bit fpr direct move
(define_mode_attr f32_dm [(SF "wn") (SD "wm")])
@@ -330,6 +318,25 @@
; Iterator for just SF/DF
(define_mode_iterator SFDF [SF DF])
+; SF/DF suffix for traditional floating instructions
+(define_mode_attr Ftrad [(SF "s") (DF "")])
+
+; SF/DF suffix for VSX instructions
+(define_mode_attr Fvsx [(SF "sp") (DF "dp")])
+
+; SF/DF constraint for arithmetic on traditional floating point registers
+(define_mode_attr Ff [(SF "f") (DF "d")])
+
+; SF/DF constraint for arithmetic on VSX registers
+(define_mode_attr Fv [(SF "wy") (DF "ws")])
+
+; s/d suffix for things like fp_addsub_s/fp_addsub_d
+(define_mode_attr Fs [(SF "s") (DF "d")])
+
+; FRE/FRES support
+(define_mode_attr Ffre [(SF "fres") (DF "fre")])
+(define_mode_attr FFRE [(SF "FRES") (DF "FRE")])
+
; Conditional returns.
(define_code_iterator any_return [return simple_return])
(define_code_attr return_pred [(return "direct_return ()")
@@ -371,6 +378,8 @@
(define_mode_attr rreg [(SF "f")
(DF "ws")
+ (TF "f")
+ (TD "f")
(V4SF "wf")
(V2DF "wd")])
@@ -536,7 +545,7 @@
"")
(define_insn "*zero_extendsidi2_lfiwzx"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wm")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wu")
(zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
"TARGET_POWERPC64 && TARGET_LFIWZX"
"@
@@ -706,7 +715,7 @@
"")
(define_insn "*extendsidi2_lfiwax"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wm")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu")
(sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))]
"TARGET_POWERPC64 && TARGET_LFIWAX"
"@
@@ -2371,7 +2380,9 @@
(clobber (match_scratch:DI 3 "=&r,&r,&r"))
(clobber (match_scratch:DI 4 "=&r,X,&r"))]
"TARGET_POWERPC64 && !TARGET_LDBRX
- && (REG_P (operands[0]) || REG_P (operands[1]))"
+ && (REG_P (operands[0]) || REG_P (operands[1]))
+ && !(MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
+ && !(MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))"
"#"
[(set_attr "length" "16,12,36")])
@@ -2671,7 +2682,7 @@
(match_operand:SI 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
- ""
+ "TARGET_32BIT"
"@
mullw. %3,%1,%2
#"
@@ -2684,7 +2695,7 @@
(match_operand:SI 2 "gpc_reg_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
- "reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 3)
(mult:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -2699,7 +2710,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(mult:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_32BIT"
"@
mullw. %0,%1,%2
#"
@@ -2713,7 +2724,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(mult:SI (match_dup 1) (match_dup 2)))]
- "reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 0)
(mult:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -4714,22 +4725,172 @@
(const_int 0)))]
"")
-;; Floating-point insns, excluding normal data motion.
-;;
-;; PowerPC has a full set of single-precision floating point instructions.
-;;
-;; For the POWER architecture, we pretend that we have both SFmode and
-;; DFmode insns, while, in fact, all fp insns are actually done in double.
-;; The only conversions we will do will be when storing to memory. In that
-;; case, we will use the "frsp" instruction before storing.
-;;
-;; Note that when we store into a single-precision memory location, we need to
-;; use the frsp insn first. If the register being stored isn't dead, we
-;; need a scratch register for the frsp. But this is difficult when the store
-;; is done by reload. It is not incorrect to do the frsp on the register in
-;; this case, we just lose precision that we would have otherwise gotten but
-;; is not guaranteed. Perhaps this should be tightened up at some point.
+
+;; Floating-point insns, excluding normal data motion. We combine the SF/DF
+;; modes here, and also add in conditional vsx/power8-vector support to access
+;; values in the traditional Altivec registers if the appropriate
+;; -mupper-regs-{df,sf} option is enabled.
+
+(define_expand "abs<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*abs<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fabs %0,%1
+ xsabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_insn "*nabs<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (neg:SFDF
+ (abs:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnabs %0,%1
+ xsnabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*neg<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fneg %0,%1
+ xsnegdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "add<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*add<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fadd<Ftrad> %0,%1,%2
+ xsadd<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*sub<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fsub<Ftrad> %0,%1,%2
+ xssub<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*mul<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmul<Ftrad> %0,%1,%2
+ xsmul<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "dmul")
+ (set_attr "fp_type" "fp_mul_<Fs>")])
+
+(define_expand "div<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
+ "")
+
+(define_insn "*div<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
+ "@
+ fdiv<Ftrad> %0,%1,%2
+ xsdiv<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "<Fs>div")
+ (set_attr "fp_type" "fp_div_<Fs>")])
+
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
+ && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
+ "@
+ fsqrt<Ftrad> %0,%1
+ xssqrt<Fvsx> %x0,%x1"
+ [(set_attr "type" "<Fs>sqrt")
+ (set_attr "fp_type" "fp_sqrt_<Fs>")])
+
+;; Floating point reciprocal approximation
+(define_insn "fre<Fs>"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_FRES))]
+ "TARGET_<FFRE>"
+ "@
+ fre<Ftrad> %0,%1
+ xsre<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+
+(define_insn "*rsqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_RSQRT))]
+ "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
+ "@
+ frsqrte<Ftrad> %0,%1
+ xsrsqrte<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+;; Floating point comparisons
+(define_insn "*cmp<mode>_fpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
+ (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fcmpu %0,%1,%2
+ xscmpudp %0,%x1,%x2"
+ [(set_attr "type" "fpcompare")])
+
+;; Floating point conversions
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
@@ -4737,13 +4898,16 @@
"")
(define_insn_and_split "*extendsfdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d")
- (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wv")
+ (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"@
#
fmr %0,%1
- lfs%U1%X1 %0,%1"
+ lfs%U1%X1 %0,%1
+ #
+ xxlor %x0,%x1,%x1
+ lxsspx %x0,%y1"
"&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
[(const_int 0)]
{
@@ -4759,7 +4923,16 @@
(if_then_else
(match_test "update_address_mem (operands[1], VOIDmode)")
(const_string "fpload_u")
- (const_string "fpload")))])])
+ (const_string "fpload")))
+ (const_string "fp")
+ (const_string "vecsimple")
+ (if_then_else
+ (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+ (const_string "fpload_ux")
+ (if_then_else
+ (match_test "update_address_mem (operands[1], VOIDmode)")
+ (const_string "fpload_u")
+ (const_string "fpload")))])])
(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -4774,175 +4947,6 @@
"frsp %0,%1"
[(set_attr "type" "fp")])
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "addsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fadds %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "subsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fsubs %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmuls %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_mul_s")])
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fdivs %0,%1,%2"
- [(set_attr "type" "sdiv")])
-
-(define_insn "fres"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRES"
- "fres %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fmaf support
-(define_insn "*fmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*fmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
- && TARGET_FPRS && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fsqrts %0,%1"
- [(set_attr "type" "ssqrt")])
-
-(define_insn "*rsqrtsf_internal1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTES"
- "frsqrtes %0,%1"
- [(set_attr "type" "fp")])
-
;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
;; builtins.c and optabs.c that are not correct for IBM long double
;; when little-endian.
@@ -5010,37 +5014,82 @@
;; Use an unspec rather providing an if-then-else in RTL, to prevent the
;; compiler from optimizing -0.0
(define_insn "copysign<mode>3_fcpsgn"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_COPYSIGN))]
- "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "fcpsgn %0,%2,%1"
+ "TARGET_<MODE>_FPR && TARGET_CMPB"
+ "@
+ fcpsgn %0,%2,%1
+ xscpsgn<Fvsx> %x0,%x2,%x1"
[(set_attr "type" "fp")])
;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
;; fsel instruction and some auxiliary computations. Then we just have a
;; single DEFINE_INSN for fsel and the define_splits to make them if made by
;; combine.
-(define_expand "smaxsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
+;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
+;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
+;; computations. Then we just have a single DEFINE_INSN for fsel and the
+;; define_splits to make them if made by combine. On VSX machines we have the
+;; min/max instructions.
+;;
+;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
+;; to allow either DF/SF to use only traditional registers.
-(define_expand "sminsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
+(define_expand "smax<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+})
+
+(define_insn "*smax<mode>3_vsx"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmaxdp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+})
+
+(define_insn "*smin<mode>3_vsx"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmindp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_split
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (match_operator:SFDF 3 "min_max_operator"
+ [(match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")]))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math
+ && !TARGET_VSX"
+ [(const_int 0)]
+{
+ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1],
+ operands[2]);
+ DONE;
+})
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -5172,208 +5221,9 @@
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*negdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "absdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*absdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*nabsdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "adddf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*adddf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fadd %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "subdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*subdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsub %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*muldf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fmul %0,%1,%2"
- [(set_attr "type" "dmul")
- (set_attr "fp_type" "fp_mul_d")])
-
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT
- && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn "*divdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fdiv %0,%1,%2"
- [(set_attr "type" "ddiv")])
-
-(define_insn "*fred_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRE && !VECTOR_UNIT_VSX_P (DFmode)"
- "fre %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*rsqrtdf_internal1"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTE && !VECTOR_UNIT_VSX_P (DFmode)"
- "frsqrte %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fma support
-(define_insn "*fmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*fmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
- "")
-
-(define_insn "*sqrtdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsqrt %0,%1"
- [(set_attr "type" "dsqrt")])
-
;; The conditional move instructions allow us to perform max and min
;; operations even when
-(define_expand "smaxdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
-
-(define_expand "smindf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
-
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(match_operator:DF 3 "min_max_operator"
@@ -6057,66 +5907,52 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FCTID))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"fctid %0,%1"
[(set_attr "type" "fp")])
-(define_expand "btrunc<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
-
-(define_insn "*btrunc<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(define_insn "btrunc<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "friz %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "ceil<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ friz %0,%1
+ xsrdpiz %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_insn "*ceil<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(define_insn "ceil<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frip %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "floor<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frip %0,%1
+ xsrdpip %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_insn "*floor<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(define_insn "floor<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frim %0,%1"
- [(set_attr "type" "fp")])
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frim %0,%1
+ xsrdpim %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
;; No VSX equivalent to frin
(define_insn "round<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIN))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"frin %0,%1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
@@ -8748,8 +8584,8 @@
}")
(define_insn "mov<mode>_hardfloat"
- [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wm,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
- (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wm,r,<f32_dm>,r,h,0,G,Fn"))]
+ [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wu,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
+ (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wu,r,<f32_dm>,r,h,0,G,Fn"))]
"(gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))
&& (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)"
@@ -8960,8 +8796,8 @@
;; reloading.
(define_insn "*mov<mode>_hardfloat32"
- [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r")
- (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))]
+ [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,!r,!r,!r")
+ (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,G,H,F"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -8970,10 +8806,7 @@
lfd%U1%X1 %0,%1
fmr %0,%1
lxsd%U1x %x0,%y1
- lxsd%U1x %x0,%y1
stxsd%U0x %x1,%y0
- stxsd%U0x %x1,%y0
- xxlor %x0,%x1,%x1
xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
#
@@ -9003,27 +8836,18 @@
(const_string "fpload_ux")
(const_string "fpload"))
(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "fpstore_ux")
(const_string "fpstore"))
(const_string "vecsimple")
(const_string "vecsimple")
- (const_string "vecsimple")
(const_string "store")
(const_string "load")
(const_string "two")
(const_string "fp")
(const_string "fp")
(const_string "*")])
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")])
+ (set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")])
(define_insn "*mov<mode>_softfloat32"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
@@ -9040,8 +8864,8 @@
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*mov<mode>_hardfloat64"
- [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
- (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
+ [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
+ (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -9050,10 +8874,7 @@
lfd%U1%X1 %0,%1
fmr %0,%1
lxsd%U1x %x0,%y1
- lxsd%U1x %x0,%y1
stxsd%U0x %x1,%y0
- stxsd%U0x %x1,%y0
- xxlor %x0,%x1,%x1
xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
std%U0%X0 %1,%0
@@ -9090,20 +8911,11 @@
(const_string "fpload_ux")
(const_string "fpload"))
(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "fpstore_ux")
(const_string "fpstore"))
(const_string "vecsimple")
(const_string "vecsimple")
- (const_string "vecsimple")
(if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "store_ux")
@@ -9129,7 +8941,7 @@
(const_string "mffgpr")
(const_string "mftgpr")
(const_string "mffgpr")])
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
(define_insn "*mov<mode>_softfloat64"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
@@ -9180,10 +8992,40 @@
;; It's important to list Y->r and r->Y before r->r because otherwise
;; reload, given m->r, will try to pick r->r and reload it, which
;; doesn't make progress.
-(define_insn_and_split "*mov<mode>_internal"
+
+;; We can't split little endian direct moves of TDmode, because the words are
+;; not swapped like they are for TImode or TFmode. Subregs therefore are
+;; problematical. Don't allow direct move for this case.
+
+(define_insn_and_split "*mov<mode>_64bit_dm"
+ [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r,r,wm")
+ (match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r,wm,r"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
+ && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
+ && (gpc_reg_operand (operands[0], <MODE>mode)
+ || gpc_reg_operand (operands[1], <MODE>mode))"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
+ [(set_attr "length" "8,8,8,12,12,8,8,8")])
+
+(define_insn_and_split "*movtd_64bit_nodm"
+ [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
+ (match_operand:TD 1 "input_operand" "d,m,d,r,YGHF,r"))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 && !WORDS_BIG_ENDIAN
+ && (gpc_reg_operand (operands[0], TDmode)
+ || gpc_reg_operand (operands[1], TDmode))"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
+ [(set_attr "length" "8,8,8,12,12,8")])
+
+(define_insn_and_split "*mov<mode>_32bit"
[(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
(match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r"))]
- "TARGET_HARD_FLOAT && TARGET_FPRS
+ "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
"#"
@@ -9619,6 +9461,15 @@
[(set_attr "length" "12")
(set_attr "type" "three")])
+(define_split
+ [(set (match_operand:FMOVE128_GPR 0 "nonimmediate_operand" "")
+ (match_operand:FMOVE128_GPR 1 "input_operand" ""))]
+ "reload_completed
+ && (int_reg_operand (operands[0], <MODE>mode)
+ || int_reg_operand (operands[1], <MODE>mode))"
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
+
;; Move SFmode to a VSX from a GPR register. Because scalar floating point
;; type is stored internally as double precision in the VSX registers, we have
;; to convert it from the vector format.
@@ -9628,7 +9479,7 @@
(unspec:SF [(match_operand:SF 1 "register_operand" "r")]
UNSPEC_P8V_RELOAD_FROM_GPR))
(clobber (match_operand:DI 2 "register_operand" "=r"))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && WORDS_BIG_ENDIAN"
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -9655,7 +9506,7 @@
[(set (match_operand:DF 0 "register_operand" "=r")
(unspec:DF [(match_operand:FMOVE128_GPR 1 "register_operand" "wa")]
UNSPEC_P8V_RELOAD_FROM_VSX))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && WORDS_BIG_ENDIAN"
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"mfvsrd %0,%x1"
[(set_attr "type" "mftgpr")])
@@ -9665,7 +9516,7 @@
[(match_operand:FMOVE128_GPR 1 "register_operand" "wa")]
UNSPEC_P8V_RELOAD_FROM_VSX))
(clobber (match_operand:FMOVE128_GPR 2 "register_operand" "=wa"))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && WORDS_BIG_ENDIAN"
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -9692,7 +9543,7 @@
(unspec:SF [(match_operand:SF 1 "register_operand" "wa")]
UNSPEC_P8V_RELOAD_FROM_VSX))
(clobber (match_operand:V4SF 2 "register_operand" "=wa"))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && WORDS_BIG_ENDIAN"
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -9714,7 +9565,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:V4SF 1 "register_operand" "wa")]
UNSPEC_P8V_RELOAD_FROM_VSX))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && WORDS_BIG_ENDIAN"
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"mfvsrd %0,%x1"
[(set_attr "type" "mftgpr")])
@@ -9727,8 +9578,8 @@
;; Use of fprs is disparaged slightly otherwise reload prefers to reload
;; a gpr into a fpr instead of reloading an invalid 'Y' address
(define_insn "*movdi_internal32"
- [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=Y,r,r,?m,?*d,?*d,r,?wa")
- (match_operand:DI 1 "input_operand" "r,Y,r,d,m,d,IJKnGHF,O"))]
+ [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=Y,r,r,?m,?*d,?*d,r")
+ (match_operand:DI 1 "input_operand" "r,Y,r,d,m,d,IJKnGHF"))]
"! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -9739,8 +9590,7 @@
stfd%U0%X0 %1,%0
lfd%U1%X1 %0,%1
fmr %0,%1
- #
- xxlxor %x0,%x0,%x0"
+ #"
[(set_attr_alternative "type"
[(const_string "store")
(const_string "load")
@@ -9760,8 +9610,7 @@
(const_string "fpload_u")
(const_string "fpload")))
(const_string "fp")
- (const_string "*")
- (const_string "vecsimple")])])
+ (const_string "*")])])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -9796,8 +9645,8 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wa,?wa,r,*h,*h,?wa,r,?*wg,r,?*wm")
- (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wa,Z,wa,*h,r,0,O,*wg,r,*wm,r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*wg,r,?*wm")
+ (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*wg,r,*wm,r"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -9811,13 +9660,9 @@
stfd%U0%X0 %1,%0
lfd%U1%X1 %0,%1
fmr %0,%1
- stxsd%U0x %x1,%y0
- lxsd%U1x %x0,%y1
- xxlor %x0,%x1,%x1
mf%1 %0
mt%0 %1
nop
- xxlxor %x0,%x0,%x0
mftgpr %0,%1
mffgpr %0,%1
mfvsrd %0,%x1
@@ -9856,24 +9701,14 @@
(const_string "fpload_u")
(const_string "fpload")))
(const_string "fp")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (const_string "vecsimple")
(const_string "mfjmpr")
(const_string "mtjmpr")
(const_string "*")
- (const_string "vecsimple")
(const_string "mftgpr")
(const_string "mffgpr")
(const_string "mftgpr")
(const_string "mffgpr")])
- (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4")])
;; immediate value valid for a single instruction hiding in a const_double
(define_insn ""
@@ -9976,15 +9811,15 @@
(const_string "conditional")))])
(define_insn "*mov<mode>_ppc64"
- [(set (match_operand:TI2 0 "nonimmediate_operand" "=Y,r,r,r")
- (match_operand:TI2 1 "input_operand" "r,Y,r,F"))]
+ [(set (match_operand:TI2 0 "nonimmediate_operand" "=wQ,Y,r,r,r,r")
+ (match_operand:TI2 1 "input_operand" "r,r,wQ,Y,r,n"))]
"(TARGET_POWERPC64 && VECTOR_MEM_NONE_P (<MODE>mode)
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode)))"
{
return rs6000_output_move_128bit (operands);
}
- [(set_attr "type" "store,load,*,*")
+ [(set_attr "type" "store,store,load,load,*,*")
(set_attr "length" "8")])
(define_split
@@ -10877,7 +10712,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD)
(clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
+ "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
{
if (TARGET_CMODEL != CMODEL_SMALL)
return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;"
@@ -10985,7 +10820,8 @@
(unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD)
(clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS"
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS
+ && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
"bl %z1(%3@tlsgd)\;nop"
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -11017,7 +10853,7 @@
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)
(clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
+ "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
{
if (TARGET_CMODEL != CMODEL_SMALL)
return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;"
@@ -11118,7 +10954,8 @@
(match_operand 2 "" "g")))
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
(clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS"
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS
+ && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
"bl %z1(%&@tlsld)\;nop"
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -11487,7 +11324,7 @@
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unspec:SI [(const_int 0)] UNSPEC_TOC))
(use (reg:SI 2))])]
- "DEFAULT_ABI == ABI_AIX && TARGET_32BIT"
+ "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_32BIT"
"*
{
char buf[30];
@@ -11502,7 +11339,7 @@
[(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(unspec:DI [(const_int 0)] UNSPEC_TOC))
(use (reg:DI 2))])]
- "DEFAULT_ABI == ABI_AIX && TARGET_64BIT"
+ "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_64BIT"
"*
{
char buf[30];
@@ -11532,7 +11369,7 @@
[(parallel [(set (reg:SI LR_REGNO)
(match_operand:SI 0 "immediate_operand" "s"))
(use (unspec [(match_dup 0)] UNSPEC_TOC))])]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ "TARGET_ELF && DEFAULT_ABI == ABI_V4
&& (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"")
@@ -11540,7 +11377,7 @@
[(set (reg:SI LR_REGNO)
(match_operand:SI 0 "immediate_operand" "s"))
(use (unspec [(match_dup 0)] UNSPEC_TOC))]
- "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4
&& (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%0\\n%0:"
[(set_attr "type" "branch")
@@ -11550,7 +11387,7 @@
[(set (reg:SI LR_REGNO)
(match_operand:SI 0 "immediate_operand" "s"))
(use (unspec [(match_dup 0)] UNSPEC_TOC))]
- "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4
&& (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"*
{
@@ -11570,7 +11407,7 @@
(label_ref (match_operand 1 "" ""))]
UNSPEC_TOCPTR))
(match_dup 1)])]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
"")
(define_insn "load_toc_v4_PIC_1b_normal"
@@ -11579,7 +11416,7 @@
(label_ref (match_operand 1 "" ""))]
UNSPEC_TOCPTR))
(match_dup 1)]
- "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
"bcl 20,31,$+8\;.long %0-$"
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -11590,7 +11427,7 @@
(label_ref (match_operand 1 "" ""))]
UNSPEC_TOCPTR))
(match_dup 1)]
- "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
"*
{
char name[32];
@@ -11608,7 +11445,7 @@
(mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(minus:SI (match_operand:SI 2 "immediate_operand" "s")
(match_operand:SI 3 "immediate_operand" "s")))))]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2"
"lwz %0,%2-%3(%1)"
[(set_attr "type" "load")])
@@ -11618,7 +11455,7 @@
(high:SI
(minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
(match_operand:SI 3 "symbol_ref_operand" "s")))))]
- "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic"
"addis %0,%1,%2-%3@ha")
(define_insn "load_toc_v4_PIC_3c"
@@ -11626,7 +11463,7 @@
(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
(match_operand:SI 3 "symbol_ref_operand" "s"))))]
- "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic"
"addi %0,%1,%2-%3@l")
;; If the TOC is shared over a translation unit, as happens with all
@@ -11690,7 +11527,7 @@
(unspec [(match_operand:DI 1 "" "")
(match_operand:DI 2 "gpc_reg_operand" "b")]
UNSPEC_TOCREL)
- (match_operand 3 "const_int_operand" "n"))))]
+ (match_operand:DI 3 "add_cint_operand" "n"))))]
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%2,%1+%3@toc@ha")
@@ -11701,7 +11538,7 @@
(unspec [(match_operand:P 1 "" "")
(match_operand:P 2 "gpc_reg_operand" "b")]
UNSPEC_TOCREL)
- (match_operand 3 "const_int_operand" "n"))))]
+ (match_operand:P 3 "add_cint_operand" "n"))))]
"TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1+%3@u(%2)")
@@ -11768,8 +11605,13 @@
operands[0] = XEXP (operands[0], 0);
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]);
+ DONE;
+ }
+
if (GET_CODE (operands[0]) != SYMBOL_REF
- || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
{
if (INTVAL (operands[2]) & CALL_LONG)
@@ -11782,12 +11624,6 @@
operands[0] = force_reg (Pmode, operands[0]);
break;
- case ABI_AIX:
- /* AIX function pointers are really pointers to a three word
- area. */
- rs6000_call_indirect_aix (NULL_RTX, operands[0], operands[1]);
- DONE;
-
default:
gcc_unreachable ();
}
@@ -11813,8 +11649,13 @@
operands[1] = XEXP (operands[1], 0);
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]);
+ DONE;
+ }
+
if (GET_CODE (operands[1]) != SYMBOL_REF
- || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
{
if (INTVAL (operands[3]) & CALL_LONG)
@@ -11827,12 +11668,6 @@
operands[1] = force_reg (Pmode, operands[1]);
break;
- case ABI_AIX:
- /* AIX function pointers are really pointers to a three word
- area. */
- rs6000_call_indirect_aix (operands[0], operands[1], operands[2]);
- DONE;
-
default:
gcc_unreachable ();
}
@@ -11924,135 +11759,6 @@
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
-;; Call to indirect functions with the AIX abi using a 3 word descriptor.
-;; Operand0 is the addresss of the function to call
-;; Operand1 is the flag for System V.4 for unprototyped or FP registers
-;; Operand2 is the location in the function descriptor to load r2 from
-;; Operand3 is the stack location to hold the current TOC pointer
-
-(define_insn "call_indirect_aix<ptrsize>"
- [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
- (match_operand 1 "" "g,g"))
- (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
- (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
- (use (reg:P STATIC_CHAIN_REGNUM))
- (clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
- "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
- [(set_attr "type" "jmpreg")
- (set_attr "length" "12")])
-
-;; Like call_indirect_aix<ptrsize>, but no use of the static chain
-;; Operand0 is the addresss of the function to call
-;; Operand1 is the flag for System V.4 for unprototyped or FP registers
-;; Operand2 is the location in the function descriptor to load r2 from
-;; Operand3 is the stack location to hold the current TOC pointer
-
-(define_insn "call_indirect_aix<ptrsize>_nor11"
- [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
- (match_operand 1 "" "g,g"))
- (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
- (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
- (clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
- "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
- [(set_attr "type" "jmpreg")
- (set_attr "length" "12")])
-
-;; Operand0 is the return result of the function
-;; Operand1 is the addresss of the function to call
-;; Operand2 is the flag for System V.4 for unprototyped or FP registers
-;; Operand3 is the location in the function descriptor to load r2 from
-;; Operand4 is the stack location to hold the current TOC pointer
-
-(define_insn "call_value_indirect_aix<ptrsize>"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
- (match_operand 2 "" "g,g")))
- (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
- (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
- (use (reg:P STATIC_CHAIN_REGNUM))
- (clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
- "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
- [(set_attr "type" "jmpreg")
- (set_attr "length" "12")])
-
-;; Like call_value_indirect_aix<ptrsize>, but no use of the static chain
-;; Operand0 is the return result of the function
-;; Operand1 is the addresss of the function to call
-;; Operand2 is the flag for System V.4 for unprototyped or FP registers
-;; Operand3 is the location in the function descriptor to load r2 from
-;; Operand4 is the stack location to hold the current TOC pointer
-
-(define_insn "call_value_indirect_aix<ptrsize>_nor11"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
- (match_operand 2 "" "g,g")))
- (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
- (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
- (clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
- "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
- [(set_attr "type" "jmpreg")
- (set_attr "length" "12")])
-
-;; Call to function which may be in another module. Restore the TOC
-;; pointer (r2) after the call unless this is System V.
-;; Operand2 is nonzero if we are using the V.4 calling sequence and
-;; either the function was not prototyped, or it was prototyped as a
-;; variable argument function. It is > 0 if FP registers were passed
-;; and < 0 if they were not.
-
-(define_insn "*call_nonlocal_aix32"
- [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
- (match_operand 1 "" "g"))
- (use (match_operand:SI 2 "immediate_operand" "O"))
- (clobber (reg:SI LR_REGNO))]
- "TARGET_32BIT
- && DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[2]) & CALL_LONG) == 0"
- "bl %z0\;nop"
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
-
-(define_insn "*call_nonlocal_aix64"
- [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
- (match_operand 1 "" "g"))
- (use (match_operand:SI 2 "immediate_operand" "O"))
- (clobber (reg:SI LR_REGNO))]
- "TARGET_64BIT
- && DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[2]) & CALL_LONG) == 0"
- "bl %z0\;nop"
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
-
-(define_insn "*call_value_nonlocal_aix32"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
- (match_operand 2 "" "g")))
- (use (match_operand:SI 3 "immediate_operand" "O"))
- (clobber (reg:SI LR_REGNO))]
- "TARGET_32BIT
- && DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[3]) & CALL_LONG) == 0"
- "bl %z1\;nop"
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
-
-(define_insn "*call_value_nonlocal_aix64"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
- (match_operand 2 "" "g")))
- (use (match_operand:SI 3 "immediate_operand" "O"))
- (clobber (reg:SI LR_REGNO))]
- "TARGET_64BIT
- && DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[3]) & CALL_LONG) == 0"
- "bl %z1\;nop"
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
;; A function pointer under System V is just a normal pointer
;; operands[0] is the function pointer
@@ -12235,6 +11941,104 @@
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
+
+;; Call to AIX abi function in the same module.
+
+(define_insn "*call_local_aix<mode>"
+ [(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s"))
+ (match_operand 1 "" "g"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "bl %z0"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*call_value_local_aix<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "current_file_function_operand" "s"))
+ (match_operand 2 "" "g")))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "bl %z1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+;; Call to AIX abi function which may be in another module.
+;; Restore the TOC pointer (r2) after the call.
+
+(define_insn "*call_nonlocal_aix<mode>"
+ [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s"))
+ (match_operand 1 "" "g"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "bl %z0\;nop"
+ [(set_attr "type" "branch")
+ (set_attr "length" "8")])
+
+(define_insn "*call_value_nonlocal_aix<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
+ (match_operand 2 "" "g")))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "bl %z1\;nop"
+ [(set_attr "type" "branch")
+ (set_attr "length" "8")])
+
+;; Call to indirect functions with the AIX abi using a 3 word descriptor.
+;; Operand0 is the addresss of the function to call
+;; Operand2 is the location in the function descriptor to load r2 from
+;; Operand3 is the stack location to hold the current TOC pointer
+
+(define_insn "*call_indirect_aix<mode>"
+ [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
+ (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX"
+ "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
+
+(define_insn "*call_value_indirect_aix<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+ (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_AIX"
+ "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
+
+;; Call to indirect functions with the ELFv2 ABI.
+;; Operand0 is the addresss of the function to call
+;; Operand2 is the stack location to hold the current TOC pointer
+
+(define_insn "*call_indirect_elfv2<mode>"
+ [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
+ (match_operand 1 "" "g,g"))
+ (set (reg:P TOC_REGNUM) (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_ELFv2"
+ "b%T0l\;<ptrload> 2,%2"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "8")])
+
+(define_insn "*call_value_indirect_elfv2<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
+ (match_operand 2 "" "g,g")))
+ (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_ELFv2"
+ "b%T1l\;<ptrload> 2,%3"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "8")])
+
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
[(parallel [(call (match_operand 0 "" "")
@@ -12282,6 +12086,39 @@
gcc_assert (GET_CODE (operands[1]) == CONST_INT);
operands[0] = XEXP (operands[0], 0);
+
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]);
+ DONE;
+ }
+}")
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "register_operand" "")
+ (call (mem:SI (match_operand 1 "address_operand" ""))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (use (reg:SI LR_REGNO))
+ (simple_return)])]
+ ""
+ "
+{
+#if TARGET_MACHO
+ if (MACHOPIC_INDIRECT)
+ operands[1] = machopic_indirect_call_target (operands[1]);
+#endif
+
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
+
+ operands[1] = XEXP (operands[1], 0);
+
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]);
+ DONE;
+ }
}")
;; this and similar patterns must be marked as using LR, otherwise
@@ -12349,7 +12186,6 @@
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
-
(define_insn "*sibcall_value_local64"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
@@ -12371,35 +12207,6 @@
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
-(define_insn "*sibcall_nonlocal_aix<mode>"
- [(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
- (match_operand 1 "" "g,g"))
- (use (match_operand:SI 2 "immediate_operand" "O,O"))
- (use (reg:SI LR_REGNO))
- (simple_return)]
- "DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[2]) & CALL_LONG) == 0"
- "@
- b %z0
- b%T0"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
-
-(define_insn "*sibcall_value_nonlocal_aix<mode>"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
- (match_operand 2 "" "g,g")))
- (use (match_operand:SI 3 "immediate_operand" "O,O"))
- (use (reg:SI LR_REGNO))
- (simple_return)]
- "DEFAULT_ABI == ABI_AIX
- && (INTVAL (operands[3]) & CALL_LONG) == 0"
- "@
- b %z1
- b%T1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
-
(define_insn "*sibcall_nonlocal_sysv<mode>"
[(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
(match_operand 1 "" ""))
@@ -12430,27 +12237,6 @@
[(set_attr "type" "branch")
(set_attr "length" "4,8,4,8")])
-(define_expand "sibcall_value"
- [(parallel [(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "address_operand" ""))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNO))
- (simple_return)])]
- ""
- "
-{
-#if TARGET_MACHO
- if (MACHOPIC_INDIRECT)
- operands[1] = machopic_indirect_call_target (operands[1]);
-#endif
-
- gcc_assert (GET_CODE (operands[1]) == MEM);
- gcc_assert (GET_CODE (operands[2]) == CONST_INT);
-
- operands[1] = XEXP (operands[1], 0);
-}")
-
(define_insn "*sibcall_value_nonlocal_sysv<mode>"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
@@ -12482,6 +12268,31 @@
[(set_attr "type" "branch")
(set_attr "length" "4,8,4,8")])
+;; AIX ABI sibling call patterns.
+
+(define_insn "*sibcall_aix<mode>"
+ [(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
+ (match_operand 1 "" "g,g"))
+ (simple_return)]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "@
+ b %z0
+ b%T0"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_value_aix<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
+ (match_operand 2 "" "g,g")))
+ (simple_return)]
+ "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+ "@
+ b %z1
+ b%T1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
(define_expand "sibcall_epilogue"
[(use (const_int 0))]
""
@@ -12822,23 +12633,6 @@
[(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
-(define_insn "*cmpsf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
-(define_insn "*cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
;; Only need to compare second words if first words equal
(define_insn "*cmptf_internal1"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
@@ -14734,6 +14528,14 @@
"mfcr %0"
[(set_attr "type" "mfcr")])
+(define_insn "*crsave"
+ [(match_parallel 0 "crsave_operation"
+ [(set (match_operand:SI 1 "memory_operand" "=m")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))])]
+ ""
+ "stw %2,%1"
+ [(set_attr "type" "store")])
+
(define_insn "*stmw"
[(match_parallel 0 "stmw_operation"
[(set (match_operand:SI 1 "memory_operand" "=m")
@@ -15133,6 +14935,20 @@
""
"")
+(define_insn "*fma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmadd<Ftrad> %0,%1,%2,%3
+ xsmadda<Fvsx> %x0,%x1,%x2
+ xsmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Altivec only has fma and nfms.
(define_expand "fms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15143,6 +14959,20 @@
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*fms<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmsub<Ftrad> %0,%1,%2,%3
+ xsmsuba<Fvsx> %x0,%x1,%x2
+ xsmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
(define_expand "fnma<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15176,6 +15006,21 @@
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*nfma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmadd<Ftrad> %0,%1,%2,%3
+ xsnmadda<Fvsx> %x0,%x1,%x2
+ xsnmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Not an official optab name, but used from builtins.
(define_expand "nfms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15187,6 +15032,23 @@
""
"")
+(define_insn "*nfmssf4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmsub<Ftrad> %0,%1,%2,%3
+ xsnmsuba<Fvsx> %x0,%x1,%x2
+ xsnmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
+
(define_expand "rs6000_get_timebase"
[(use (match_operand:DI 0 "gpc_reg_operand" ""))]
""
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index f36e4758031..5b56eb0da56 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -1,6 +1,6 @@
; Options for the rs6000 port of the compiler
;
-; Copyright (C) 2005-2013 Free Software Foundation, Inc.
+; Copyright (C) 2005-2014 Free Software Foundation, Inc.
; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
;
; This file is part of GCC.
@@ -137,6 +137,14 @@ maltivec
Target Report Mask(ALTIVEC) Var(rs6000_isa_flags)
Use AltiVec instructions
+maltivec=le
+Target Report RejectNegative Var(rs6000_altivec_element_order, 1) Save
+Generate Altivec instructions using little-endian element order
+
+maltivec=be
+Target Report RejectNegative Var(rs6000_altivec_element_order, 2)
+Generate Altivec instructions using big-endian element order
+
mhard-dfp
Target Report Mask(DFP) Var(rs6000_isa_flags)
Use decimal floating point instructions
@@ -181,13 +189,16 @@ mvsx
Target Report Mask(VSX) Var(rs6000_isa_flags)
Use vector/scalar (VSX) instructions
+mvsx-scalar-float
+Target Undocumented Report Var(TARGET_VSX_SCALAR_FLOAT) Init(1)
+; If -mpower8-vector, use VSX arithmetic instructions for SFmode (on by default)
+
mvsx-scalar-double
-Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
-; If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
+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 Var(TARGET_VSX_SCALAR_MEMORY)
-; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
+Target Undocumented Report Alias(mupper-regs-df)
mvsx-align-128
Target Undocumented Report Var(TARGET_VSX_ALIGN_128)
@@ -363,6 +374,14 @@ mabi=no-spe
Target RejectNegative Var(rs6000_spe_abi, 0)
Do not use the SPE ABI extensions
+mabi=elfv1
+Target RejectNegative Var(rs6000_elf_abi, 1) Save
+Use the ELFv1 ABI
+
+mabi=elfv2
+Target RejectNegative Var(rs6000_elf_abi, 2)
+Use the ELFv2 ABI
+
; These are here for testing during development only, do not document
; in the manual please.
@@ -443,6 +462,10 @@ 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)
+mlra
+Target Report Var(rs6000_lra_flag) Init(0) Save
+Use LRA instead of reload
+
msched-costly-dep=
Target RejectNegative Joined Var(rs6000_sched_costly_dep_str)
Determine which dependences between insns are considered costly
@@ -545,4 +568,20 @@ Use ISA 2.07 transactional memory (HTM) instructions
mquad-memory
Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags)
-Generate the quad word memory instructions (lq/stq/lqarx/stqcx).
+Generate the quad word memory instructions (lq/stq).
+
+mquad-memory-atomic
+Target Report Mask(QUAD_MEMORY_ATOMIC) Var(rs6000_isa_flags)
+Generate the quad word memory atomic instructions (lqarx/stqcx).
+
+mcompat-align-parm
+Target Report Var(rs6000_compat_align_parm) Init(1) Save
+Generate aggregate parameter passing code with at most 64-bit alignment.
+
+mupper-regs-df
+Target Undocumented Mask(UPPER_REGS_DF) Var(rs6000_isa_flags)
+Allow double variables in upper registers with -mcpu=power7 or -mvsx
+
+mupper-regs-sf
+Target Undocumented Mask(UPPER_REGS_SF) Var(rs6000_isa_flags)
+Allow float variables in upper registers with -mcpu=power8 or -mp8-vector
diff --git a/gcc/config/rs6000/rtems.h b/gcc/config/rs6000/rtems.h
index b910b5ec5a2..fb22be1e8bb 100644
--- a/gcc/config/rs6000/rtems.h
+++ b/gcc/config/rs6000/rtems.h
@@ -34,6 +34,9 @@
} \
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)"
diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md
index 8616b3eca5f..8357f951f9b 100644
--- a/gcc/config/rs6000/sync.md
+++ b/gcc/config/rs6000/sync.md
@@ -1,5 +1,5 @@
;; Machine description for PowerPC synchronization instructions.
-;; Copyright (C) 2005-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2014 Free Software Foundation, Inc.
;; Contributed by Geoffrey Keating.
;; This file is part of GCC.
@@ -204,25 +204,63 @@
"<QHI:larx> %0,%y1"
[(set_attr "type" "load_l")])
-;; Use PTImode to get even/odd register pairs
+;; Use PTImode to get even/odd register pairs.
+
+;; Use a temporary register to force getting an even register for the
+;; lqarx/stqcrx. instructions. Under AT 7.0, we need use an explicit copy,
+;; even in big endian mode, unless we are using the LRA register allocator. In
+;; GCC 4.9, the register allocator is smart enough to assign a even/odd
+;; register pair.
+
+;; On little endian systems where non-atomic quad word load/store instructions
+;; are not used, the address can be register+offset, so make sure the address
+;; is indexed or indirect before register allocation.
+
(define_expand "load_lockedti"
[(use (match_operand:TI 0 "quad_int_reg_operand" ""))
(use (match_operand:TI 1 "memory_operand" ""))]
"TARGET_SYNC_TI"
{
- /* Use a temporary register to force getting an even register for the
- lqarx/stqcrx. instructions. Normal optimizations will eliminate this
- extra copy. */
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
rtx pti = gen_reg_rtx (PTImode);
- emit_insn (gen_load_lockedpti (pti, operands[1]));
- emit_move_insn (operands[0], gen_lowpart (TImode, pti));
+
+ if (!indexed_or_indirect_operand (op1, TImode))
+ {
+ rtx old_addr = XEXP (op1, 0);
+ rtx new_addr = force_reg (Pmode, old_addr);
+ operands[1] = op1 = change_address (op1, TImode, new_addr);
+ }
+
+ emit_insn (gen_load_lockedpti (pti, op1));
+ if (WORDS_BIG_ENDIAN && rs6000_lra_flag)
+ emit_move_insn (op0, gen_lowpart (TImode, pti));
+ else
+ {
+ rtx op0_lo = gen_lowpart (DImode, op0);
+ rtx op0_hi = gen_highpart (DImode, op0);
+ rtx pti_lo = gen_lowpart (DImode, pti);
+ rtx pti_hi = gen_highpart (DImode, pti);
+
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, op0));
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_move_insn (op0_hi, pti_hi);
+ emit_move_insn (op0_lo, pti_lo);
+ }
+ else
+ {
+ emit_move_insn (op0_hi, pti_lo);
+ emit_move_insn (op0_lo, pti_hi);
+ }
+ }
DONE;
})
(define_insn "load_lockedpti"
[(set (match_operand:PTI 0 "quad_int_reg_operand" "=&r")
(unspec_volatile:PTI
- [(match_operand:TI 1 "memory_operand" "Z")] UNSPECV_LL))]
+ [(match_operand:TI 1 "indexed_or_indirect_operand" "Z")] UNSPECV_LL))]
"TARGET_SYNC_TI
&& !reg_mentioned_p (operands[0], operands[1])
&& quad_int_reg_operand (operands[0], PTImode)"
@@ -238,6 +276,15 @@
"<stcx> %2,%y1"
[(set_attr "type" "store_c")])
+;; Use a temporary register to force getting an even register for the
+;; lqarx/stqcrx. instructions. Under AT 7.0, we need use an explicit copy,
+;; even in big endian mode. In GCC 4.9, the register allocator is smart enough
+;; to assign a even/odd register pair.
+
+;; On little endian systems where non-atomic quad word load/store instructions
+;; are not used, the address can be register+offset, so make sure the address
+;; is indexed or indirect before register allocation.
+
(define_expand "store_conditionalti"
[(use (match_operand:CC 0 "cc_reg_operand" ""))
(use (match_operand:TI 1 "memory_operand" ""))
@@ -247,21 +294,50 @@
rtx op0 = operands[0];
rtx op1 = operands[1];
rtx op2 = operands[2];
- rtx pti_op1 = change_address (op1, PTImode, XEXP (op1, 0));
- rtx pti_op2 = gen_reg_rtx (PTImode);
-
- /* Use a temporary register to force getting an even register for the
- lqarx/stqcrx. instructions. Normal optimizations will eliminate this
- extra copy. */
- emit_move_insn (pti_op2, gen_lowpart (PTImode, op2));
- emit_insn (gen_store_conditionalpti (op0, pti_op1, pti_op2));
+ rtx addr = XEXP (op1, 0);
+ rtx pti_mem;
+ rtx pti_reg;
+
+ if (!indexed_or_indirect_operand (op1, TImode))
+ {
+ rtx new_addr = force_reg (Pmode, addr);
+ operands[1] = op1 = change_address (op1, TImode, new_addr);
+ addr = new_addr;
+ }
+
+ pti_mem = change_address (op1, PTImode, addr);
+ pti_reg = gen_reg_rtx (PTImode);
+
+ if (WORDS_BIG_ENDIAN && rs6000_lra_flag)
+ emit_move_insn (pti_reg, gen_lowpart (PTImode, op2));
+ else
+ {
+ rtx op2_lo = gen_lowpart (DImode, op2);
+ rtx op2_hi = gen_highpart (DImode, op2);
+ rtx pti_lo = gen_lowpart (DImode, pti_reg);
+ rtx pti_hi = gen_highpart (DImode, pti_reg);
+
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, op0));
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_move_insn (pti_hi, op2_hi);
+ emit_move_insn (pti_lo, op2_lo);
+ }
+ else
+ {
+ emit_move_insn (pti_hi, op2_lo);
+ emit_move_insn (pti_lo, op2_hi);
+ }
+ }
+
+ emit_insn (gen_store_conditionalpti (op0, pti_mem, pti_reg));
DONE;
})
(define_insn "store_conditionalpti"
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
(unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
- (set (match_operand:PTI 1 "memory_operand" "=Z")
+ (set (match_operand:PTI 1 "indexed_or_indirect_operand" "=Z")
(match_operand:PTI 2 "quad_int_reg_operand" "r"))]
"TARGET_SYNC_TI && quad_int_reg_operand (operands[2], PTImode)"
"stqcx. %2,%y1"
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 9d42a92b7a2..b663c2ea013 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -45,7 +45,7 @@
& (OPTION_MASK_RELOCATABLE \
| OPTION_MASK_MINIMAL_TOC)) \
&& flag_pic > 1) \
- || DEFAULT_ABI == ABI_AIX)
+ || DEFAULT_ABI != ABI_V4)
#define TARGET_BITFIELD_TYPE (! TARGET_NO_BITFIELD_TYPE)
#define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
@@ -147,7 +147,7 @@ do { \
rs6000_sdata_name); \
} \
\
- else if (flag_pic && DEFAULT_ABI != ABI_AIX \
+ else if (flag_pic && DEFAULT_ABI == ABI_V4 \
&& (rs6000_sdata == SDATA_EABI \
|| rs6000_sdata == SDATA_SYSV)) \
{ \
@@ -173,14 +173,14 @@ do { \
error ("-mrelocatable and -mno-minimal-toc are incompatible"); \
} \
\
- if (TARGET_RELOCATABLE && rs6000_current_abi == ABI_AIX) \
+ if (TARGET_RELOCATABLE && rs6000_current_abi != ABI_V4) \
{ \
rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE; \
error ("-mrelocatable and -mcall-%s are incompatible", \
rs6000_abi_name); \
} \
\
- if (!TARGET_64BIT && flag_pic > 1 && rs6000_current_abi == ABI_AIX) \
+ if (!TARGET_64BIT && flag_pic > 1 && rs6000_current_abi != ABI_V4) \
{ \
flag_pic = 0; \
error ("-fPIC and -mcall-%s are incompatible", \
@@ -193,7 +193,7 @@ do { \
} \
\
/* Treat -fPIC the same as -mrelocatable. */ \
- if (flag_pic > 1 && DEFAULT_ABI != ABI_AIX) \
+ if (flag_pic > 1 && DEFAULT_ABI == ABI_V4) \
{ \
rs6000_isa_flags |= OPTION_MASK_RELOCATABLE | OPTION_MASK_MINIMAL_TOC; \
TARGET_NO_FP_IN_TOC = 1; \
@@ -317,7 +317,7 @@ do { \
/* Put PC relative got entries in .got2. */
#define MINIMAL_TOC_SECTION_ASM_OP \
- (TARGET_RELOCATABLE || (flag_pic && DEFAULT_ABI != ABI_AIX) \
+ (TARGET_RELOCATABLE || (flag_pic && DEFAULT_ABI == ABI_V4) \
? "\t.section\t\".got2\",\"aw\"" : "\t.section\t\".got1\",\"aw\"")
#define SDATA_SECTION_ASM_OP "\t.section\t\".sdata\",\"aw\""
@@ -522,8 +522,6 @@ extern int fixuplabelno;
#define ENDIAN_SELECT(BIG_OPT, LITTLE_OPT, DEFAULT_OPT) \
"%{mlittle|mlittle-endian:" LITTLE_OPT ";" \
"mbig|mbig-endian:" BIG_OPT ";" \
- "mcall-aixdesc|mcall-freebsd|mcall-netbsd|" \
- "mcall-openbsd|mcall-linux:" BIG_OPT ";" \
"mcall-i960-old:" LITTLE_OPT ";" \
":" DEFAULT_OPT "}"
@@ -536,25 +534,12 @@ extern int fixuplabelno;
%{memb|msdata=eabi: -memb}" \
ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
-#define CC1_ENDIAN_BIG_SPEC ""
-
-#define CC1_ENDIAN_LITTLE_SPEC "\
-%{!mstrict-align: %{!mno-strict-align: \
- %{!mcall-i960-old: \
- -mstrict-align \
- } \
-}}"
-
-#define CC1_ENDIAN_DEFAULT_SPEC "%(cc1_endian_big)"
-
#ifndef CC1_SECURE_PLT_DEFAULT_SPEC
#define CC1_SECURE_PLT_DEFAULT_SPEC ""
#endif
-/* Pass -G xxx to the compiler and set correct endian mode. */
+/* Pass -G xxx to the compiler. */
#define CC1_SPEC "%{G*} %(cc1_cpu)" \
- ENDIAN_SELECT(" %(cc1_endian_big)", " %(cc1_endian_little)", \
- " %(cc1_endian_default)") \
"%{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \
%{mrelocatable: -meabi } \
@@ -949,9 +934,6 @@ extern const char *rs6000_extra_static_libdirs (int argc, const char **argv);
{ "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
{ "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
- { "cc1_endian_big", CC1_ENDIAN_BIG_SPEC }, \
- { "cc1_endian_little", CC1_ENDIAN_LITTLE_SPEC }, \
- { "cc1_endian_default", CC1_ENDIAN_DEFAULT_SPEC }, \
{ "cc1_secure_plt_default", CC1_SECURE_PLT_DEFAULT_SPEC }, \
{ "cpp_os_ads", CPP_OS_ADS_SPEC }, \
{ "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
diff --git a/gcc/config/rs6000/sysv4le.h b/gcc/config/rs6000/sysv4le.h
index 3901122a738..28da1c99c85 100644
--- a/gcc/config/rs6000/sysv4le.h
+++ b/gcc/config/rs6000/sysv4le.h
@@ -22,9 +22,6 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_LITTLE_ENDIAN
-#undef CC1_ENDIAN_DEFAULT_SPEC
-#define CC1_ENDIAN_DEFAULT_SPEC "%(cc1_endian_little)"
-
#undef DEFAULT_ASM_ENDIAN
#define DEFAULT_ASM_ENDIAN " -mlittle"
@@ -34,3 +31,7 @@
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS { "mlittle", "mcall-sysv" }
+
+/* Little-endian PowerPC64 Linux uses the ELF v2 ABI by default. */
+#define LINUX64_DEFAULT_ABI_ELFv2
+
diff --git a/gcc/config/rs6000/t-linux64 b/gcc/config/rs6000/t-linux64
index 9175de2ffe3..70e928dd7cd 100644
--- a/gcc/config/rs6000/t-linux64
+++ b/gcc/config/rs6000/t-linux64
@@ -25,8 +25,8 @@
# it doesn't tell anything about the 32bit libraries on those systems. Set
# MULTILIB_OSDIRNAMES according to what is found on the target.
-MULTILIB_OPTIONS = m64/m32
-MULTILIB_DIRNAMES = 64 32
-MULTILIB_EXTRA_OPTS = fPIC
-MULTILIB_OSDIRNAMES = ../lib64$(call if_multiarch,:powerpc64-linux-gnu)
-MULTILIB_OSDIRNAMES += $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu)
+MULTILIB_OPTIONS := m64/m32
+MULTILIB_DIRNAMES := 64 32
+MULTILIB_EXTRA_OPTS :=
+MULTILIB_OSDIRNAMES := m64=../lib64$(call if_multiarch,:powerpc64-linux-gnu)
+MULTILIB_OSDIRNAMES += m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu)
diff --git a/gcc/config/rs6000/t-linux64bele b/gcc/config/rs6000/t-linux64bele
new file mode 100644
index 00000000000..97c1ee6fb4d
--- /dev/null
+++ b/gcc/config/rs6000/t-linux64bele
@@ -0,0 +1,7 @@
+#rs6000/t-linux64end
+
+MULTILIB_OPTIONS += mlittle
+MULTILIB_DIRNAMES += le
+MULTILIB_OSDIRNAMES += $(subst =,.mlittle=,$(subst lible32,lib32le,$(subst lible64,lib64le,$(subst lib,lible,$(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES))))))
+MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mlittle%,$(MULTILIB_OSDIRNAMES)))
+MULTILIB_MATCHES := ${MULTILIB_MATCHES_ENDIAN}
diff --git a/gcc/config/rs6000/t-linux64le b/gcc/config/rs6000/t-linux64le
new file mode 100644
index 00000000000..0cf38e1523a
--- /dev/null
+++ b/gcc/config/rs6000/t-linux64le
@@ -0,0 +1,3 @@
+#rs6000/t-linux64le
+
+MULTILIB_OSDIRNAMES := $(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES))
diff --git a/gcc/config/rs6000/t-linux64lebe b/gcc/config/rs6000/t-linux64lebe
new file mode 100644
index 00000000000..2e63bdb9fc9
--- /dev/null
+++ b/gcc/config/rs6000/t-linux64lebe
@@ -0,0 +1,7 @@
+#rs6000/t-linux64leend
+
+MULTILIB_OPTIONS += mbig
+MULTILIB_DIRNAMES += be
+MULTILIB_OSDIRNAMES += $(subst =,.mbig=,$(subst libbe32,lib32be,$(subst libbe64,lib64be,$(subst lib,libbe,$(subst le-linux,-linux,$(MULTILIB_OSDIRNAMES))))))
+MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mbig%,$(MULTILIB_OSDIRNAMES)))
+MULTILIB_MATCHES := ${MULTILIB_MATCHES_ENDIAN}
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 2eaa2d325c3..9d2bcc1ba48 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -88,7 +88,8 @@
(smax "smax")])
-;; Vector move instructions.
+;; Vector move instructions. Little-endian VSX loads and stores require
+;; special handling to circumvent "element endianness."
(define_expand "mov<mode>"
[(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
(match_operand:VEC_M 1 "any_operand" ""))]
@@ -104,6 +105,16 @@
&& !vlogical_operand (operands[1], <MODE>mode))
operands[1] = force_reg (<MODE>mode, operands[1]);
}
+ if (!BYTES_BIG_ENDIAN
+ && VECTOR_MEM_VSX_P (<MODE>mode)
+ && <MODE>mode != TImode
+ && !gpr_or_gpr_p (operands[0], operands[1])
+ && (memory_operand (operands[0], <MODE>mode)
+ ^ memory_operand (operands[1], <MODE>mode)))
+ {
+ rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
+ DONE;
+ }
})
;; Generic vector floating point load/store instructions. These will match
@@ -862,7 +873,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -874,7 +885,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -886,7 +897,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -898,7 +909,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -910,7 +921,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
@@ -922,7 +933,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
@@ -936,8 +947,19 @@
(match_operand:V16QI 3 "vlogical_operand" "")]
"VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
{
- emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], operands[2],
- operands[3]));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ {
+ /* We have changed lvsr to lvsl, so to complete the transformation
+ of vperm for LE, we must swap the inputs. */
+ rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[2],
+ operands[1], operands[3]),
+ UNSPEC_VPERM);
+ emit_move_insn (operands[0], unspec);
+ }
DONE;
})
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 11d6b8bb4d0..48cea325898 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -213,9 +213,363 @@
UNSPEC_VSX_ROUND_I
UNSPEC_VSX_ROUND_IC
UNSPEC_VSX_SLDWI
+ UNSPEC_VSX_XXSPLTW
])
;; VSX moves
+
+;; The patterns for LE permuted loads and stores come before the general
+;; VSX moves so they match first.
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (match_operand:VSX_D 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 1) (const_int 0)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (match_operand:VSX_W 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_v8hi"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (match_operand:V8HI 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 2)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_v16qi"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (match_operand:V16QI 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 2)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn "*vsx_le_perm_store_<mode>"
+ [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
+ (match_operand:VSX_D 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:VSX_D 0 "memory_operand" "")
+ (match_operand:VSX_D 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 1) (const_int 0)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:VSX_D 0 "memory_operand" "")
+ (match_operand:VSX_D 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_<mode>"
+ [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+ (match_operand:VSX_W 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:VSX_W 0 "memory_operand" "")
+ (match_operand:VSX_W 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:VSX_W 0 "memory_operand" "")
+ (match_operand:VSX_W 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_v8hi"
+ [(set (match_operand:V8HI 0 "memory_operand" "=Z")
+ (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:V8HI 0 "memory_operand" "")
+ (match_operand:V8HI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 2)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:V8HI 0 "memory_operand" "")
+ (match_operand:V8HI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 1)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_v16qi"
+ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
+ (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:V16QI 0 "memory_operand" "")
+ (match_operand:V16QI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 2)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:V16QI 0 "memory_operand" "")
+ (match_operand:V16QI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 1)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "")
+
+
(define_insn "*vsx_mov<mode>"
[(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,wQ,?&r,??Y,??r,??r,<VSr>,?wa,*r,v,wZ, v")
(match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,wQ,r,Y,r,j,j,j,W,v,wZ"))]
@@ -316,40 +670,42 @@
"")
-;; VSX scalar and vector floating point arithmetic instructions
+;; VSX vector floating point arithmetic instructions. The VSX scalar
+;; instructions are now combined with the insn for the traditional floating
+;; point unit.
(define_insn "*vsx_add<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>add<VSs> %x0,%x1,%x2"
+ "xvadd<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_sub<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sub<VSs> %x0,%x1,%x2"
+ "xvsub<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_mul<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>mul<VSs> %x0,%x1,%x2"
- [(set_attr "type" "<VStype_mul>")
+ "xvmul<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_mul>")])
(define_insn "*vsx_div<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>div<VSs> %x0,%x1,%x2"
+ "xvdiv<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_div>")
(set_attr "fp_type" "<VSfptype_div>")])
@@ -392,94 +748,72 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_fre<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRES))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>re<VSs> %x0,%x1"
+ "xvre<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_neg<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>neg<VSs> %x0,%x1"
+ "xvneg<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_abs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>abs<VSs> %x0,%x1"
+ "xvabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_nabs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B
- (abs:VSX_B
- (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F
+ (abs:VSX_F
+ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>nabs<VSs> %x0,%x1"
+ "xvnabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_smax<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>max<VSs> %x0,%x1,%x2"
+ "xvmax<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_smin<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>min<VSs> %x0,%x1,%x2"
+ "xvmin<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Special VSX version of smin/smax for single precision floating point. Since
-;; both numbers are rounded to single precision, we can just use the DP version
-;; of the instruction.
-
-(define_insn "*vsx_smaxsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmaxdp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_insn "*vsx_sminsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmindp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
(define_insn "*vsx_sqrt<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sqrt<VSs> %x0,%x1"
+ "xvsqrt<VSs> %x0,%x1"
[(set_attr "type" "<VStype_sqrt>")
(set_attr "fp_type" "<VSfptype_sqrt>")])
(define_insn "*vsx_rsqrte<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_RSQRT))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>rsqrte<VSs> %x0,%x1"
+ "xvrsqrte<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -518,26 +852,10 @@
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Fused vector multiply/add instructions Support the classical DF versions of
-;; fma, which allows the target to be a separate register from the 3 inputs.
-;; Under VSX, the target must be either the addend or the first multiply.
-;; Where we can, also do the same for the Altivec V4SF fmas.
-
-(define_insn "*vsx_fmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
+;; Fused vector multiply/add instructions. Support the classical Altivec
+;; versions of fma, which allows the target to be a separate register from the
+;; 3 inputs. Under VSX, the target must be either the addend or the first
+;; multiply.
(define_insn "*vsx_fmav4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
@@ -568,23 +886,6 @@
xvmaddmdp %x0,%x1,%x3"
[(set_attr "type" "vecdouble")])
-(define_insn "*vsx_fmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_fms<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(fma:VSX_F
@@ -594,29 +895,12 @@
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3"
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")])
-(define_insn "*vsx_nfmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfma<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(neg:VSX_F
@@ -626,31 +910,13 @@
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")
(set_attr "fp_type" "<VSfptype_mul>")])
-(define_insn "*vsx_nfmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfmsv4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
(neg:V4SF
@@ -712,16 +978,6 @@
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Floating point scalar compare
-(define_insn "*vsx_cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
- (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_VSX_P (DFmode)"
- "xscmpudp %0,%x1,%x2"
- [(set_attr "type" "fpcompare")])
-
;; Compare vectors producing a vector result and a predicate, setting CR6 to
;; indicate a combined status
(define_insn "*vsx_eq_<mode>_p"
@@ -788,13 +1044,13 @@
;; Copy sign
(define_insn "vsx_copysign<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B
- [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F
+ [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_COPYSIGN))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
+ "xvcpsgn<VSs> %x0,%x2,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -855,10 +1111,10 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_btrunc<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>iz %x0,%x1"
+ "xvr<VSs>iz %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -872,20 +1128,20 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_floor<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIM))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>im %x0,%x1"
+ "xvr<VSs>im %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_ceil<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIP))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>ip %x0,%x1"
+ "xvr<VSs>ip %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -1060,7 +1316,12 @@
(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
(match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
- "xxpermdi %x0,%x1,%x2,0"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "xxpermdi %x0,%x1,%x2,0";
+ else
+ return "xxpermdi %x0,%x2,%x1,0";
+}
[(set_attr "type" "vecperm")])
;; Special purpose concat using xxpermdi to glue two single precision values
@@ -1073,9 +1334,161 @@
(match_operand:SF 2 "vsx_register_operand" "f,f")]
UNSPEC_VSX_CONCAT))]
"VECTOR_MEM_VSX_P (V2DFmode)"
- "xxpermdi %x0,%x1,%x2,0"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "xxpermdi %x0,%x1,%x2,0";
+ else
+ return "xxpermdi %x0,%x2,%x1,0";
+}
+ [(set_attr "type" "vecperm")])
+
+;; xxpermdi for little endian loads and stores. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_xxpermdi2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x1,2"
[(set_attr "type" "vecperm")])
+(define_insn "*vsx_xxpermdi4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxpermdi8_le_V8HI"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxpermdi16_le_V16QI"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+;; lxvd2x for little endian loads. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_lxvd2x2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "memory_operand" "Z")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "memory_operand" "Z")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x8_le_V8HI"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "memory_operand" "Z")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x16_le_V16QI"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "memory_operand" "Z")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+;; stxvd2x for little endian stores. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_stxvd2x2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x8_le_V8HI"
+ [(set (match_operand:V8HI 0 "memory_operand" "=Z")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x16_le_V16QI"
+ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
;; Set the element of a V2DI/VD2F mode
(define_insn "vsx_set_<mode>"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
@@ -1085,9 +1498,10 @@
UNSPEC_VSX_SET))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
- if (INTVAL (operands[3]) == 0)
+ int idx_first = BYTES_BIG_ENDIAN ? 0 : 1;
+ if (INTVAL (operands[3]) == idx_first)
return \"xxpermdi %x0,%x2,%x1,1\";
- else if (INTVAL (operands[3]) == 1)
+ else if (INTVAL (operands[3]) == 1 - idx_first)
return \"xxpermdi %x0,%x1,%x2,0\";
else
gcc_unreachable ();
@@ -1102,8 +1516,12 @@
[(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
+ int fldDM;
gcc_assert (UINTVAL (operands[2]) <= 1);
- operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
+ fldDM = INTVAL (operands[2]) << 1;
+ if (!BYTES_BIG_ENDIAN)
+ fldDM = 3 - fldDM;
+ operands[3] = GEN_INT (fldDM);
return \"xxpermdi %x0,%x1,%x1,%3\";
}
[(set_attr "type" "vecperm")])
@@ -1123,6 +1541,21 @@
(const_string "fpload")))
(set_attr "length" "4")])
+;; Optimize extracting element 1 from memory for little endian
+(define_insn "*vsx_extract_<mode>_one_le"
+ [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa")
+ (vec_select:<VS_scalar>
+ (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z")
+ (parallel [(const_int 1)])))]
+ "VECTOR_MEM_VSX_P (<MODE>mode) && !WORDS_BIG_ENDIAN"
+ "lxsd%U1x %x0,%y1"
+ [(set (attr "type")
+ (if_then_else
+ (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+ (const_string "fpload_ux")
+ (const_string "fpload")))
+ (set_attr "length" "4")])
+
;; Extract a SF element from V4SF
(define_insn_and_split "vsx_extract_v4sf"
[(set (match_operand:SF 0 "vsx_register_operand" "=f,f")
@@ -1143,7 +1576,7 @@
rtx op2 = operands[2];
rtx op3 = operands[3];
rtx tmp;
- HOST_WIDE_INT ele = INTVAL (op2);
+ HOST_WIDE_INT ele = BYTES_BIG_ENDIAN ? INTVAL (op2) : 3 - INTVAL (op2);
if (ele == 0)
tmp = op1;
@@ -1188,7 +1621,18 @@
op1 = gen_lowpart (V2DImode, op1);
}
}
- emit_insn (gen (target, op0, op1, perm0, perm1));
+ /* In little endian mode, vsx_xxpermdi2_<mode>_1 will perform a
+ transformation we don't want; it is necessary for
+ rs6000_expand_vec_perm_const_1 but not for this use. So we
+ prepare for that by reversing the transformation here. */
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen (target, op0, op1, perm0, perm1));
+ else
+ {
+ rtx p0 = GEN_INT (3 - INTVAL (perm1));
+ rtx p1 = GEN_INT (3 - INTVAL (perm0));
+ emit_insn (gen (target, op1, op0, p0, p1));
+ }
DONE;
})
@@ -1202,9 +1646,32 @@
(match_operand 4 "const_2_to_3_operand" "")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
- int mask = (INTVAL (operands[3]) << 1) | (INTVAL (operands[4]) - 2);
+ int op3, op4, mask;
+
+ /* For little endian, swap operands and invert/swap selectors
+ to get the correct xxpermdi. The operand swap sets up the
+ inputs as a little endian array. The selectors are swapped
+ because they are defined to use big endian ordering. The
+ selectors are inverted to get the correct doublewords for
+ little endian ordering. */
+ if (BYTES_BIG_ENDIAN)
+ {
+ op3 = INTVAL (operands[3]);
+ op4 = INTVAL (operands[4]);
+ }
+ else
+ {
+ op3 = 3 - INTVAL (operands[4]);
+ op4 = 3 - INTVAL (operands[3]);
+ }
+
+ mask = (op3 << 1) | (op4 - 2);
operands[3] = GEN_INT (mask);
- return "xxpermdi %x0,%x1,%x2,%3";
+
+ if (BYTES_BIG_ENDIAN)
+ return "xxpermdi %x0,%x1,%x2,%3";
+ else
+ return "xxpermdi %x0,%x2,%x1,%3";
}
[(set_attr "type" "vecperm")])
@@ -1223,24 +1690,56 @@
;; Expanders for builtins
(define_expand "vsx_mergel_<mode>"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
- (vec_select:VSX_D
- (vec_concat:<VS_double>
- (match_operand:VSX_D 1 "vsx_register_operand" "")
- (match_operand:VSX_D 2 "vsx_register_operand" ""))
- (parallel [(const_int 1) (const_int 3)])))]
+ [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
+ (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
+ (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
- "")
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
+ x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
+ x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
(define_expand "vsx_mergeh_<mode>"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "")
- (vec_select:VSX_D
- (vec_concat:<VS_double>
- (match_operand:VSX_D 1 "vsx_register_operand" "")
- (match_operand:VSX_D 2 "vsx_register_operand" ""))
- (parallel [(const_int 0) (const_int 2)])))]
+ [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
+ (use (match_operand:VSX_D 1 "vsx_register_operand" ""))
+ (use (match_operand:VSX_D 2 "vsx_register_operand" ""))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
- "")
+{
+ rtvec v;
+ rtx x;
+
+ /* Special handling for LE with -maltivec=be. */
+ if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+ {
+ v = gen_rtvec (2, GEN_INT (1), GEN_INT (3));
+ x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[2], operands[1]);
+ }
+ else
+ {
+ v = gen_rtvec (2, GEN_INT (0), GEN_INT (2));
+ x = gen_rtx_VEC_CONCAT (<VS_double>mode, operands[1], operands[2]);
+ }
+
+ x = gen_rtx_VEC_SELECT (<MODE>mode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
;; V2DF/V2DI splat
(define_insn "vsx_splat_<mode>"
@@ -1266,6 +1765,20 @@
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
+{
+ if (!BYTES_BIG_ENDIAN)
+ operands[2] = GEN_INT (3 - INTVAL (operands[2]));
+
+ return "xxspltw %x0,%x1,%2";
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "vsx_xxspltw_<mode>_direct"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
+ (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "wf,wa")
+ (match_operand:QI 2 "u5bit_cint_operand" "i,i")]
+ UNSPEC_VSX_XXSPLTW))]
+ "VECTOR_MEM_VSX_P (<MODE>mode)"
"xxspltw %x0,%x1,%2"
[(set_attr "type" "vecperm")])
@@ -1463,7 +1976,7 @@
(set (match_operand:VSX_M2 2 "vsx_register_operand" "")
(mem:VSX_M2 (plus:P (match_dup 0)
(match_operand:P 3 "int_reg_operand" ""))))]
- "TARGET_P8_FUSION"
+ "TARGET_VSX && TARGET_P8_FUSION"
"li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3"
[(set_attr "length" "8")
(set_attr "type" "vecload")])
@@ -1474,7 +1987,7 @@
(set (match_operand:VSX_M2 2 "vsx_register_operand" "")
(mem:VSX_M2 (plus:P (match_operand:P 3 "int_reg_operand" "")
(match_dup 0))))]
- "TARGET_P8_FUSION"
+ "TARGET_VSX && TARGET_P8_FUSION"
"li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3"
[(set_attr "length" "8")
(set_attr "type" "vecload")])
diff --git a/gcc/config/s390/htmintrin.h b/gcc/config/s390/htmintrin.h
new file mode 100644
index 00000000000..7aaa9f5bf7c
--- /dev/null
+++ b/gcc/config/s390/htmintrin.h
@@ -0,0 +1,57 @@
+/* GNU compiler hardware transactional execution intrinsics
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _HTMINTRIN_H
+#define _HTMINTRIN_H
+
+
+/* Condition codes generated by tbegin */
+#define _HTM_TBEGIN_STARTED 0
+#define _HTM_TBEGIN_INDETERMINATE 1
+#define _HTM_TBEGIN_TRANSIENT 2
+#define _HTM_TBEGIN_PERSISTENT 3
+
+/* The abort codes below this threshold are reserved for machine
+ use. */
+#define _HTM_FIRST_USER_ABORT_CODE 256
+
+/* The transaction diagnostic block is it is defined in the Principles
+ of Operation chapter 5-91. */
+
+struct __htm_tdb {
+ unsigned char format; /* 0 */
+ unsigned char flags;
+ unsigned char reserved1[4];
+ unsigned short nesting_depth;
+ unsigned long long abort_code; /* 8 */
+ unsigned long long conflict_token; /* 16 */
+ unsigned long long atia; /* 24 */
+ unsigned char eaid; /* 32 */
+ unsigned char dxc;
+ unsigned char reserved2[2];
+ unsigned int program_int_id;
+ unsigned long long exception_id; /* 40 */
+ unsigned long long bea; /* 48 */
+ unsigned char reserved3[72]; /* 56 */
+ unsigned long long gprs[16]; /* 128 */
+} __attribute__((__packed__, __aligned__ (8)));
+
+
+#endif /* _HTMINTRIN_H */
diff --git a/gcc/config/s390/htmxlintrin.h b/gcc/config/s390/htmxlintrin.h
new file mode 100644
index 00000000000..952b40975c2
--- /dev/null
+++ b/gcc/config/s390/htmxlintrin.h
@@ -0,0 +1,189 @@
+/* XL compiler hardware transactional execution intrinsics
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _HTMXLINTRIN_H
+#define _HTMXLINTRIN_H
+
+#include <stdint.h>
+
+#include <htmintrin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These intrinsics are being made available for compatibility with
+ the IBM XL compiler. For documentation please see the "z/OS XL
+ C/C++ Programming Guide" publically available on the web. */
+
+/* FIXME: __TM_simple_begin and __TM_begin should be marked
+ __always_inline__ as well but this currently produces an error
+ since the tbegin builtins are "returns_twice" and setjmp_call_p
+ (calls.c) therefore identifies the functions as calling setjmp.
+ The tree inliner currently refuses to inline functions calling
+ setjmp. */
+
+long
+__TM_simple_begin ()
+{
+ return __builtin_tbegin_nofloat (0);
+}
+
+long
+__TM_begin (void* const tdb)
+{
+ return __builtin_tbegin_nofloat (tdb);
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_end ()
+{
+ return __builtin_tend ();
+}
+
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_abort ()
+{
+ return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
+}
+
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_named_abort (unsigned char const code)
+{
+ return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
+}
+
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_non_transactional_store (void* const addr, long long const value)
+{
+ __builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_nesting_depth (void* const tdb_ptr)
+{
+ int depth = __builtin_tx_nesting_depth ();
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (depth != 0)
+ return depth;
+
+ if (tdb->format != 1)
+ return 0;
+ return tdb->nesting_depth;
+}
+
+/* Transaction failure diagnostics */
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_user_abort (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ if (tdb->format != 1)
+ return 0;
+
+ if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
+ {
+ *code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
+ return 1;
+ }
+ return 0;
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_illegal (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 4 /* unfiltered program interruption */
+ || tdb->abort_code == 11 /* restricted instruction */));
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_footprint_exceeded (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 7 /* fetch overflow */
+ || tdb->abort_code == 8 /* store overflow */));
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_nested_too_deep (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_conflict (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return (tdb->format == 1
+ && (tdb->abort_code == 9 /* fetch conflict */
+ || tdb->abort_code == 10 /* store conflict */));
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_failure_persistent (long const result)
+{
+ return result == _HTM_TBEGIN_PERSISTENT;
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_address (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+#ifdef __s390x__
+ return tdb->atia;
+#else
+ return tdb->atia & 0xffffffff;
+#endif
+}
+
+extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_code (void* const tdb_ptr)
+{
+ struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
+
+ return tdb->abort_code;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTMXLINTRIN_H */
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 523326e177d..069b42489a7 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -176,7 +176,11 @@
{
if (GET_CODE (XEXP (op, 0)) != REG
|| REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
+ || (XEXP (op, 1) != const0_rtx
+ && !(CONST_INT_P (XEXP (op, 1))
+ && GET_MODE (XEXP (op, 0)) == CCRAWmode
+ && INTVAL (XEXP (op, 1)) >= 0
+ && INTVAL (XEXP (op, 1)) <= 15)))
return false;
return (s390_branch_condition_mask (op) >= 0);
@@ -224,7 +228,11 @@
if (GET_CODE (XEXP (op, 0)) != REG
|| REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
+ || (XEXP (op, 1) != const0_rtx
+ && !(CONST_INT_P (XEXP (op, 1))
+ && GET_MODE (XEXP (op, 0)) == CCRAWmode
+ && INTVAL (XEXP (op, 1)) >= 0
+ && INTVAL (XEXP (op, 1)) <= 15)))
return false;
switch (GET_MODE (XEXP (op, 0)))
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index 419108fb473..5e0b50cafa1 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -152,6 +152,14 @@ The compare and swap instructions sets the condition code to 0/1 if the
operands were equal/unequal. The CCZ1 mode ensures the result can be
effectively placed into a register.
+CCRAW
+
+The cc mode generated by a non-compare instruction. The condition
+code mask for the CC consumer is determined by the comparison operator
+(only EQ and NE allowed) and the immediate value given as second
+operand to the operator. For the other CC modes this value used to be
+0.
+
*/
@@ -172,3 +180,4 @@ CC_MODE (CCT);
CC_MODE (CCT1);
CC_MODE (CCT2);
CC_MODE (CCT3);
+CC_MODE (CCRAW);
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 1a8205359e4..7b43ed01b65 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -58,7 +58,7 @@ extern bool s390_match_ccmode (rtx, enum machine_mode);
extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
-extern void s390_emit_jump (rtx, rtx);
+extern rtx s390_emit_jump (rtx, rtx);
extern bool symbolic_reference_mentioned_p (rtx);
extern bool tls_symbolic_reference_mentioned_p (rtx);
extern bool legitimate_la_operand_p (rtx);
@@ -87,6 +87,7 @@ extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx,
rtx, rtx, bool);
extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
rtx, rtx, rtx, bool);
+extern void s390_expand_tbegin (rtx, rtx, rtx, bool);
extern rtx s390_return_addr_rtx (int, rtx);
extern rtx s390_back_chain_rtx (void);
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
@@ -109,5 +110,6 @@ extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
extern int s390_branch_condition_mask (rtx);
extern int s390_compare_and_branch_condition_mask (rtx);
extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT);
+extern void s390_asm_output_function_label (FILE *, const char *, tree);
#endif /* RTX_CODE */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index ac33371937e..257e33c8469 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -367,6 +367,10 @@ struct GTY(()) machine_function
const char *some_ld_name;
bool has_landing_pad_p;
+
+ /* True if the current function may contain a tbegin clobbering
+ FPRs. */
+ bool tbegin_p;
};
/* Few accessor macros for struct cfun->machine->s390_frame_layout. */
@@ -403,6 +407,65 @@ struct GTY(()) machine_function
bytes on a z10 (or higher) CPU. */
#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
+static const int s390_hotpatch_trampoline_halfwords_default = 12;
+static const int s390_hotpatch_trampoline_halfwords_max = 1000000;
+static int s390_hotpatch_trampoline_halfwords = -1;
+
+/* Return the argument of the given hotpatch attribute or the default value if
+ no argument is present. */
+
+static inline int
+get_hotpatch_attribute (tree hotpatch_attr)
+{
+ const_tree args;
+
+ args = TREE_VALUE (hotpatch_attr);
+
+ return (args) ?
+ TREE_INT_CST_LOW (TREE_VALUE (args)):
+ s390_hotpatch_trampoline_halfwords_default;
+}
+
+/* Check whether the hotpatch attribute is applied to a function and, if it has
+ an argument, the argument is valid. */
+
+static tree
+s390_handle_hotpatch_attribute (tree *node, tree name, tree args,
+ 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;
+ }
+ else if (args)
+ {
+ tree expr = TREE_VALUE (args);
+
+ if (TREE_CODE (expr) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (expr))
+ || TREE_INT_CST_HIGH (expr) != 0
+ || TREE_INT_CST_LOW (expr) > (unsigned int)
+ s390_hotpatch_trampoline_halfwords_max)
+ {
+ error ("requested %qE attribute is not a non-negative integer"
+ " constant or too large (max. %d)", name,
+ s390_hotpatch_trampoline_halfwords_max);
+ *no_add_attrs = true;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+static const struct attribute_spec s390_attribute_table[] = {
+ { "hotpatch", 0, 1, true, false, false, s390_handle_hotpatch_attribute, false
+ },
+ /* End element. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+
/* Return the alignment for LABEL. We default to the -falign-labels
value except for the literal pool base label. */
int
@@ -824,9 +887,9 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
*op1 = constm1_rtx;
}
- /* Remove redundant UNSPEC_CCU_TO_INT conversions if possible. */
+ /* Remove redundant UNSPEC_STRCMPCC_TO_INT conversions if possible. */
if (GET_CODE (*op0) == UNSPEC
- && XINT (*op0, 1) == UNSPEC_CCU_TO_INT
+ && XINT (*op0, 1) == UNSPEC_STRCMPCC_TO_INT
&& XVECLEN (*op0, 0) == 1
&& GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
&& GET_CODE (XVECEXP (*op0, 0, 0)) == REG
@@ -852,25 +915,36 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
}
}
- /* Remove redundant UNSPEC_CCZ_TO_INT conversions if possible. */
+ /* Remove redundant UNSPEC_CC_TO_INT conversions if possible. */
if (GET_CODE (*op0) == UNSPEC
- && XINT (*op0, 1) == UNSPEC_CCZ_TO_INT
+ && XINT (*op0, 1) == UNSPEC_CC_TO_INT
&& XVECLEN (*op0, 0) == 1
- && GET_MODE (XVECEXP (*op0, 0, 0)) == CCZmode
&& GET_CODE (XVECEXP (*op0, 0, 0)) == REG
&& REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
- && *op1 == const0_rtx)
+ && CONST_INT_P (*op1))
{
enum rtx_code new_code = UNKNOWN;
- switch (*code)
+ switch (GET_MODE (XVECEXP (*op0, 0, 0)))
{
- case EQ: new_code = EQ; break;
- case NE: new_code = NE; break;
- default: break;
+ case CCZmode:
+ case CCRAWmode:
+ switch (*code)
+ {
+ case EQ: new_code = EQ; break;
+ case NE: new_code = NE; break;
+ default: break;
+ }
+ break;
+ default: break;
}
if (new_code != UNKNOWN)
{
+ /* For CCRAWmode put the required cc mask into the second
+ operand. */
+ if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode
+ && INTVAL (*op1) >= 0 && INTVAL (*op1) <= 3)
+ *op1 = gen_rtx_CONST_INT (VOIDmode, 1 << (3 - INTVAL (*op1)));
*op0 = XVECEXP (*op0, 0, 0);
*code = new_code;
}
@@ -942,10 +1016,11 @@ s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem,
const0_rtx);
}
-/* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
- unconditional jump, else a conditional jump under condition COND. */
+/* Emit a jump instruction to TARGET and return it. If COND is
+ NULL_RTX, emit an unconditional jump, else a conditional jump under
+ condition COND. */
-void
+rtx
s390_emit_jump (rtx target, rtx cond)
{
rtx insn;
@@ -955,7 +1030,7 @@ s390_emit_jump (rtx target, rtx cond)
target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);
insn = gen_rtx_SET (VOIDmode, pc_rtx, target);
- emit_jump_insn (insn);
+ return emit_jump_insn (insn);
}
/* Return branch condition mask to implement a branch
@@ -971,7 +1046,10 @@ s390_branch_condition_mask (rtx code)
gcc_assert (GET_CODE (XEXP (code, 0)) == REG);
gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);
- gcc_assert (XEXP (code, 1) == const0_rtx);
+ gcc_assert (XEXP (code, 1) == const0_rtx
+ || (GET_MODE (XEXP (code, 0)) == CCRAWmode
+ && CONST_INT_P (XEXP (code, 1))));
+
switch (GET_MODE (XEXP (code, 0)))
{
@@ -1145,6 +1223,17 @@ s390_branch_condition_mask (rtx code)
}
break;
+ case CCRAWmode:
+ switch (GET_CODE (code))
+ {
+ case EQ:
+ return INTVAL (XEXP (code, 1));
+ case NE:
+ return (INTVAL (XEXP (code, 1))) ^ 0xf;
+ default:
+ gcc_unreachable ();
+ }
+
default:
return -1;
}
@@ -1204,7 +1293,9 @@ s390_branch_condition_mnemonic (rtx code, int inv)
if (GET_CODE (XEXP (code, 0)) == REG
&& REGNO (XEXP (code, 0)) == CC_REGNUM
- && XEXP (code, 1) == const0_rtx)
+ && (XEXP (code, 1) == const0_rtx
+ || (GET_MODE (XEXP (code, 0)) == CCRAWmode
+ && CONST_INT_P (XEXP (code, 1)))))
mask = s390_branch_condition_mask (code);
else
mask = s390_compare_and_branch_condition_mask (code);
@@ -1563,6 +1654,46 @@ s390_init_machine_status (void)
static void
s390_option_override (void)
{
+ unsigned int i;
+ cl_deferred_option *opt;
+ vec<cl_deferred_option> *v =
+ (vec<cl_deferred_option> *) s390_deferred_options;
+
+ if (v)
+ FOR_EACH_VEC_ELT (*v, i, opt)
+ {
+ switch (opt->opt_index)
+ {
+ case OPT_mhotpatch:
+ s390_hotpatch_trampoline_halfwords = (opt->value) ?
+ s390_hotpatch_trampoline_halfwords_default : -1;
+ break;
+ case OPT_mhotpatch_:
+ {
+ int val;
+
+ val = integral_argument (opt->arg);
+ if (val == -1)
+ {
+ /* argument is not a plain number */
+ error ("argument to %qs should be a non-negative integer",
+ "-mhotpatch=");
+ break;
+ }
+ else if (val > s390_hotpatch_trampoline_halfwords_max)
+ {
+ error ("argument to %qs is too large (max. %d)",
+ "-mhotpatch=", s390_hotpatch_trampoline_halfwords_max);
+ break;
+ }
+ s390_hotpatch_trampoline_halfwords = val;
+ break;
+ }
+ default:
+ gcc_unreachable ();
+ }
+ }
+
/* Set up function hooks. */
init_machine_status = s390_init_machine_status;
@@ -1602,6 +1733,11 @@ s390_option_override (void)
if (!(target_flags_explicit & MASK_HARD_DFP) && TARGET_DFP)
target_flags |= MASK_HARD_DFP;
+ /* Enable hardware transactions if available and not explicitly
+ disabled by user. E.g. with -m31 -march=zEC12 -mzarch */
+ if (!(target_flags_explicit & MASK_OPT_HTM) && TARGET_CPU_HTM && TARGET_ZARCH)
+ target_flags |= MASK_OPT_HTM;
+
if (TARGET_HARD_DFP && !TARGET_DFP)
{
if (target_flags_explicit & MASK_HARD_DFP)
@@ -2979,15 +3115,22 @@ s390_preferred_reload_class (rtx op, reg_class_t rclass)
prefer ADDR_REGS. If 'class' is not a superset
of ADDR_REGS, e.g. FP_REGS, reject this reload. */
case CONST:
- /* A larl operand with odd addend will get fixed via secondary
- reload. So don't request it to be pushed into literal
- pool. */
+ /* Symrefs cannot be pushed into the literal pool with -fPIC
+ so we *MUST NOT* return NO_REGS for these cases
+ (s390_cannot_force_const_mem will return true).
+
+ On the other hand we MUST return NO_REGS for symrefs with
+ invalid addend which might have been pushed to the literal
+ pool (no -fPIC). Usually we would expect them to be
+ handled via secondary reload but this does not happen if
+ they are used as literal pool slot replacement in reload
+ inheritance (see emit_input_reload_insns). */
if (TARGET_CPU_ZARCH
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP(op, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP(op, 0), 1)) == CONST_INT)
{
- if (reg_class_subset_p (ADDR_REGS, rclass))
+ if (flag_pic && reg_class_subset_p (ADDR_REGS, rclass))
return ADDR_REGS;
else
return NO_REGS;
@@ -5275,6 +5418,102 @@ get_some_local_dynamic_name (void)
gcc_unreachable ();
}
+/* Returns -1 if the function should not be made hotpatchable. Otherwise it
+ returns a number >= 0 that is the desired size of the hotpatch trampoline
+ in halfwords. */
+
+static int s390_function_num_hotpatch_trampoline_halfwords (tree decl,
+ bool do_warn)
+{
+ tree attr;
+
+ if (DECL_DECLARED_INLINE_P (decl)
+ || DECL_ARTIFICIAL (decl)
+ || MAIN_NAME_P (DECL_NAME (decl)))
+ {
+ /* - Explicitly inlined functions cannot be hotpatched.
+ - Artificial functions need not be hotpatched.
+ - Making the main function hotpatchable is useless. */
+ return -1;
+ }
+ attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
+ if (attr || s390_hotpatch_trampoline_halfwords >= 0)
+ {
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)))
+ {
+ if (do_warn)
+ warning (OPT_Wattributes, "function %qE with the %qs attribute"
+ " is not hotpatchable", DECL_NAME (decl), "always_inline");
+ return -1;
+ }
+ else
+ {
+ return (attr) ?
+ get_hotpatch_attribute (attr) : s390_hotpatch_trampoline_halfwords;
+ }
+ }
+
+ return -1;
+}
+
+/* Hook to determine if one function can safely inline another. */
+
+static bool
+s390_can_inline_p (tree caller, tree callee)
+{
+ if (s390_function_num_hotpatch_trampoline_halfwords (callee, false) >= 0)
+ return false;
+
+ return default_target_can_inline_p (caller, callee);
+}
+
+/* Write the extra assembler code needed to declare a function properly. */
+
+void
+s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
+ tree decl)
+{
+ int hotpatch_trampoline_halfwords = -1;
+
+ if (decl)
+ {
+ hotpatch_trampoline_halfwords =
+ s390_function_num_hotpatch_trampoline_halfwords (decl, true);
+ if (hotpatch_trampoline_halfwords >= 0
+ && decl_function_context (decl) != NULL_TREE)
+ {
+ warning_at (0, DECL_SOURCE_LOCATION (decl),
+ "hotpatch_prologue is not compatible with nested"
+ " function");
+ hotpatch_trampoline_halfwords = -1;
+ }
+ }
+
+ if (hotpatch_trampoline_halfwords > 0)
+ {
+ int i;
+
+ /* Add a trampoline code area before the function label and initialize it
+ with two-byte nop instructions. This area can be overwritten with code
+ that jumps to a patched version of the function. */
+ for (i = 0; i < hotpatch_trampoline_halfwords; i++)
+ asm_fprintf (asm_out_file, "\tnopr\t%%r7\n");
+ /* Note: The function label must be aligned so that (a) the bytes of the
+ following nop do not cross a cacheline boundary, and (b) a jump address
+ (eight bytes for 64 bit targets, 4 bytes for 32 bit targets) can be
+ stored directly before the label without crossing a cacheline
+ boundary. All this is necessary to make sure the trampoline code can
+ be changed atomically. */
+ }
+
+ ASM_OUTPUT_LABEL (asm_out_file, fname);
+
+ /* Output a four-byte nop if hotpatching is enabled. This can be overwritten
+ atomically with a relative backwards jump to the trampoline area. */
+ if (hotpatch_trampoline_halfwords >= 0)
+ asm_fprintf (asm_out_file, "\tnop\t0\n");
+}
+
/* Output machine-dependent UNSPECs occurring in address constant X
in assembler syntax to stdio stream FILE. Returns true if the
constant X could be recognized, false otherwise. */
@@ -7028,25 +7267,12 @@ s390_chunkify_start (void)
or a casesi jump, check all potential targets. */
else if (GET_CODE (insn) == JUMP_INSN)
{
- rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
- pat = XVECEXP (pat, 0, 0);
-
- if (GET_CODE (pat) == SET)
- {
- rtx label = JUMP_LABEL (insn);
- if (label)
- {
- if (s390_find_pool (pool_list, label)
- != s390_find_pool (pool_list, insn))
- bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
- }
- }
- else if (GET_CODE (pat) == PARALLEL
- && XVECLEN (pat, 0) == 2
- && GET_CODE (XVECEXP (pat, 0, 0)) == SET
- && GET_CODE (XVECEXP (pat, 0, 1)) == USE
- && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == LABEL_REF)
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL
+ && XVECLEN (pat, 0) == 2
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET
+ && GET_CODE (XVECEXP (pat, 0, 1)) == USE
+ && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == LABEL_REF)
{
/* Find the jump table used by this casesi jump. */
rtx vec_label = XEXP (XEXP (XVECEXP (pat, 0, 1), 0), 0);
@@ -7068,8 +7294,23 @@ s390_chunkify_start (void)
bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
}
}
+ continue;
}
- }
+
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+
+ if (GET_CODE (pat) == SET)
+ {
+ rtx label = JUMP_LABEL (insn);
+ if (label)
+ {
+ if (s390_find_pool (pool_list, label)
+ != s390_find_pool (pool_list, insn))
+ bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
+ }
+ }
+ }
}
/* Insert base register reload insns before every pool. */
@@ -7341,11 +7582,11 @@ s390_reg_clobbered_rtx (rtx setreg, const_rtx set_insn ATTRIBUTE_UNUSED, void *d
if (GET_CODE (setreg) == SUBREG)
{
rtx inner = SUBREG_REG (setreg);
- if (!GENERAL_REG_P (inner))
+ if (!GENERAL_REG_P (inner) && !FP_REG_P (inner))
return;
regno = subreg_regno (setreg);
}
- else if (GENERAL_REG_P (setreg))
+ else if (GENERAL_REG_P (setreg) || FP_REG_P (setreg))
regno = REGNO (setreg);
else
return;
@@ -7368,13 +7609,13 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
rtx cur_insn;
unsigned int i;
- memset (regs_ever_clobbered, 0, 16 * sizeof (int));
+ memset (regs_ever_clobbered, 0, 32 * sizeof (int));
/* For non-leaf functions we have to consider all call clobbered regs to be
clobbered. */
if (!crtl->is_leaf)
{
- for (i = 0; i < 16; i++)
+ for (i = 0; i < 32; i++)
regs_ever_clobbered[i] = call_really_used_regs[i];
}
@@ -7396,7 +7637,7 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
See expand_builtin_unwind_init. For regs_ever_live this is done by
reload. */
if (cfun->has_nonlocal_label)
- for (i = 0; i < 16; i++)
+ for (i = 0; i < 32; i++)
if (!call_really_used_regs[i])
regs_ever_clobbered[i] = 1;
@@ -7462,17 +7703,6 @@ s390_register_info (int clobbered_regs[])
{
int i, j;
- /* fprs 8 - 15 are call saved for 64 Bit ABI. */
- cfun_frame_layout.fpr_bitmap = 0;
- cfun_frame_layout.high_fprs = 0;
- if (TARGET_64BIT)
- for (i = 24; i < 32; i++)
- if (df_regs_ever_live_p (i) && !global_regs[i])
- {
- cfun_set_fpr_bit (i - 16);
- cfun_frame_layout.high_fprs++;
- }
-
/* Find first and last gpr to be saved. We trust regs_ever_live
data, except that we don't save and restore global registers.
@@ -7481,6 +7711,32 @@ s390_register_info (int clobbered_regs[])
s390_regs_ever_clobbered (clobbered_regs);
+ /* fprs 8 - 15 are call saved for 64 Bit ABI. */
+ if (!epilogue_completed)
+ {
+ cfun_frame_layout.fpr_bitmap = 0;
+ cfun_frame_layout.high_fprs = 0;
+ for (i = 16; i <= 31; i++)
+ {
+ if (call_really_used_regs[i])
+ continue;
+ /* During reload we have to use the df_regs_ever_live infos
+ since reload is marking FPRs used as spill slots there as
+ live before actually making the code changes. Without
+ this we fail during elimination offset verification. */
+ if ((clobbered_regs[i]
+ || (df_regs_ever_live_p (i)
+ && (reload_in_progress
+ || crtl->saves_all_registers)))
+ && !global_regs[i])
+ {
+ cfun_set_fpr_bit (i - 16);
+ if (i >= 24)
+ cfun_frame_layout.high_fprs++;
+ }
+ }
+ }
+
for (i = 0; i < 16; i++)
clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
@@ -7508,6 +7764,7 @@ s390_register_info (int clobbered_regs[])
|| TARGET_TPF_PROFILING
|| cfun_save_high_fprs_p
|| get_frame_size () > 0
+ || (reload_completed && cfun_frame_layout.frame_size > 0)
|| cfun->calls_alloca
|| cfun->stdarg);
@@ -7606,11 +7863,6 @@ s390_register_info (int clobbered_regs[])
cfun_set_fpr_bit (i);
}
}
-
- if (!TARGET_64BIT)
- for (i = 2; i < 4; i++)
- if (df_regs_ever_live_p (i + 16) && !global_regs[i + 16])
- cfun_set_fpr_bit (i);
}
/* Fill cfun->machine with info about frame of current function. */
@@ -7731,7 +7983,7 @@ s390_init_frame_layout (void)
{
HOST_WIDE_INT frame_size;
int base_used;
- int clobbered_regs[16];
+ int clobbered_regs[32];
/* On S/390 machines, we may need to perform branch splitting, which
will require both base and return address register. We have no
@@ -7766,6 +8018,163 @@ s390_init_frame_layout (void)
while (frame_size != cfun_frame_layout.frame_size);
}
+/* Remove the FPR clobbers from a tbegin insn if it can be proven that
+ the TX is nonescaping. A transaction is considered escaping if
+ there is at least one path from tbegin returning CC0 to the
+ function exit block without an tend.
+
+ The check so far has some limitations:
+ - only single tbegin/tend BBs are supported
+ - the first cond jump after tbegin must separate the CC0 path from ~CC0
+ - when CC is copied to a GPR and the CC0 check is done with the GPR
+ this is not supported
+*/
+
+static void
+s390_optimize_nonescaping_tx (void)
+{
+ const unsigned int CC0 = 1 << 3;
+ basic_block tbegin_bb = NULL;
+ basic_block tend_bb = NULL;
+ basic_block bb;
+ rtx insn;
+ bool result = true;
+ int bb_index;
+ rtx tbegin_insn = NULL_RTX;
+
+ if (!cfun->machine->tbegin_p)
+ return;
+
+ for (bb_index = 0; bb_index < n_basic_blocks; bb_index++)
+ {
+ bb = BASIC_BLOCK (bb_index);
+
+ if (!bb)
+ continue;
+
+ FOR_BB_INSNS (bb, insn)
+ {
+ rtx ite, cc, pat, target;
+ unsigned HOST_WIDE_INT mask;
+
+ if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
+ continue;
+
+ pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+
+ if (GET_CODE (pat) != SET
+ || GET_CODE (SET_SRC (pat)) != UNSPEC_VOLATILE)
+ continue;
+
+ if (XINT (SET_SRC (pat), 1) == UNSPECV_TBEGIN)
+ {
+ rtx tmp;
+
+ tbegin_insn = insn;
+
+ /* Just return if the tbegin doesn't have clobbers. */
+ if (GET_CODE (PATTERN (insn)) != PARALLEL)
+ return;
+
+ if (tbegin_bb != NULL)
+ return;
+
+ /* Find the next conditional jump. */
+ for (tmp = NEXT_INSN (insn);
+ tmp != NULL_RTX;
+ tmp = NEXT_INSN (tmp))
+ {
+ if (reg_set_p (gen_rtx_REG (CCmode, CC_REGNUM), tmp))
+ return;
+ if (!JUMP_P (tmp))
+ continue;
+
+ ite = SET_SRC (PATTERN (tmp));
+ if (GET_CODE (ite) != IF_THEN_ELSE)
+ continue;
+
+ cc = XEXP (XEXP (ite, 0), 0);
+ if (!REG_P (cc) || !CC_REGNO_P (REGNO (cc))
+ || GET_MODE (cc) != CCRAWmode
+ || GET_CODE (XEXP (XEXP (ite, 0), 1)) != CONST_INT)
+ return;
+
+ if (bb->succs->length () != 2)
+ return;
+
+ mask = INTVAL (XEXP (XEXP (ite, 0), 1));
+ if (GET_CODE (XEXP (ite, 0)) == NE)
+ mask ^= 0xf;
+
+ if (mask == CC0)
+ target = XEXP (ite, 1);
+ else if (mask == (CC0 ^ 0xf))
+ target = XEXP (ite, 2);
+ else
+ return;
+
+ {
+ edge_iterator ei;
+ edge e1, e2;
+
+ ei = ei_start (bb->succs);
+ e1 = ei_safe_edge (ei);
+ ei_next (&ei);
+ e2 = ei_safe_edge (ei);
+
+ if (e2->flags & EDGE_FALLTHRU)
+ {
+ e2 = e1;
+ e1 = ei_safe_edge (ei);
+ }
+
+ if (!(e1->flags & EDGE_FALLTHRU))
+ return;
+
+ tbegin_bb = (target == pc_rtx) ? e1->dest : e2->dest;
+ }
+ if (tmp == BB_END (bb))
+ break;
+ }
+ }
+
+ if (XINT (SET_SRC (pat), 1) == UNSPECV_TEND)
+ {
+ if (tend_bb != NULL)
+ return;
+ tend_bb = bb;
+ }
+ }
+ }
+
+ /* Either we successfully remove the FPR clobbers here or we are not
+ able to do anything for this TX. Both cases don't qualify for
+ another look. */
+ cfun->machine->tbegin_p = false;
+
+ if (tbegin_bb == NULL || tend_bb == NULL)
+ return;
+
+ calculate_dominance_info (CDI_POST_DOMINATORS);
+ result = dominated_by_p (CDI_POST_DOMINATORS, tbegin_bb, tend_bb);
+ free_dominance_info (CDI_POST_DOMINATORS);
+
+ if (!result)
+ return;
+
+ PATTERN (tbegin_insn) = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ XVECEXP (PATTERN (tbegin_insn), 0, 0),
+ XVECEXP (PATTERN (tbegin_insn), 0, 1)));
+ INSN_CODE (tbegin_insn) = -1;
+ df_insn_rescan (tbegin_insn);
+
+ return;
+}
+
/* Update frame layout. Recompute actual register save data based on
current info and update regs_ever_live for the special registers.
May be called multiple times, but may never cause *more* registers
@@ -7774,7 +8183,7 @@ s390_init_frame_layout (void)
static void
s390_update_frame_layout (void)
{
- int clobbered_regs[16];
+ int clobbered_regs[32];
s390_register_info (clobbered_regs);
@@ -8204,8 +8613,10 @@ s390_emit_prologue (void)
int offset;
int next_fpr = 0;
- /* Complete frame layout. */
+ /* Try to get rid of the FPR clobbers. */
+ s390_optimize_nonescaping_tx ();
+ /* Complete frame layout. */
s390_update_frame_layout ();
/* Annotate all constant pool references to let the scheduler know
@@ -9353,6 +9764,275 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
return build_va_arg_indirect_ref (addr);
}
+/* Emit rtl for the tbegin or tbegin_retry (RETRY != NULL_RTX)
+ expanders.
+ DEST - Register location where CC will be stored.
+ TDB - Pointer to a 256 byte area where to store the transaction.
+ diagnostic block. NULL if TDB is not needed.
+ RETRY - Retry count value. If non-NULL a retry loop for CC2
+ is emitted
+ CLOBBER_FPRS_P - If true clobbers for all FPRs are emitted as part
+ of the tbegin instruction pattern. */
+
+void
+s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
+{
+ rtx retry_plus_two = gen_reg_rtx (SImode);
+ rtx retry_reg = gen_reg_rtx (SImode);
+ rtx retry_label = NULL_RTX;
+
+ if (retry != NULL_RTX)
+ {
+ emit_move_insn (retry_reg, retry);
+ emit_insn (gen_addsi3 (retry_plus_two, retry_reg, const2_rtx));
+ emit_insn (gen_addsi3 (retry_reg, retry_reg, const1_rtx));
+ retry_label = gen_label_rtx ();
+ emit_label (retry_label);
+ }
+
+ if (clobber_fprs_p)
+ emit_insn (gen_tbegin_1 (gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK), tdb));
+ else
+ emit_insn (gen_tbegin_nofloat_1 (gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK),
+ tdb));
+
+ emit_move_insn (dest, gen_rtx_UNSPEC (SImode,
+ gen_rtvec (1, gen_rtx_REG (CCRAWmode,
+ CC_REGNUM)),
+ UNSPEC_CC_TO_INT));
+ if (retry != NULL_RTX)
+ {
+ const int CC0 = 1 << 3;
+ const int CC1 = 1 << 2;
+ const int CC3 = 1 << 0;
+ rtx jump;
+ rtx count = gen_reg_rtx (SImode);
+ rtx leave_label = gen_label_rtx ();
+
+ /* Exit for success and permanent failures. */
+ jump = s390_emit_jump (leave_label,
+ gen_rtx_EQ (VOIDmode,
+ gen_rtx_REG (CCRAWmode, CC_REGNUM),
+ gen_rtx_CONST_INT (VOIDmode, CC0 | CC1 | CC3)));
+ LABEL_NUSES (leave_label) = 1;
+
+ /* CC2 - transient failure. Perform retry with ppa. */
+ emit_move_insn (count, retry_plus_two);
+ emit_insn (gen_subsi3 (count, count, retry_reg));
+ emit_insn (gen_tx_assist (count));
+ jump = emit_jump_insn (gen_doloop_si64 (retry_label,
+ retry_reg,
+ retry_reg));
+ JUMP_LABEL (jump) = retry_label;
+ LABEL_NUSES (retry_label) = 1;
+ emit_label (leave_label);
+ }
+}
+
+/* Builtins. */
+
+enum s390_builtin
+{
+ S390_BUILTIN_TBEGIN,
+ S390_BUILTIN_TBEGIN_NOFLOAT,
+ S390_BUILTIN_TBEGIN_RETRY,
+ S390_BUILTIN_TBEGIN_RETRY_NOFLOAT,
+ S390_BUILTIN_TBEGINC,
+ S390_BUILTIN_TEND,
+ S390_BUILTIN_TABORT,
+ S390_BUILTIN_NON_TX_STORE,
+ S390_BUILTIN_TX_NESTING_DEPTH,
+ S390_BUILTIN_TX_ASSIST,
+
+ S390_BUILTIN_max
+};
+
+static enum insn_code const code_for_builtin[S390_BUILTIN_max] = {
+ CODE_FOR_tbegin,
+ CODE_FOR_tbegin_nofloat,
+ CODE_FOR_tbegin_retry,
+ CODE_FOR_tbegin_retry_nofloat,
+ CODE_FOR_tbeginc,
+ CODE_FOR_tend,
+ CODE_FOR_tabort,
+ CODE_FOR_ntstg,
+ CODE_FOR_etnd,
+ CODE_FOR_tx_assist
+};
+
+static void
+s390_init_builtins (void)
+{
+ tree ftype, uint64_type;
+ tree returns_twice_attr = tree_cons (get_identifier ("returns_twice"),
+ NULL, NULL);
+ tree noreturn_attr = tree_cons (get_identifier ("noreturn"), NULL, NULL);
+
+ /* void foo (void) */
+ ftype = build_function_type_list (void_type_node, NULL_TREE);
+ add_builtin_function ("__builtin_tbeginc", ftype, S390_BUILTIN_TBEGINC,
+ BUILT_IN_MD, NULL, NULL_TREE);
+
+ /* void foo (int) */
+ ftype = build_function_type_list (void_type_node, integer_type_node,
+ NULL_TREE);
+ add_builtin_function ("__builtin_tabort", ftype,
+ S390_BUILTIN_TABORT, BUILT_IN_MD, NULL, noreturn_attr);
+ add_builtin_function ("__builtin_tx_assist", ftype,
+ S390_BUILTIN_TX_ASSIST, BUILT_IN_MD, NULL, NULL_TREE);
+
+ /* int foo (void *) */
+ ftype = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE);
+ add_builtin_function ("__builtin_tbegin", ftype, S390_BUILTIN_TBEGIN,
+ BUILT_IN_MD, NULL, returns_twice_attr);
+ add_builtin_function ("__builtin_tbegin_nofloat", ftype,
+ S390_BUILTIN_TBEGIN_NOFLOAT,
+ BUILT_IN_MD, NULL, returns_twice_attr);
+
+ /* int foo (void *, int) */
+ ftype = build_function_type_list (integer_type_node, ptr_type_node,
+ integer_type_node, NULL_TREE);
+ add_builtin_function ("__builtin_tbegin_retry", ftype,
+ S390_BUILTIN_TBEGIN_RETRY,
+ BUILT_IN_MD,
+ NULL, returns_twice_attr);
+ add_builtin_function ("__builtin_tbegin_retry_nofloat", ftype,
+ S390_BUILTIN_TBEGIN_RETRY_NOFLOAT,
+ BUILT_IN_MD,
+ NULL, returns_twice_attr);
+
+ /* int foo (void) */
+ ftype = build_function_type_list (integer_type_node, NULL_TREE);
+ add_builtin_function ("__builtin_tx_nesting_depth", ftype,
+ S390_BUILTIN_TX_NESTING_DEPTH,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_tend", ftype,
+ S390_BUILTIN_TEND, BUILT_IN_MD, NULL, NULL_TREE);
+
+ /* void foo (uint64_t *, uint64_t) */
+ if (TARGET_64BIT)
+ uint64_type = long_unsigned_type_node;
+ else
+ uint64_type = long_long_unsigned_type_node;
+
+ ftype = build_function_type_list (void_type_node,
+ build_pointer_type (uint64_type),
+ uint64_type, NULL_TREE);
+ add_builtin_function ("__builtin_non_tx_store", ftype,
+ S390_BUILTIN_NON_TX_STORE,
+ BUILT_IN_MD, NULL, NULL_TREE);
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+#define MAX_ARGS 2
+
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ enum insn_code icode;
+ rtx op[MAX_ARGS], pat;
+ int arity;
+ bool nonvoid;
+ tree arg;
+ call_expr_arg_iterator iter;
+
+ if (fcode >= S390_BUILTIN_max)
+ internal_error ("bad builtin fcode");
+ icode = code_for_builtin[fcode];
+ if (icode == 0)
+ internal_error ("bad builtin fcode");
+
+ if (!TARGET_HTM)
+ error ("Transactional execution builtins not enabled (-mhtm)\n");
+
+ /* Set a flag in the machine specific cfun part in order to support
+ saving/restoring of FPRs. */
+ if (fcode == S390_BUILTIN_TBEGIN || fcode == S390_BUILTIN_TBEGIN_RETRY)
+ cfun->machine->tbegin_p = true;
+
+ nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
+
+ arity = 0;
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ {
+ const struct insn_operand_data *insn_op;
+
+ if (arg == error_mark_node)
+ return NULL_RTX;
+ if (arity >= MAX_ARGS)
+ return NULL_RTX;
+
+ insn_op = &insn_data[icode].operand[arity + nonvoid];
+
+ op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
+
+ if (!(*insn_op->predicate) (op[arity], insn_op->mode))
+ {
+ if (insn_op->predicate == memory_operand)
+ {
+ /* Don't move a NULL pointer into a register. Otherwise
+ we have to rely on combine being able to move it back
+ in order to get an immediate 0 in the instruction. */
+ if (op[arity] != const0_rtx)
+ op[arity] = copy_to_mode_reg (Pmode, op[arity]);
+ op[arity] = gen_rtx_MEM (insn_op->mode, op[arity]);
+ }
+ else
+ op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
+ }
+
+ arity++;
+ }
+
+ if (nonvoid)
+ {
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ if (!target
+ || GET_MODE (target) != tmode
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+ }
+
+ switch (arity)
+ {
+ case 0:
+ pat = GEN_FCN (icode) (target);
+ break;
+ case 1:
+ if (nonvoid)
+ pat = GEN_FCN (icode) (target, op[0]);
+ else
+ pat = GEN_FCN (icode) (op[0]);
+ break;
+ case 2:
+ if (nonvoid)
+ pat = GEN_FCN (icode) (target, op[0], op[1]);
+ else
+ pat = GEN_FCN (icode) (op[0], op[1]);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (!pat)
+ return NULL_RTX;
+ emit_insn (pat);
+
+ if (nonvoid)
+ return target;
+ else
+ return const0_rtx;
+}
+
+
/* Output assembly code for the trampoline template to
stdio stream FILE.
@@ -11008,6 +11688,11 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS s390_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN s390_expand_builtin
+
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA s390_output_addr_const_extra
@@ -11130,6 +11815,12 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE s390_attribute_table
+
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P s390_can_inline_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index bd0bc232a5d..a937c30d2e2 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -34,7 +34,8 @@ enum processor_flags
PF_DFP = 16,
PF_Z10 = 32,
PF_Z196 = 64,
- PF_ZEC12 = 128
+ PF_ZEC12 = 128,
+ PF_TX = 256
};
/* This is necessary to avoid a warning about comparing different enum
@@ -61,6 +62,8 @@ enum processor_flags
(s390_arch_flags & PF_Z196)
#define TARGET_CPU_ZEC12 \
(s390_arch_flags & PF_ZEC12)
+#define TARGET_CPU_HTM \
+ (s390_arch_flags & PF_TX)
/* These flags indicate that the generated code should run on a cpu
providing the respective hardware facility when run in
@@ -78,6 +81,7 @@ enum processor_flags
(TARGET_ZARCH && TARGET_CPU_Z196)
#define TARGET_ZEC12 \
(TARGET_ZARCH && TARGET_CPU_ZEC12)
+#define TARGET_HTM (TARGET_OPT_HTM)
#define TARGET_AVOID_CMP_AND_BRANCH (s390_tune == PROCESSOR_2817_Z196)
@@ -93,23 +97,25 @@ enum processor_flags
#define TARGET_TPF 0
/* Target CPU builtins. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_assert ("cpu=s390"); \
- builtin_assert ("machine=s390"); \
- builtin_define ("__s390__"); \
- if (TARGET_ZARCH) \
- builtin_define ("__zarch__"); \
- if (TARGET_64BIT) \
- builtin_define ("__s390x__"); \
- if (TARGET_LONG_DOUBLE_128) \
- builtin_define ("__LONG_DOUBLE_128__"); \
- } \
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_assert ("cpu=s390"); \
+ builtin_assert ("machine=s390"); \
+ builtin_define ("__s390__"); \
+ if (TARGET_ZARCH) \
+ builtin_define ("__zarch__"); \
+ if (TARGET_64BIT) \
+ builtin_define ("__s390x__"); \
+ if (TARGET_LONG_DOUBLE_128) \
+ builtin_define ("__LONG_DOUBLE_128__"); \
+ if (TARGET_HTM) \
+ builtin_define ("__HTM__"); \
+ } \
while (0)
#ifdef DEFAULT_TARGET_64BIT
-#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP)
+#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP | MASK_OPT_HTM)
#else
#define TARGET_DEFAULT 0
#endif
@@ -164,6 +170,11 @@ enum processor_flags
#define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
| S390_TDC_NEGATIVE_INFINITY )
+/* This is used by float.h to define the float_t and double_t data
+ types. For historical reasons both are double on s390 what cannot
+ be changed anymore. */
+#define TARGET_FLT_EVAL_METHOD 1
+
/* Target machine storage layout. */
/* Everything is big-endian. */
@@ -206,7 +217,7 @@ enum processor_flags
#define STACK_BOUNDARY 64
/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 32
+#define FUNCTION_BOUNDARY 64
/* There is no point aligning anything to a rounder boundary than this. */
#define BIGGEST_ALIGNMENT 64
@@ -867,6 +878,9 @@ do { \
fputc ('\n', (FILE)); \
} while (0)
+#undef ASM_OUTPUT_FUNCTION_LABEL
+#define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \
+ s390_asm_output_function_label (FILE, NAME, DECL)
/* Miscellaneous parameters. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index cad4f5f579a..fab189843c8 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -59,11 +59,17 @@
(define_c_enum "unspec" [
; Miscellaneous
UNSPEC_ROUND
- UNSPEC_CCU_TO_INT
- UNSPEC_CCZ_TO_INT
UNSPEC_ICM
UNSPEC_TIE
+ ; Convert CC into a str comparison result and copy it into an
+ ; integer register
+ ; cc0->0, cc1->1, cc2->-1, (cc3->-1)
+ UNSPEC_STRCMPCC_TO_INT
+
+ ; Copy CC as is into the lower 2 bits of an integer register
+ UNSPEC_CC_TO_INT
+
; GOT/PLT and lt-relative accesses
UNSPEC_LTREL_OFFSET
UNSPEC_LTREL_BASE
@@ -138,6 +144,16 @@
; Atomic Support
UNSPECV_CAS
UNSPECV_ATOMIC_OP
+
+ ; Transactional Execution support
+ UNSPECV_TBEGIN
+ UNSPECV_TBEGIN_TDB
+ UNSPECV_TBEGINC
+ UNSPECV_TEND
+ UNSPECV_TABORT
+ UNSPECV_ETND
+ UNSPECV_NTSTG
+ UNSPECV_PPA
])
;;
@@ -191,6 +207,9 @@
(PFPO_OP1_TYPE_SHIFT 8)
])
+; Immediate operands for tbegin and tbeginc
+(define_constants [(TBEGIN_MASK 65292)]) ; 0xff0c
+(define_constants [(TBEGINC_MASK 65288)]) ; 0xff08
;; Instruction operand type as used in the Principles of Operation.
;; Used to determine defaults for length and other attribute values.
@@ -2246,19 +2265,19 @@
(define_insn "movcc"
[(set (match_operand:CC 0 "nonimmediate_operand" "=d,c,d,d,d,R,T")
- (match_operand:CC 1 "nonimmediate_operand" "d,d,c,R,T,d,d"))]
+ (match_operand:CC 1 "nonimmediate_operand" " d,d,c,R,T,d,d"))]
""
"@
lr\t%0,%1
tmh\t%1,12288
ipm\t%0
- st\t%0,%1
- sty\t%0,%1
- l\t%1,%0
- ly\t%1,%0"
+ l\t%0,%1
+ ly\t%0,%1
+ st\t%1,%0
+ sty\t%1,%0"
[(set_attr "op_type" "RR,RI,RRE,RX,RXY,RX,RXY")
- (set_attr "type" "lr,*,*,store,store,load,load")
- (set_attr "z10prop" "z10_fr_E1,z10_super,*,z10_rec,z10_rec,z10_fwd_A3,z10_fwd_A3")
+ (set_attr "type" "lr,*,*,load,load,store,store")
+ (set_attr "z10prop" "z10_fr_E1,z10_super,*,z10_fwd_A3,z10_fwd_A3,z10_rec,z10_rec")
(set_attr "z196prop" "*,*,z196_ends,*,*,*,*")])
;
@@ -2578,7 +2597,7 @@
(use (reg:SI 0))])
(parallel
[(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CCU_TO_INT))
+ (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_STRCMPCC_TO_INT))
(clobber (reg:CC CC_REGNUM))])]
""
{
@@ -2820,7 +2839,7 @@
(match_dup 2)]
UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
+ (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HARD_FLOAT"
{
operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
@@ -2832,12 +2851,21 @@
(match_dup 2)]
UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
+ (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HARD_FLOAT"
{
operands[2] = GEN_INT (S390_TDC_INFINITY);
})
+(define_insn_and_split "*cc_to_int"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand 1 "register_operand" "0")]
+ UNSPEC_CC_TO_INT))]
+ "operands != NULL"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
+
; This insn is used to generate all variants of the Test Data Class
; instruction, namely tcxb, tcdb, and tceb. The insn's first operand
; is the register to be tested and the second one is the bit mask
@@ -2853,14 +2881,6 @@
[(set_attr "op_type" "RXE")
(set_attr "type" "fsimp<mode>")])
-(define_insn_and_split "*ccz_to_int"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:CCZ 1 "register_operand" "0")]
- UNSPEC_CCZ_TO_INT))]
- ""
- "#"
- "reload_completed"
- [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
;
@@ -3205,7 +3225,7 @@
(define_insn_and_split "cmpint"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT))
+ UNSPEC_STRCMPCC_TO_INT))
(clobber (reg:CC CC_REGNUM))]
""
"#"
@@ -3218,10 +3238,10 @@
(define_insn_and_split "*cmpint_cc"
[(set (reg CC_REGNUM)
(compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT)
+ UNSPEC_STRCMPCC_TO_INT)
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT))]
+ (unspec:SI [(match_dup 1)] UNSPEC_STRCMPCC_TO_INT))]
"s390_match_ccmode (insn, CCSmode)"
"#"
"&& reload_completed"
@@ -3238,7 +3258,7 @@
(define_insn_and_split "*cmpint_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT)))
+ UNSPEC_STRCMPCC_TO_INT)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ZARCH"
"#"
@@ -3252,11 +3272,11 @@
[(set (reg CC_REGNUM)
(compare (ashiftrt:DI (ashift:DI (subreg:DI
(unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT) 0)
+ UNSPEC_STRCMPCC_TO_INT) 0)
(const_int 32)) (const_int 32))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT)))]
+ (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_STRCMPCC_TO_INT)))]
"s390_match_ccmode (insn, CCSmode) && TARGET_ZARCH"
"#"
"&& reload_completed"
@@ -5507,7 +5527,7 @@
(if_then_else:GPR
(match_operator 1 "s390_comparison"
[(match_operand 2 "cc_reg_operand" " c,c, c, c, c, c, c")
- (const_int 0)])
+ (match_operand 5 "const_int_operand" "")])
(match_operand:GPR 3 "nonimmediate_operand" " d,0,QS, 0, d, 0,QS")
(match_operand:GPR 4 "nonimmediate_operand" " 0,d, 0,QS, 0, d,QS")))]
"TARGET_Z196"
@@ -7907,7 +7927,8 @@
(define_insn "*cjump_64"
[(set (pc)
(if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM)
+ (match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_CPU_ZARCH"
@@ -7926,7 +7947,8 @@
(define_insn "*cjump_31"
[(set (pc)
(if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM)
+ (match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_CPU_ZARCH"
@@ -9795,3 +9817,216 @@
"cpsdr\t%0,%2,%1"
[(set_attr "op_type" "RRF")
(set_attr "type" "fsimp<mode>")])
+
+
+;;
+;;- Transactional execution instructions
+;;
+
+; This splitter helps combine to make use of CC directly when
+; comparing the integer result of a tbegin builtin with a constant.
+; The unspec is already removed by canonicalize_comparison. So this
+; splitters only job is to turn the PARALLEL into separate insns
+; again. Unfortunately this only works with the very first cc/int
+; compare since combine is not able to deal with data flow across
+; basic block boundaries.
+
+; It needs to be an insn pattern as well since combine does not apply
+; the splitter directly. Combine would only use it if it actually
+; would reduce the number of instructions.
+(define_insn_and_split "*ccraw_to_int"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "s390_eqne_operator"
+ [(reg:CCRAW CC_REGNUM)
+ (match_operand 1 "const_int_operand" "")])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 3)
+ (unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))
+ (set (pc)
+ (if_then_else (match_op_dup 0 [(reg:CCRAW CC_REGNUM) (match_dup 1)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "")
+
+; Non-constrained transaction begin
+
+(define_expand "tbegin"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")]
+ "TARGET_HTM"
+{
+ s390_expand_tbegin (operands[0], operands[1], NULL_RTX, true);
+ DONE;
+})
+
+(define_expand "tbegin_nofloat"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")]
+ "TARGET_HTM"
+{
+ s390_expand_tbegin (operands[0], operands[1], NULL_RTX, false);
+ DONE;
+})
+
+(define_expand "tbegin_retry"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:SI 2 "general_operand" "")]
+ "TARGET_HTM"
+{
+ s390_expand_tbegin (operands[0], operands[1], operands[2], true);
+ DONE;
+})
+
+(define_expand "tbegin_retry_nofloat"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:SI 2 "general_operand" "")]
+ "TARGET_HTM"
+{
+ s390_expand_tbegin (operands[0], operands[1], operands[2], false);
+ DONE;
+})
+
+(define_insn "tbegin_1"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" "D")]
+ UNSPECV_TBEGIN))
+ (set (match_operand:BLK 1 "memory_operand" "=Q")
+ (unspec_volatile:BLK [(match_dup 0)] UNSPECV_TBEGIN_TDB))
+ (clobber (reg:DF 16))
+ (clobber (reg:DF 17))
+ (clobber (reg:DF 18))
+ (clobber (reg:DF 19))
+ (clobber (reg:DF 20))
+ (clobber (reg:DF 21))
+ (clobber (reg:DF 22))
+ (clobber (reg:DF 23))
+ (clobber (reg:DF 24))
+ (clobber (reg:DF 25))
+ (clobber (reg:DF 26))
+ (clobber (reg:DF 27))
+ (clobber (reg:DF 28))
+ (clobber (reg:DF 29))
+ (clobber (reg:DF 30))
+ (clobber (reg:DF 31))]
+; CONST_OK_FOR_CONSTRAINT_P does not work with D constraint since D is
+; not supposed to be used for immediates (see genpreds.c).
+ "TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff"
+ "tbegin\t%1,%x0"
+ [(set_attr "op_type" "SIL")])
+
+; Same as above but without the FPR clobbers
+(define_insn "tbegin_nofloat_1"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" "D")]
+ UNSPECV_TBEGIN))
+ (set (match_operand:BLK 1 "memory_operand" "=Q")
+ (unspec_volatile:BLK [(match_dup 0)] UNSPECV_TBEGIN_TDB))]
+ "TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff"
+ "tbegin\t%1,%x0"
+ [(set_attr "op_type" "SIL")])
+
+
+; Constrained transaction begin
+
+(define_expand "tbeginc"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(const_int TBEGINC_MASK)]
+ UNSPECV_TBEGINC))]
+ "TARGET_HTM"
+ "")
+
+(define_insn "*tbeginc_1"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" " D")]
+ UNSPECV_TBEGINC))]
+ "TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff"
+ "tbeginc\t0,%x0"
+ [(set_attr "op_type" "SIL")])
+
+; Transaction end
+
+(define_expand "tend"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(const_int 0)] UNSPECV_TEND))
+ (set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
+ "TARGET_HTM"
+ "")
+
+(define_insn "*tend_1"
+ [(set (reg:CCRAW CC_REGNUM)
+ (unspec_volatile:CCRAW [(const_int 0)] UNSPECV_TEND))]
+ "TARGET_HTM"
+ "tend"
+ [(set_attr "op_type" "S")])
+
+; Transaction abort
+
+(define_expand "tabort"
+ [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "")]
+ UNSPECV_TABORT)]
+ "TARGET_HTM && operands != NULL"
+{
+ if (CONST_INT_P (operands[0])
+ && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 255)
+ {
+ error ("Invalid transaction abort code: " HOST_WIDE_INT_PRINT_DEC
+ ". Values in range 0 through 255 are reserved.",
+ INTVAL (operands[0]));
+ FAIL;
+ }
+})
+
+(define_insn "*tabort_1"
+ [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "Y")]
+ UNSPECV_TABORT)]
+ "TARGET_HTM && operands != NULL"
+ "tabort\t%Y0"
+ [(set_attr "op_type" "S")])
+
+; Transaction extract nesting depth
+
+(define_insn "etnd"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_ETND))]
+ "TARGET_HTM"
+ "etnd\t%0"
+ [(set_attr "op_type" "RRE")])
+
+; Non-transactional store
+
+(define_insn "ntstg"
+ [(set (match_operand:DI 0 "memory_operand" "=RT")
+ (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "d")]
+ UNSPECV_NTSTG))]
+ "TARGET_HTM"
+ "ntstg\t%1,%0"
+ [(set_attr "op_type" "RXY")])
+
+; Transaction perform processor assist
+
+(define_expand "tx_assist"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "")
+ (reg:SI GPR0_REGNUM)
+ (const_int 1)]
+ UNSPECV_PPA)]
+ "TARGET_HTM"
+ "")
+
+(define_insn "*ppa"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "register_operand" "d")
+ (match_operand 2 "const_int_operand" "I")]
+ UNSPECV_PPA)]
+ "TARGET_HTM && INTVAL (operands[2]) < 16"
+ "ppa\t%0,%1,%2"
+ [(set_attr "op_type" "RRF")])
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index b326441173c..65d17c3342e 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -96,6 +96,14 @@ mhard-float
Target Report RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT)
Enable hardware floating point
+mhotpatch
+Target Report Var(s390_deferred_options) Defer
+Prepend the function label with 12 two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching.
+
+mhotpatch=
+Target RejectNegative Report Joined Var(s390_deferred_options) Defer
+Prepend the function label with the given number of two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching.
+
mlong-double-128
Target Report RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128)
Use 128-bit long double
@@ -104,6 +112,10 @@ mlong-double-64
Target Report RejectNegative Negative(mlong-double-128) InverseMask(LONG_DOUBLE_128)
Use 64-bit long double
+mhtm
+Target Report Mask(OPT_HTM)
+Use hardware transactional execution instructions
+
mpacked-stack
Target Report Mask(PACKED_STACK)
Use packed stack layout
diff --git a/gcc/config/s390/s390intrin.h b/gcc/config/s390/s390intrin.h
new file mode 100644
index 00000000000..e1a00ce58e3
--- /dev/null
+++ b/gcc/config/s390/s390intrin.h
@@ -0,0 +1,33 @@
+/* S/390 System z specific intrinsics
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _S390INTRIN_H
+#define _S390INTRIN_H
+
+#ifndef __s390__
+ #error s390intrin.h included on wrong platform/compiler
+#endif
+
+#ifdef __HTM__
+#include <htmintrin.h>
+#endif
+
+
+#endif /* _S390INTRIN_H*/
diff --git a/gcc/config/sh/constraints.md b/gcc/config/sh/constraints.md
index 59bf6b5addf..df7823764e5 100644
--- a/gcc/config/sh/constraints.md
+++ b/gcc/config/sh/constraints.md
@@ -221,6 +221,7 @@
(define_constraint "Q"
"A pc relative load operand."
(and (match_code "mem")
+ (match_test "GET_MODE (op) != QImode")
(match_test "IS_PC_RELATIVE_LOAD_ADDR_P (XEXP (op, 0))")))
(define_constraint "Bsc"
@@ -295,13 +296,15 @@
(define_memory_constraint "Sdd"
"A memory reference that uses displacement addressing."
- (and (match_test "MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS")
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == PLUS")
(match_test "REG_P (XEXP (XEXP (op, 0), 0))")
(match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))")))
(define_memory_constraint "Snd"
"A memory reference that excludes displacement addressing."
- (match_test "! satisfies_constraint_Sdd (op)"))
+ (and (match_code "mem")
+ (match_test "! satisfies_constraint_Sdd (op)")))
(define_memory_constraint "Sbv"
"A memory reference, as used in SH2A bclr.b, bset.b, etc."
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index dcbd75bb890..b1905fa0d34 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -389,6 +389,12 @@
XEXP (XEXP (op, 0), 1),
TARGET_SH2A, true)")))
+;; Returns true if OP is a displacement address that can fit into a
+;; 16 bit (non-SH2A) memory load / store insn.
+(define_predicate "short_displacement_mem_operand"
+ (match_test "sh_disp_addr_displacement (op)
+ <= sh_max_mov_insn_displacement (GET_MODE (op), false)"))
+
;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn.
(define_predicate "zero_extend_movu_operand"
(and (match_operand 0 "displacement_mem_operand")
@@ -413,6 +419,11 @@
if (t_reg_operand (op, mode))
return 0;
+ /* Disallow PC relative QImode loads, since these is no insn to do that
+ and an imm8 load should be used instead. */
+ if (IS_PC_RELATIVE_LOAD_ADDR_P (op) && GET_MODE (op) == QImode)
+ return false;
+
if (MEM_P (op))
{
rtx inside = XEXP (op, 0);
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 4671c5499cc..8f99caac0ce 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -159,6 +159,8 @@ extern bool sh_vector_mode_supported_p (enum machine_mode);
extern bool sh_cfun_trap_exit_p (void);
extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
extern int sh_eval_treg_value (rtx op);
+extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op);
+extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a);
/* Result value of sh_find_set_of_reg. */
struct set_of_reg
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 44e1e4ce30e..2819da80939 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -310,9 +310,7 @@ static rtx sh_trampoline_adjust_address (rtx);
static void sh_conditional_register_usage (void);
static bool sh_legitimate_constant_p (enum machine_mode, rtx);
static int mov_insn_size (enum machine_mode, bool);
-static int max_mov_insn_displacement (enum machine_mode, bool);
static int mov_insn_alignment_mask (enum machine_mode, bool);
-static HOST_WIDE_INT disp_addr_displacement (rtx);
static bool sequence_insn_p (rtx);
static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
@@ -3628,8 +3626,8 @@ mov_insn_size (enum machine_mode mode, bool consider_sh2a)
/* Determine the maximum possible displacement for a move insn for the
specified mode. */
-static int
-max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a)
+int
+sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a)
{
/* The 4 byte displacement move insns are the same as the 2 byte
versions but take a 12 bit displacement. All we need to do is to
@@ -3665,8 +3663,8 @@ mov_insn_alignment_mask (enum machine_mode mode, bool consider_sh2a)
}
/* Return the displacement value of a displacement address. */
-static inline HOST_WIDE_INT
-disp_addr_displacement (rtx x)
+HOST_WIDE_INT
+sh_disp_addr_displacement (rtx x)
{
gcc_assert (satisfies_constraint_Sdd (x));
return INTVAL (XEXP (XEXP (x, 0), 1));
@@ -3703,12 +3701,12 @@ sh_address_cost (rtx x, enum machine_mode mode,
HImode and QImode loads/stores with displacement put pressure on
R0 which will most likely require another reg copy. Thus account
a higher cost for that. */
- if (offset > 0 && offset <= max_mov_insn_displacement (mode, false))
+ if (offset > 0 && offset <= sh_max_mov_insn_displacement (mode, false))
return (mode == HImode || mode == QImode) ? 2 : 1;
/* The displacement would fit into a 4 byte move insn (SH2A). */
if (TARGET_SH2A
- && offset > 0 && offset <= max_mov_insn_displacement (mode, true))
+ && offset > 0 && offset <= sh_max_mov_insn_displacement (mode, true))
return 2;
/* The displacement is probably out of range and will require extra
@@ -10218,7 +10216,7 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op, bool consider_sh2a,
else
{
const HOST_WIDE_INT offset = INTVAL (op);
- const int max_disp = max_mov_insn_displacement (mode, consider_sh2a);
+ const int max_disp = sh_max_mov_insn_displacement (mode, consider_sh2a);
const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a);
/* If the mode does not support any displacement always return false.
@@ -10404,7 +10402,7 @@ sh_find_mov_disp_adjust (enum machine_mode mode, HOST_WIDE_INT offset)
effectively disable the small displacement insns. */
const int mode_sz = GET_MODE_SIZE (mode);
const int mov_insn_sz = mov_insn_size (mode, false);
- const int max_disp = max_mov_insn_displacement (mode, false);
+ const int max_disp = sh_max_mov_insn_displacement (mode, false);
const int max_disp_next = max_disp + mov_insn_sz;
HOST_WIDE_INT align_modifier = offset > 127 ? mov_insn_sz : 0;
HOST_WIDE_INT offset_adjust;
@@ -13165,7 +13163,8 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
the insns must have the appropriate alternatives. */
if ((mode == QImode || mode == HImode) && rclass != R0_REGS
&& satisfies_constraint_Sdd (x)
- && disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false))
+ && sh_disp_addr_displacement (x)
+ <= sh_max_mov_insn_displacement (mode, false))
return R0_REGS;
/* When reload is trying to address a QImode or HImode subreg on the stack,
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 9a3836ffa84..ef24ce9e36c 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -6831,30 +6831,9 @@ label:
prepare_move_operands (operands, QImode);
})
-;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be
-;; selected to copy QImode regs. If one of them happens to be allocated
-;; on the stack, reload will stick to movqi insn and generate wrong
-;; displacement addressing because of the generic m alternatives.
-;; With the movqi_reg_reg being specified before movqi it will be initially
-;; picked to load/store regs. If the regs regs are on the stack reload will
-;; try other insns and not stick to movqi_reg_reg.
-;; The same applies to the movhi variants.
-;;
-;; Notice, that T bit is not allowed as a mov src operand here. This is to
-;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which
-;; introduces zero extensions after T bit stores and redundant reg copies.
-;;
-;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a
-;; predicate for the mov src operand because reload will have trouble
-;; reloading MAC subregs otherwise. For that probably special patterns
-;; would be required.
-(define_insn "*mov<mode>_reg_reg"
- [(set (match_operand:QIHI 0 "arith_reg_dest" "=r")
- (match_operand:QIHI 1 "register_operand" "r"))]
- "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
- "mov %1,%0"
- [(set_attr "type" "move")])
-
+;; Specifying the displacement addressing load / store patterns separately
+;; before the generic movqi / movhi pattern allows controlling the order
+;; in which load / store insns are selected in a more fine grained way.
;; FIXME: The non-SH2A and SH2A variants should be combined by adding
;; "enabled" attribute as it is done in other targets.
(define_insn "*mov<mode>_store_mem_disp04"
@@ -6904,38 +6883,44 @@ label:
[(set_attr "type" "load")
(set_attr "length" "2,2,4")])
-;; The m constraints basically allow any kind of addresses to be used with any
-;; source/target register as the other operand. This is not true for
-;; displacement addressing modes on anything but SH2A. That's why the
-;; specialized load/store insns are specified above.
-(define_insn "*movqi"
- [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l")
- (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))]
+;; The order of the constraint alternatives is important here.
+;; Q/r has to come first, otherwise PC relative loads might wrongly get
+;; placed into delay slots. Since there is no QImode PC relative load, the
+;; Q constraint and general_movsrc_operand will reject it for QImode.
+;; The Snd alternatives should come before Sdd in order to avoid a preference
+;; of using r0 als the register operand for addressing modes other than
+;; displacement addressing.
+;; The Sdd alternatives allow only r0 as register operand, even though on
+;; SH2A any register could be allowed by switching to a 32 bit insn.
+;; Generally sticking to the r0 is preferrable, since it generates smaller
+;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A.
+(define_insn "*mov<mode>"
+ [(set (match_operand:QIHI 0 "general_movdst_operand"
+ "=r,r,r,Snd,r, Sdd,z, r,l")
+ (match_operand:QIHI 1 "general_movsrc_operand"
+ "Q,r,i,r, Snd,z, Sdd,l,r"))]
"TARGET_SH1
- && (arith_reg_operand (operands[0], QImode)
- || arith_reg_operand (operands[1], QImode))"
+ && (arith_reg_operand (operands[0], <MODE>mode)
+ || arith_reg_operand (operands[1], <MODE>mode))"
"@
+ mov.<bw> %1,%0
mov %1,%0
- mov.b %1,%0
- mov.b %1,%0
- sts %1,%0
- lds %1,%0"
- [(set_attr "type" "movi8,load,store,prget,prset")])
-
-(define_insn "*movhi"
- [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
- (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))]
- "TARGET_SH1
- && (arith_reg_operand (operands[0], HImode)
- || arith_reg_operand (operands[1], HImode))"
- "@
- mov.w %1,%0
mov %1,%0
- mov.w %1,%0
- mov.w %1,%0
+ mov.<bw> %1,%0
+ mov.<bw> %1,%0
+ mov.<bw> %1,%0
+ mov.<bw> %1,%0
sts %1,%0
lds %1,%0"
- [(set_attr "type" "pcload,movi8,load,store,prget,prset")])
+ [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset")
+ (set (attr "length")
+ (cond [(and (match_operand 0 "displacement_mem_operand")
+ (not (match_operand 0 "short_displacement_mem_operand")))
+ (const_int 4)
+ (and (match_operand 1 "displacement_mem_operand")
+ (not (match_operand 1 "short_displacement_mem_operand")))
+ (const_int 4)]
+ (const_int 2)))])
(define_insn "*movqi_media"
[(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
@@ -8423,11 +8408,9 @@ label:
while (true)
{
- /* It's not safe to go beyond the current basic block after reload. */
set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
- reload_completed
- ? prev_nonnote_insn_bb
- : prev_nonnote_insn);
+ prev_nonnote_insn);
+
if (s1.set_src == NULL_RTX)
break;
@@ -8445,15 +8428,25 @@ label:
continue;
}
- /* It's only safe to remove the testing insn if the T bit is not
- modified between the testing insn and the insn that stores the
- T bit. Notice that some T bit stores such as negc also modify
- the T bit. */
- if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
- || modified_in_p (get_t_reg_rtx (), s1.insn))
- operands[2] = NULL_RTX;
+ /* It's only safe to remove the testing insn if the T bit is not
+ modified between the testing insn and the insn that stores the
+ T bit. Notice that some T bit stores such as negc also modify
+ the T bit. */
+ if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
+ || modified_in_p (get_t_reg_rtx (), s1.insn)
+ || !no_labels_between_p (s1.insn, testing_insn))
+ operands[2] = NULL_RTX;
+ else
+ {
+ /* If the insn that sets the tested reg has a REG_DEAD note on
+ the T bit remove that note since we're extending the usage
+ of the T bit. */
+ rtx n = find_regno_note (s1.insn, REG_DEAD, T_REG);
+ if (n != NULL_RTX)
+ remove_note (s1.insn, n);
+ }
- break;
+ break;
}
if (operands[2] == NULL_RTX)
diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt
index c314e144c21..8a6788eb3d1 100644
--- a/gcc/config/sh/sh.opt
+++ b/gcc/config/sh/sh.opt
@@ -21,7 +21,7 @@
;; Used for various architecture options.
Mask(SH_E)
-;; Set if the default precision of th FPU is single.
+;; Set if the default precision of the FPU is single.
Mask(FPU_SINGLE)
;; Set if the a double-precision FPU is present but is restricted to
diff --git a/gcc/config/sparc/leon.md b/gcc/config/sparc/leon.md
index 60815079da6..b511397fe36 100644
--- a/gcc/config/sparc/leon.md
+++ b/gcc/config/sparc/leon.md
@@ -17,40 +17,48 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Leon is a single-issue processor.
(define_automaton "leon")
-(define_cpu_unit "leon_memory, leon_fpalu" "leon")
-(define_cpu_unit "leon_fpmds" "leon")
-(define_cpu_unit "write_buf" "leon")
+(define_cpu_unit "leon_memory" "leon")
(define_insn_reservation "leon_load" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "load,sload,fpload"))
+ (and (eq_attr "cpu" "leon") (eq_attr "type" "load,sload"))
"leon_memory")
-(define_insn_reservation "leon_store" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "store,fpstore"))
- "leon_memory+write_buf")
-
-(define_insn_reservation "leon_fp_alu" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fp,fpmove"))
- "leon_fpalu, nothing")
-
-(define_insn_reservation "leon_fp_mult" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpmul"))
- "leon_fpmds, nothing")
-
-(define_insn_reservation "leon_fp_div" 16
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpdivs,fpdivd"))
- "leon_fpmds, nothing*15")
-
-(define_insn_reservation "leon_fp_sqrt" 23
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpsqrts,fpsqrtd"))
- "leon_fpmds, nothing*21")
+;; Use a double reservation to work around the load pipeline hazard on UT699.
+(define_insn_reservation "leon3_load" 1
+ (and (eq_attr "cpu" "leon3") (eq_attr "type" "load,sload"))
+ "leon_memory*2")
+(define_insn_reservation "leon_store" 2
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "store"))
+ "leon_memory*2")
+
+;; This describes Gaisler Research's FPU
+
+(define_automaton "grfpu")
+
+(define_cpu_unit "grfpu_alu" "grfpu")
+(define_cpu_unit "grfpu_ds" "grfpu")
+
+(define_insn_reservation "leon_fp_alu" 4
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fp,fpcmp,fpmul"))
+ "grfpu_alu, nothing*3")
+
+(define_insn_reservation "leon_fp_divs" 16
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivs"))
+ "grfpu_ds*14, nothing*2")
+
+(define_insn_reservation "leon_fp_divd" 17
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivd"))
+ "grfpu_ds*15, nothing*2")
+
+(define_insn_reservation "leon_fp_sqrts" 24
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrts"))
+ "grfpu_ds*22, nothing*2")
+
+(define_insn_reservation "leon_fp_sqrtd" 25
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrtd"))
+ "grfpu_ds*23, nothing*2")
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
index 72791772eb2..b5e9761af2b 100644
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -30,6 +30,7 @@ enum processor_type {
PROCESSOR_SUPERSPARC,
PROCESSOR_HYPERSPARC,
PROCESSOR_LEON,
+ PROCESSOR_LEON3,
PROCESSOR_SPARCLITE,
PROCESSOR_F930,
PROCESSOR_F934,
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index fb01ae92a2a..c5bcb3ba8cf 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "df.h"
#include "opts.h"
+#include "tree-pass.h"
/* Processor costs */
@@ -226,6 +227,30 @@ struct processor_costs leon_costs = {
};
static const
+struct processor_costs leon3_costs = {
+ COSTS_N_INSNS (1), /* int load */
+ COSTS_N_INSNS (1), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (1), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (1), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (1), /* fmul */
+ COSTS_N_INSNS (14), /* fdivs */
+ COSTS_N_INSNS (15), /* fdivd */
+ COSTS_N_INSNS (22), /* fsqrts */
+ COSTS_N_INSNS (23), /* fsqrtd */
+ COSTS_N_INSNS (5), /* imul */
+ COSTS_N_INSNS (5), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (35), /* idiv */
+ COSTS_N_INSNS (35), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+static const
struct processor_costs sparclet_costs = {
COSTS_N_INSNS (3), /* int load */
COSTS_N_INSNS (3), /* int signed load */
@@ -538,7 +563,6 @@ static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
HOST_WIDE_INT, const_tree);
-static void sparc_reorg (void);
static struct machine_function * sparc_init_machine_status (void);
static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
static rtx sparc_tls_get_addr (void);
@@ -680,9 +704,6 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg
-
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -804,6 +825,206 @@ char sparc_hard_reg_printed[8];
struct gcc_target targetm = TARGET_INITIALIZER;
+/* Return the memory reference contained in X if any, zero otherwise. */
+
+static rtx
+mem_ref (rtx x)
+{
+ if (GET_CODE (x) == SIGN_EXTEND || GET_CODE (x) == ZERO_EXTEND)
+ x = XEXP (x, 0);
+
+ if (MEM_P (x))
+ return x;
+
+ return NULL_RTX;
+}
+
+/* We use a machine specific pass to enable workarounds for errata.
+ We need to have the (essentially) final form of the insn stream in order
+ to properly detect the various hazards. Therefore, this machine specific
+ pass runs as late as possible. The pass is inserted in the pass pipeline
+ at the end of sparc_option_override. */
+
+static bool
+sparc_gate_work_around_errata (void)
+{
+ /* The only errata we handle are those of the AT697F and UT699. */
+ return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
+}
+
+static unsigned int
+sparc_do_work_around_errata (void)
+{
+ rtx insn, next;
+
+ /* Force all instructions to be split into their final form. */
+ split_all_insns_noflow ();
+
+ /* Now look for specific patterns in the insn stream. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+ bool insert_nop = false;
+ rtx set;
+
+ /* Look into the instruction in a delay slot. */
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, 1);
+
+ /* Look for a single-word load into an odd-numbered FP register. */
+ if (sparc_fix_at697f
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+ && MEM_P (SET_SRC (set))
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) > 31
+ && REGNO (SET_DEST (set)) % 2 != 0)
+ {
+ /* The wrong dependency is on the enclosing double register. */
+ unsigned int x = REGNO (SET_DEST (set)) - 1;
+ unsigned int src1, src2, dest;
+ int code;
+
+ /* If the insn has a delay slot, then it cannot be problematic. */
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+ continue;
+
+ extract_insn (next);
+ code = INSN_CODE (next);
+
+ switch (code)
+ {
+ case CODE_FOR_adddf3:
+ case CODE_FOR_subdf3:
+ case CODE_FOR_muldf3:
+ case CODE_FOR_divdf3:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ src2 = REGNO (recog_data.operand[2]);
+ if (src1 != src2)
+ {
+ /* Case [1-4]:
+ ld [address], %fx+1
+ FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
+ if ((src1 == x || src2 == x)
+ && (dest == src1 || dest == src2))
+ insert_nop = true;
+ }
+ else
+ {
+ /* Case 5:
+ ld [address], %fx+1
+ FPOPd %fx, %fx, %fx */
+ if (src1 == x
+ && dest == src1
+ && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
+ insert_nop = true;
+ }
+ break;
+
+ case CODE_FOR_sqrtdf2:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ /* Case 6:
+ ld [address], %fx+1
+ fsqrtd %fx, %fx */
+ if (src1 == x && dest == src1)
+ insert_nop = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Look for a single-word load into an integer register. */
+ else if (sparc_fix_ut699
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4
+ && mem_ref (SET_SRC (set)) != NULL_RTX
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) < 32)
+ {
+ /* There is no problem if the second memory access has a data
+ dependency on the first single-cycle load. */
+ rtx x = SET_DEST (set);
+
+ /* If the insn has a delay slot, then it cannot be problematic. */
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+ continue;
+
+ /* Look for a second memory access to/from an integer register. */
+ if ((set = single_set (next)) != NULL_RTX)
+ {
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
+ rtx mem;
+
+ /* LDD is affected. */
+ if ((mem = mem_ref (src)) != NULL_RTX
+ && REG_P (dest)
+ && REGNO (dest) < 32
+ && !reg_mentioned_p (x, XEXP (mem, 0)))
+ insert_nop = true;
+
+ /* STD is *not* affected. */
+ else if ((mem = mem_ref (dest)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (mem)) <= 4
+ && (src == const0_rtx
+ || (REG_P (src)
+ && REGNO (src) < 32
+ && REGNO (src) != REGNO (x)))
+ && !reg_mentioned_p (x, XEXP (mem, 0)))
+ insert_nop = true;
+ }
+ }
+
+ else
+ next = NEXT_INSN (insn);
+
+ if (insert_nop)
+ emit_insn_before (gen_nop (), next);
+ }
+
+ return 0;
+}
+
+struct rtl_opt_pass pass_work_around_errata =
+{
+ {
+ RTL_PASS,
+ "errata", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ sparc_gate_work_around_errata, /* gate */
+ sparc_do_work_around_errata, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_MACH_DEP, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_rtl_sharing, /* todo_flags_finish */
+ }
+};
+
+struct register_pass_info insert_pass_work_around_errata =
+{
+ &pass_work_around_errata.pass, /* pass */
+ "dbr", /* reference_pass_name */
+ 1, /* ref_pass_instance_number */
+ PASS_POS_INSERT_AFTER /* po_op */
+};
+
+/* Helpers for TARGET_DEBUG_OPTIONS. */
static void
dump_target_flag_bits (const int flags)
{
@@ -888,6 +1109,7 @@ sparc_option_override (void)
{ TARGET_CPU_supersparc, PROCESSOR_SUPERSPARC },
{ TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC },
{ TARGET_CPU_leon, PROCESSOR_LEON },
+ { TARGET_CPU_leon3, PROCESSOR_LEON3 },
{ TARGET_CPU_sparclite, PROCESSOR_F930 },
{ TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X },
{ TARGET_CPU_sparclet, PROCESSOR_TSC701 },
@@ -902,7 +1124,7 @@ sparc_option_override (void)
};
const struct cpu_default *def;
/* Table of values for -m{cpu,tune}=. This must match the order of
- the PROCESSOR_* enumeration. */
+ the enum processor_type in sparc-opts.h. */
static struct cpu_table {
const char *const name;
const int disable;
@@ -914,8 +1136,8 @@ sparc_option_override (void)
/* TI TMS390Z55 supersparc */
{ "supersparc", MASK_ISA, MASK_V8 },
{ "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
- /* LEON */
- { "leon", MASK_ISA, MASK_V8|MASK_FPU },
+ { "leon", MASK_ISA, MASK_V8|MASK_LEON|MASK_FPU },
+ { "leon3", MASK_ISA, MASK_V8|MASK_LEON3|MASK_FPU },
{ "sparclite", MASK_ISA, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
{ "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
@@ -1075,6 +1297,9 @@ sparc_option_override (void)
#ifndef HAVE_AS_SPARC4
& ~MASK_CBCOND
#endif
+#ifndef HAVE_AS_LEON
+ & ~(MASK_LEON | MASK_LEON3)
+#endif
);
/* If -mfpu or -mno-fpu was explicitly used, don't override with
@@ -1164,6 +1389,9 @@ sparc_option_override (void)
case PROCESSOR_LEON:
sparc_costs = &leon_costs;
break;
+ case PROCESSOR_LEON3:
+ sparc_costs = &leon3_costs;
+ break;
case PROCESSOR_SPARCLET:
case PROCESSOR_TSC701:
sparc_costs = &sparclet_costs;
@@ -1200,6 +1428,10 @@ sparc_option_override (void)
/* Choose the most relaxed model for the processor. */
else if (TARGET_V9)
sparc_memory_model = SMM_RMO;
+ else if (TARGET_LEON3)
+ sparc_memory_model = SMM_TSO;
+ else if (TARGET_LEON)
+ sparc_memory_model = SMM_SC;
else if (TARGET_V8)
sparc_memory_model = SMM_PSO;
else
@@ -1241,6 +1473,13 @@ sparc_option_override (void)
pessimizes for double floating-point registers. */
if (!global_options_set.x_flag_ira_share_save_slots)
flag_ira_share_save_slots = 0;
+
+ /* We register a machine specific pass to work around errata, if any.
+ The pass mut be scheduled as late as possible so that we have the
+ (essentially) final form of the insn stream to work on.
+ Registering the pass must be done at start up. It's convenient to
+ do it here. */
+ register_pass (&insert_pass_work_around_errata);
}
/* Miscellaneous utilities. */
@@ -10355,7 +10594,8 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
tmp = e0.add_with_sign (tmp, false, &add1_ovf);
if (tmp.is_negative ())
tmp = tmp.neg_with_overflow (&neg2_ovf);
-
+ else
+ neg2_ovf = false;
result = result.add_with_sign (tmp, false, &add2_ovf);
overflow |= neg1_ovf | neg2_ovf | add1_ovf | add2_ovf;
}
@@ -10897,107 +11137,6 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
return (vcall_offset >= -32768 || ! fixed_regs[5]);
}
-/* We use the machine specific reorg pass to enable workarounds for errata. */
-
-static void
-sparc_reorg (void)
-{
- rtx insn, next;
-
- /* The only erratum we handle for now is that of the AT697F processor. */
- if (!sparc_fix_at697f)
- return;
-
- /* We need to have the (essentially) final form of the insn stream in order
- to properly detect the various hazards. Run delay slot scheduling. */
- if (optimize > 0 && flag_delayed_branch)
- {
- cleanup_barriers ();
- dbr_schedule (get_insns ());
- }
-
- /* Now look for specific patterns in the insn stream. */
- for (insn = get_insns (); insn; insn = next)
- {
- bool insert_nop = false;
- rtx set;
-
- /* Look for a single-word load into an odd-numbered FP register. */
- if (NONJUMP_INSN_P (insn)
- && (set = single_set (insn)) != NULL_RTX
- && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
- && MEM_P (SET_SRC (set))
- && REG_P (SET_DEST (set))
- && REGNO (SET_DEST (set)) > 31
- && REGNO (SET_DEST (set)) % 2 != 0)
- {
- /* The wrong dependency is on the enclosing double register. */
- unsigned int x = REGNO (SET_DEST (set)) - 1;
- unsigned int src1, src2, dest;
- int code;
-
- /* If the insn has a delay slot, then it cannot be problematic. */
- next = next_active_insn (insn);
- if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
- code = -1;
- else
- {
- extract_insn (next);
- code = INSN_CODE (next);
- }
-
- switch (code)
- {
- case CODE_FOR_adddf3:
- case CODE_FOR_subdf3:
- case CODE_FOR_muldf3:
- case CODE_FOR_divdf3:
- dest = REGNO (recog_data.operand[0]);
- src1 = REGNO (recog_data.operand[1]);
- src2 = REGNO (recog_data.operand[2]);
- if (src1 != src2)
- {
- /* Case [1-4]:
- ld [address], %fx+1
- FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
- if ((src1 == x || src2 == x)
- && (dest == src1 || dest == src2))
- insert_nop = true;
- }
- else
- {
- /* Case 5:
- ld [address], %fx+1
- FPOPd %fx, %fx, %fx */
- if (src1 == x
- && dest == src1
- && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
- insert_nop = true;
- }
- break;
-
- case CODE_FOR_sqrtdf2:
- dest = REGNO (recog_data.operand[0]);
- src1 = REGNO (recog_data.operand[1]);
- /* Case 6:
- ld [address], %fx+1
- fsqrtd %fx, %fx */
- if (src1 == x && dest == src1)
- insert_nop = true;
- break;
-
- default:
- break;
- }
- }
- else
- next = NEXT_INSN (insn);
-
- if (insert_nop)
- emit_insn_after (gen_nop (), insn);
- }
-}
-
/* How to allocate a 'struct machine_function'. */
static struct machine_function *
@@ -11174,6 +11313,11 @@ sparc_emit_membar_for_model (enum memmodel model,
/* Total Store Ordering: all memory transactions with store semantics
are followed by an implied StoreStore. */
implied |= StoreStore;
+
+ /* If we're not looking for a raw barrer (before+after), then atomic
+ operations get the benefit of being both load and store. */
+ if (load_store == 3 && before_after == 1)
+ implied |= StoreLoad;
/* FALLTHRU */
case SMM_PSO:
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index c6122c115cd..d96c1b6b422 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -136,21 +136,22 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CPU_supersparc 2
#define TARGET_CPU_hypersparc 3
#define TARGET_CPU_leon 4
-#define TARGET_CPU_sparclite 5
-#define TARGET_CPU_f930 5 /* alias */
-#define TARGET_CPU_f934 5 /* alias */
-#define TARGET_CPU_sparclite86x 6
-#define TARGET_CPU_sparclet 7
-#define TARGET_CPU_tsc701 7 /* alias */
-#define TARGET_CPU_v9 8 /* generic v9 implementation */
-#define TARGET_CPU_sparcv9 8 /* alias */
-#define TARGET_CPU_sparc64 8 /* alias */
-#define TARGET_CPU_ultrasparc 9
-#define TARGET_CPU_ultrasparc3 10
-#define TARGET_CPU_niagara 11
-#define TARGET_CPU_niagara2 12
-#define TARGET_CPU_niagara3 13
-#define TARGET_CPU_niagara4 14
+#define TARGET_CPU_leon3 5
+#define TARGET_CPU_sparclite 6
+#define TARGET_CPU_f930 6 /* alias */
+#define TARGET_CPU_f934 6 /* alias */
+#define TARGET_CPU_sparclite86x 7
+#define TARGET_CPU_sparclet 8
+#define TARGET_CPU_tsc701 8 /* alias */
+#define TARGET_CPU_v9 9 /* generic v9 implementation */
+#define TARGET_CPU_sparcv9 9 /* alias */
+#define TARGET_CPU_sparc64 9 /* alias */
+#define TARGET_CPU_ultrasparc 10
+#define TARGET_CPU_ultrasparc3 11
+#define TARGET_CPU_niagara 12
+#define TARGET_CPU_niagara2 13
+#define TARGET_CPU_niagara3 14
+#define TARGET_CPU_niagara4 15
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
@@ -232,9 +233,10 @@ extern enum cmodel sparc_cmodel;
#define ASM_CPU32_DEFAULT_SPEC ""
#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_leon
+#if TARGET_CPU_DEFAULT == TARGET_CPU_leon \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_leon3
#define CPP_CPU32_DEFAULT_SPEC "-D__leon__ -D__sparc_v8__"
-#define ASM_CPU32_DEFAULT_SPEC ""
+#define ASM_CPU32_DEFAULT_SPEC AS_LEON_FLAG
#endif
#endif
@@ -282,6 +284,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
%{mcpu=leon:-D__leon__ -D__sparc_v8__} \
+%{mcpu=leon3:-D__leon__ -D__sparc_v8__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
%{mcpu=ultrasparc3:-D__sparc_v9__} \
@@ -329,7 +332,8 @@ extern enum cmodel sparc_cmodel;
%{mcpu=v8:-Av8} \
%{mcpu=supersparc:-Av8} \
%{mcpu=hypersparc:-Av8} \
-%{mcpu=leon:-Av8} \
+%{mcpu=leon:" AS_LEON_FLAG "} \
+%{mcpu=leon3:" AS_LEON_FLAG "} \
%{mv8plus:-Av8plus} \
%{mcpu=v9:-Av9} \
%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
@@ -1754,6 +1758,12 @@ extern int sparc_indent_opcode;
#define AS_NIAGARA4_FLAG "-Av9" AS_NIAGARA3_FLAG
#endif
+#ifdef HAVE_AS_LEON
+#define AS_LEON_FLAG "-Aleon"
+#else
+#define AS_LEON_FLAG "-Av8"
+#endif
+
/* We use gcc _mcount for profiling. */
#define NO_PROFILE_COUNTERS 0
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index b60af43334c..737cff0310e 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -206,7 +206,7 @@
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
;; Attribute for cpu type.
-;; These must match the values for enum processor_type in sparc.h.
+;; These must match the values of the enum processor_type in sparc-opts.h.
(define_attr "cpu"
"v7,
cypress,
@@ -214,6 +214,7 @@
supersparc,
hypersparc,
leon,
+ leon3,
sparclite,
f930,
f934,
@@ -5548,7 +5549,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"
+ "(TARGET_V8 || TARGET_V9) && TARGET_FPU && !sparc_fix_ut699"
"fsmuld\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
@@ -5577,20 +5578,37 @@
"fdivq\t%1, %2, %0"
[(set_attr "type" "fpdivd")])
-(define_insn "divdf3"
+(define_expand "divdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
+ "")
+
+(define_insn "*divdf3_nofix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (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"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")])
+(define_insn "*divdf3_fix"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (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]"
+ [(set_attr "type" "fpdivd")
+ (set_attr "fptype" "double")
+ (set_attr "length" "2")])
+
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
- "TARGET_FPU"
+ "TARGET_FPU && !sparc_fix_ut699"
"fdivs\t%1, %2, %0"
[(set_attr "type" "fpdivs")])
@@ -5791,18 +5809,33 @@
"fsqrtq\t%1, %0"
[(set_attr "type" "fpsqrtd")])
-(define_insn "sqrtdf2"
+(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
+ "")
+
+(define_insn "*sqrtdf2_nofix"
+ [(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"
[(set_attr "type" "fpsqrtd")
(set_attr "fptype" "double")])
+(define_insn "*sqrtdf2_fix"
+ [(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]"
+ [(set_attr "type" "fpsqrtd")
+ (set_attr "fptype" "double")
+ (set_attr "length" "2")])
+
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_FPU"
+ "TARGET_FPU && !sparc_fix_ut699"
"fsqrts\t%1, %0"
[(set_attr "type" "fpsqrts")])
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 764c652e837..3ccd54fa463 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -146,6 +146,9 @@ EnumValue
Enum(sparc_processor_type) String(leon) Value(PROCESSOR_LEON)
EnumValue
+Enum(sparc_processor_type) String(leon3) Value(PROCESSOR_LEON3)
+
+EnumValue
Enum(sparc_processor_type) String(sparclite) Value(PROCESSOR_SPARCLITE)
EnumValue
@@ -201,9 +204,19 @@ Target Report RejectNegative Var(sparc_fix_at697f)
Enable workaround for single erratum of AT697F processor
(corresponding to erratum #13 of AT697E processor)
+mfix-ut699
+Target Report RejectNegative Var(sparc_fix_ut699)
+Enable workarounds for the errata of the UT699 processor
+
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double
+Mask(LEON)
+;; Generate code for LEON
+
+Mask(LEON3)
+;; Generate code for LEON3
+
Mask(SPARCLITE)
;; Generate code for SPARClite
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index 1c1b9774bc3..130f5219194 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -161,7 +161,8 @@
(match_operand:SI 5 "const_int_operand" "") ;; is_weak
(match_operand:SI 6 "const_int_operand" "") ;; mod_s
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
- "TARGET_V9 && (<MODE>mode != DImode || TARGET_ARCH64 || TARGET_V8PLUS)"
+ "(TARGET_V9 || TARGET_LEON3)
+ && (<MODE>mode != DImode || TARGET_ARCH64 || TARGET_V8PLUS)"
{
sparc_expand_compare_and_swap (operands);
DONE;
@@ -176,7 +177,7 @@
[(match_operand:I48MODE 2 "register_operand" "")
(match_operand:I48MODE 3 "register_operand" "")]
UNSPECV_CAS))])]
- "TARGET_V9"
+ "TARGET_V9 || TARGET_LEON3"
"")
(define_insn "*atomic_compare_and_swap<mode>_1"
@@ -187,7 +188,7 @@
[(match_operand:I48MODE 2 "register_operand" "r")
(match_operand:I48MODE 3 "register_operand" "0")]
UNSPECV_CAS))]
- "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
+ "(TARGET_V9 || TARGET_LEON3) && (<MODE>mode != DImode || TARGET_ARCH64)"
"cas<modesuffix>\t%1, %2, %0"
[(set_attr "type" "multi")])
@@ -220,7 +221,7 @@
(match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
- "TARGET_V8 || TARGET_V9"
+ "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699"
{
enum memmodel model = (enum memmodel) INTVAL (operands[3]);
@@ -236,7 +237,7 @@
UNSPECV_SWAP))
(set (match_dup 1)
(match_operand:SI 2 "register_operand" "0"))]
- "TARGET_V8 || TARGET_V9"
+ "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699"
"swap\t%1, %0"
[(set_attr "type" "multi")])
@@ -244,7 +245,7 @@
[(match_operand:QI 0 "register_operand" "")
(match_operand:QI 1 "memory_operand" "")
(match_operand:SI 2 "const_int_operand" "")]
- ""
+ "!sparc_fix_ut699"
{
enum memmodel model = (enum memmodel) INTVAL (operands[2]);
rtx ret;
@@ -268,6 +269,6 @@
(unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
UNSPECV_LDSTUB))
(set (match_dup 1) (const_int -1))]
- ""
+ "!sparc_fix_ut699"
"ldstub\t%1, %0"
[(set_attr "type" "multi")])
diff --git a/gcc/config/sparc/t-rtems b/gcc/config/sparc/t-rtems
index 63d021770b5..f1a3d845e32 100644
--- a/gcc/config/sparc/t-rtems
+++ b/gcc/config/sparc/t-rtems
@@ -17,6 +17,6 @@
# <http://www.gnu.org/licenses/>.
#
-MULTILIB_OPTIONS = msoft-float mcpu=v8
-MULTILIB_DIRNAMES = soft v8
+MULTILIB_OPTIONS = msoft-float mcpu=v8/mcpu=leon3
+MULTILIB_DIRNAMES = soft v8 leon3
MULTILIB_MATCHES = msoft-float=mno-fpu
diff --git a/gcc/config/sparc/t-sparc b/gcc/config/sparc/t-sparc
index d7b17fbd02b..664f4a42418 100644
--- a/gcc/config/sparc/t-sparc
+++ b/gcc/config/sparc/t-sparc
@@ -23,7 +23,7 @@ sparc.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \
$(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
$(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \
- $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) \
+ $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) $(TREE_PASS_H) \
langhooks.h reload.h $(PARAMS_H) $(DF_H) $(OPTS_H) \
gt-sparc.h
diff --git a/gcc/configure b/gcc/configure
index 96d9141a294..13d5c0fe8d8 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -11222,13 +11222,11 @@ else
/* | A-Za-z:\\/* ) realsrcdir=${srcdir};;
*) realsrcdir=../${srcdir};;
esac
- saved_CFLAGS="${CFLAGS}"
CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
- LDFLAGS="${LDFLAGS_FOR_BUILD}" \
+ LDFLAGS="${LDFLAGS_FOR_BUILD}" GMPINC="" \
${realsrcdir}/configure \
--enable-languages=${enable_languages-all} \
--target=$target_alias --host=$build_alias --build=$build_alias
- CFLAGS="${saved_CFLAGS}"
# We just finished tests for the build machine, so rename
# the file auto-build.h in the gcc directory.
@@ -11816,6 +11814,7 @@ STMP_FIXINC=stmp-fixinc
if test x$build != x$host || test "x$coverage_flags" != x
then
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)'
+ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CXXFLAGS_FOR_BUILD)'
BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
fi
@@ -13703,7 +13702,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
@@ -13728,7 +13727,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -13747,7 +13749,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -17941,7 +17946,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17944 "configure"
+#line 17949 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18047,7 +18052,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18050 "configure"
+#line 18055 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -24376,6 +24381,43 @@ if test $gcc_cv_as_sparc_sparc4 = yes; then
$as_echo "#define HAVE_AS_SPARC4 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 :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_leon=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ smac %g2, %g3, %g1
+ umac %g2, %g3, %g1
+ cas [%g2], %g3, %g1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -Aleon -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_leon=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_leon" >&5
+$as_echo "$gcc_cv_as_sparc_leon" >&6; }
+if test $gcc_cv_as_sparc_leon = yes; then
+
+$as_echo "#define HAVE_AS_LEON 1" >>confdefs.h
+
+fi
;;
i[34567]86-*-* | x86_64-*-*)
@@ -27352,8 +27394,8 @@ if test x"$enable_plugin" = x"yes"; then
$as_echo_n "checking for exported symbols... " >&6; }
if test "x$export_sym_check" != x; then
echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
- ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
: # No need to use a flag
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -27362,8 +27404,8 @@ $as_echo "yes" >&6; }
$as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -rdynamic" >&5
$as_echo_n "checking for -rdynamic... " >&6; }
- ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
plugin_rdynamic=yes
pluginlibs="-rdynamic"
else
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 791f4497d64..49b9c8ebee3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1516,13 +1516,11 @@ else
/* | [A-Za-z]:[\\/]* ) realsrcdir=${srcdir};;
*) realsrcdir=../${srcdir};;
esac
- saved_CFLAGS="${CFLAGS}"
CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
- LDFLAGS="${LDFLAGS_FOR_BUILD}" \
+ LDFLAGS="${LDFLAGS_FOR_BUILD}" GMPINC="" \
${realsrcdir}/configure \
--enable-languages=${enable_languages-all} \
--target=$target_alias --host=$build_alias --build=$build_alias
- CFLAGS="${saved_CFLAGS}"
# We just finished tests for the build machine, so rename
# the file auto-build.h in the gcc directory.
@@ -1953,6 +1951,7 @@ STMP_FIXINC=stmp-fixinc AC_SUBST(STMP_FIXINC)
if test x$build != x$host || test "x$coverage_flags" != x
then
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)'
+ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CXXFLAGS_FOR_BUILD)'
BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
fi
@@ -3677,6 +3676,19 @@ foo:
kasumi_fi_xor %f46, %f48, %f50, %f52],,
[AC_DEFINE(HAVE_AS_SPARC4, 1,
[Define if your assembler supports SPARC4 instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([LEON instructions],
+ gcc_cv_as_sparc_leon,,
+ [-Aleon],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ smac %g2, %g3, %g1
+ umac %g2, %g3, %g1
+ cas [[%g2]], %g3, %g1],,
+ [AC_DEFINE(HAVE_AS_LEON, 1,
+ [Define if your assembler supports LEON instructions.])])
;;
changequote(,)dnl
@@ -5259,15 +5271,15 @@ if test x"$enable_plugin" = x"yes"; then
AC_MSG_CHECKING([for exported symbols])
if test "x$export_sym_check" != x; then
echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
- ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
: # No need to use a flag
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for -rdynamic])
- ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
plugin_rdynamic=yes
pluginlibs="-rdynamic"
else
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fd4ceeb2cff..ee37ecbbbd5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,164 @@
+2014-01-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/56060
+ PR c++/59730
+ * pt.c (type_dependent_expression_p): Handle EXPR_PACK_EXPANSION.
+
+2013-12-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/58954
+ * pt.c (resolve_overloaded_unification): Discard access checks.
+
+2013-12-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/59044
+ PR c++/59052
+ * pt.c (most_specialized_class): Use the partially instantiated
+ template for deduction. Drop the TMPL parameter.
+
+2013-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59268
+ * pt.c (tsubst_copy_and_build): Handle POINTER_PLUS_EXPR.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/59032
+ * typeck.c (cp_build_unary_op): Allow vector increment and decrement.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR middle-end/59037
+ * semantics.c (cxx_fold_indirect_ref): Don't create out-of-bounds
+ BIT_FIELD_REF.
+
+2013-11-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59297
+ * semantics.c (finish_omp_atomic): Call finish_expr_stmt
+ rather than add_stmt.
+
+2013-11-23 Easwaran Raman <eraman@google.com>
+
+ PR c++/59031
+ * call.c (build_new_method_call_1): Comnpare function context
+ with BASELINK_BINFO type rather than instance type before
+ marking the call with LOOKUP_NONVIRTUAL.
+
+2013-10-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/58162
+ * parser.c (cp_parser_late_parse_one_default_arg): Set
+ TARGET_EXPR_DIRECT_INIT_P.
+
+2013-11-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cvt.c (cp_convert_to_pointer): Call build_ptrmemfunc before
+ maybe_warn_zero_as_null_pointer_constant to avoid duplicate
+ -Wzero-as-null-pointer-constant diagnostics.
+
+ * typeck.c (build_ptrmemfunc): Use cp_build_c_cast.
+
+2013-10-25 Tom de Vries <tom@codesourcery.com>
+
+ PR c++/58282
+ * except.c (build_must_not_throw_expr): Handle
+ flag_exceptions.
+
+2013-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58596
+ * semantics.c (lambda_expr_this_capture): Handle NSDMIs in the
+ cp_unevaluated_operand case.
+
+2013-10-16 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58633
+ * parser.c (cp_parser_pseudo_destructor_name): Revert r174385 changes.
+
+2013-10-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/57850
+ * decl2.c (dump_tu): Split out from...
+ (cp_write_global_declarations): ...here. Call it in PCH mode.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58568
+ * semantics.c (begin_lambda_type): Check return value of xref_tag
+ for error_mark_node; tidy.
+ * decl.c (grokdeclarator): Tweak error message.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58535
+ * parser.c (cp_parser_function_specifier_opt): Upon error about
+ virtual templates don't set ds_virtual.
+
+2013-09-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58457
+ * class.c (instantiate_type): Loosen a bit the gcc_assert.
+
+2013-09-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/58273
+ * pt.c (any_type_dependent_elements_p): Actually check for
+ type-dependence, not value-dependence.
+
+2013-09-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/58325
+ * init.c (build_vec_delete): Call mark_rvalue_use on base.
+
+2013-08-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/58119
+ * cp-tree.h (WILDCARD_TYPE_P): Split out from...
+ (MAYBE_CLASS_TYPE_P): ...here.
+ * cvt.c (build_expr_type_conversion): Don't complain about a
+ template that can't match the desired type category.
+
+2013-08-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/58083
+ * name-lookup.c (push_class_level_binding_1): It's OK to push a
+ lambda type after the enclosing type is complete.
+
+2013-08-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/57825
+ * tree.c (strip_typedefs) [METHOD_TYPE]: Preserve ref-qualifier.
+
+2013-07-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/57901
+ * semantics.c (build_data_member_initialization, constexpr_fn_retval):
+ Use break_out_target_exprs instead of unshare_expr.
+
+ PR c++/58022
+ * typeck2.c (abstract_virtuals_error_sfinae): Don't remember
+ lookup in SFINAE context.
+
+2013-07-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/57981
+ * decl.c (check_default_argument): Take a tsubst_flags_t parameter.
+ (grokparms): Adjust.
+ * parser.c (cp_parser_late_parse_one_default_arg): Likewise.
+ * pt.c (tsubst_default_argument, tsubst_default_arguments): Take
+ a tsubst_flags_t parameter.
+ (tsubst_decl): Adjust.
+ * call.c (convert_default_arg): Likewise.
+ * cp-tree.h (check_default_argument, tsubst_default_argument):
+ Update declarations.
+
2013-07-12 Jason Merrill <jason@redhat.com>
* init.c (build_vec_init): Value-initialize the rest of the array.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9275133d636..a9c64981361 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6390,7 +6390,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
push_defarg_context (fn);
if (fn && DECL_TEMPLATE_INFO (fn))
- arg = tsubst_default_argument (fn, type, arg);
+ arg = tsubst_default_argument (fn, type, arg, complain);
/* Due to:
@@ -7414,7 +7414,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
tree basetype = NULL_TREE;
- tree access_binfo;
+ tree access_binfo, binfo;
tree optype;
tree first_mem_arg = NULL_TREE;
tree instance_ptr;
@@ -7454,6 +7454,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (!conversion_path)
conversion_path = BASELINK_BINFO (fns);
access_binfo = BASELINK_ACCESS_BINFO (fns);
+ binfo = BASELINK_BINFO (fns);
optype = BASELINK_OPTYPE (fns);
fns = BASELINK_FUNCTIONS (fns);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
@@ -7697,13 +7698,13 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
{
/* Optimize away vtable lookup if we know that this
function can't be overridden. We need to check if
- the context and the instance type are the same,
+ the context and the type where we found fn are the same,
actually FN might be defined in a different class
type because of a using-declaration. In this case, we
do not want to perform a non-virtual call. */
if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& same_type_ignoring_top_level_qualifiers_p
- (DECL_CONTEXT (fn), TREE_TYPE (instance))
+ (DECL_CONTEXT (fn), BINFO_TYPE (binfo))
&& resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
if (explicit_targs)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ea321b82fe5..578c92bc634 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7508,7 +7508,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
dependent on overload resolution. */
gcc_assert (TREE_CODE (rhs) == ADDR_EXPR
|| TREE_CODE (rhs) == COMPONENT_REF
- || really_overloaded_fn (rhs)
+ || is_overloaded_fn (rhs)
|| (flag_ms_extensions && TREE_CODE (rhs) == FUNCTION_DECL));
/* This should really only be used when attempting to distinguish
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3dbe71a80f2..fb8f9209099 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -344,7 +344,8 @@ struct GTY(()) tree_overload {
/* Returns true iff NODE is a BASELINK. */
#define BASELINK_P(NODE) \
(TREE_CODE (NODE) == BASELINK)
-/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */
+/* The BINFO indicating the base in which lookup found the
+ BASELINK_FUNCTIONS. */
#define BASELINK_BINFO(NODE) \
(((struct tree_baselink*) BASELINK_CHECK (NODE))->binfo)
/* The functions referred to by the BASELINK; either a FUNCTION_DECL,
@@ -1211,17 +1212,20 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* The _DECL for this _TYPE. */
#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
-/* Nonzero if T is a class (or struct or union) type. Also nonzero
- for template type parameters, typename types, and instantiated
- template template parameters. Keep these checks in ascending code
- order. */
-#define MAYBE_CLASS_TYPE_P(T) \
+/* Nonzero if T is a type that could resolve to any kind of concrete type
+ at instantiation time. */
+#define WILDCARD_TYPE_P(T) \
(TREE_CODE (T) == TEMPLATE_TYPE_PARM \
|| TREE_CODE (T) == TYPENAME_TYPE \
|| TREE_CODE (T) == TYPEOF_TYPE \
|| TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \
- || TREE_CODE (T) == DECLTYPE_TYPE \
- || CLASS_TYPE_P (T))
+ || TREE_CODE (T) == DECLTYPE_TYPE)
+
+/* Nonzero if T is a class (or struct or union) type. Also nonzero
+ for template type parameters, typename types, and instantiated
+ template template parameters. Keep these checks in ascending code
+ order. */
+#define MAYBE_CLASS_TYPE_P(T) (WILDCARD_TYPE_P (T) || CLASS_TYPE_P (T))
/* Set CLASS_TYPE_P for T to VAL. T must be a class, struct, or
union type. */
@@ -5178,7 +5182,7 @@ extern tree static_fn_type (tree);
extern void revert_static_member_fn (tree);
extern void fixup_anonymous_aggr (tree);
extern tree compute_array_index_type (tree, tree, tsubst_flags_t);
-extern tree check_default_argument (tree, tree);
+extern tree check_default_argument (tree, tree, tsubst_flags_t);
typedef int (*walk_namespaces_fn) (tree, void *);
extern int walk_namespaces (walk_namespaces_fn,
void *);
@@ -5453,7 +5457,8 @@ extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
extern void print_candidates (tree);
extern void instantiate_pending_templates (int);
-extern tree tsubst_default_argument (tree, tree, tree);
+extern tree tsubst_default_argument (tree, tree, tree,
+ tsubst_flags_t);
extern tree tsubst (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool, bool);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index f83f3704927..340fececce2 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -203,13 +203,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
if (null_ptr_cst_p (expr))
{
- if (complain & tf_warning)
- maybe_warn_zero_as_null_pointer_constant (expr, loc);
-
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
/*c_cast_p=*/false, complain);
+ if (complain & tf_warning)
+ maybe_warn_zero_as_null_pointer_constant (expr, loc);
+
/* A NULL pointer-to-data-member is represented by -1, not by
zero. */
tree val = (TYPE_PTRDATAMEM_P (type)
@@ -1583,17 +1583,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (DECL_NONCONVERTING_P (cand))
continue;
- if (TREE_CODE (cand) == TEMPLATE_DECL)
- {
- if (complain)
- {
- error ("ambiguous default type conversion from %qT",
- basetype);
- error (" candidate conversions include %qD", cand);
- }
- return error_mark_node;
- }
-
candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
switch (TREE_CODE (candidate))
@@ -1627,11 +1616,23 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
break;
default:
+ /* A wildcard could be instantiated to match any desired
+ type, but we can't deduce the template argument. */
+ if (WILDCARD_TYPE_P (candidate))
+ win = true;
break;
}
if (win)
{
+ if (TREE_CODE (cand) == TEMPLATE_DECL)
+ {
+ if (complain)
+ error ("default type conversion can't deduce template"
+ " argument for %qD", cand);
+ return error_mark_node;
+ }
+
if (winner)
{
if (complain)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 09296debeae..893fbd161c5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8780,8 +8780,8 @@ grokdeclarator (const cp_declarator *declarator,
&& !uniquely_derived_from_p (ctype,
current_class_type))
{
- error ("type %qT is not derived from type %qT",
- ctype, current_class_type);
+ error ("invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
}
}
@@ -10878,7 +10878,7 @@ local_variable_p_walkfn (tree *tp, int *walk_subtrees,
DECL, if there is no DECL available. */
tree
-check_default_argument (tree decl, tree arg)
+check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
{
tree var;
tree decl_type;
@@ -10910,13 +10910,14 @@ check_default_argument (tree decl, tree arg)
A default argument expression is implicitly converted to the
parameter type. */
++cp_unevaluated_operand;
- perform_implicit_conversion_flags (decl_type, arg, tf_warning_or_error,
+ perform_implicit_conversion_flags (decl_type, arg, complain,
LOOKUP_IMPLICIT);
--cp_unevaluated_operand;
if (warn_zero_as_null_pointer_constant
&& TYPE_PTR_OR_PTRMEM_P (decl_type)
&& null_ptr_cst_p (arg)
+ && (complain & tf_warning)
&& maybe_warn_zero_as_null_pointer_constant (arg, input_location))
return nullptr_node;
@@ -10930,10 +10931,14 @@ check_default_argument (tree decl, tree arg)
var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
if (var)
{
- if (DECL_NAME (var) == this_identifier)
- permerror (input_location, "default argument %qE uses %qD", arg, var);
- else
- error ("default argument %qE uses local variable %qD", arg, var);
+ if (complain & tf_warning_or_error)
+ {
+ if (DECL_NAME (var) == this_identifier)
+ permerror (input_location, "default argument %qE uses %qD",
+ arg, var);
+ else
+ error ("default argument %qE uses local variable %qD", arg, var);
+ }
return error_mark_node;
}
@@ -11084,7 +11089,7 @@ grokparms (tree parmlist, tree *parms)
if (any_error)
init = NULL_TREE;
else if (init && !processing_template_decl)
- init = check_default_argument (decl, init);
+ init = check_default_argument (decl, init, tf_warning_or_error);
}
DECL_CHAIN (decl) = decls;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 628be934bff..9252233fe82 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3960,6 +3960,22 @@ handle_tls_init (void)
expand_or_defer_fn (finish_function (0));
}
+/* The entire file is now complete. If requested, dump everything
+ to a file. */
+
+static void
+dump_tu (void)
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_tu, &flags);
+
+ if (stream)
+ {
+ dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_tu, stream);
+ }
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
@@ -3990,6 +4006,7 @@ cp_write_global_declarations (void)
if (pch_file)
{
c_common_write_pch ();
+ dump_tu ();
return;
}
@@ -4359,16 +4376,7 @@ cp_write_global_declarations (void)
/* The entire file is now complete. If requested, dump everything
to a file. */
- {
- int flags;
- FILE *stream = dump_begin (TDI_tu, &flags);
-
- if (stream)
- {
- dump_node (global_namespace, flags & ~TDF_SLIM, stream);
- dump_end (TDI_tu, stream);
- }
- }
+ dump_tu ();
if (flag_detailed_statistics)
{
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 216ec103f52..604f274fb97 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -380,6 +380,9 @@ build_must_not_throw_expr (tree body, tree cond)
{
tree type = body ? TREE_TYPE (body) : void_type_node;
+ if (!flag_exceptions)
+ return body;
+
if (cond && !value_dependent_expression_p (cond))
{
cond = cxx_constant_value (cond);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6f3196a3a9c..ea40caa8f64 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -4064,6 +4064,7 @@ build_vec_delete (tree base, tree maxindex,
tree cookie_addr;
tree size_ptr_type = build_pointer_type (sizetype);
+ base = mark_rvalue_use (base);
if (TREE_SIDE_EFFECTS (base))
{
base_init = get_target_expr (base);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 62f62fdcbfc..1f82e70e7df 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3014,8 +3014,10 @@ push_class_level_binding_1 (tree name, tree x)
if (name == error_mark_node)
return false;
- /* Check for invalid member names. */
- gcc_assert (TYPE_BEING_DEFINED (current_class_type));
+ /* Check for invalid member names. But don't worry about a default
+ argument-scope lambda being pushed after the class is complete. */
+ gcc_assert (TYPE_BEING_DEFINED (current_class_type)
+ || LAMBDA_TYPE_P (TREE_TYPE (decl)));
/* Check that we're pushing into the right binding level. */
gcc_assert (current_class_type == class_binding_level->this_entity);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 15918a9ae08..f6fa168d161 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6421,10 +6421,6 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
/* Look for the `~'. */
cp_parser_require (parser, CPP_COMPL, RT_COMPL);
- /* Once we see the ~, this has to be a pseudo-destructor. */
- if (!processing_template_decl && !cp_parser_error_occurred (parser))
- cp_parser_commit_to_tentative_parse (parser);
-
/* Look for the type-name again. We are not responsible for
checking that it matches the first type-name. */
*type = cp_parser_nonclass_name (parser);
@@ -11139,7 +11135,8 @@ cp_parser_function_specifier_opt (cp_parser* parser,
A member function template shall not be virtual. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
error_at (token->location, "templates may not be %<virtual%>");
- set_and_check_decl_spec_loc (decl_specs, ds_virtual, token);
+ else
+ set_and_check_decl_spec_loc (decl_specs, ds_virtual, token);
break;
case RID_EXPLICIT:
@@ -22566,7 +22563,8 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
/* In a non-template class, check conversions now. In a template,
we'll wait and instantiate these as needed. */
if (TREE_CODE (decl) == PARM_DECL)
- parsed_arg = check_default_argument (parmtype, parsed_arg);
+ parsed_arg = check_default_argument (parmtype, parsed_arg,
+ tf_warning_or_error);
else
{
int flags = LOOKUP_IMPLICIT;
@@ -22574,6 +22572,9 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
&& CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg))
flags = LOOKUP_NORMAL;
parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags);
+ if (TREE_CODE (parsed_arg) == TARGET_EXPR)
+ /* This represents the whole initialization. */
+ TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true;
}
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 043a8f80819..67a0c4e59b1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -170,7 +170,7 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized_class (tree, tree, tsubst_flags_t);
+static tree most_specialized_class (tree, tsubst_flags_t);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
@@ -184,7 +184,7 @@ static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
static bool template_template_parm_bindings_ok_p (tree, tree);
static int template_args_equal (tree, tree);
-static void tsubst_default_arguments (tree);
+static void tsubst_default_arguments (tree, tsubst_flags_t);
static tree for_each_template_parm_r (tree *, int *, void *);
static tree copy_default_args_to_explicit_spec_1 (tree, tree);
static void copy_default_args_to_explicit_spec (tree);
@@ -4261,7 +4261,7 @@ process_partial_specialization (tree decl)
if (COMPLETE_TYPE_P (inst_type)
&& CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
{
- tree spec = most_specialized_class (inst_type, maintmpl, tf_none);
+ tree spec = most_specialized_class (inst_type, tf_none);
if (spec && TREE_TYPE (spec) == type)
permerror (input_location,
"partial specialization of %qT after instantiation "
@@ -8572,7 +8572,7 @@ instantiate_class_template_1 (tree type)
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, templ, tf_warning_or_error);
+ t = most_specialized_class (type, tf_warning_or_error);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
@@ -9864,7 +9864,7 @@ tsubst_aggr_type (tree t,
FN), which has the indicated TYPE. */
tree
-tsubst_default_argument (tree fn, tree type, tree arg)
+tsubst_default_argument (tree fn, tree type, tree arg, tsubst_flags_t complain)
{
tree saved_class_ptr = NULL_TREE;
tree saved_class_ref = NULL_TREE;
@@ -9904,7 +9904,7 @@ tsubst_default_argument (tree fn, tree type, tree arg)
stack. */
++function_depth;
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
- tf_warning_or_error, NULL_TREE,
+ complain, NULL_TREE,
/*integral_constant_expression_p=*/false);
--function_depth;
pop_deferring_access_checks();
@@ -9916,12 +9916,13 @@ tsubst_default_argument (tree fn, tree type, tree arg)
cp_function_chain->x_current_class_ref = saved_class_ref;
}
- if (errorcount+sorrycount > errs)
+ if (errorcount+sorrycount > errs
+ && (complain & tf_warning_or_error))
inform (input_location,
" when instantiating default argument for call to %D", fn);
/* Make sure the default argument is reasonable. */
- arg = check_default_argument (type, arg);
+ arg = check_default_argument (type, arg, complain);
pop_access_scope (fn);
@@ -9931,7 +9932,7 @@ tsubst_default_argument (tree fn, tree type, tree arg)
/* Substitute into all the default arguments for FN. */
static void
-tsubst_default_arguments (tree fn)
+tsubst_default_arguments (tree fn, tsubst_flags_t complain)
{
tree arg;
tree tmpl_args;
@@ -9952,7 +9953,8 @@ tsubst_default_arguments (tree fn)
if (TREE_PURPOSE (arg))
TREE_PURPOSE (arg) = tsubst_default_argument (fn,
TREE_VALUE (arg),
- TREE_PURPOSE (arg));
+ TREE_PURPOSE (arg),
+ complain);
}
/* Substitute the ARGS into the T, which is a _DECL. Return the
@@ -10303,7 +10305,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (!member
&& !PRIMARY_TEMPLATE_P (gen_tmpl)
&& !uses_template_parms (argvec))
- tsubst_default_arguments (r);
+ tsubst_default_arguments (r, complain);
}
else
DECL_TEMPLATE_INFO (r) = NULL_TREE;
@@ -13708,6 +13710,10 @@ tsubst_copy_and_build (tree t,
RETURN (r);
}
+ case POINTER_PLUS_EXPR:
+ return fold_build_pointer_plus (RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 1)));
+
case SCOPE_REF:
RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
/*address_p=*/false));
@@ -15747,7 +15753,7 @@ resolve_overloaded_unification (tree tparms,
if (subargs != error_mark_node
&& !any_dependent_template_arguments_p (subargs))
{
- elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
+ elem = TREE_TYPE (instantiate_template (fn, subargs, tf_none));
if (try_one_overload (tparms, targs, tempargs, parm,
elem, strict, sub_strict, addr_p, explain_p)
&& (!goodfn || !same_type_p (goodfn, elem)))
@@ -17551,7 +17557,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
return -1;
}
-/* Determine which of two partial specializations of MAIN_TMPL is more
+/* Determine which of two partial specializations of TMPL is more
specialized.
PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding
@@ -17567,7 +17573,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
two templates is more specialized. */
static int
-more_specialized_class (tree main_tmpl, tree pat1, tree pat2)
+more_specialized_class (tree tmpl, tree pat1, tree pat2)
{
tree targs;
tree tmpl1, tmpl2;
@@ -17582,7 +17588,7 @@ more_specialized_class (tree main_tmpl, tree pat1, tree pat2)
types in the arguments, and we need our dependency check functions
to behave correctly. */
++processing_template_decl;
- targs = get_class_bindings (main_tmpl, TREE_VALUE (pat1),
+ targs = get_class_bindings (tmpl, TREE_VALUE (pat1),
CLASSTYPE_TI_ARGS (tmpl1),
CLASSTYPE_TI_ARGS (tmpl2));
if (targs)
@@ -17591,7 +17597,7 @@ more_specialized_class (tree main_tmpl, tree pat1, tree pat2)
any_deductions = true;
}
- targs = get_class_bindings (main_tmpl, TREE_VALUE (pat2),
+ targs = get_class_bindings (tmpl, TREE_VALUE (pat2),
CLASSTYPE_TI_ARGS (tmpl2),
CLASSTYPE_TI_ARGS (tmpl1));
if (targs)
@@ -17671,7 +17677,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
}
/* Return the innermost template arguments that, when applied to a partial
- specialization of MAIN_TMPL whose innermost template parameters are
+ specialization of TMPL whose innermost template parameters are
TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
ARGS.
@@ -17686,7 +17692,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
is bound to `double'. */
static tree
-get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args)
+get_class_bindings (tree tmpl, tree tparms, tree spec_args, tree args)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree deduced_args;
@@ -17726,8 +17732,8 @@ get_class_bindings (tree main_tmpl, tree tparms, tree spec_args, tree args)
`T' is `A' but unify () does not check whether `typename T::X'
is `int'. */
spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE);
- spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (main_tmpl),
- spec_args, main_tmpl,
+ spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ spec_args, tmpl,
tf_none, false, false);
if (spec_args == error_mark_node
/* We only need to check the innermost arguments; the other
@@ -17875,30 +17881,30 @@ most_general_template (tree decl)
}
/* Return the most specialized of the class template partial
- specializations of TMPL which can produce TYPE, a specialization of
- TMPL. The value returned is actually a TREE_LIST; the TREE_TYPE is
+ specializations which can produce TYPE, a specialization of some class
+ template. The value returned is actually a TREE_LIST; the TREE_TYPE is
a _TYPE node corresponding to the partial specialization, while the
TREE_PURPOSE is the set of template arguments that must be
substituted into the TREE_TYPE in order to generate TYPE.
If the choice of partial specialization is ambiguous, a diagnostic
is issued, and the error_mark_node is returned. If there are no
- partial specializations of TMPL matching TYPE, then NULL_TREE is
- returned. */
+ partial specializations matching TYPE, then NULL_TREE is
+ returned, indicating that the primary template should be used. */
static tree
-most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
+most_specialized_class (tree type, tsubst_flags_t complain)
{
tree list = NULL_TREE;
tree t;
tree champ;
int fate;
bool ambiguous_p;
- tree args;
tree outer_args = NULL_TREE;
- tmpl = most_general_template (tmpl);
- args = CLASSTYPE_TI_ARGS (type);
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree main_tmpl = most_general_template (tmpl);
+ tree args = CLASSTYPE_TI_ARGS (type);
/* For determining which partial specialization to use, only the
innermost args are interesting. */
@@ -17908,7 +17914,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
args = INNERMOST_TEMPLATE_ARGS (args);
}
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t))
{
tree partial_spec_args;
tree spec_args;
@@ -17942,8 +17948,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
partial_spec_args =
coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- add_to_template_args (outer_args,
- partial_spec_args),
+ partial_spec_args,
tmpl, tf_none,
/*require_all_args=*/true,
/*use_default_args=*/true);
@@ -19953,6 +19958,10 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == SCOPE_REF)
return false;
+ /* Always dependent, on the number of arguments if nothing else. */
+ if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
+ return true;
+
if (BASELINK_P (expression))
expression = BASELINK_FUNCTIONS (expression);
@@ -20125,7 +20134,7 @@ bool
any_type_dependent_elements_p (const_tree list)
{
for (; list; list = TREE_CHAIN (list))
- if (value_dependent_expression_p (TREE_VALUE (list)))
+ if (type_dependent_expression_p (TREE_VALUE (list)))
return true;
return false;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3699ea5e9a2..c2b9b4af245 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5059,7 +5059,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
}
stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
}
- add_stmt (stmt);
+ finish_expr_stmt (stmt);
}
void
@@ -5956,7 +5956,7 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
|| TREE_CODE (t) == MODIFY_EXPR)
{
member = TREE_OPERAND (t, 0);
- init = unshare_expr (TREE_OPERAND (t, 1));
+ init = break_out_target_exprs (TREE_OPERAND (t, 1));
}
else if (TREE_CODE (t) == CALL_EXPR)
{
@@ -5964,7 +5964,7 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
/* We don't use build_cplus_new here because it complains about
abstract bases. Leaving the call unwrapped means that it has the
wrong type, but cxx_eval_constant_expression doesn't care. */
- init = unshare_expr (t);
+ init = break_out_target_exprs (t);
}
else if (TREE_CODE (t) == DECL_EXPR)
/* Declaring a temporary, don't add it to the CONSTRUCTOR. */
@@ -6201,7 +6201,7 @@ constexpr_fn_retval (tree body)
}
case RETURN_EXPR:
- return unshare_expr (TREE_OPERAND (body, 0));
+ return break_out_target_exprs (TREE_OPERAND (body, 0));
case DECL_EXPR:
if (TREE_CODE (DECL_EXPR_DECL (body)) == USING_DECL)
@@ -7543,7 +7543,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
tree index = bitsize_int (indexi);
- if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+ if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type))
return fold_build3_loc (loc,
BIT_FIELD_REF, type, op00,
part_width, index);
@@ -9007,6 +9007,8 @@ begin_lambda_type (tree lambda)
name,
/*scope=*/ts_lambda,
/*template_header_p=*/false);
+ if (type == error_mark_node)
+ return error_mark_node;
}
/* Designate it as a struct so that we can use aggregate initialization. */
@@ -9021,8 +9023,6 @@ begin_lambda_type (tree lambda)
/* Start the class. */
type = begin_class_definition (type);
- if (type == error_mark_node)
- return error_mark_node;
return type;
}
@@ -9481,7 +9481,14 @@ lambda_expr_this_capture (tree lambda)
/* In unevaluated context this isn't an odr-use, so just return the
nearest 'this'. */
if (cp_unevaluated_operand)
- return lookup_name (this_identifier);
+ {
+ /* In an NSDMI the fake 'this' pointer that we're using for
+ parsing is in scope_chain. */
+ if (LAMBDA_EXPR_EXTRA_SCOPE (lambda)
+ && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (lambda)) == FIELD_DECL)
+ return scope_chain->x_current_class_ptr;
+ return lookup_name (this_identifier);
+ }
/* Try to default capture 'this' if we can. */
if (!this_capture
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a75663406d4..c7502d6207b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1220,6 +1220,8 @@ strip_typedefs (tree t)
result =
build_method_type_directly (class_type, type,
TREE_CHAIN (arg_types));
+ result
+ = build_ref_qualified_type (result, type_memfn_rqual (t));
}
else
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1a64b6890dc..cec6c452ade 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5588,7 +5588,9 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
}
else
- inc = integer_one_node;
+ inc = (TREE_CODE (argtype) == VECTOR_TYPE
+ ? build_one_cst (argtype)
+ : integer_one_node);
inc = cp_convert (argtype, inc, complain);
@@ -7611,7 +7613,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
/* Handle null pointer to member function conversions. */
if (null_ptr_cst_p (pfn))
{
- pfn = build_c_cast (input_location, type, pfn);
+ pfn = cp_build_c_cast (type, pfn, complain);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
pfn);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 9b7db62183d..9c9f0751f33 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -262,7 +262,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
so that we can check again once it is completed. This makes sense
only for objects for which we have a declaration or at least a
name. */
- if (!COMPLETE_TYPE_P (type))
+ if (!COMPLETE_TYPE_P (type) && (complain & tf_error))
{
void **slot;
struct pending_abstract_type *pat;
diff --git a/gcc/cse.c b/gcc/cse.c
index b200fef4dfb..1d450749769 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -6082,6 +6082,18 @@ cse_process_notes_1 (rtx x, rtx object, bool *changed)
return x;
}
+ case UNSIGNED_FLOAT:
+ {
+ rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed);
+ /* We don't substitute negative VOIDmode constants into these rtx,
+ since they would impede folding. */
+ if (GET_MODE (new_rtx) != VOIDmode
+ || (CONST_INT_P (new_rtx) && INTVAL (new_rtx) >= 0)
+ || (CONST_DOUBLE_P (new_rtx) && CONST_DOUBLE_HIGH (new_rtx) >= 0))
+ validate_change (object, &XEXP (x, 0), new_rtx, 0);
+ return x;
+ }
+
case REG:
i = REG_QTY (REGNO (x));
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 0cf5c8614a3..81a388a7940 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3121,6 +3121,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 hotpatch [(@var{prologue-halfwords})]
+@cindex @code{hotpatch} attribute
+
+On S/390 System z targets, you can use this function attribute to
+make GCC generate a ``hot-patching'' function prologue. The
+@code{hotpatch} has no effect on funtions that are explicitly
+inline. If the @option{-mhotpatch} or @option{-mno-hotpatch}
+command-line option is used at the same time, the @code{hotpatch}
+attribute takes precedence. If an argument is given, the maximum
+allowed value is 1000000.
+
@item naked
@cindex function without a prologue/epilogue code
Use this attribute on the ARM, AVR, MCORE, RX and SPU ports to indicate that
@@ -7412,6 +7423,8 @@ This built-in function performs an atomic test-and-set operation on
the byte at @code{*@var{ptr}}. The byte is set to some implementation
defined nonzero ``set'' value and the return value is @code{true} if and only
if the previous contents were ``set''.
+It should be only used for operands of type @code{bool} or @code{char}. For
+other types only part of the value may be set.
All memory models are valid.
@@ -7421,6 +7434,10 @@ All memory models are valid.
This built-in function performs an atomic clear operation on
@code{*@var{ptr}}. After the operation, @code{*@var{ptr}} contains 0.
+It should be only used for operands of type @code{bool} or @code{char} and
+in conjunction with @code{__atomic_test_and_set}.
+For other types it may only clear partially. If the type is not @code{bool}
+prefer using @code{__atomic_store}.
The valid memory model variants are
@code{__ATOMIC_RELAXED}, @code{__ATOMIC_SEQ_CST}, and
@@ -7492,18 +7509,20 @@ End lock elision on a lock variable.
Memory model must be @code{__ATOMIC_RELEASE} or stronger.
@end table
-When a lock acquire fails it's required for good performance to abort
+When a lock acquire fails it is required for good performance to abort
the transaction quickly. This can be done with a @code{_mm_pause}
@smallexample
#include <immintrin.h> // For _mm_pause
+int lockvar;
+
/* Acquire lock with lock elision */
while (__atomic_exchange_n(&lockvar, 1, __ATOMIC_ACQUIRE|__ATOMIC_HLE_ACQUIRE))
_mm_pause(); /* Abort failed transaction */
...
/* Free lock with lock elision */
-__atomic_clear(&lockvar, __ATOMIC_RELEASE|__ATOMIC_HLE_RELEASE);
+__atomic_store_n(&lockvar, 0, __ATOMIC_RELEASE|__ATOMIC_HLE_RELEASE);
@end smallexample
@node Object Size Checking
@@ -8785,7 +8804,9 @@ instructions, but allow the compiler to schedule those calls.
* picoChip Built-in Functions::
* PowerPC Built-in Functions::
* PowerPC AltiVec/VSX Built-in Functions::
+* PowerPC Hardware Transactional Memory Built-in Functions::
* RX Built-in Functions::
+* S/390 System z Built-in Functions::
* SH Built-in Functions::
* SPARC VIS Built-in Functions::
* SPU Built-in Functions::
@@ -14246,6 +14267,196 @@ The second argument to the @var{__builtin_crypto_vshasigmad} and
integer that is 0 or 1. The third argument to these builtin functions
must be a constant integer in the range of 0 to 15.
+@node PowerPC Hardware Transactional Memory Built-in Functions
+@subsection PowerPC Hardware Transactional Memory Built-in Functions
+GCC provides two interfaces for accessing the Hardware Transactional
+Memory (HTM) instructions available on some of the PowerPC family
+of prcoessors (eg, POWER8). The two interfaces come in a low level
+interface, consisting of built-in functions specific to PowerPC and a
+higher level interface consisting of inline functions that are common
+between PowerPC and S/390.
+
+@subsubsection PowerPC HTM Low Level Built-in Functions
+
+The following low level built-in functions are available with
+@option{-mhtm} or @option{-mcpu=CPU} where CPU is `power8' or later.
+They all generate the machine instruction that is part of the name.
+
+The HTM built-ins return true or false depending on their success and
+their arguments match exactly the type and order of the associated
+hardware instruction's operands. Refer to the ISA manual for a
+description of each instruction's operands.
+
+@smallexample
+unsigned int __builtin_tbegin (unsigned int)
+unsigned int __builtin_tend (unsigned int)
+
+unsigned int __builtin_tabort (unsigned int)
+unsigned int __builtin_tabortdc (unsigned int, unsigned int, unsigned int)
+unsigned int __builtin_tabortdci (unsigned int, unsigned int, int)
+unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int)
+unsigned int __builtin_tabortwci (unsigned int, unsigned int, int)
+
+unsigned int __builtin_tcheck (unsigned int)
+unsigned int __builtin_treclaim (unsigned int)
+unsigned int __builtin_trechkpt (void)
+unsigned int __builtin_tsr (unsigned int)
+@end smallexample
+
+In addition to the above HTM built-ins, we have added built-ins for
+some common extended mnemonics of the HTM instructions:
+
+@smallexample
+unsigned int __builtin_tendall (void)
+unsigned int __builtin_tresume (void)
+unsigned int __builtin_tsuspend (void)
+@end smallexample
+
+The following set of built-in functions are available to gain access
+to the HTM specific special purpose registers.
+
+@smallexample
+unsigned long __builtin_get_texasr (void)
+unsigned long __builtin_get_texasru (void)
+unsigned long __builtin_get_tfhar (void)
+unsigned long __builtin_get_tfiar (void)
+
+void __builtin_set_texasr (unsigned long);
+void __builtin_set_texasru (unsigned long);
+void __builtin_set_tfhar (unsigned long);
+void __builtin_set_tfiar (unsigned long);
+@end smallexample
+
+Example usage of these low level built-in functions may look like:
+
+@smallexample
+#include <htmintrin.h>
+
+int num_retries = 10;
+
+while (1)
+ @{
+ if (__builtin_tbegin (0))
+ @{
+ /* Transaction State Initiated. */
+ if (is_locked (lock))
+ __builtin_tabort (0);
+ ... transaction code...
+ __builtin_tend (0);
+ break;
+ @}
+ else
+ @{
+ /* Transaction State Failed. Use locks if the transaction
+ failure is "persistent" or we've tried too many times. */
+ if (num_retries-- <= 0
+ || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+ @{
+ acquire_lock (lock);
+ ... non transactional fallback path...
+ release_lock (lock);
+ break;
+ @}
+ @}
+ @}
+@end smallexample
+
+One final built-in function has been added that returns the value of
+the 2-bit Transaction State field of the Machine Status Register (MSR)
+as stored in @code{CR0}.
+
+@smallexample
+unsigned long __builtin_ttest (void)
+@end smallexample
+
+This built-in can be used to determine the current transaction state
+using the following code example:
+
+@smallexample
+#include <htmintrin.h>
+
+unsigned char tx_state = _HTM_STATE (__builtin_ttest ());
+
+if (tx_state == _HTM_TRANSACTIONAL)
+ @{
+ /* Code to use in transactional state. */
+ @}
+else if (tx_state == _HTM_NONTRANSACTIONAL)
+ @{
+ /* Code to use in non-transactional state. */
+ @}
+else if (tx_state == _HTM_SUSPENDED)
+ @{
+ /* Code to use in transaction suspended state. */
+ @}
+@end smallexample
+
+@subsubsection PowerPC HTM High Level Inline Functions
+
+The following high level HTM interface is made available by including
+@code{<htmxlintrin.h>} and using @option{-mhtm} or @option{-mcpu=CPU}
+where CPU is `power8' or later. This interface is common between PowerPC
+and S/390, allowing users to write one HTM source implementation that
+can be compiled and executed on either system.
+
+@smallexample
+long __TM_simple_begin (void)
+long __TM_begin (void* const TM_buff)
+long __TM_end (void)
+void __TM_abort (void)
+void __TM_named_abort (unsigned char const code)
+void __TM_resume (void)
+void __TM_suspend (void)
+
+long __TM_is_user_abort (void* const TM_buff)
+long __TM_is_named_user_abort (void* const TM_buff, unsigned char *code)
+long __TM_is_illegal (void* const TM_buff)
+long __TM_is_footprint_exceeded (void* const TM_buff)
+long __TM_nesting_depth (void* const TM_buff)
+long __TM_is_nested_too_deep(void* const TM_buff)
+long __TM_is_conflict(void* const TM_buff)
+long __TM_is_failure_persistent(void* const TM_buff)
+long __TM_failure_address(void* const TM_buff)
+long long __TM_failure_code(void* const TM_buff)
+@end smallexample
+
+Using these common set of HTM inline functions, we can create
+a more portable version of the HTM example in the previous
+section that will work on either PowerPC or S/390:
+
+@smallexample
+#include <htmxlintrin.h>
+
+int num_retries = 10;
+TM_buff_type TM_buff;
+
+while (1)
+ @{
+ if (__TM_begin (TM_buff))
+ @{
+ /* Transaction State Initiated. */
+ if (is_locked (lock))
+ __TM_abort ();
+ ... transaction code...
+ __TM_end ();
+ break;
+ @}
+ else
+ @{
+ /* Transaction State Failed. Use locks if the transaction
+ failure is "persistent" or we've tried too many times. */
+ if (num_retries-- <= 0
+ || __TM_is_failure_persistent (TM_buff))
+ @{
+ acquire_lock (lock);
+ ... non transactional fallback path...
+ release_lock (lock);
+ break;
+ @}
+ @}
+ @}
+@end smallexample
+
@node RX Built-in Functions
@subsection RX Built-in Functions
GCC supports some of the RX instructions which cannot be expressed in
@@ -14361,6 +14572,120 @@ bit in the processor status word.
Generates the @code{wait} machine instruction.
@end deftypefn
+@node S/390 System z Built-in Functions
+@subsection S/390 System z Built-in Functions
+@deftypefn {Built-in Function} int __builtin_tbegin (void*)
+Generates the @code{tbegin} machine instruction starting a
+non-constraint hardware transaction. If the parameter is non-NULL the
+memory area is used to store the transaction diagnostic buffer and
+will be passed as first operand to @code{tbegin}. This buffer can be
+defined using the @code{struct __htm_tdb} C struct defined in
+@code{htmintrin.h} and must reside on a double-word boundary. The
+second tbegin operand is set to @code{0xff0c}. This enables
+save/restore of all GPRs and disables aborts for FPR and AR
+manipulations inside the transaction body. The condition code set by
+the tbegin instruction is returned as integer value. The tbegin
+instruction by definition overwrites the content of all FPRs. The
+compiler will generate code which saves and restores the FPRs. For
+soft-float code it is recommended to used the @code{*_nofloat}
+variant. In order to prevent a TDB from being written it is required
+to pass an constant zero value as parameter. Passing the zero value
+through a variable is not sufficient. Although modifications of
+access registers inside the transaction will not trigger an
+transaction abort it is not supported to actually modify them. Access
+registers do not get saved when entering a transaction. They will have
+undefined state when reaching the abort code.
+@end deftypefn
+
+Macros for the possible return codes of tbegin are defined in the
+@code{htmintrin.h} header file:
+
+@table @code
+@item _HTM_TBEGIN_STARTED
+@code{tbegin} has been executed as part of normal processing. The
+transaction body is supposed to be executed.
+@item _HTM_TBEGIN_INDETERMINATE
+The transaction was aborted due to an indeterminate condition which
+might be persistent.
+@item _HTM_TBEGIN_TRANSIENT
+The transaction aborted due to a transient failure. The transaction
+should be re-executed in that case.
+@item _HTM_TBEGIN_PERSISTENT
+The transaction aborted due to a persistent failure. Re-execution
+under same circumstances will not be productive.
+@end table
+
+@defmac _HTM_FIRST_USER_ABORT_CODE
+The @code{_HTM_FIRST_USER_ABORT_CODE} defined in @code{htmintrin.h}
+specifies the first abort code which can be used for
+@code{__builtin_tabort}. Values below this threshold are reserved for
+machine use.
+@end defmac
+
+@deftp {Data type} {struct __htm_tdb}
+The @code{struct __htm_tdb} defined in @code{htmintrin.h} describes
+the structure of the transaction diagnostic block as specified in the
+Principles of Operation manual chapter 5-91.
+@end deftp
+
+@deftypefn {Built-in Function} int __builtin_tbegin_nofloat (void*)
+Same as @code{__builtin_tbegin} but without FPR saves and restores.
+Using this variant in code making use of FPRs will leave the FPRs in
+undefined state when entering the transaction abort handler code.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_tbegin_retry (void*, int)
+In addition to @code{__builtin_tbegin} a loop for transient failures
+is generated. If tbegin returns a condition code of 2 the transaction
+will be retried as often as specified in the second argument. The
+perform processor assist instruction is used to tell the CPU about the
+number of fails so far.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_tbegin_retry_nofloat (void*, int)
+Same as @code{__builtin_tbegin_retry} but without FPR saves and
+restores. Using this variant in code making use of FPRs will leave
+the FPRs in undefined state when entering the transaction abort
+handler code.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_tbeginc (void)
+Generates the @code{tbeginc} machine instruction starting a constraint
+hardware transaction. The second operand is set to @code{0xff08}.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_tend (void)
+Generates the @code{tend} machine instruction finishing a transaction
+and making the changes visible to other threads. The condition code
+generated by tend is returned as integer value.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_tabort (int)
+Generates the @code{tabort} machine instruction with the specified
+abort code. Abort codes from 0 through 255 are reserved and will
+result in an error message.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_tx_assist (int)
+Generates the @code{ppa rX,rY,1} machine instruction. Where the
+integer parameter is loaded into rX and a value of zero is loaded into
+rY. The integer parameter specifies the number of times the
+transaction repeatedly aborted.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_tx_nesting_depth (void)
+Generates the @code{etnd} machine instruction. The current nesting
+depth is returned as integer value. For a nesting depth of 0 the code
+is not executed as part of an transaction.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_non_tx_store (uint64_t *, uint64_t)
+
+Generates the @code{ntstg} machine instruction. The second argument
+is written to the first arguments location. The store operation will
+not be rolled-back in case of an transaction abort.
+@end deftypefn
+
@node SH Built-in Functions
@subsection SH Built-in Functions
The following built-in functions are supported on the SH1, SH2, SH3 and SH4
diff --git a/gcc/doc/implement-cxx.texi b/gcc/doc/implement-cxx.texi
index e9236cab6f4..43a8a597ab6 100644
--- a/gcc/doc/implement-cxx.texi
+++ b/gcc/doc/implement-cxx.texi
@@ -9,8 +9,8 @@
A conforming implementation of ISO C++ is required to document its
choice of behavior in each of the areas that are designated
``implementation defined''. The following lists all such areas,
-along with the section numbers from the ISO/IEC 14822:1998 and ISO/IEC
-14822:2003 standards. Some areas are only implementation-defined in
+along with the section numbers from the ISO/IEC 14882:1998 and ISO/IEC
+14882:2003 standards. Some areas are only implementation-defined in
one version of the standard.
Some choices depend on the externally determined ABI for the platform
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f0d7b8c11aa..9947270db8f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -161,7 +161,7 @@ in the following sections.
-pipe -pass-exit-codes @gol
-x @var{language} -v -### --help@r{[}=@var{class}@r{[},@dots{}@r{]]} --target-help @gol
--version -wrapper @@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} @gol
--fdump-ada-spec@r{[}-slim@r{]} -fada-spec-parent=@var{arg} -fdump-go-spec=@var{file}}
+-fdump-ada-spec@r{[}-slim@r{]} -fada-spec-parent=@var{unit} -fdump-go-spec=@var{file}}
@item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}.
@@ -858,7 +858,9 @@ See RS/6000 and PowerPC Options.
-msave-toc-indirect -mno-save-toc-indirect @gol
-mpower8-fusion -mno-mpower8-fusion -mpower8-vector -mno-power8-vector @gol
-mcrypto -mno-crypto -mdirect-move -mno-direct-move @gol
--mquad-memory -mno-quad-memory}
+-mquad-memory -mno-quad-memory @gol
+-mquad-memory-atomic -mno-quad-memory-atomic @gol
+-mcompat-align-parm -mno-compat-align-parm}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
@@ -882,7 +884,8 @@ See RS/6000 and PowerPC Options.
-msmall-exec -mno-small-exec -mmvcle -mno-mvcle @gol
-m64 -m31 -mdebug -mno-debug -mesa -mzarch @gol
-mtpf-trace -mno-tpf-trace -mfused-madd -mno-fused-madd @gol
--mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard}
+-mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard @gol
+-mhotpatch[=@var{halfwords}] -mno-hotpatch}
@emph{Score Options}
@gccoptlist{-meb -mel @gol
@@ -931,7 +934,7 @@ See RS/6000 and PowerPC Options.
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
-mcbcond -mno-cbcond @gol
-mfmaf -mno-fmaf -mpopc -mno-popc @gol
--mfix-at697f}
+-mfix-at697f -mfix-ut699}
@emph{SPU Options}
@gccoptlist{-mwarn-reloc -merror-reloc @gol
@@ -1463,11 +1466,18 @@ Define an argument called @var{key} with a value of @var{value}
for the plugin called @var{name}.
@item -fdump-ada-spec@r{[}-slim@r{]}
-For C and C++ source and include files, generate corresponding Ada
-specs. @xref{Generating Ada Bindings for C and C++ headers,,, gnat_ugn,
+@opindex fdump-ada-spec
+For C and C++ source and include files, generate corresponding Ada specs.
+@xref{Generating Ada Bindings for C and C++ headers,,, gnat_ugn,
GNAT User's Guide}, which provides detailed documentation on this feature.
+@item -fada-spec-parent=@var{unit}
+@opindex fada-spec-parent
+In conjunction with @option{-fdump-ada-spec@r{[}-slim@r{]}} above, generate
+Ada specs as child units of parent @var{unit}.
+
@item -fdump-go-spec=@var{file}
+@opindex fdump-go-spec
For input files in any language, generate corresponding Go
declarations in @var{file}. This generates Go @code{const},
@code{type}, @code{var}, and @code{func} declarations which may be a
@@ -11412,8 +11422,11 @@ before execution begins.
@item -mpic-register=@var{reg}
@opindex mpic-register
-Specify the register to be used for PIC addressing. The default is R10
-unless stack-checking is enabled, when R9 is used.
+Specify the register to be used for PIC addressing.
+For standard PIC base case, the default will be any suitable register
+determined by compiler. For single PIC base case, the default is
+@samp{R9} if target is EABI based or stack-checking is enabled,
+otherwise the default is @samp{R10}.
@item -mpoke-function-name
@opindex mpoke-function-name
@@ -17230,7 +17243,8 @@ following options:
-mpopcntb -mpopcntd -mpowerpc64 @gol
-mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float -mdouble-float @gol
-msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx @gol
--mcrypto -mdirect-move -mpower8-fusion -mpower8-vector -mquad-memory}
+-mcrypto -mdirect-move -mpower8-fusion -mpower8-vector @gol
+-mquad-memory -mquad-memory-atomic}
The particular options set for any particular CPU varies between
compiler versions, depending on what setting seems to produce optimal
@@ -17281,6 +17295,38 @@ the AltiVec instruction set. You may also need to set
@option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
enhancements.
+When @option{-maltivec} is used, rather than @option{-maltivec=le} or
+@option{-maltivec=be}, the element order for Altivec intrinsics such
+as @code{vec_splat}, @code{vec_extract}, and @code{vec_insert} will
+match array element order corresponding to the endianness of the
+target. That is, element zero identifies the leftmost element in a
+vector register when targeting a big-endian platform, and identifies
+the rightmost element in a vector register when targeting a
+little-endian platform.
+
+@item -maltivec=be
+@opindex maltivec=be
+Generate Altivec instructions using big-endian element order,
+regardless of whether the target is big- or little-endian. This is
+the default when targeting a big-endian platform.
+
+The element order is used to interpret element numbers in Altivec
+intrinsics such as @code{vec_splat}, @code{vec_extract}, and
+@code{vec_insert}. By default, these will match array element order
+corresponding to the endianness for the target.
+
+@item -maltivec=le
+@opindex maltivec=le
+Generate Altivec instructions using little-endian element order,
+regardless of whether the target is big- or little-endian. This is
+the default when targeting a little-endian platform. This option is
+currently ignored when targeting a big-endian platform.
+
+The element order is used to interpret element numbers in Altivec
+intrinsics such as @code{vec_splat}, @code{vec_extract}, and
+@code{vec_insert}. By default, these will match array element order
+corresponding to the endianness for the target.
+
@item -mvrsave
@itemx -mno-vrsave
@opindex mvrsave
@@ -17385,10 +17431,18 @@ the vector instructions.
@itemx -mno-quad-memory
@opindex mquad-memory
@opindex mno-quad-memory
-Generate code that uses (does not use) the quad word memory
+Generate code that uses (does not use) the non-atomic quad word memory
instructions. The @option{-mquad-memory} option requires use of
64-bit mode.
+@item -mquad-memory-atomic
+@itemx -mno-quad-memory-atomic
+@opindex mquad-memory-atomic
+@opindex mno-quad-memory-atomic
+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 -mfloat-gprs=@var{yes/single/double/no}
@itemx -mfloat-gprs
@opindex mfloat-gprs
@@ -17808,7 +17862,8 @@ SVR4 ABI)@.
@opindex mabi
Extend the current ABI with a particular extension, or remove such extension.
Valid values are @var{altivec}, @var{no-altivec}, @var{spe},
-@var{no-spe}, @var{ibmlongdouble}, @var{ieeelongdouble}@.
+@var{no-spe}, @var{ibmlongdouble}, @var{ieeelongdouble},
+@var{elfv1}, @var{elfv2}@.
@item -mabi=spe
@opindex mabi=spe
@@ -17830,6 +17885,20 @@ This is a PowerPC 32-bit SYSV ABI option.
Change the current ABI to use IEEE extended-precision long double.
This is a PowerPC 32-bit Linux ABI option.
+@item -mabi=elfv1
+@opindex mabi=elfv1
+Change the current ABI to use the ELFv1 ABI.
+This is the default ABI for big-endian PowerPC 64-bit Linux.
+Overriding the default ABI requires special system support and is
+likely to fail in spectacular ways.
+
+@item -mabi=elfv2
+@opindex mabi=elfv2
+Change the current ABI to use the ELFv2 ABI.
+This is the default ABI for little-endian PowerPC 64-bit Linux.
+Overriding the default ABI requires special system support and is
+likely to fail in spectacular ways.
+
@item -mprototype
@itemx -mno-prototype
@opindex mprototype
@@ -18115,6 +18184,23 @@ stack location in the function prologue if the function calls through
a pointer on AIX and 64-bit Linux systems. If the TOC value is not
saved in the prologue, it is saved just before the call through the
pointer. The @option{-mno-save-toc-indirect} option is the default.
+
+@item -mcompat-align-parm
+@itemx -mno-compat-align-parm
+@opindex mcompat-align-parm
+Generate (do not generate) code to pass structure parameters with a
+maximum alignment of 64 bits, for compatibility with older versions
+of GCC.
+
+Older versions of GCC (prior to 4.9.0) incorrectly did not align a
+structure parameter on a 128-bit boundary when that structure contained
+a member requiring 128-bit alignment. This is corrected in more
+recent versions of GCC. This option may be used to generate code
+that is compatible with functions compiled with older versions of
+GCC.
+
+In this version of the compiler, the @option{-mcompat-align-parm}
+is the default, except when using the Linux ELFv2 ABI.
@end table
@node RX Options
@@ -18494,6 +18580,21 @@ values have to be exact powers of 2 and @var{stack-size} has to be greater than
In order to be efficient the extra code makes the assumption that the stack starts
at an address aligned to the value given by @var{stack-size}.
The @var{stack-guard} option can only be used in conjunction with @var{stack-size}.
+
+@item -mhotpatch[=@var{halfwords}]
+@itemx -mno-hotpatch
+@opindex mhotpatch
+If the hotpatch option is enabled, a ``hot-patching'' function
+prologue is generated for all functions in the compilation unit.
+The funtion label is prepended with the given number of two-byte
+Nop instructions (@var{halfwords}, maximum 1000000) or 12 Nop
+instructions if no argument is present. Functions with a
+hot-patching prologue are never inlined automatically, and a
+hot-patching prologue is never generated for functions functions
+that are explicitly inline.
+
+This option can be overridden for individual functions with the
+@code{hotpatch} attribute.
@end table
@node Score Options
@@ -19178,10 +19279,10 @@ the rules of the ABI@.
Set the instruction set, register set, and instruction scheduling parameters
for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{hypersparc},
-@samp{leon}, @samp{sparclite}, @samp{f930}, @samp{f934}, @samp{sparclite86x},
-@samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc},
-@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3},
-and @samp{niagara4}.
+@samp{leon}, @samp{leon3}, @samp{sparclite}, @samp{f930}, @samp{f934},
+@samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9},
+@samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2},
+@samp{niagara3} and @samp{niagara4}.
Native Solaris and GNU/Linux toolchains also support the value @samp{native},
which selects the best architecture option for the host processor.
@@ -19200,7 +19301,7 @@ implementations.
cypress
@item v8
-supersparc, hypersparc, leon
+supersparc, hypersparc, leon, leon3
@item sparclite
f930, f934, sparclite86x
@@ -19262,10 +19363,11 @@ option @option{-mcpu=@var{cpu_type}} does.
The same values for @option{-mcpu=@var{cpu_type}} can be used for
@option{-mtune=@var{cpu_type}}, but the only useful values are those
that select a particular CPU implementation. Those are @samp{cypress},
-@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{f930}, @samp{f934},
-@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, @samp{ultrasparc3},
-@samp{niagara}, @samp{niagara2}, @samp{niagara3} and @samp{niagara4}. With
-native Solaris and GNU/Linux toolchains, @samp{native} can also be used.
+@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{leon3}, @samp{f930},
+@samp{f934}, @samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc},
+@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3} and
+@samp{niagara4}. With native Solaris and GNU/Linux toolchains, @samp{native}
+can also be used.
@item -mv8plus
@itemx -mno-v8plus
@@ -19334,6 +19436,11 @@ later.
@opindex mfix-at697f
Enable the documented workaround for the single erratum of the Atmel AT697F
processor (which corresponds to erratum #13 of the AT697E processor).
+
+@item -mfix-ut699
+@opindex mfix-ut699
+Enable the documented workarounds for the floating-point errata and the data
+cache nullify errata of the UT699 processor.
@end table
These @samp{-m} options are supported in addition to the above
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index ed624d6e4ea..dacb83a7009 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -2070,40 +2070,52 @@ Floating point register (containing 32-bit value)
Altivec vector register
@item wa
-Any VSX register
+Any VSX register if the -mvsx option was used or NO_REGS.
@item wd
-VSX vector register to hold vector double data
+VSX vector register to hold vector double data or NO_REGS.
@item wf
-VSX vector register to hold vector float data
+VSX vector register to hold vector float data or NO_REGS.
@item wg
-If @option{-mmfpgpr} was used, a floating point register
+If @option{-mmfpgpr} was used, a floating point register or NO_REGS.
@item wl
-If the LFIWAX instruction is enabled, a floating point register
+Floating point register if the LFIWAX instruction is enabled or NO_REGS.
@item wm
-If direct moves are enabled, a VSX register.
+VSX register if direct move instructions are enabled, or NO_REGS.
@item wn
-No register.
+No register (NO_REGS).
@item wr
-General purpose register if 64-bit mode is used
+General purpose register if 64-bit instructions are enabled or NO_REGS.
@item ws
-VSX vector register to hold scalar float data
+VSX vector register to hold scalar double values or NO_REGS.
@item wt
-VSX vector register to hold 128 bit integer
+VSX vector register to hold 128 bit integer or NO_REGS.
+
+@item wu
+Altivec register to use for float/32-bit int loads/stores or NO_REGS.
+
+@item wv
+Altivec register to use for double loads/stores or NO_REGS.
+
+@item ww
+FP or VSX register to perform float operations under @option{-mvsx} or NO_REGS.
@item wx
-If the STFIWX instruction is enabled, a floating point register
+Floating point register if the STFIWX instruction is enabled or NO_REGS.
+
+@item wy
+VSX vector register to hold scalar float values or NO_REGS.
@item wz
-If the LFIWZX instruction is enabled, a floating point register
+Floating point register if the LFIWZX instruction is enabled or NO_REGS.
@item wQ
A memory address that will work with the @code{lq} and @code{stq}
diff --git a/gcc/explow.c b/gcc/explow.c
index 08a66537b90..7da8bc75f19 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -106,10 +106,10 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
if (overflow)
gcc_unreachable ();
- return immed_double_int_const (v, VOIDmode);
+ return immed_double_int_const (v, mode);
}
- return GEN_INT (INTVAL (x) + c);
+ return gen_int_mode (INTVAL (x) + c, mode);
case CONST_DOUBLE:
{
@@ -124,7 +124,7 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
To fix, add constant support wider than CONST_DOUBLE. */
gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
- return immed_double_int_const (v, VOIDmode);
+ return immed_double_int_const (v, mode);
}
case MEM:
diff --git a/gcc/expr.c b/gcc/expr.c
index 2c5f21aa9a7..d39bdce4caf 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -119,7 +119,7 @@ struct store_by_pieces_d
int reverse;
};
-static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
+static void move_by_pieces_1 (insn_gen_fn, machine_mode,
struct move_by_pieces_d *);
static bool block_move_libcall_safe_for_call_parm (void);
static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT);
@@ -128,7 +128,7 @@ static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int);
-static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
+static void store_by_pieces_2 (insn_gen_fn, machine_mode,
struct store_by_pieces_d *);
static tree clear_storage_libcall_fn (int);
static rtx compress_float_constant (rtx, rtx);
@@ -1043,7 +1043,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
to make a move insn for that mode. DATA has all the other info. */
static void
-move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+move_by_pieces_1 (insn_gen_fn genfun, machine_mode mode,
struct move_by_pieces_d *data)
{
unsigned int size = GET_MODE_SIZE (mode);
@@ -1994,12 +1994,14 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
enum machine_mode mode = GET_MODE (tmps[i]);
unsigned int bytelen = GET_MODE_SIZE (mode);
- unsigned int adj_bytelen = bytelen;
+ unsigned int adj_bytelen;
rtx dest = dst;
/* Handle trailing fragments that run over the size of the struct. */
if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
adj_bytelen = ssize - bytepos;
+ else
+ adj_bytelen = bytelen;
if (GET_CODE (dst) == CONCAT)
{
@@ -2040,6 +2042,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
}
}
+ /* Handle trailing fragments that run over the size of the struct. */
if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
{
/* store_bit_field always takes its value from the lsb.
@@ -2057,16 +2060,22 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
shift, tmps[i], 0);
}
- bytelen = adj_bytelen;
+
+ /* Make sure not to write past the end of the struct. */
+ store_bit_field (dest,
+ adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
+ bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1,
+ VOIDmode, tmps[i]);
}
/* Optimize the access just a bit. */
- if (MEM_P (dest)
- && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest))
- || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode))
- && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
- && bytelen == GET_MODE_SIZE (mode))
+ else if (MEM_P (dest)
+ && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest))
+ || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode))
+ && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
+ && bytelen == GET_MODE_SIZE (mode))
emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
+
else
store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
0, 0, mode, tmps[i]);
@@ -2657,7 +2666,7 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
to make a move insn for that mode. DATA has all the other info. */
static void
-store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+store_by_pieces_2 (insn_gen_fn genfun, machine_mode mode,
struct store_by_pieces_d *data)
{
unsigned int size = GET_MODE_SIZE (mode);
@@ -4551,19 +4560,19 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
- tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
/* If the adjustment is larger than bitpos, we would have a negative bit
- position for the lower bound and this may wreak havoc later. This can
- occur only if we have a non-null offset, so adjust offset and bitpos
- to make the lower bound non-negative. */
+ position for the lower bound and this may wreak havoc later. Adjust
+ offset and bitpos to make the lower bound non-negative in that case. */
if (bitoffset > *bitpos)
{
HOST_WIDE_INT adjust = bitoffset - *bitpos;
-
gcc_assert ((adjust % BITS_PER_UNIT) == 0);
- gcc_assert (*offset != NULL_TREE);
*bitpos += adjust;
- *offset
- = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
+ if (*offset == NULL_TREE)
+ *offset = size_int (-adjust / BITS_PER_UNIT);
+ else
+ *offset
+ = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
*bitstart = 0;
}
else
@@ -4668,8 +4677,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
expand_insn (icode, 2, ops);
}
else
- store_bit_field (mem, GET_MODE_BITSIZE (mode),
- 0, 0, 0, mode, reg);
+ store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg);
return;
}
@@ -4698,6 +4706,15 @@ expand_assignment (tree to, tree from, bool nontemporal)
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &volatilep, true);
+ /* Make sure bitpos is not negative, it can wreak havoc later. */
+ if (bitpos < 0)
+ {
+ gcc_assert (offset == NULL_TREE);
+ offset = size_int (bitpos >> (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
+ bitpos &= BITS_PER_UNIT - 1;
+ }
+
if (TREE_CODE (to) == COMPONENT_REF
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
diff --git a/gcc/expr.h b/gcc/expr.h
index 15fcb471d8d..98c9daeda9c 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -521,8 +521,8 @@ extern rtx expand_divmod (int, enum tree_code, enum machine_mode, rtx, rtx,
rtx, int);
#endif
-extern void locate_and_pad_parm (enum machine_mode, tree, int, int, tree,
- struct args_size *,
+extern void locate_and_pad_parm (enum machine_mode, tree, int, int, int,
+ tree, struct args_size *,
struct locate_and_pad_arg_data *);
/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5e3486373d0..7433686a6fb 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -469,11 +469,24 @@ negate_expr_p (tree t)
and actually traps on some architectures. But if overflow is
undefined, we can negate, because - (INT_MIN / 1) is an
overflow. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (t))
- && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
- break;
- return negate_expr_p (TREE_OPERAND (t, 1))
- || negate_expr_p (TREE_OPERAND (t, 0));
+ if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
+ break;
+ /* If overflow is undefined then we have to be careful because
+ we ask whether it's ok to associate the negate with the
+ division which is not ok for example for
+ -((a - b) / c) where (-(a - b)) / c may invoke undefined
+ overflow because of negating INT_MIN. So do not use
+ negate_expr_p here but open-code the two important cases. */
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == NEGATE_EXPR
+ || (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
+ && may_negate_without_overflow_p (TREE_OPERAND (t, 0))))
+ return true;
+ }
+ else if (negate_expr_p (TREE_OPERAND (t, 0)))
+ return true;
+ return negate_expr_p (TREE_OPERAND (t, 1));
case NOP_EXPR:
/* Negate -((double)float) as (double)(-float). */
@@ -653,16 +666,20 @@ fold_negate_expr (location_t loc, tree t)
return fold_build2_loc (loc, TREE_CODE (t), type,
TREE_OPERAND (t, 0), negate_expr (tem));
}
+ /* If overflow is undefined then we have to be careful because
+ we ask whether it's ok to associate the negate with the
+ division which is not ok for example for
+ -((a - b) / c) where (-(a - b)) / c may invoke undefined
+ overflow because of negating INT_MIN. So do not use
+ negate_expr_p here but open-code the two important cases. */
tem = TREE_OPERAND (t, 0);
- if (negate_expr_p (tem))
- {
- if (INTEGRAL_TYPE_P (type)
- && (TREE_CODE (tem) != INTEGER_CST
- || tree_int_cst_equal (tem, TYPE_MIN_VALUE (type))))
- fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
- return fold_build2_loc (loc, TREE_CODE (t), type,
- negate_expr (tem), TREE_OPERAND (t, 1));
- }
+ if ((INTEGRAL_TYPE_P (type)
+ && (TREE_CODE (tem) == NEGATE_EXPR
+ || (TREE_CODE (tem) == INTEGER_CST
+ && may_negate_without_overflow_p (tem))))
+ || !INTEGRAL_TYPE_P (type))
+ return fold_build2_loc (loc, TREE_CODE (t), type,
+ negate_expr (tem), TREE_OPERAND (t, 1));
}
break;
@@ -2647,10 +2664,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
case COMPONENT_REF:
/* Handle operand 2 the same as for ARRAY_REF. Operand 0
may be NULL when we're called to compare MEM_EXPRs. */
- if (!OP_SAME_WITH_NULL (0))
+ if (!OP_SAME_WITH_NULL (0)
+ || !OP_SAME (1))
return 0;
flags &= ~OEP_CONSTANT_ADDRESS_OF;
- return OP_SAME (1) && OP_SAME_WITH_NULL (2);
+ return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
if (!OP_SAME (0))
@@ -4220,7 +4238,7 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
}
if (low == 0 && high == 0)
- return build_int_cst (type, 1);
+ return omit_one_operand_loc (loc, type, build_int_cst (type, 1), exp);
if (low == 0)
return fold_build2_loc (loc, LE_EXPR, type, exp,
@@ -9851,6 +9869,24 @@ exact_inverse (tree type, tree cst)
}
}
+/* Mask out the tz least significant bits of X of type TYPE where
+ tz is the number of trailing zeroes in Y. */
+static double_int
+mask_with_tz (tree type, double_int x, double_int y)
+{
+ int tz = y.trailing_zeros ();
+
+ if (tz > 0)
+ {
+ double_int mask;
+
+ mask = ~double_int::mask (tz);
+ mask = mask.ext (TYPE_PRECISION (type), TYPE_UNSIGNED (type));
+ return mask & x;
+ }
+ return x;
+}
+
/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. LOC is the location of the resulting expression.
Return the folded expression if folding is successful. Otherwise,
@@ -10892,6 +10928,13 @@ fold_binary_loc (location_t loc,
fold_build2_loc (loc, MULT_EXPR, type,
build_int_cst (type, 2) , arg1));
+ /* ((T) (X /[ex] C)) * C cancels out if the conversion is
+ sign-changing only. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg0) == EXACT_DIV_EXPR
+ && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0))
+ return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+
strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
@@ -11175,6 +11218,8 @@ fold_binary_loc (location_t loc,
{
double_int c1, c2, c3, msk;
int width = TYPE_PRECISION (type), w;
+ bool try_simplify = true;
+
c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
c2 = tree_to_double_int (arg1);
@@ -11209,7 +11254,21 @@ fold_binary_loc (location_t loc,
break;
}
}
- if (c3 != c1)
+
+ /* If X is a tree of the form (Y * K1) & K2, this might conflict
+ with that optimization from the BIT_AND_EXPR optimizations.
+ This could end up in an infinite recursion. */
+ if (TREE_CODE (TREE_OPERAND (arg0, 0)) == MULT_EXPR
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
+ == INTEGER_CST)
+ {
+ tree t = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
+ double_int masked = mask_with_tz (type, c3, tree_to_double_int (t));
+
+ try_simplify = (masked != c1);
+ }
+
+ if (try_simplify && c3 != c1)
return fold_build2_loc (loc, BIT_IOR_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, type,
TREE_OPERAND (arg0, 0),
@@ -11599,22 +11658,16 @@ fold_binary_loc (location_t loc,
&& TREE_CODE (arg0) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- int arg1tz
- = tree_to_double_int (TREE_OPERAND (arg0, 1)).trailing_zeros ();
- if (arg1tz > 0)
- {
- double_int arg1mask, masked;
- arg1mask = ~double_int::mask (arg1tz);
- arg1mask = arg1mask.ext (TYPE_PRECISION (type),
- TYPE_UNSIGNED (type));
- masked = arg1mask & tree_to_double_int (arg1);
- if (masked.is_zero ())
- return omit_two_operands_loc (loc, type, build_zero_cst (type),
- arg0, arg1);
- else if (masked != tree_to_double_int (arg1))
- return fold_build2_loc (loc, code, type, op0,
- double_int_to_tree (type, masked));
- }
+ double_int masked
+ = mask_with_tz (type, tree_to_double_int (arg1),
+ tree_to_double_int (TREE_OPERAND (arg0, 1)));
+
+ if (masked.is_zero ())
+ return omit_two_operands_loc (loc, type, build_zero_cst (type),
+ arg0, arg1);
+ else if (masked != tree_to_double_int (arg1))
+ return fold_build2_loc (loc, code, type, op0,
+ double_int_to_tree (type, masked));
}
/* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
@@ -14040,14 +14093,29 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
&& integer_zerop (op2)
&& (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
{
+ /* sign_bit_p looks through both zero and sign extensions,
+ but for this optimization only sign extensions are
+ usable. */
+ tree tem2 = TREE_OPERAND (arg0, 0);
+ while (tem != tem2)
+ {
+ if (TREE_CODE (tem2) != NOP_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (tem2, 0))))
+ {
+ tem = NULL_TREE;
+ break;
+ }
+ tem2 = TREE_OPERAND (tem2, 0);
+ }
/* sign_bit_p only checks ARG1 bits within A's precision.
If <sign bit of A> has wider type than A, bits outside
of A's precision in <sign bit of A> need to be checked.
If they are all 0, this optimization needs to be done
in unsigned A's type, if they are all 1 in signed A's type,
otherwise this can't be done. */
- if (TYPE_PRECISION (TREE_TYPE (tem))
- < TYPE_PRECISION (TREE_TYPE (arg1))
+ if (tem
+ && TYPE_PRECISION (TREE_TYPE (tem))
+ < TYPE_PRECISION (TREE_TYPE (arg1))
&& TYPE_PRECISION (TREE_TYPE (tem))
< TYPE_PRECISION (type))
{
@@ -16527,7 +16595,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
tree index = bitsize_int (indexi);
- if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+ if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type))
return fold_build3_loc (loc,
BIT_FIELD_REF, type, op00,
part_width, index);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 77abdc0ec66..3cf10058273 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,141 @@
+2014-01-11 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-12-29 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/59612
+ PR fortran/57042
+ * dump-parse-tree.c (show_typespec): Check for charlen.
+ * invoke.texi: Fix documentation of -fdump-fortran-optimized and
+ -fdump-parse-tree.
+
+2014-01-04 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2014-01-02 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/59654
+ * resolve.c (resolve_typebound_procedures): No need to create the vtab
+ here.
+
+2013-12-31 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-12-30 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58998
+ * resolve.c (resolve_symbol): Check that symbol is not only flavorless
+ but also untyped.
+
+2013-12-18 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-12-15 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/59493
+ * class.c (gfc_find_intrinsic_vtab): Handle BT_CLASS.
+
+2013-11-30 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/57445
+ * trans-expr.c (gfc_conv_class_to_class): Remove spurious
+ assert.
+
+2013-11-17 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-11-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58471
+ * primary.c (gfc_expr_attr): Check for result symbol.
+
+2013-11-16 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-09-20 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58099
+ * expr.c (gfc_check_pointer_assign): Remove second call to
+ 'gfc_compare_interfaces' with swapped arguments.
+ * interface.c (gfc_compare_interfaces): Symmetrize the call to
+ 'check_result_characteristics' by calling it with swapped arguments.
+
+2013-11-16 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58771
+ * trans-io.c (transfer_expr): If the backend_decl for a derived
+ type is missing, build it with gfc_typenode_for_spec.
+
+2013-11-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/58989
+ * check.c (gfc_check_reshape): ensure that shape is a constant
+ expression.
+
+2013-11-02 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-09-23 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58355
+ * decl.c (check_extended_derived_type): Prevent segfault, modify error
+ message.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-04 Tobias Burnus <burnus@net-b.de>
+
+ Backport from mainline
+ 2013-09-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/57697
+ PR fortran/58469
+ * resolve.c (generate_component_assignments): Avoid double free
+ at runtime and freeing a still-being used expr.
+
+2013-08-24 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/57798
+ * trans-array.c (gfc_conv_ss_startstride, set_loop_bounds,
+ gfc_set_delta): Generate preliminary code before the outermost loop.
+
+2013-08-24 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (gfc_conv_section_startstride): Move &loop->pre access
+ to the callers.
+ (gfc_conv_ss_startstride, gfc_conv_expr_descriptor): Update callers.
+
+2013-08-24 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from trunk:
+ 2013-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58185
+ * match.c (copy_ts_from_selector_to_associate): Only build class
+ container for polymorphic selector. Some cleanup.
+
+2013-08-11 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from trunk:
+ 2013-08-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58058
+ * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Free the temporary
+ string, if necessary.
+
+2013-07-28 Tobias Burnus <burnus@net-b.de>
+
+ Backport from mainline
+ 2013-05-28 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/57435
+ * module.c (check_for_ambiguous): Avoid null pointer deref.
+
2013-07-08 Tobias Burnus <burnus@net-b.de>
PR fortran/57785
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 586adee8b34..c9520f628ea 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -3208,7 +3208,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
"than %d elements", &shape->where, GFC_MAX_DIMENSIONS);
return FAILURE;
}
- else if (shape->expr_type == EXPR_ARRAY)
+ else if (shape->expr_type == EXPR_ARRAY && gfc_is_constant_expr (shape))
{
gfc_expr *e;
int i, extent;
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index d8e7b6ded7a..55c072b8235 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -2486,7 +2486,7 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts)
return NULL;
/* Sometimes the typespec is passed from a single call. */
- if (ts->type == BT_DERIVED)
+ if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
return gfc_find_derived_vtab (ts->u.derived);
/* Find the top-level namespace. */
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 72c511c8b24..b748cfd9561 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -7384,6 +7384,7 @@ syntax:
/* Check a derived type that is being extended. */
+
static gfc_symbol*
check_extended_derived_type (char *name)
{
@@ -7395,14 +7396,15 @@ check_extended_derived_type (char *name)
return NULL;
}
+ extended = gfc_find_dt_in_generic (extended);
+
+ /* F08:C428. */
if (!extended)
{
- gfc_error ("No such symbol in TYPE definition at %C");
+ gfc_error ("Symbol '%s' at %C has not been previously defined", name);
return NULL;
}
- extended = gfc_find_dt_in_generic (extended);
-
if (extended->attr.flavor != FL_DERIVED)
{
gfc_error ("'%s' in EXTENDS expression at %C is not a "
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 14ff0041219..501a4ebb566 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -110,7 +110,8 @@ show_typespec (gfc_typespec *ts)
break;
case BT_CHARACTER:
- show_expr (ts->u.cl->length);
+ if (ts->u.cl)
+ show_expr (ts->u.cl->length);
fprintf(dumpfile, " %d", ts->kind);
break;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index d16bdb09089..7f101ba03d5 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -3555,14 +3555,6 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
return FAILURE;
}
- if (!gfc_compare_interfaces (s2, s1, name, 0, 1,
- err, sizeof(err), NULL, NULL))
- {
- gfc_error ("Interface mismatch in procedure pointer assignment "
- "at %L: %s", &rvalue->where, err);
- return FAILURE;
- }
-
return SUCCESS;
}
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 895eee48c2f..725cd8a4b76 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1245,7 +1245,8 @@ check_result_characteristics (gfc_symbol *s1, gfc_symbol *s2,
return FAILURE;
}
- if (r1->ts.u.cl->length)
+ if (s1->ts.u.cl && s1->ts.u.cl->length
+ && s2->ts.u.cl && s2->ts.u.cl->length)
{
int compval = gfc_dep_compare_expr (r1->ts.u.cl->length,
r2->ts.u.cl->length);
@@ -1367,8 +1368,8 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
if (s1->attr.function && s2->attr.function)
{
/* If both are functions, check result characteristics. */
- if (check_result_characteristics (s1, s2, errmsg, err_len)
- == FAILURE)
+ if (check_result_characteristics (s1, s2, errmsg, err_len) == FAILURE
+ || check_result_characteristics (s2, s1, errmsg, err_len) == FAILURE)
return 0;
}
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index db958f9b37f..b0b43d8478b 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -982,11 +982,12 @@ Output the internal parse tree after translating the source program
into internal representation. Only really useful for debugging the
GNU Fortran compiler itself.
-@item -fdump-optimized-tree
+@item -fdump-fortran-optimized
@opindex @code{fdump-fortran-optimized}
Output the parse tree after front-end optimization. Only really
useful for debugging the GNU Fortran compiler itself.
+@item -fdump-parse-tree
@opindex @code{fdump-parse-tree}
Output the internal parse tree after translating the source program
into internal representation. Only really useful for debugging the
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index e9a701bb608..a320248fe3e 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -5142,7 +5142,6 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector)
{
gfc_ref *ref;
gfc_symbol *assoc_sym;
- int i;
assoc_sym = associate->symtree->n.sym;
@@ -5153,9 +5152,8 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector)
while (ref && ref->next)
ref = ref->next;
- if (selector->ts.type == BT_CLASS
- && CLASS_DATA (selector)->as
- && ref && ref->type == REF_ARRAY)
+ if (selector->ts.type == BT_CLASS && CLASS_DATA (selector)->as
+ && ref && ref->type == REF_ARRAY)
{
/* Ensure that the array reference type is set. We cannot use
gfc_resolve_expr at this point, so the usable parts of
@@ -5163,7 +5161,7 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector)
if (ref->u.ar.type == AR_UNKNOWN)
{
ref->u.ar.type = AR_ELEMENT;
- for (i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
+ for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
if (ref->u.ar.dimen_type[i] == DIMEN_RANGE
|| ref->u.ar.dimen_type[i] == DIMEN_VECTOR
|| (ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN
@@ -5182,37 +5180,19 @@ copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector)
selector->rank = 0;
}
- if (selector->ts.type != BT_CLASS)
+ if (selector->rank)
{
- /* The correct class container has to be available. */
- if (selector->rank)
- {
- assoc_sym->attr.dimension = 1;
- assoc_sym->as = gfc_get_array_spec ();
- assoc_sym->as->rank = selector->rank;
- assoc_sym->as->type = AS_DEFERRED;
- }
- else
- assoc_sym->as = NULL;
-
- assoc_sym->ts.type = BT_CLASS;
- assoc_sym->ts.u.derived = selector->ts.u.derived;
- assoc_sym->attr.pointer = 1;
- gfc_build_class_symbol (&assoc_sym->ts, &assoc_sym->attr,
- &assoc_sym->as, false);
+ assoc_sym->attr.dimension = 1;
+ assoc_sym->as = gfc_get_array_spec ();
+ assoc_sym->as->rank = selector->rank;
+ assoc_sym->as->type = AS_DEFERRED;
}
else
+ assoc_sym->as = NULL;
+
+ if (selector->ts.type == BT_CLASS)
{
/* The correct class container has to be available. */
- if (selector->rank)
- {
- assoc_sym->attr.dimension = 1;
- assoc_sym->as = gfc_get_array_spec ();
- assoc_sym->as->rank = selector->rank;
- assoc_sym->as->type = AS_DEFERRED;
- }
- else
- assoc_sym->as = NULL;
assoc_sym->ts.type = BT_CLASS;
assoc_sym->ts.u.derived = CLASS_DATA (selector)->ts.u.derived;
assoc_sym->attr.pointer = 1;
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 1b385558424..f0f8f971ed8 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4465,7 +4465,7 @@ check_for_ambiguous (gfc_symbol *st_sym, pointer_info *info)
module_locus locus;
symbol_attribute attr;
- if (st_sym->name == gfc_current_ns->proc_name->name)
+ if (gfc_current_ns->proc_name && st_sym->name == gfc_current_ns->proc_name->name)
{
gfc_error ("'%s' of module '%s', imported at %C, is also the name of the "
"current program unit", st_sym->name, module_name);
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index d14922416cf..db288b59a85 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2252,7 +2252,7 @@ gfc_expr_attr (gfc_expr *e)
case EXPR_FUNCTION:
gfc_clear_attr (&attr);
- if (e->value.function.esym != NULL)
+ if (e->value.function.esym && e->value.function.esym->result)
{
gfc_symbol *sym = e->value.function.esym->result;
attr = sym->attr;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index a5966b18db0..5a06498a19b 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -9997,6 +9997,26 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
temp_code = build_assignment (EXEC_ASSIGN,
t1, (*code)->expr1,
NULL, NULL, (*code)->loc);
+
+ /* For allocatable LHS, check whether it is allocated. Note
+ that allocatable components with defined assignment are
+ not yet support. See PR 57696. */
+ if ((*code)->expr1->symtree->n.sym->attr.allocatable)
+ {
+ gfc_code *block;
+ gfc_expr *e =
+ gfc_lval_expr_from_sym ((*code)->expr1->symtree->n.sym);
+ block = gfc_get_code ();
+ block->op = EXEC_IF;
+ block->block = gfc_get_code ();
+ block->block->op = EXEC_IF;
+ block->block->expr1
+ = gfc_build_intrinsic_call (ns,
+ GFC_ISYM_ALLOCATED, "allocated",
+ (*code)->loc, 1, e);
+ block->block->next = temp_code;
+ temp_code = block;
+ }
add_code_to_chain (&temp_code, &tmp_head, &tmp_tail);
}
@@ -10005,8 +10025,37 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
gfc_free_expr (this_code->ext.actual->expr);
this_code->ext.actual->expr = gfc_copy_expr (t1);
add_comp_ref (this_code->ext.actual->expr, comp1);
+
+ /* If the LHS variable is allocatable and wasn't allocated and
+ the temporary is allocatable, pointer assign the address of
+ the freshly allocated LHS to the temporary. */
+ if ((*code)->expr1->symtree->n.sym->attr.allocatable
+ && gfc_expr_attr ((*code)->expr1).allocatable)
+ {
+ gfc_code *block;
+ gfc_expr *cond;
+
+ cond = gfc_get_expr ();
+ cond->ts.type = BT_LOGICAL;
+ cond->ts.kind = gfc_default_logical_kind;
+ cond->expr_type = EXPR_OP;
+ cond->where = (*code)->loc;
+ cond->value.op.op = INTRINSIC_NOT;
+ cond->value.op.op1 = gfc_build_intrinsic_call (ns,
+ GFC_ISYM_ALLOCATED, "allocated",
+ (*code)->loc, 1, gfc_copy_expr (t1));
+ block = gfc_get_code ();
+ block->op = EXEC_IF;
+ block->block = gfc_get_code ();
+ block->block->op = EXEC_IF;
+ block->block->expr1 = cond;
+ block->block->next = build_assignment (EXEC_POINTER_ASSIGN,
+ t1, (*code)->expr1,
+ NULL, NULL, (*code)->loc);
+ add_code_to_chain (&block, &head, &tail);
+ }
}
- }
+ }
else if (this_code->op == EXEC_ASSIGN && !this_code->next)
{
/* Don't add intrinsic assignments since they are already
@@ -10028,13 +10077,6 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
}
}
- /* This is probably not necessary. */
- if (this_code)
- {
- gfc_free_statements (this_code);
- this_code = NULL;
- }
-
/* Put the temporary assignments at the top of the generated code. */
if (tmp_head && component_assignment_level == 1)
{
@@ -10043,6 +10085,30 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
tmp_head = tmp_tail = NULL;
}
+ // If we did a pointer assignment - thus, we need to ensure that the LHS is
+ // not accidentally deallocated. Hence, nullify t1.
+ if (t1 && (*code)->expr1->symtree->n.sym->attr.allocatable
+ && gfc_expr_attr ((*code)->expr1).allocatable)
+ {
+ gfc_code *block;
+ gfc_expr *cond;
+ gfc_expr *e;
+
+ e = gfc_lval_expr_from_sym ((*code)->expr1->symtree->n.sym);
+ cond = gfc_build_intrinsic_call (ns, GFC_ISYM_ASSOCIATED, "associated",
+ (*code)->loc, 2, gfc_copy_expr (t1), e);
+ block = gfc_get_code ();
+ block->op = EXEC_IF;
+ block->block = gfc_get_code ();
+ block->block->op = EXEC_IF;
+ block->block->expr1 = cond;
+ block->block->next = build_assignment (EXEC_POINTER_ASSIGN,
+ t1, gfc_get_null_expr (&(*code)->loc),
+ NULL, NULL, (*code)->loc);
+ gfc_append_code (tail, block);
+ tail = block;
+ }
+
/* Now attach the remaining code chain to the input code. Step on
to the end of the new code since resolution is complete. */
gcc_assert ((*code)->op == EXEC_ASSIGN);
@@ -10052,7 +10118,8 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
gfc_free_expr ((*code)->expr1);
gfc_free_expr ((*code)->expr2);
**code = *head;
- free (head);
+ if (head != tail)
+ free (head);
*code = tail;
component_assignment_level--;
@@ -12358,9 +12425,6 @@ resolve_typebound_procedures (gfc_symbol* derived)
resolve_bindings_derived = derived;
resolve_bindings_result = SUCCESS;
- /* Make sure the vtab has been generated. */
- gfc_find_derived_vtab (derived);
-
if (derived->f2k_derived->tb_sym_root)
gfc_traverse_symtree (derived->f2k_derived->tb_sym_root,
&resolve_typebound_procedure);
@@ -13189,7 +13253,8 @@ resolve_symbol (gfc_symbol *sym)
if (sym->attr.flavor == FL_UNKNOWN
|| (sym->attr.flavor == FL_PROCEDURE && !sym->attr.intrinsic
&& !sym->attr.generic && !sym->attr.external
- && sym->attr.if_source == IFSRC_UNKNOWN))
+ && sym->attr.if_source == IFSRC_UNKNOWN
+ && sym->ts.type == BT_UNKNOWN))
{
/* If we find that a flavorless symbol is an interface in one of the
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 75fed2f651c..b34f6fb19a6 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -3674,7 +3674,7 @@ evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
/* Calculate the lower bound of an array section. */
static void
-gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
+gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
{
gfc_expr *stride = NULL;
tree desc;
@@ -3703,12 +3703,12 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
/* Calculate the start of the range. For vector subscripts this will
be the range of the vector. */
- evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
+ evaluate_bound (block, info->start, ar->start, desc, dim, true);
/* Similarly calculate the end. Although this is not used in the
scalarizer, it is needed when checking bounds and where the end
is an expression with side-effects. */
- evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
+ evaluate_bound (block, info->end, ar->end, desc, dim, false);
/* Calculate the stride. */
if (stride == NULL)
@@ -3717,8 +3717,8 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
{
gfc_init_se (&se, NULL);
gfc_conv_expr_type (&se, stride, gfc_array_index_type);
- gfc_add_block_to_block (&loop->pre, &se.pre);
- info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
+ gfc_add_block_to_block (block, &se.pre);
+ info->stride[dim] = gfc_evaluate_now (se.expr, block);
}
}
@@ -3735,6 +3735,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
gfc_ss *ss;
tree desc;
+ gfc_loopinfo * const outer_loop = outermost_loop (loop);
+
loop->dimen = 0;
/* Determine the rank of the loop. */
for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
@@ -3794,10 +3796,11 @@ done:
/* Get the descriptor for the array. If it is a cross loops array,
we got the descriptor already in the outermost loop. */
if (ss->parent == NULL)
- gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
+ gfc_conv_ss_descriptor (&outer_loop->pre, ss,
+ !loop->array_parameter);
for (n = 0; n < ss->dimen; n++)
- gfc_conv_section_startstride (loop, ss, ss->dim[n]);
+ gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
break;
case GFC_SS_INTRINSIC:
@@ -3833,7 +3836,7 @@ done:
fold_convert (gfc_array_index_type,
rank),
gfc_index_one_node);
- info->end[0] = gfc_evaluate_now (tmp, &loop->pre);
+ info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
info->start[0] = gfc_index_zero_node;
info->stride[0] = gfc_index_one_node;
continue;
@@ -4115,7 +4118,7 @@ done:
}
tmp = gfc_finish_block (&block);
- gfc_add_expr_to_block (&loop->pre, tmp);
+ gfc_add_expr_to_block (&outer_loop->pre, tmp);
}
for (loop = loop->nested; loop; loop = loop->next)
@@ -4398,6 +4401,8 @@ set_loop_bounds (gfc_loopinfo *loop)
mpz_t i;
bool nonoptional_arr;
+ gfc_loopinfo * const outer_loop = outermost_loop (loop);
+
loopspec = loop->specloop;
mpz_init (i);
@@ -4583,7 +4588,7 @@ set_loop_bounds (gfc_loopinfo *loop)
else
{
/* Set the delta for this section. */
- info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
+ info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
/* Number of iterations is (end - start + step) / step.
with start = 0, this simplifies to
last = end / step;
@@ -4595,7 +4600,7 @@ set_loop_bounds (gfc_loopinfo *loop)
gfc_array_index_type, tmp, info->stride[dim]);
tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
tmp, build_int_cst (gfc_array_index_type, -1));
- loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
+ loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
/* Make the loop variable start at 0. */
loop->from[n] = gfc_index_zero_node;
}
@@ -4671,6 +4676,8 @@ gfc_set_delta (gfc_loopinfo *loop)
tree tmp;
int n, dim;
+ gfc_loopinfo * const outer_loop = outermost_loop (loop);
+
loopspec = loop->specloop;
/* Calculate the translation from loop variables to array indices. */
@@ -4706,7 +4713,7 @@ gfc_set_delta (gfc_loopinfo *loop)
gfc_array_index_type,
info->start[dim], tmp);
- info->delta[dim] = gfc_evaluate_now (tmp, &loop->pre);
+ info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
}
}
}
@@ -6690,10 +6697,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
/* Make sure the call to gfc_conv_section_startstride won't
- generate unnecessary code to calculate stride. */
+ generate unnecessary code to calculate stride. */
gcc_assert (ar->stride[n + ndim] == NULL);
- gfc_conv_section_startstride (&loop, ss, n + ndim);
+ gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
loop.from[n + loop.dimen] = info->start[n + ndim];
loop.to[n + loop.dimen] = info->end[n + ndim];
}
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 2c3ff1fc3cd..f1452fa423a 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -670,7 +670,6 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
gfc_add_modify (&parmse->post, vptr,
fold_convert (TREE_TYPE (vptr), ctree));
- gcc_assert (!optional || (optional && !copyback));
if (optional)
{
tree tmp2;
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index a2bb2a78ee7..ddd9eaea5c2 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -5653,8 +5653,7 @@ scalar_transfer:
if (expr->ts.type == BT_CHARACTER)
{
- tree direct;
- tree indirect;
+ tree direct, indirect, free;
ptr = convert (gfc_get_pchar_type (expr->ts.kind), source);
tmpdecl = gfc_create_var (gfc_get_pchar_type (expr->ts.kind),
@@ -5687,6 +5686,13 @@ scalar_transfer:
tmp = build3_v (COND_EXPR, tmp, direct, indirect);
gfc_add_expr_to_block (&se->pre, tmp);
+ /* Free the temporary string, if necessary. */
+ free = gfc_call_free (tmpdecl);
+ tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
+ dest_word_len, source_bytes);
+ tmp = build3_v (COND_EXPR, tmp, free, build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&se->post, tmp);
+
se->expr = tmpdecl;
se->string_length = fold_convert (gfc_charlen_type_node, dest_word_len);
}
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 9394810f01f..a11453d082d 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -243,16 +243,16 @@ gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
/* The code to generate the error. */
gfc_start_block (&block);
-
+
arg1 = gfc_build_addr_expr (NULL_TREE, var);
-
+
arg2 = build_int_cst (integer_type_node, error_code),
-
+
asprintf (&message, "%s", _(msgid));
arg3 = gfc_build_addr_expr (pchar_type_node,
gfc_build_localized_cstring_const (message));
free (message);
-
+
tmp = build_call_expr_loc (input_location,
gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
@@ -521,7 +521,7 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
"Unit number in I/O statement too small",
&se.pre);
-
+
/* UNIT numbers should be less than the max. */
val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
@@ -1000,7 +1000,7 @@ gfc_trans_open (gfc_code * code)
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
p->convert);
-
+
if (p->newunit)
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
p->newunit);
@@ -1234,7 +1234,7 @@ gfc_trans_inquire (gfc_code * code)
{
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
p->exist);
-
+
if (p->unit && !p->iostat)
{
p->iostat = create_dummy_iostat ();
@@ -1322,7 +1322,7 @@ gfc_trans_inquire (gfc_code * code)
if (p->pad)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
p->pad);
-
+
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
p->convert);
@@ -1547,7 +1547,7 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name,
tree dtype;
tree dt_parm_addr;
tree decl = NULL_TREE;
- int n_dim;
+ int n_dim;
int itype;
int rank = 0;
@@ -2032,7 +2032,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
if (gfc_notification_std (GFC_STD_GNU) != SILENT)
{
gfc_error_now ("Derived type '%s' at %L has PRIVATE components",
- ts->u.derived->name, code != NULL ? &(code->loc) :
+ ts->u.derived->name, code != NULL ? &(code->loc) :
&gfc_current_locus);
return;
}
@@ -2041,7 +2041,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
ts->kind = ts->u.derived->ts.kind;
ts->f90_type = ts->u.derived->ts.f90_type;
}
-
+
kind = ts->kind;
function = NULL;
arg2 = NULL;
@@ -2123,7 +2123,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
function = iocall[IOCALL_X_CHARACTER_WIDE];
else
function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
-
+
tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
tmp = build_call_expr_loc (input_location,
function, 4, tmp, addr_expr, arg2, arg3);
@@ -2158,6 +2158,12 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
expr = build_fold_indirect_ref_loc (input_location,
expr);
+ /* Make sure that the derived type has been built. An external
+ function, if only referenced in an io statement requires this
+ check (see PR58771). */
+ if (ts->u.derived->backend_decl == NULL_TREE)
+ tmp = gfc_typenode_for_spec (ts);
+
for (c = ts->u.derived->components; c; c = c->next)
{
field = c->backend_decl;
diff --git a/gcc/function.c b/gcc/function.c
index e673f21a57d..1ab49c18c8b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2507,6 +2507,7 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
}
locate_and_pad_parm (data->promoted_mode, data->passed_type, in_regs,
+ all->reg_parm_stack_space,
entry_parm ? data->partial : 0, current_function_decl,
&all->stack_args_size, &data->locate);
@@ -3485,11 +3486,7 @@ assign_parms (tree fndecl)
/* Adjust function incoming argument size for alignment and
minimum length. */
-#ifdef REG_PARM_STACK_SPACE
- crtl->args.size = MAX (crtl->args.size,
- REG_PARM_STACK_SPACE (fndecl));
-#endif
-
+ crtl->args.size = MAX (crtl->args.size, all.reg_parm_stack_space);
crtl->args.size = CEIL_ROUND (crtl->args.size,
PARM_BOUNDARY / BITS_PER_UNIT);
@@ -3693,6 +3690,9 @@ gimplify_parameters (void)
IN_REGS is nonzero if the argument will be passed in registers. It will
never be set if REG_PARM_STACK_SPACE is not defined.
+ REG_PARM_STACK_SPACE is the number of bytes of stack space reserved
+ for arguments which are passed in registers.
+
FNDECL is the function in which the argument was defined.
There are two types of rounding that are done. The first, controlled by
@@ -3713,19 +3713,16 @@ gimplify_parameters (void)
void
locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
- int partial, tree fndecl ATTRIBUTE_UNUSED,
+ int reg_parm_stack_space, int partial,
+ tree fndecl ATTRIBUTE_UNUSED,
struct args_size *initial_offset_ptr,
struct locate_and_pad_arg_data *locate)
{
tree sizetree;
enum direction where_pad;
unsigned int boundary, round_boundary;
- int reg_parm_stack_space = 0;
int part_size_in_regs;
-#ifdef REG_PARM_STACK_SPACE
- reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
-
/* If we have found a stack parm before we reach the end of the
area reserved for registers, skip that area. */
if (! in_regs)
@@ -3743,7 +3740,6 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
initial_offset_ptr->constant = reg_parm_stack_space;
}
}
-#endif /* REG_PARM_STACK_SPACE */
part_size_in_regs = (reg_parm_stack_space == 0 ? partial : 0);
@@ -3806,11 +3802,7 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
locate->slot_offset.constant += part_size_in_regs;
- if (!in_regs
-#ifdef REG_PARM_STACK_SPACE
- || REG_PARM_STACK_SPACE (fndecl) > 0
-#endif
- )
+ if (!in_regs || reg_parm_stack_space > 0)
pad_to_arg_alignment (&locate->slot_offset, boundary,
&locate->alignment_pad);
@@ -3830,11 +3822,7 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
pad_below (&locate->offset, passed_mode, sizetree);
#else /* !ARGS_GROW_DOWNWARD */
- if (!in_regs
-#ifdef REG_PARM_STACK_SPACE
- || REG_PARM_STACK_SPACE (fndecl) > 0
-#endif
- )
+ if (!in_regs || reg_parm_stack_space > 0)
pad_to_arg_alignment (initial_offset_ptr, boundary,
&locate->alignment_pad);
locate->slot_offset = *initial_offset_ptr;
@@ -5093,6 +5081,7 @@ expand_function_end (void)
amount. BLKmode results are handled using the group load/store
machinery. */
if (TYPE_MODE (TREE_TYPE (decl_result)) != BLKmode
+ && REG_P (real_decl_rtl)
&& targetm.calls.return_in_msb (TREE_TYPE (decl_result)))
{
emit_move_insn (gen_rtx_REG (GET_MODE (decl_rtl),
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 995c5c55f11..59afaa452aa 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -404,9 +404,9 @@ output_insn_data (void)
}
if (d->name && d->name[0] != '*')
- printf (" (insn_gen_fn) gen_%s,\n", d->name);
+ printf (" { (insn_gen_fn::stored_funcptr) gen_%s },\n", d->name);
else
- printf (" 0,\n");
+ printf (" { 0 },\n");
printf (" &operand_data[%d],\n", d->operand_number);
printf (" %d,\n", d->n_generator_args);
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b9211a9add2..06edced86cd 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -178,7 +178,7 @@ canonicalize_constructor_val (tree cval, tree from_decl)
/* Make sure we create a cgraph node for functions we'll reference.
They can be non-existent if the reference comes from an entry
of an external vtable for example. */
- cgraph_get_create_node (base);
+ cgraph_get_create_real_symbol_node (base);
}
/* Fixup types in global initializers. */
if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0)))
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index b06d194da65..9ac0d60e542 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -238,6 +238,7 @@ gimple_check_call_args (gimple stmt, tree fndecl)
break;
arg = gimple_call_arg (stmt, i);
if (p == error_mark_node
+ || DECL_ARG_TYPE (p) == error_mark_node
|| arg == error_mark_node
|| (!types_compatible_p (DECL_ARG_TYPE (p), TREE_TYPE (arg))
&& !fold_convertible_p (DECL_ARG_TYPE (p), arg)))
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 57b343ab5cf..5cda3873eb3 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -1525,11 +1525,23 @@ unconditional_cands_with_known_stride_p (slsr_cand_t root)
static void
replace_ref (tree *expr, slsr_cand_t c)
{
- tree add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr),
- c->base_expr, c->stride);
- tree mem_ref = fold_build2 (MEM_REF, TREE_TYPE (*expr), add_expr,
- double_int_to_tree (c->cand_type, c->index));
-
+ tree add_expr, mem_ref, acc_type = TREE_TYPE (*expr);
+ unsigned HOST_WIDE_INT misalign;
+ unsigned align;
+
+ /* Ensure the memory reference carries the minimum alignment
+ requirement for the data type. See PR58041. */
+ get_object_alignment_1 (*expr, &align, &misalign);
+ if (misalign != 0)
+ align = (misalign & -misalign);
+ if (align < TYPE_ALIGN (acc_type))
+ acc_type = build_aligned_type (acc_type, align);
+
+ add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr),
+ c->base_expr, c->stride);
+ mem_ref = fold_build2 (MEM_REF, acc_type, add_expr,
+ double_int_to_tree (c->cand_type, c->index));
+
/* Gimplify the base addressing expression for the new MEM_REF tree. */
gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
TREE_OPERAND (mem_ref, 0)
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 785c2f021a7..9b5de4a25a3 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3841,42 +3841,46 @@ get_base_loadstore (tree op)
/* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
VISIT_ADDR if non-NULL on loads, store and address-taken operands
- passing the STMT, the base of the operand and DATA to it. The base
- will be either a decl, an indirect reference (including TARGET_MEM_REF)
- or the argument of an address expression.
+ passing the STMT, the base of the operand, the operand itself containing
+ the base and DATA to it. The base will be either a decl, an indirect
+ reference (including TARGET_MEM_REF) or the argument of an address
+ expression.
Returns the results of these callbacks or'ed. */
bool
walk_stmt_load_store_addr_ops (gimple stmt, void *data,
- bool (*visit_load)(gimple, tree, void *),
- bool (*visit_store)(gimple, tree, void *),
- bool (*visit_addr)(gimple, tree, void *))
+ walk_stmt_load_store_addr_fn visit_load,
+ walk_stmt_load_store_addr_fn visit_store,
+ walk_stmt_load_store_addr_fn visit_addr)
{
bool ret = false;
unsigned i;
if (gimple_assign_single_p (stmt))
{
- tree lhs, rhs;
+ tree lhs, rhs, arg;
if (visit_store)
{
- lhs = get_base_loadstore (gimple_assign_lhs (stmt));
+ arg = gimple_assign_lhs (stmt);
+ lhs = get_base_loadstore (arg);
if (lhs)
- ret |= visit_store (stmt, lhs, data);
+ ret |= visit_store (stmt, lhs, arg, data);
}
- rhs = gimple_assign_rhs1 (stmt);
+ arg = gimple_assign_rhs1 (stmt);
+ rhs = arg;
while (handled_component_p (rhs))
rhs = TREE_OPERAND (rhs, 0);
if (visit_addr)
{
if (TREE_CODE (rhs) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
else if (TREE_CODE (rhs) == TARGET_MEM_REF
&& TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), arg,
+ data);
else if (TREE_CODE (rhs) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
- 0), data);
+ 0), arg, data);
else if (TREE_CODE (rhs) == CONSTRUCTOR)
{
unsigned int ix;
@@ -3884,23 +3888,23 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
if (TREE_CODE (val) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
else if (TREE_CODE (val) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
ret |= visit_addr (stmt,
TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
- 0), data);
+ 0), arg, data);
}
lhs = gimple_assign_lhs (stmt);
if (TREE_CODE (lhs) == TARGET_MEM_REF
&& TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), lhs, data);
}
if (visit_load)
{
rhs = get_base_loadstore (rhs);
if (rhs)
- ret |= visit_load (stmt, rhs, data);
+ ret |= visit_load (stmt, rhs, arg, data);
}
}
else if (visit_addr
@@ -3913,17 +3917,17 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
if (op == NULL_TREE)
;
else if (TREE_CODE (op) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
/* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
tree with two operands. */
else if (i == 1 && COMPARISON_CLASS_P (op))
{
if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
- 0), data);
+ 0), op, data);
if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
- 0), data);
+ 0), op, data);
}
}
}
@@ -3931,38 +3935,39 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
if (visit_store)
{
- tree lhs = gimple_call_lhs (stmt);
- if (lhs)
+ tree arg = gimple_call_lhs (stmt);
+ if (arg)
{
- lhs = get_base_loadstore (lhs);
+ tree lhs = get_base_loadstore (arg);
if (lhs)
- ret |= visit_store (stmt, lhs, data);
+ ret |= visit_store (stmt, lhs, arg, data);
}
}
if (visit_load || visit_addr)
for (i = 0; i < gimple_call_num_args (stmt); ++i)
{
- tree rhs = gimple_call_arg (stmt, i);
+ tree arg = gimple_call_arg (stmt, i);
if (visit_addr
- && TREE_CODE (rhs) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+ && TREE_CODE (arg) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
else if (visit_load)
{
- rhs = get_base_loadstore (rhs);
+ tree rhs = get_base_loadstore (arg);
if (rhs)
- ret |= visit_load (stmt, rhs, data);
+ ret |= visit_load (stmt, rhs, arg, data);
}
}
if (visit_addr
&& gimple_call_chain (stmt)
&& TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
- data);
+ gimple_call_chain (stmt), data);
if (visit_addr
&& gimple_call_return_slot_opt_p (stmt)
&& gimple_call_lhs (stmt) != NULL_TREE
&& TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
- ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
+ ret |= visit_addr (stmt, gimple_call_lhs (stmt),
+ gimple_call_lhs (stmt), data);
}
else if (gimple_code (stmt) == GIMPLE_ASM)
{
@@ -3978,7 +3983,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
tree link = gimple_asm_output_op (stmt, i);
tree op = get_base_loadstore (TREE_VALUE (link));
if (op && visit_store)
- ret |= visit_store (stmt, op, data);
+ ret |= visit_store (stmt, op, TREE_VALUE (link), data);
if (visit_addr)
{
constraint = TREE_STRING_POINTER
@@ -3987,7 +3992,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
&allows_reg, &is_inout);
if (op && !allows_reg && allows_mem)
- ret |= visit_addr (stmt, op, data);
+ ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
}
}
if (visit_load || visit_addr)
@@ -3997,14 +4002,14 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
tree op = TREE_VALUE (link);
if (visit_addr
&& TREE_CODE (op) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
else if (visit_load || visit_addr)
{
op = get_base_loadstore (op);
if (op)
{
if (visit_load)
- ret |= visit_load (stmt, op, data);
+ ret |= visit_load (stmt, op, TREE_VALUE (link), data);
if (visit_addr)
{
constraint = TREE_STRING_POINTER
@@ -4013,7 +4018,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
0, oconstraints,
&allows_mem, &allows_reg);
if (!allows_reg && allows_mem)
- ret |= visit_addr (stmt, op, data);
+ ret |= visit_addr (stmt, op, TREE_VALUE (link),
+ data);
}
}
}
@@ -4026,12 +4032,12 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
if (visit_addr
&& TREE_CODE (op) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
else if (visit_load)
{
- op = get_base_loadstore (op);
- if (op)
- ret |= visit_load (stmt, op, data);
+ tree base = get_base_loadstore (op);
+ if (base)
+ ret |= visit_load (stmt, base, op, data);
}
}
}
@@ -4042,9 +4048,16 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
tree op = PHI_ARG_DEF (stmt, i);
if (TREE_CODE (op) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
}
}
+ else if (visit_addr
+ && gimple_code (stmt) == GIMPLE_GOTO)
+ {
+ tree op = gimple_goto_dest (stmt);
+ if (TREE_CODE (op) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
+ }
return ret;
}
@@ -4054,8 +4067,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
bool
walk_stmt_load_store_ops (gimple stmt, void *data,
- bool (*visit_load)(gimple, tree, void *),
- bool (*visit_store)(gimple, tree, void *))
+ walk_stmt_load_store_addr_fn visit_load,
+ walk_stmt_load_store_addr_fn visit_store)
{
return walk_stmt_load_store_addr_ops (stmt, data,
visit_load, visit_store, NULL);
@@ -4064,8 +4077,7 @@ walk_stmt_load_store_ops (gimple stmt, void *data,
/* Helper for gimple_ior_addresses_taken_1. */
static bool
-gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
- tree addr, void *data)
+gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
{
bitmap addresses_taken = (bitmap)data;
addr = get_base_address (addr);
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 1bbd7d76a11..1ccede5f835 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -888,13 +888,14 @@ extern tree gimple_signed_type (tree);
extern alias_set_type gimple_get_alias_set (tree);
extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
unsigned *);
+typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void *);
extern bool walk_stmt_load_store_addr_ops (gimple, void *,
- bool (*)(gimple, tree, void *),
- bool (*)(gimple, tree, void *),
- bool (*)(gimple, tree, void *));
+ walk_stmt_load_store_addr_fn,
+ walk_stmt_load_store_addr_fn,
+ walk_stmt_load_store_addr_fn);
extern bool walk_stmt_load_store_ops (gimple, void *,
- bool (*)(gimple, tree, void *),
- bool (*)(gimple, tree, void *));
+ walk_stmt_load_store_addr_fn,
+ walk_stmt_load_store_addr_fn);
extern bool gimple_ior_addresses_taken (bitmap, gimple);
extern bool gimple_call_builtin_p (gimple, enum built_in_class);
extern bool gimple_call_builtin_p (gimple, enum built_in_function);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index e7119283ff3..a9a9229f45f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2060,6 +2060,9 @@ gimplify_conversion (tree *expr_p)
/* Nonlocal VLAs seen in the current function. */
static struct pointer_set_t *nonlocal_vlas;
+/* The VAR_DECLs created for nonlocal VLAs for debug info purposes. */
+static tree nonlocal_vla_vars;
+
/* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
DECL_VALUE_EXPR, and it's worth re-examining things. */
@@ -2106,14 +2109,13 @@ gimplify_var_or_parm_decl (tree *expr_p)
ctx = ctx->outer_context;
if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
{
- tree copy = copy_node (decl), block;
+ tree copy = copy_node (decl);
lang_hooks.dup_lang_specific_decl (copy);
SET_DECL_RTL (copy, 0);
TREE_USED (copy) = 1;
- block = DECL_INITIAL (current_function_decl);
- DECL_CHAIN (copy) = BLOCK_VARS (block);
- BLOCK_VARS (block) = copy;
+ DECL_CHAIN (copy) = nonlocal_vla_vars;
+ nonlocal_vla_vars = copy;
SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
DECL_HAS_VALUE_EXPR_P (copy) = 1;
}
@@ -4369,7 +4371,7 @@ gimple_fold_indirect_ref (tree t)
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
tree index = bitsize_int (indexi);
if (offset / part_widthi
- <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+ < TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
part_width, index);
}
@@ -6131,7 +6133,7 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl)
region's REDUCTION clause. */
static bool
-omp_check_private (struct gimplify_omp_ctx *ctx, tree decl)
+omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
{
splay_tree_node n;
@@ -6140,8 +6142,11 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl)
ctx = ctx->outer_context;
if (ctx == NULL)
return !(is_global_var (decl)
- /* References might be private, but might be shared too. */
- || lang_hooks.decls.omp_privatize_by_reference (decl));
+ /* References might be private, but might be shared too,
+ when checking for copyprivate, assume they might be
+ private, otherwise assume they might be shared. */
+ || (!copyprivate
+ && lang_hooks.decls.omp_privatize_by_reference (decl)));
n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
if (n != NULL)
@@ -6267,12 +6272,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
remove = true;
break;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
+ && !remove
+ && !omp_check_private (ctx, decl, true))
+ {
+ remove = true;
+ if (is_global_var (decl))
+ {
+ if (DECL_THREAD_LOCAL_P (decl))
+ remove = false;
+ else if (DECL_HAS_VALUE_EXPR_P (decl))
+ {
+ tree value = get_base_address (DECL_VALUE_EXPR (decl));
+
+ if (value
+ && DECL_P (value)
+ && DECL_THREAD_LOCAL_P (value))
+ remove = false;
+ }
+ }
+ if (remove)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "copyprivate variable %qE is not threadprivate"
+ " or private in outer context", DECL_NAME (decl));
+ }
do_notice:
if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true);
if (check_non_private
&& region_type == ORT_WORKSHARE
- && omp_check_private (ctx, decl))
+ && omp_check_private (ctx, decl, false))
{
error ("%s variable %qE is private in outer context",
check_non_private, DECL_NAME (decl));
@@ -8261,6 +8290,21 @@ gimplify_body (tree fndecl, bool do_parms)
if (nonlocal_vlas)
{
+ if (nonlocal_vla_vars)
+ {
+ /* tree-nested.c may later on call declare_vars (..., true);
+ which relies on BLOCK_VARS chain to be the tail of the
+ gimple_bind_vars chain. Ensure we don't violate that
+ assumption. */
+ if (gimple_bind_block (outer_bind)
+ == DECL_INITIAL (current_function_decl))
+ declare_vars (nonlocal_vla_vars, outer_bind, true);
+ else
+ BLOCK_VARS (DECL_INITIAL (current_function_decl))
+ = chainon (BLOCK_VARS (DECL_INITIAL (current_function_decl)),
+ nonlocal_vla_vars);
+ nonlocal_vla_vars = NULL_TREE;
+ }
pointer_set_destroy (nonlocal_vlas);
nonlocal_vlas = NULL;
}
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index d478c3ed9b4..fd4dc32559b 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,65 @@
+2013-12-11 Ian Lance Taylor <iant@google.com>
+
+ * go-lang.c (go_langhook_post_options): Disable sibling calls by
+ default.
+
+2013-10-16 Ian Lance Taylor <iant@google.com>
+
+ Bring in from mainline:
+
+ 2013-10-11 Chris Manghane <cmang@google.com>
+ * go-gcc.cc (Gcc_backend::function_code_expression): New
+ function.
+
+ 2013-10-10 Chris Manghane <cmang@google.com>
+ * go-gcc.cc (Backend::error_function): New function.
+ (Backend::function): New function.
+ (Backend::make_function): New function.
+ (function_to_tree): New function.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-04 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Backend::convert_expression): New function.
+
+2013-10-02 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc: Include "real.h" and "realmpfr.h".
+ (Backend::integer_constant_expression): New function.
+ (Backend::float_constant_expression): New function.
+ (Backend::complex_constant_expression): New function.
+
+2013-09-30 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Backend::error_expression): New function.
+ (Backend::var_expression): New function.
+ (Backend::indirect_expression): New function.
+
+2013-08-28 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::immutable_struct): Set TREE_PUBLIC if
+ the struct is not hidden.
+ (Gcc_backend::immutable_struct_set_init): Don't set TREE_PUBLIC.
+
+2013-08-06 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::immutable_struct_set_init): Use
+ compute_reloc_for_constant.
+
+2013-08-02 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (immutable_struct_set_init): Always call
+ resolve_unique_section.
+
+2013-07-24 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::non_zero_size_type): If a struct has a
+ fields, recreate those fields with the first one with a non-zero
+ size.
+
2013-06-18 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::immutable_struct): Add is_hidden
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index bd2d0dd0829..81e9ad18610 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -29,6 +29,8 @@
#include "gimple.h"
#include "toplev.h"
#include "output.h"
+#include "real.h"
+#include "realmpfr.h"
#include "go-c.h"
@@ -208,6 +210,31 @@ class Gcc_backend : public Backend
Bexpression*
zero_expression(Btype*);
+ Bexpression*
+ error_expression()
+ { return this->make_expression(error_mark_node); }
+
+ Bexpression*
+ var_expression(Bvariable* var, Location);
+
+ Bexpression*
+ indirect_expression(Bexpression* expr, bool known_valid, Location);
+
+ Bexpression*
+ integer_constant_expression(Btype* btype, mpz_t val);
+
+ Bexpression*
+ float_constant_expression(Btype* btype, mpfr_t val);
+
+ Bexpression*
+ complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag);
+
+ Bexpression*
+ convert_expression(Btype* type, Bexpression* expr, Location);
+
+ Bexpression*
+ function_code_expression(Bfunction*, Location);
+
// Statements.
Bstatement*
@@ -310,6 +337,17 @@ class Gcc_backend : public Backend
Bexpression*
label_address(Blabel*, Location);
+ // Functions.
+
+ Bfunction*
+ error_function()
+ { return this->make_function(error_mark_node); }
+
+ Bfunction*
+ function(Btype* fntype, const std::string& name, const std::string& asm_name,
+ bool is_visible, bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section, Location);
+
private:
// Make a Bexpression from a tree.
Bexpression*
@@ -326,6 +364,10 @@ class Gcc_backend : public Backend
make_type(tree t)
{ return new Btype(t); }
+ Bfunction*
+ make_function(tree t)
+ { return new Bfunction(t); }
+
Btype*
fill_in_struct(Btype*, const std::vector<Btyped_identifier>&);
@@ -848,6 +890,113 @@ Gcc_backend::zero_expression(Btype* btype)
return tree_to_expr(ret);
}
+// An expression that references a variable.
+
+Bexpression*
+Gcc_backend::var_expression(Bvariable* var, Location)
+{
+ tree ret = var->get_tree();
+ if (ret == error_mark_node)
+ return this->error_expression();
+ return tree_to_expr(ret);
+}
+
+// An expression that indirectly references an expression.
+
+Bexpression*
+Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid,
+ Location location)
+{
+ tree ret = build_fold_indirect_ref_loc(location.gcc_location(),
+ expr->get_tree());
+ if (known_valid)
+ TREE_THIS_NOTRAP(ret) = 1;
+ return tree_to_expr(ret);
+}
+
+// Return a typed value as a constant integer.
+
+Bexpression*
+Gcc_backend::integer_constant_expression(Btype* btype, mpz_t val)
+{
+ tree t = btype->get_tree();
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ tree ret = double_int_to_tree(t, mpz_get_double_int(t, val, true));
+ return tree_to_expr(ret);
+}
+
+// Return a typed value as a constant floating-point number.
+
+Bexpression*
+Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val)
+{
+ tree t = btype->get_tree();
+ tree ret;
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ REAL_VALUE_TYPE r1;
+ real_from_mpfr(&r1, val, t, GMP_RNDN);
+ REAL_VALUE_TYPE r2;
+ real_convert(&r2, TYPE_MODE(t), &r1);
+ ret = build_real(t, r2);
+ return tree_to_expr(ret);
+}
+
+// Return a typed real and imaginary value as a constant complex number.
+
+Bexpression*
+Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag)
+{
+ tree t = btype->get_tree();
+ tree ret;
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ REAL_VALUE_TYPE r1;
+ real_from_mpfr(&r1, real, TREE_TYPE(t), GMP_RNDN);
+ REAL_VALUE_TYPE r2;
+ real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1);
+
+ REAL_VALUE_TYPE r3;
+ real_from_mpfr(&r3, imag, TREE_TYPE(t), GMP_RNDN);
+ REAL_VALUE_TYPE r4;
+ real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3);
+
+ ret = build_complex(t, build_real(TREE_TYPE(t), r2),
+ build_real(TREE_TYPE(t), r4));
+ return tree_to_expr(ret);
+}
+
+// An expression that converts an expression to a different type.
+
+Bexpression*
+Gcc_backend::convert_expression(Btype* type, Bexpression* expr, Location)
+{
+ tree type_tree = type->get_tree();
+ tree expr_tree = expr->get_tree();
+ if (type_tree == error_mark_node || expr_tree == error_mark_node)
+ return this->error_expression();
+
+ tree ret = fold_convert(type_tree, expr_tree);
+ return tree_to_expr(ret);
+}
+
+// Get the address of a function.
+
+Bexpression*
+Gcc_backend::function_code_expression(Bfunction* bfunc, Location location)
+{
+ tree func = bfunc->get_tree();
+ if (func == error_mark_node)
+ return this->error_expression();
+
+ tree ret = build_fold_addr_expr_loc(location.gcc_location(), func);
+ return this->make_expression(ret);
+}
+
// An expression as a statement.
Bstatement*
@@ -1242,20 +1391,41 @@ Gcc_backend::non_zero_size_type(tree type)
switch (TREE_CODE(type))
{
case RECORD_TYPE:
- {
- if (go_non_zero_struct == NULL_TREE)
- {
- type = make_node(RECORD_TYPE);
- tree field = build_decl(UNKNOWN_LOCATION, FIELD_DECL,
- get_identifier("dummy"),
- boolean_type_node);
- DECL_CONTEXT(field) = type;
- TYPE_FIELDS(type) = field;
- layout_type(type);
- go_non_zero_struct = type;
- }
- return go_non_zero_struct;
- }
+ if (TYPE_FIELDS(type) != NULL_TREE)
+ {
+ tree ns = make_node(RECORD_TYPE);
+ tree field_trees = NULL_TREE;
+ tree *pp = &field_trees;
+ for (tree field = TYPE_FIELDS(type);
+ field != NULL_TREE;
+ field = DECL_CHAIN(field))
+ {
+ tree ft = TREE_TYPE(field);
+ if (field == TYPE_FIELDS(type))
+ ft = non_zero_size_type(ft);
+ tree f = build_decl(DECL_SOURCE_LOCATION(field), FIELD_DECL,
+ DECL_NAME(field), ft);
+ DECL_CONTEXT(f) = ns;
+ *pp = f;
+ pp = &DECL_CHAIN(f);
+ }
+ TYPE_FIELDS(ns) = field_trees;
+ layout_type(ns);
+ return ns;
+ }
+
+ if (go_non_zero_struct == NULL_TREE)
+ {
+ type = make_node(RECORD_TYPE);
+ tree field = build_decl(UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier("dummy"),
+ boolean_type_node);
+ DECL_CONTEXT(field) = type;
+ TYPE_FIELDS(type) = field;
+ layout_type(type);
+ go_non_zero_struct = type;
+ }
+ return go_non_zero_struct;
case ARRAY_TYPE:
{
@@ -1454,8 +1624,8 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
// Create a named immutable initialized data structure.
Bvariable*
-Gcc_backend::immutable_struct(const std::string& name, bool, bool,
- Btype* btype, Location location)
+Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
+ bool, Btype* btype, Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
@@ -1469,6 +1639,8 @@ Gcc_backend::immutable_struct(const std::string& name, bool, bool,
TREE_CONSTANT(decl) = 1;
TREE_USED(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
+ if (!is_hidden)
+ TREE_PUBLIC(decl) = 1;
// We don't call rest_of_decl_compilation until we have the
// initializer.
@@ -1482,8 +1654,7 @@ Gcc_backend::immutable_struct(const std::string& name, bool, bool,
void
Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
- bool is_hidden, bool is_common, Btype*,
- Location,
+ bool, bool is_common, Btype*, Location,
Bexpression* initializer)
{
tree decl = var->get_tree();
@@ -1494,16 +1665,14 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
DECL_INITIAL(decl) = init_tree;
// We can't call make_decl_one_only until we set DECL_INITIAL.
- if (!is_common)
- {
- if (!is_hidden)
- TREE_PUBLIC(decl) = 1;
- }
- else
- {
- make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
- resolve_unique_section(decl, 1, 0);
- }
+ if (is_common)
+ make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
+
+ // These variables are often unneeded in the final program, so put
+ // them in their own section so that linker GC can discard them.
+ resolve_unique_section(decl,
+ compute_reloc_for_constant (init_tree),
+ 1);
rest_of_decl_compilation(decl, 1, 0);
}
@@ -1586,6 +1755,56 @@ Gcc_backend::label_address(Blabel* label, Location location)
return this->make_expression(ret);
}
+// Declare or define a new function.
+
+Bfunction*
+Gcc_backend::function(Btype* fntype, const std::string& name,
+ const std::string& asm_name, bool is_visible,
+ bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section,
+ Location location)
+{
+ tree functype = fntype->get_tree();
+ if (functype != error_mark_node)
+ {
+ gcc_assert(FUNCTION_POINTER_TYPE_P(functype));
+ functype = TREE_TYPE(functype);
+ }
+ tree id = get_identifier_from_string(name);
+ if (functype == error_mark_node || id == error_mark_node)
+ return this->error_function();
+
+ tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype);
+ if (!asm_name.empty())
+ SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+ if (is_visible)
+ TREE_PUBLIC(decl) = 1;
+ if (is_declaration)
+ DECL_EXTERNAL(decl) = 1;
+ else
+ {
+ tree restype = TREE_TYPE(functype);
+ tree resdecl =
+ build_decl(location.gcc_location(), RESULT_DECL, NULL_TREE, restype);
+ DECL_ARTIFICIAL(resdecl) = 1;
+ DECL_IGNORED_P(resdecl) = 1;
+ DECL_CONTEXT(resdecl) = decl;
+ DECL_RESULT(decl) = resdecl;
+ }
+ if (!is_inlinable)
+ DECL_UNINLINABLE(decl) = 1;
+ if (disable_split_stack)
+ {
+ tree attr = get_identifier("__no_split_stack__");
+ DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
+ }
+ if (in_unique_section)
+ resolve_unique_section(decl, 0, 1);
+
+ go_preserve_from_gc(decl);
+ return new Bfunction(decl);
+}
+
// The single backend.
static Gcc_backend gcc_backend;
@@ -1661,3 +1880,9 @@ var_to_tree(Bvariable* bv)
{
return bv->get_tree();
}
+
+tree
+function_to_tree(Bfunction* bf)
+{
+ return bf->get_tree();
+}
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 659cd8ef700..7e92deb9257 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -269,6 +269,10 @@ go_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT)
flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
+ /* Tail call optimizations can confuse uses of runtime.Callers. */
+ if (!global_options_set.x_flag_optimize_sibling_calls)
+ global_options.x_flag_optimize_sibling_calls = 0;
+
/* Returning false means that the backend should be used. */
return false;
}
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index ac29b03e453..ca997f08ade 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -7,6 +7,9 @@
#ifndef GO_BACKEND_H
#define GO_BACKEND_H
+#include <gmp.h>
+#include <mpfr.h>
+
// Pointers to these types are created by the backend, passed to the
// frontend, and passed back to the backend. The types must be
// defined by the backend using these names.
@@ -20,7 +23,7 @@ class Bexpression;
// The backend representation of a statement.
class Bstatement;
-// The backend representation of a function definition.
+// The backend representation of a function definition or declaration.
class Bfunction;
// The backend representation of a block.
@@ -231,6 +234,43 @@ class Backend
virtual Bexpression*
zero_expression(Btype*) = 0;
+ // Create an error expression. This is used for cases which should
+ // not occur in a correct program, in order to keep the compilation
+ // going without crashing.
+ virtual Bexpression*
+ error_expression() = 0;
+
+ // Create a reference to a variable.
+ virtual Bexpression*
+ var_expression(Bvariable* var, Location) = 0;
+
+ // Create an expression that indirects through the pointer expression EXPR
+ // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer
+ // is known to point to a valid memory location.
+ virtual Bexpression*
+ indirect_expression(Bexpression* expr, bool known_valid, Location) = 0;
+
+ // Return an expression for the multi-precision integer VAL in BTYPE.
+ virtual Bexpression*
+ integer_constant_expression(Btype* btype, mpz_t val) = 0;
+
+ // Return an expression for the floating point value VAL in BTYPE.
+ virtual Bexpression*
+ float_constant_expression(Btype* btype, mpfr_t val) = 0;
+
+ // Return an expression for the complex value REAL/IMAG in BTYPE.
+ virtual Bexpression*
+ complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) = 0;
+
+ // Return an expression that converts EXPR to TYPE.
+ virtual Bexpression*
+ convert_expression(Btype* type, Bexpression* expr, Location) = 0;
+
+ // Create an expression for the address of a function. This is used to
+ // get the address of the code for a function.
+ virtual Bexpression*
+ function_code_expression(Bfunction*, Location) = 0;
+
// Statements.
// Create an error statement. This is used for cases which should
@@ -463,6 +503,32 @@ class Backend
// recover.
virtual Bexpression*
label_address(Blabel*, Location) = 0;
+
+ // Functions.
+
+ // Create an error function. This is used for cases which should
+ // not occur in a correct program, in order to keep the compilation
+ // going without crashing.
+ virtual Bfunction*
+ error_function() = 0;
+
+ // Declare or define a function of FNTYPE.
+ // NAME is the Go name of the function. ASM_NAME, if not the empty string, is
+ // the name that should be used in the symbol table; this will be non-empty if
+ // a magic extern comment is used.
+ // IS_VISIBLE is true if this function should be visible outside of the
+ // current compilation unit. IS_DECLARATION is true if this is a function
+ // declaration rather than a definition; the function definition will be in
+ // another compilation unit.
+ // IS_INLINABLE is true if the function can be inlined.
+ // DISABLE_SPLIT_STACK is true if this function may not split the stack; this
+ // is used for the implementation of recover.
+ // IN_UNIQUE_SECTION is true if this function should be put into a unique
+ // location if possible; this is used for field tracking.
+ virtual Bfunction*
+ function(Btype* fntype, const std::string& name, const std::string& asm_name,
+ bool is_visible, bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section, Location) = 0;
};
// The backend interface has to define this function.
@@ -482,5 +548,6 @@ extern tree expr_to_tree(Bexpression*);
extern tree stat_to_tree(Bstatement*);
extern tree block_to_tree(Bblock*);
extern tree var_to_tree(Bvariable*);
+extern tree function_to_tree(Bfunction*);
#endif // !defined(GO_BACKEND_H)
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 2b60d90a5dc..6ba351e2f42 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -610,102 +610,57 @@ Expression::get_tree(Translate_context* context)
return this->do_get_tree(context);
}
-// Return a tree for VAL in TYPE.
-
-tree
-Expression::integer_constant_tree(mpz_t val, tree type)
+// Return a backend expression for VAL.
+Bexpression*
+Expression::backend_numeric_constant_expression(Translate_context* context,
+ Numeric_constant* val)
{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE)
- return double_int_to_tree(type,
- mpz_get_double_int(type, val, true));
- else if (TREE_CODE(type) == REAL_TYPE)
- {
- mpfr_t fval;
- mpfr_init_set_z(fval, val, GMP_RNDN);
- tree ret = Expression::float_constant_tree(fval, type);
- mpfr_clear(fval);
- return ret;
- }
- else if (TREE_CODE(type) == COMPLEX_TYPE)
- {
- mpfr_t fval;
- mpfr_init_set_z(fval, val, GMP_RNDN);
- tree real = Expression::float_constant_tree(fval, TREE_TYPE(type));
- mpfr_clear(fval);
- tree imag = build_real_from_int_cst(TREE_TYPE(type),
- integer_zero_node);
- return build_complex(type, real, imag);
- }
- else
- go_unreachable();
-}
-
-// Return a tree for VAL in TYPE.
+ Gogo* gogo = context->gogo();
+ Type* type = val->type();
+ if (type == NULL)
+ return gogo->backend()->error_expression();
-tree
-Expression::float_constant_tree(mpfr_t val, tree type)
-{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE)
+ Btype* btype = type->get_backend(gogo);
+ Bexpression* ret;
+ if (type->integer_type() != NULL)
{
mpz_t ival;
- mpz_init(ival);
- mpfr_get_z(ival, val, GMP_RNDN);
- tree ret = Expression::integer_constant_tree(ival, type);
+ if (!val->to_int(&ival))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->integer_constant_expression(btype, ival);
mpz_clear(ival);
- return ret;
}
- else if (TREE_CODE(type) == REAL_TYPE)
+ else if (type->float_type() != NULL)
{
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, val, type, GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(type), &r1);
- return build_real(type, r2);
+ mpfr_t fval;
+ if (!val->to_float(&fval))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->float_constant_expression(btype, fval);
+ mpfr_clear(fval);
}
- else if (TREE_CODE(type) == COMPLEX_TYPE)
+ else if (type->complex_type() != NULL)
{
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, val, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1);
- tree imag = build_real_from_int_cst(TREE_TYPE(type),
- integer_zero_node);
- return build_complex(type, build_real(TREE_TYPE(type), r2), imag);
+ mpfr_t real;
+ mpfr_t imag;
+ if (!val->to_complex(&real, &imag))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->complex_constant_expression(btype, real, imag);
+ mpfr_clear(real);
+ mpfr_clear(imag);
}
else
go_unreachable();
-}
-
-// Return a tree for REAL/IMAG in TYPE.
-
-tree
-Expression::complex_constant_tree(mpfr_t real, mpfr_t imag, tree type)
-{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE || TREE_CODE(type) == REAL_TYPE)
- return Expression::float_constant_tree(real, type);
- else if (TREE_CODE(type) == COMPLEX_TYPE)
- {
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, real, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1);
-
- REAL_VALUE_TYPE r3;
- real_from_mpfr(&r3, imag, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r4;
- real_convert(&r4, TYPE_MODE(TREE_TYPE(type)), &r3);
- return build_complex(type, build_real(TREE_TYPE(type), r2),
- build_real(TREE_TYPE(type), r4));
- }
- else
- go_unreachable();
+ return ret;
}
// Return a tree which evaluates to true if VAL, of arbitrary integer
@@ -978,22 +933,19 @@ Var_expression::do_get_tree(Translate_context* context)
{
Bvariable* bvar = this->variable_->get_backend_variable(context->gogo(),
context->function());
- tree ret = var_to_tree(bvar);
- if (ret == error_mark_node)
- return error_mark_node;
bool is_in_heap;
+ Location loc = this->location();
if (this->variable_->is_variable())
is_in_heap = this->variable_->var_value()->is_in_heap();
else if (this->variable_->is_result_variable())
is_in_heap = this->variable_->result_var_value()->is_in_heap();
else
go_unreachable();
+
+ Bexpression* ret = context->backend()->var_expression(bvar, loc);
if (is_in_heap)
- {
- ret = build_fold_indirect_ref_loc(this->location().gcc_location(), ret);
- TREE_THIS_NOTRAP(ret) = 1;
- }
- return ret;
+ ret = context->backend()->indirect_expression(ret, true, loc);
+ return expr_to_tree(ret);
}
// Ast dump for variable expression.
@@ -1043,23 +995,24 @@ Temporary_reference_expression::do_address_taken(bool)
tree
Temporary_reference_expression::do_get_tree(Translate_context* context)
{
+ Gogo* gogo = context->gogo();
Bvariable* bvar = this->statement_->get_backend_variable(context);
+ Bexpression* ret = gogo->backend()->var_expression(bvar, this->location());
- // The gcc backend can't represent the same set of recursive types
+ // The backend can't always represent the same set of recursive types
// that the Go frontend can. In some cases this means that a
// temporary variable won't have the right backend type. Correct
// that here by adding a type cast. We need to use base() to push
// the circularity down one level.
- tree ret = var_to_tree(bvar);
+ Type* stype = this->statement_->type();
if (!this->is_lvalue_
- && POINTER_TYPE_P(TREE_TYPE(ret))
- && VOID_TYPE_P(TREE_TYPE(TREE_TYPE(ret))))
+ && stype->has_pointer()
+ && stype->deref()->is_void_type())
{
- Btype* type_btype = this->type()->base()->get_backend(context->gogo());
- tree type_tree = type_to_tree(type_btype);
- ret = fold_convert_loc(this->location().gcc_location(), type_tree, ret);
+ Btype* btype = this->type()->base()->get_backend(gogo);
+ ret = gogo->backend()->convert_expression(btype, ret, this->location());
}
- return ret;
+ return expr_to_tree(ret);
}
// Ast dump for temporary reference.
@@ -1266,7 +1219,7 @@ Func_expression::do_type()
// Get the tree for the code of a function expression.
-tree
+Bexpression*
Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
{
Function_type* fntype;
@@ -1284,25 +1237,18 @@ Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
error_at(loc,
"invalid use of special builtin function %qs; must be called",
no->message_name().c_str());
- return error_mark_node;
+ return gogo->backend()->error_expression();
}
- tree id = no->get_id(gogo);
- if (id == error_mark_node)
- return error_mark_node;
-
- tree fndecl;
+ Bfunction* fndecl;
if (no->is_function())
- fndecl = no->func_value()->get_or_make_decl(gogo, no, id);
+ fndecl = no->func_value()->get_or_make_decl(gogo, no);
else if (no->is_function_declaration())
- fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no, id);
+ fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no);
else
go_unreachable();
- if (fndecl == error_mark_node)
- return error_mark_node;
-
- return build_fold_addr_expr_loc(loc.gcc_location(), fndecl);
+ return gogo->backend()->function_code_expression(fndecl, loc);
}
// Get the tree for a function expression. This is used when we take
@@ -1382,7 +1328,7 @@ Expression::make_func_reference(Named_object* function, Expression* closure,
Func_descriptor_expression::Func_descriptor_expression(Named_object* fn)
: Expression(EXPRESSION_FUNC_DESCRIPTOR, fn->location()),
- fn_(fn), dfn_(NULL), dvar_(NULL)
+ fn_(fn), dvar_(NULL)
{
go_assert(!fn->is_function() || !fn->func_value()->needs_closure());
}
@@ -1417,18 +1363,6 @@ Func_descriptor_expression::do_type()
return Func_descriptor_expression::descriptor_type;
}
-// Copy a Func_descriptor_expression;
-
-Expression*
-Func_descriptor_expression::do_copy()
-{
- Func_descriptor_expression* fde =
- Expression::make_func_descriptor(this->fn_);
- if (this->dfn_ != NULL)
- fde->set_descriptor_wrapper(this->dfn_);
- return fde;
-}
-
// The tree for a function descriptor.
tree
@@ -1455,11 +1389,8 @@ Func_descriptor_expression::do_get_tree(Translate_context* context)
Bvariable* bvar;
if (no->package() != NULL
|| Linemap::is_predeclared_location(no->location()))
- {
- bvar = context->backend()->immutable_struct_reference(var_name, btype,
- loc);
- go_assert(this->dfn_ == NULL);
- }
+ bvar = context->backend()->immutable_struct_reference(var_name, btype,
+ loc);
else
{
Location bloc = Linemap::predeclared_location();
@@ -1469,8 +1400,7 @@ Func_descriptor_expression::do_get_tree(Translate_context* context)
bvar = context->backend()->immutable_struct(var_name, is_hidden, false,
btype, bloc);
Expression_list* vals = new Expression_list();
- go_assert(this->dfn_ != NULL);
- vals->push_back(Expression::make_func_code_reference(this->dfn_, bloc));
+ vals->push_back(Expression::make_func_code_reference(this->fn_, bloc));
Expression* init =
Expression::make_struct_composite_literal(this->type(), vals, bloc);
Translate_context bcontext(gogo, NULL, NULL, NULL);
@@ -1555,8 +1485,10 @@ class Func_code_reference_expression : public Expression
tree
Func_code_reference_expression::do_get_tree(Translate_context* context)
{
- return Func_expression::get_code_pointer(context->gogo(), this->function_,
- this->location());
+ Bexpression* ret =
+ Func_expression::get_code_pointer(context->gogo(), this->function_,
+ this->location());
+ return expr_to_tree(ret);
}
// Make a reference to the code of a function.
@@ -2017,21 +1949,18 @@ Integer_expression::do_check_types(Gogo*)
tree
Integer_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type = NULL;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
else if (this->type_ != NULL && this->type_->float_type() != NULL)
{
// We are converting to an abstract floating point type.
- Type* ftype = Type::lookup_float_type("float64");
- type = type_to_tree(ftype->get_backend(gogo));
+ resolved_type = Type::lookup_float_type("float64");
}
else if (this->type_ != NULL && this->type_->complex_type() != NULL)
{
// We are converting to an abstract complex type.
- Type* ctype = Type::lookup_complex_type("complex128");
- type = type_to_tree(ctype->get_backend(gogo));
+ resolved_type = Type::lookup_complex_type("complex128");
}
else
{
@@ -2042,16 +1971,23 @@ Integer_expression::do_get_tree(Translate_context* context)
int bits = mpz_sizeinbase(this->val_, 2);
Type* int_type = Type::lookup_integer_type("int");
if (bits < int_type->integer_type()->bits())
- type = type_to_tree(int_type->get_backend(gogo));
+ resolved_type = int_type;
else if (bits < 64)
- {
- Type* t = Type::lookup_integer_type("int64");
- type = type_to_tree(t->get_backend(gogo));
- }
+ resolved_type = Type::lookup_integer_type("int64");
else
- type = long_long_integer_type_node;
+ {
+ if (!saw_errors())
+ error_at(this->location(),
+ "unknown type for large integer constant");
+ Bexpression* ret = context->gogo()->backend()->error_expression();
+ return expr_to_tree(ret);
+ }
}
- return Expression::integer_constant_tree(this->val_, type);
+ Numeric_constant nc;
+ nc.set_int(resolved_type, this->val_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write VAL to export data.
@@ -2305,24 +2241,32 @@ Float_expression::do_check_types(Gogo*)
tree
Float_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
else if (this->type_ != NULL && this->type_->integer_type() != NULL)
{
// We have an abstract integer type. We just hope for the best.
- type = type_to_tree(Type::lookup_integer_type("int")->get_backend(gogo));
+ resolved_type = Type::lookup_integer_type("int");
+ }
+ else if (this->type_ != NULL && this->type_->complex_type() != NULL)
+ {
+ // We are converting to an abstract complex type.
+ resolved_type = Type::lookup_complex_type("complex128");
}
else
{
// If we still have an abstract type here, then this is being
// used in a constant expression which didn't get reduced. We
// just use float64 and hope for the best.
- Type* ft = Type::lookup_float_type("float64");
- type = type_to_tree(ft->get_backend(gogo));
+ resolved_type = Type::lookup_float_type("float64");
}
- return Expression::float_constant_tree(this->val_, type);
+
+ Numeric_constant nc;
+ nc.set_float(resolved_type, this->val_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write a floating point number to a string dump.
@@ -2482,19 +2426,32 @@ Complex_expression::do_check_types(Gogo*)
tree
Complex_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
+ else if (this->type_ != NULL && this->type_->integer_type() != NULL)
+ {
+ // We are converting to an abstract integer type.
+ resolved_type = Type::lookup_integer_type("int");
+ }
+ else if (this->type_ != NULL && this->type_->float_type() != NULL)
+ {
+ // We are converting to an abstract float type.
+ resolved_type = Type::lookup_float_type("float64");
+ }
else
{
// If we still have an abstract type here, this this is being
// used in a constant expression which didn't get reduced. We
// just use complex128 and hope for the best.
- Type* ct = Type::lookup_complex_type("complex128");
- type = type_to_tree(ct->get_backend(gogo));
+ resolved_type = Type::lookup_complex_type("complex128");
}
- return Expression::complex_constant_tree(this->real_, this->imag_, type);
+
+ Numeric_constant nc;
+ nc.set_complex(resolved_type, this->real_, this->imag_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write REAL/IMAG to export data.
@@ -3093,8 +3050,7 @@ class Type_conversion_expression : public Expression
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
bool
- do_is_constant() const
- { return this->expr_->is_constant(); }
+ do_is_constant() const;
bool
do_numeric_constant_value(Numeric_constant*) const;
@@ -3236,6 +3192,27 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*,
return this;
}
+// Return whether a type conversion is a constant.
+
+bool
+Type_conversion_expression::do_is_constant() const
+{
+ if (!this->expr_->is_constant())
+ return false;
+
+ // A conversion to a type that may not be used as a constant is not
+ // a constant. For example, []byte(nil).
+ Type* type = this->type_;
+ if (type->integer_type() == NULL
+ && type->float_type() == NULL
+ && type->complex_type() == NULL
+ && !type->is_boolean_type()
+ && !type->is_string_type())
+ return false;
+
+ return true;
+}
+
// Return the constant numeric value if there is one.
bool
@@ -5624,6 +5601,15 @@ Binary_expression::do_determine_type(const Type_context* context)
subcontext.type = NULL;
}
+ if (this->op_ == OPERATOR_ANDAND || this->op_ == OPERATOR_OROR)
+ {
+ // For a logical operation, the context does not determine the
+ // types of the operands. The operands must be some boolean
+ // type but if the context has a boolean type they do not
+ // inherit it. See http://golang.org/issue/3924.
+ subcontext.type = NULL;
+ }
+
// Set the context for the left hand operand.
if (is_shift_op)
{
@@ -6005,6 +5991,43 @@ Binary_expression::do_get_tree(Translate_context* context)
right);
}
+ // For complex division Go wants slightly different results than the
+ // GCC library provides, so we have our own runtime routine.
+ if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL)
+ {
+ const char *name;
+ tree *pdecl;
+ Type* ctype;
+ static tree complex64_div_decl;
+ static tree complex128_div_decl;
+ switch (this->left_->type()->complex_type()->bits())
+ {
+ case 64:
+ name = "__go_complex64_div";
+ pdecl = &complex64_div_decl;
+ ctype = Type::lookup_complex_type("complex64");
+ break;
+ case 128:
+ name = "__go_complex128_div";
+ pdecl = &complex128_div_decl;
+ ctype = Type::lookup_complex_type("complex128");
+ break;
+ default:
+ go_unreachable();
+ }
+ Btype* cbtype = ctype->get_backend(gogo);
+ tree ctype_tree = type_to_tree(cbtype);
+ return Gogo::call_builtin(pdecl,
+ this->location(),
+ name,
+ 2,
+ ctype_tree,
+ ctype_tree,
+ fold_convert_loc(gccloc, ctype_tree, left),
+ type,
+ fold_convert_loc(gccloc, ctype_tree, right));
+ }
+
tree compute_type = excess_precision_type(type);
if (compute_type != NULL_TREE)
{
@@ -6792,8 +6815,8 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
}
Struct_field_list* sfl = new Struct_field_list();
- // The type here is wrong--it should be new_fntype. But we don't
- // have new_fntype yet, and it doesn't really matter.
+ // The type here is wrong--it should be the C function type. But it
+ // doesn't really matter.
Type* vt = Type::make_pointer_type(Type::make_void_type());
sfl->push_back(Struct_field(Typed_identifier("fn.0", vt, loc)));
sfl->push_back(Struct_field(Typed_identifier("val.1",
@@ -6802,17 +6825,17 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
Type* closure_type = Type::make_struct_type(sfl, loc);
closure_type = Type::make_pointer_type(closure_type);
- Function_type* new_fntype = orig_fntype->copy_with_closure(closure_type);
+ Function_type* new_fntype = orig_fntype->copy_with_names();
Named_object* new_no = gogo->start_function(Gogo::thunk_name(), new_fntype,
false, loc);
- gogo->start_block(loc);
+ Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
+ cvar->set_is_used();
+ Named_object* cp = Named_object::make_variable("$closure", NULL, cvar);
+ new_no->func_value()->set_closure_var(cp);
- Named_object* cp = gogo->lookup("closure.0", NULL);
- go_assert(cp != NULL
- && cp->is_variable()
- && cp->var_value()->is_parameter());
+ gogo->start_block(loc);
// Field 0 of the closure is the function code pointer, field 1 is
// the value on which to invoke the method.
@@ -6831,7 +6854,7 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
const Typed_identifier_list* new_params = new_fntype->parameters();
args = new Expression_list();
for (Typed_identifier_list::const_iterator p = new_params->begin();
- p + 1 != new_params->end();
+ p != new_params->end();
++p)
{
Named_object* p_no = gogo->lookup(p->name(), NULL);
@@ -7229,6 +7252,15 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
if (this->code_ == BUILTIN_OFFSETOF)
{
Expression* arg = this->one_arg();
+
+ if (arg->bound_method_expression() != NULL
+ || arg->interface_field_reference_expression() != NULL)
+ {
+ this->report_error(_("invalid use of method value as argument "
+ "of Offsetof"));
+ return this;
+ }
+
Field_reference_expression* farg = arg->field_reference_expression();
while (farg != NULL)
{
@@ -7238,7 +7270,8 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
// it must not be reached through pointer indirections.
if (farg->expr()->deref() != farg->expr())
{
- this->report_error(_("argument of Offsetof implies indirection of an embedded field"));
+ this->report_error(_("argument of Offsetof implies "
+ "indirection of an embedded field"));
return this;
}
// Go up until we reach the original base.
@@ -7514,7 +7547,7 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length)
switch (nc.to_unsigned_long(&v))
{
case Numeric_constant::NC_UL_VALID:
- return true;
+ break;
case Numeric_constant::NC_UL_NOTINT:
error_at(e->location(), "non-integer %s argument to make",
is_length ? "len" : "cap");
@@ -7526,8 +7559,23 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length)
case Numeric_constant::NC_UL_BIG:
// We don't want to give a compile-time error for a 64-bit
// value on a 32-bit target.
- return true;
+ break;
}
+
+ mpz_t val;
+ if (!nc.to_int(&val))
+ go_unreachable();
+ int bits = mpz_sizeinbase(val, 2);
+ mpz_clear(val);
+ Type* int_type = Type::lookup_integer_type("int");
+ if (bits >= int_type->integer_type()->bits())
+ {
+ error_at(e->location(), "%s argument too large for make",
+ is_length ? "len" : "cap");
+ return false;
+ }
+
+ return true;
}
if (e->type()->integer_type() != NULL)
@@ -7633,6 +7681,8 @@ Find_call_expression::expression(Expression** pexpr)
bool
Builtin_call_expression::do_is_constant() const
{
+ if (this->is_error_expression())
+ return true;
switch (this->code_)
{
case BUILTIN_LEN:
@@ -7768,8 +7818,6 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
return false;
if (arg_type->is_abstract())
return false;
- if (arg_type->named_type() != NULL)
- arg_type->named_type()->convert(this->gogo_);
unsigned int ret;
if (this->code_ == BUILTIN_SIZEOF)
@@ -9154,35 +9202,27 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// Because do_type will return an error type and thus prevent future
// errors, check for that case now to ensure that the error gets
// reported.
- if (this->get_function_type() == NULL)
+ Function_type* fntype = this->get_function_type();
+ if (fntype == NULL)
{
if (!this->fn_->type()->is_error())
this->report_error(_("expected function"));
return Expression::make_error(loc);
}
- // Recognize a call to a builtin function.
- Func_expression* fne = this->fn_->func_expression();
- if (fne != NULL
- && fne->named_object()->is_function_declaration()
- && fne->named_object()->func_declaration_value()->type()->is_builtin())
- return new Builtin_call_expression(gogo, this->fn_, this->args_,
- this->is_varargs_, loc);
-
// Handle an argument which is a call to a function which returns
// multiple results.
if (this->args_ != NULL
&& this->args_->size() == 1
- && this->args_->front()->call_expression() != NULL
- && this->fn_->type()->function_type() != NULL)
+ && this->args_->front()->call_expression() != NULL)
{
- Function_type* fntype = this->fn_->type()->function_type();
size_t rc = this->args_->front()->call_expression()->result_count();
if (rc > 1
- && fntype->parameters() != NULL
- && (fntype->parameters()->size() == rc
- || (fntype->is_varargs()
- && fntype->parameters()->size() - 1 <= rc)))
+ && ((fntype->parameters() != NULL
+ && (fntype->parameters()->size() == rc
+ || (fntype->is_varargs()
+ && fntype->parameters()->size() - 1 <= rc)))
+ || fntype->is_builtin()))
{
Call_expression* call = this->args_->front()->call_expression();
Expression_list* args = new Expression_list;
@@ -9196,6 +9236,11 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
}
}
+ // Recognize a call to a builtin function.
+ if (fntype->is_builtin())
+ return new Builtin_call_expression(gogo, this->fn_, this->args_,
+ this->is_varargs_, loc);
+
// If this call returns multiple results, create a temporary
// variable for each result.
size_t rc = this->result_count();
@@ -9204,8 +9249,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
std::vector<Temporary_statement*>* temps =
new std::vector<Temporary_statement*>;
temps->reserve(rc);
- const Typed_identifier_list* results =
- this->fn_->type()->function_type()->results();
+ const Typed_identifier_list* results = fntype->results();
for (Typed_identifier_list::const_iterator p = results->begin();
p != results->end();
++p)
@@ -9220,10 +9264,8 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// Handle a call to a varargs function by packaging up the extra
// parameters.
- if (this->fn_->type()->function_type() != NULL
- && this->fn_->type()->function_type()->is_varargs())
+ if (fntype->is_varargs())
{
- Function_type* fntype = this->fn_->type()->function_type();
const Typed_identifier_list* parameters = fntype->parameters();
go_assert(parameters != NULL && !parameters->empty());
Type* varargs_type = parameters->back().type();
@@ -9729,21 +9771,21 @@ Call_expression::do_get_tree(Translate_context* context)
const bool has_closure = func != NULL && func->closure() != NULL;
const bool is_interface_method = interface_method != NULL;
- int closure_arg;
+ bool has_closure_arg;
if (has_closure)
- closure_arg = 1;
+ has_closure_arg = true;
else if (func != NULL)
- closure_arg = 0;
+ has_closure_arg = false;
else if (is_interface_method)
- closure_arg = 0;
+ has_closure_arg = false;
else
- closure_arg = 1;
+ has_closure_arg = true;
int nargs;
tree* args;
if (this->args_ == NULL || this->args_->empty())
{
- nargs = (is_interface_method ? 1 : 0) + closure_arg;
+ nargs = is_interface_method ? 1 : 0;
args = nargs == 0 ? NULL : new tree[nargs];
}
else if (fntype->parameters() == NULL || fntype->parameters()->empty())
@@ -9752,7 +9794,7 @@ Call_expression::do_get_tree(Translate_context* context)
go_assert(!is_interface_method
&& fntype->is_method()
&& this->args_->size() == 1);
- nargs = 1 + closure_arg;
+ nargs = 1;
args = new tree[nargs];
args[0] = this->args_->front()->get_tree(context);
}
@@ -9763,7 +9805,6 @@ Call_expression::do_get_tree(Translate_context* context)
nargs = this->args_->size();
int i = is_interface_method ? 1 : 0;
nargs += i;
- nargs += closure_arg;
args = new tree[nargs];
Typed_identifier_list::const_iterator pp = params->begin();
@@ -9787,18 +9828,12 @@ Call_expression::do_get_tree(Translate_context* context)
return error_mark_node;
}
go_assert(pp == params->end());
- go_assert(i + closure_arg == nargs);
+ go_assert(i == nargs);
}
tree fntype_tree = type_to_tree(fntype->get_backend(gogo));
- if (fntype_tree == error_mark_node)
- return error_mark_node;
- go_assert(POINTER_TYPE_P(fntype_tree));
- if (TREE_TYPE(fntype_tree) == error_mark_node)
- return error_mark_node;
- go_assert(TREE_CODE(TREE_TYPE(fntype_tree)) == RECORD_TYPE);
- tree fnfield_type = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(fntype_tree)));
- if (fnfield_type == error_mark_node)
+ tree fnfield_type = type_to_tree(fntype->get_backend_fntype(gogo));
+ if (fntype_tree == error_mark_node || fnfield_type == error_mark_node)
return error_mark_node;
go_assert(FUNCTION_POINTER_TYPE_P(fnfield_type));
tree rettype = TREE_TYPE(TREE_TYPE(fnfield_type));
@@ -9806,21 +9841,23 @@ Call_expression::do_get_tree(Translate_context* context)
return error_mark_node;
tree fn;
+ tree closure_tree;
if (func != NULL)
{
Named_object* no = func->named_object();
- go_assert(!no->is_function()
- || !no->func_value()->is_descriptor_wrapper());
- fn = Func_expression::get_code_pointer(gogo, no, location);
- if (has_closure)
+ fn = expr_to_tree(Func_expression::get_code_pointer(gogo, no, location));
+ if (!has_closure)
+ closure_tree = NULL_TREE;
+ else
{
- go_assert(closure_arg == 1 && nargs > 0);
- args[nargs - 1] = func->closure()->get_tree(context);
+ closure_tree = func->closure()->get_tree(context);
+ if (closure_tree == error_mark_node)
+ return error_mark_node;
}
}
else if (!is_interface_method)
{
- tree closure_tree = this->fn_->get_tree(context);
+ closure_tree = this->fn_->get_tree(context);
if (closure_tree == error_mark_node)
return error_mark_node;
tree fnc = fold_convert_loc(location.gcc_location(), fntype_tree,
@@ -9834,8 +9871,6 @@ Call_expression::do_get_tree(Translate_context* context)
build_fold_indirect_ref_loc(location.gcc_location(),
fnc),
field, NULL_TREE);
- go_assert(closure_arg == 1 && nargs > 0);
- args[nargs - 1] = closure_tree;
}
else
{
@@ -9843,7 +9878,7 @@ Call_expression::do_get_tree(Translate_context* context)
&args[0]);
if (fn == error_mark_node)
return error_mark_node;
- go_assert(closure_arg == 0);
+ closure_tree = NULL_TREE;
}
if (fn == error_mark_node || TREE_TYPE(fn) == error_mark_node)
@@ -9894,6 +9929,32 @@ Call_expression::do_get_tree(Translate_context* context)
if (func == NULL)
fn = save_expr(fn);
+ if (!has_closure_arg)
+ go_assert(closure_tree == NULL_TREE);
+ else
+ {
+ // Pass the closure argument by calling the function function
+ // __go_set_closure. In the order_evaluations pass we have
+ // ensured that if any parameters contain call expressions, they
+ // will have been moved out to temporary variables.
+
+ go_assert(closure_tree != NULL_TREE);
+ closure_tree = fold_convert_loc(location.gcc_location(), ptr_type_node,
+ closure_tree);
+ static tree set_closure_fndecl;
+ tree set_closure = Gogo::call_builtin(&set_closure_fndecl,
+ location,
+ "__go_set_closure",
+ 1,
+ void_type_node,
+ ptr_type_node,
+ closure_tree);
+ if (set_closure == error_mark_node)
+ return error_mark_node;
+ fn = build2_loc(location.gcc_location(), COMPOUND_EXPR,
+ TREE_TYPE(fn), set_closure, fn);
+ }
+
tree ret = build_call_array(excess_type != NULL_TREE ? excess_type : rettype,
fn, nargs, args);
delete[] args;
@@ -10838,11 +10899,20 @@ String_index_expression::do_determine_type(const Type_context*)
void
String_index_expression::do_check_types(Gogo*)
{
- if (this->start_->type()->integer_type() == NULL)
+ Numeric_constant nc;
+ unsigned long v;
+ if (this->start_->type()->integer_type() == NULL
+ && !this->start_->type()->is_error()
+ && (!this->start_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
this->report_error(_("index must be integer"));
if (this->end_ != NULL
&& this->end_->type()->integer_type() == NULL
- && !this->end_->is_nil_expression())
+ && !this->end_->type()->is_error()
+ && !this->end_->is_nil_expression()
+ && !this->end_->is_error_expression()
+ && (!this->end_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
this->report_error(_("slice end must be integer"));
std::string sval;
@@ -11314,7 +11384,7 @@ Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
}
Expression* e = Expression::make_composite_literal(array_type, 0, false,
- bytes, loc);
+ bytes, false, loc);
Variable* var = new Variable(array_type, e, true, false, false, loc);
@@ -11609,25 +11679,25 @@ Interface_field_reference_expression::create_thunk(Gogo* gogo,
return Named_object::make_erroneous_name(Gogo::thunk_name());
Struct_field_list* sfl = new Struct_field_list();
- // The type here is wrong--it should be new_fntype. But we don't
- // have new_fntype yet, and it doesn't really matter.
+ // The type here is wrong--it should be the C function type. But it
+ // doesn't really matter.
Type* vt = Type::make_pointer_type(Type::make_void_type());
sfl->push_back(Struct_field(Typed_identifier("fn.0", vt, loc)));
sfl->push_back(Struct_field(Typed_identifier("val.1", type, loc)));
Type* closure_type = Type::make_struct_type(sfl, loc);
closure_type = Type::make_pointer_type(closure_type);
- Function_type* new_fntype = orig_fntype->copy_with_closure(closure_type);
+ Function_type* new_fntype = orig_fntype->copy_with_names();
Named_object* new_no = gogo->start_function(Gogo::thunk_name(), new_fntype,
false, loc);
- gogo->start_block(loc);
+ Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
+ cvar->set_is_used();
+ Named_object* cp = Named_object::make_variable("$closure", NULL, cvar);
+ new_no->func_value()->set_closure_var(cp);
- Named_object* cp = gogo->lookup("closure.0", NULL);
- go_assert(cp != NULL
- && cp->is_variable()
- && cp->var_value()->is_parameter());
+ gogo->start_block(loc);
// Field 0 of the closure is the function code pointer, field 1 is
// the value on which to invoke the method.
@@ -11647,7 +11717,7 @@ Interface_field_reference_expression::create_thunk(Gogo* gogo,
const Typed_identifier_list* new_params = new_fntype->parameters();
args = new Expression_list();
for (Typed_identifier_list::const_iterator p = new_params->begin();
- p + 1 != new_params->end();
+ p != new_params->end();
++p)
{
Named_object* p_no = gogo->lookup(p->name(), NULL);
@@ -13257,9 +13327,11 @@ class Composite_literal_expression : public Parser_expression
{
public:
Composite_literal_expression(Type* type, int depth, bool has_keys,
- Expression_list* vals, Location location)
+ Expression_list* vals, bool all_are_names,
+ Location location)
: Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
- type_(type), depth_(depth), vals_(vals), has_keys_(has_keys)
+ type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
+ all_are_names_(all_are_names)
{ }
protected:
@@ -13277,6 +13349,7 @@ class Composite_literal_expression : public Parser_expression
(this->vals_ == NULL
? NULL
: this->vals_->copy()),
+ this->all_are_names_,
this->location());
}
@@ -13306,6 +13379,9 @@ class Composite_literal_expression : public Parser_expression
// If this is true, then VALS_ is a list of pairs: a key and a
// value. In an array initializer, a missing key will be NULL.
bool has_keys_;
+ // If this is true, then HAS_KEYS_ is true, and every key is a
+ // simple identifier.
+ bool all_are_names_;
};
// Traversal.
@@ -13408,6 +13484,8 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
std::vector<Expression*> vals(field_count);
std::vector<int>* traverse_order = new(std::vector<int>);
Expression_list::const_iterator p = this->vals_->begin();
+ Expression* external_expr = NULL;
+ const Named_object* external_no = NULL;
while (p != this->vals_->end())
{
Expression* name_expr = *p;
@@ -13513,6 +13591,12 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
if (no != NULL)
{
+ if (no->package() != NULL && external_expr == NULL)
+ {
+ external_expr = name_expr;
+ external_no = no;
+ }
+
name = no->name();
// A predefined name won't be packed. If it starts with a
@@ -13562,6 +13646,23 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
traverse_order->push_back(index);
}
+ if (!this->all_are_names_)
+ {
+ // This is a weird case like bug462 in the testsuite.
+ if (external_expr == NULL)
+ error_at(this->location(), "unknown field in %qs literal",
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ else
+ error_at(external_expr->location(), "unknown field %qs in %qs",
+ external_no->message_name().c_str(),
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ return Expression::make_error(location);
+ }
+
Expression_list* list = new Expression_list;
list->reserve(field_count);
for (size_t i = 0; i < field_count; ++i)
@@ -13851,11 +13952,11 @@ Composite_literal_expression::do_dump_expression(
Expression*
Expression::make_composite_literal(Type* type, int depth, bool has_keys,
- Expression_list* vals,
+ Expression_list* vals, bool all_are_names,
Location location)
{
return new Composite_literal_expression(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// Return whether this expression is a composite literal.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 67a4bb985e6..35bfcfe8e4f 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -291,10 +291,13 @@ class Expression
make_unsafe_cast(Type*, Expression*, Location);
// Make a composite literal. The DEPTH parameter is how far down we
- // are in a list of composite literals with omitted types.
+ // are in a list of composite literals with omitted types. HAS_KEYS
+ // is true if the expression list has keys alternating with values.
+ // ALL_ARE_NAMES is true if all the keys could be struct field
+ // names.
static Expression*
make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
- Location);
+ bool all_are_names, Location);
// Make a struct composite literal.
static Expression*
@@ -652,17 +655,10 @@ class Expression
Type* left_type, tree left_tree, Type* right_type,
tree right_tree, Location);
- // Return a tree for the multi-precision integer VAL in TYPE.
- static tree
- integer_constant_tree(mpz_t val, tree type);
-
- // Return a tree for the floating point value VAL in TYPE.
- static tree
- float_constant_tree(mpfr_t val, tree type);
-
- // Return a tree for the complex value REAL/IMAG in TYPE.
- static tree
- complex_constant_tree(mpfr_t real, mpfr_t imag, tree type);
+ // Return the backend expression for the numeric constant VAL.
+ static Bexpression*
+ backend_numeric_constant_expression(Translate_context*,
+ Numeric_constant* val);
// Export the expression. This is only used for constants. It will
// be used for things like values of named constants and sizes of
@@ -1518,8 +1514,8 @@ class Func_expression : public Expression
closure()
{ return this->closure_; }
- // Return a tree for the code for a function.
- static tree
+ // Return a backend expression for the code of a function.
+ static Bexpression*
get_code_pointer(Gogo*, Named_object* function, Location loc);
protected:
@@ -1570,14 +1566,6 @@ class Func_descriptor_expression : public Expression
public:
Func_descriptor_expression(Named_object* fn);
- // Set the descriptor wrapper.
- void
- set_descriptor_wrapper(Named_object* dfn)
- {
- go_assert(this->dfn_ == NULL);
- this->dfn_ = dfn;
- }
-
// Make the function descriptor type, so that it can be converted.
static void
make_func_descriptor_type();
@@ -1594,7 +1582,8 @@ class Func_descriptor_expression : public Expression
{ }
Expression*
- do_copy();
+ do_copy()
+ { return Expression::make_func_descriptor(this->fn_); }
bool
do_is_addressable() const
@@ -1612,8 +1601,6 @@ class Func_descriptor_expression : public Expression
// The function for which this is the descriptor.
Named_object* fn_;
- // The descriptor function.
- Named_object* dfn_;
// The descriptor variable.
Bvariable* dvar_;
};
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index a1fe5fec7ca..ca80869da6a 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -985,64 +985,6 @@ Gogo::write_globals()
delete[] vec;
}
-// Get a tree for the identifier for a named object.
-
-tree
-Named_object::get_id(Gogo* gogo)
-{
- go_assert(!this->is_variable() && !this->is_result_variable());
- std::string decl_name;
- if (this->is_function_declaration()
- && !this->func_declaration_value()->asm_name().empty())
- decl_name = this->func_declaration_value()->asm_name();
- else if (this->is_type()
- && Linemap::is_predeclared_location(this->type_value()->location()))
- {
- // We don't need the package name for builtin types.
- decl_name = Gogo::unpack_hidden_name(this->name_);
- }
- else
- {
- std::string package_name;
- if (this->package_ == NULL)
- package_name = gogo->package_name();
- else
- package_name = this->package_->package_name();
-
- decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
-
- Function_type* fntype;
- if (this->is_function())
- fntype = this->func_value()->type();
- else if (this->is_function_declaration())
- fntype = this->func_declaration_value()->type();
- else
- fntype = NULL;
- if (fntype != NULL && fntype->is_method())
- {
- decl_name.push_back('.');
- decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
- }
- }
- if (this->is_type())
- {
- unsigned int index;
- const Named_object* in_function = this->type_value()->in_function(&index);
- if (in_function != NULL)
- {
- decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
- if (index > 0)
- {
- char buf[30];
- snprintf(buf, sizeof buf, "%u", index);
- decl_name += '$';
- decl_name += buf;
- }
- }
- }
- return get_identifier_from_string(decl_name);
-}
-
// Get a tree for a named object.
tree
@@ -1051,11 +993,12 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
if (this->tree_ != NULL_TREE)
return this->tree_;
- tree name;
- if (this->classification_ == NAMED_OBJECT_TYPE)
- name = NULL_TREE;
- else
- name = this->get_id(gogo);
+ if (Gogo::is_erroneous_name(this->name_))
+ {
+ this->tree_ = error_mark_node;
+ return error_mark_node;
+ }
+
tree decl;
switch (this->classification_)
{
@@ -1083,6 +1026,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
decl = error_mark_node;
else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
{
+ tree name = get_identifier_from_string(this->get_id(gogo));
decl = build_decl(named_constant->location().gcc_location(),
CONST_DECL, name, TREE_TYPE(expr_tree));
DECL_INITIAL(decl) = expr_tree;
@@ -1145,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
case NAMED_OBJECT_FUNC:
{
Function* func = this->u_.func_value;
- decl = func->get_or_make_decl(gogo, this, name);
+ decl = function_to_tree(func->get_or_make_decl(gogo, this));
if (decl != error_mark_node)
{
if (func->block() != NULL)
@@ -1270,133 +1214,12 @@ Variable::get_init_block(Gogo* gogo, Named_object* function, tree var_decl)
return block_tree;
}
-// Get a tree for a function decl.
-
-tree
-Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
-{
- if (this->fndecl_ == NULL_TREE)
- {
- tree functype = type_to_tree(this->type_->get_backend(gogo));
-
- if (functype != error_mark_node)
- {
- // The type of a function comes back as a pointer to a
- // struct whose first field is the function, but we want the
- // real function type for a function declaration.
- go_assert(POINTER_TYPE_P(functype)
- && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
- functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
- go_assert(FUNCTION_POINTER_TYPE_P(functype));
- functype = TREE_TYPE(functype);
-
- // In the struct, the function type always has a trailing
- // closure argument. For the function body, we only use
- // that trailing arg if this is a function literal or if it
- // is a wrapper created to store in a descriptor. Remove it
- // in that case.
- if (this->enclosing_ == NULL && !this->is_descriptor_wrapper_)
- {
- tree old_params = TYPE_ARG_TYPES(functype);
- go_assert(old_params != NULL_TREE
- && old_params != void_list_node);
- tree new_params = NULL_TREE;
- tree *pp = &new_params;
- while (TREE_CHAIN (old_params) != void_list_node)
- {
- tree p = TREE_VALUE(old_params);
- go_assert(TYPE_P(p));
- *pp = tree_cons(NULL_TREE, p, NULL_TREE);
- pp = &TREE_CHAIN(*pp);
- old_params = TREE_CHAIN (old_params);
- }
- *pp = void_list_node;
- functype = build_function_type(TREE_TYPE(functype), new_params);
- }
- }
-
- if (functype == error_mark_node)
- this->fndecl_ = error_mark_node;
- else
- {
- tree decl = build_decl(this->location().gcc_location(), FUNCTION_DECL,
- id, functype);
-
- this->fndecl_ = decl;
-
- if (no->package() != NULL)
- ;
- else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
- ;
- else if (Gogo::unpack_hidden_name(no->name()) == "init"
- && !this->type_->is_method())
- ;
- else if (Gogo::unpack_hidden_name(no->name()) == "main"
- && gogo->is_main_package())
- TREE_PUBLIC(decl) = 1;
- // Methods have to be public even if they are hidden because
- // they can be pulled into type descriptors when using
- // anonymous fields.
- else if (!Gogo::is_hidden_name(no->name())
- || this->type_->is_method())
- {
- TREE_PUBLIC(decl) = 1;
- std::string asm_name = gogo->pkgpath_symbol();
- asm_name.append(1, '.');
- asm_name.append(Gogo::unpack_hidden_name(no->name()));
- if (this->type_->is_method())
- {
- asm_name.append(1, '.');
- Type* rtype = this->type_->receiver()->type();
- asm_name.append(rtype->mangled_name(gogo));
- }
- SET_DECL_ASSEMBLER_NAME(decl,
- get_identifier_from_string(asm_name));
- }
-
- // Why do we have to do this in the frontend?
- tree restype = TREE_TYPE(functype);
- tree resdecl =
- build_decl(this->location().gcc_location(), RESULT_DECL, NULL_TREE,
- restype);
- DECL_ARTIFICIAL(resdecl) = 1;
- DECL_IGNORED_P(resdecl) = 1;
- DECL_CONTEXT(resdecl) = decl;
- DECL_RESULT(decl) = resdecl;
-
- // If a function calls the predeclared recover function, we
- // can't inline it, because recover behaves differently in a
- // function passed directly to defer. If this is a recover
- // thunk that we built to test whether a function can be
- // recovered, we can't inline it, because that will mess up
- // our return address comparison.
- if (this->calls_recover_ || this->is_recover_thunk_)
- DECL_UNINLINABLE(decl) = 1;
-
- // If this is a thunk created to call a function which calls
- // the predeclared recover function, we need to disable
- // stack splitting for the thunk.
- if (this->is_recover_thunk_)
- {
- tree attr = get_identifier("__no_split_stack__");
- DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
- }
-
- if (this->in_unique_section_)
- resolve_unique_section (decl, 0, 1);
-
- go_preserve_from_gc(decl);
- }
- }
- return this->fndecl_;
-}
-
-// Get a tree for a function declaration.
+// Get the backend representation.
-tree
-Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
+Bfunction*
+Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
{
- if (this->fndecl_ == NULL_TREE)
+ if (this->fndecl_ == NULL)
{
// Let Go code use an asm declaration to pick up a builtin
// function.
@@ -1406,78 +1229,46 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
builtin_functions.find(this->asm_name_);
if (p != builtin_functions.end())
{
- this->fndecl_ = p->second;
+ this->fndecl_ = tree_to_function(p->second);
return this->fndecl_;
}
}
- tree functype = type_to_tree(this->fntype_->get_backend(gogo));
-
- if (functype != error_mark_node)
- {
- // The type of a function comes back as a pointer to a
- // struct whose first field is the function, but we want the
- // real function type for a function declaration.
- go_assert(POINTER_TYPE_P(functype)
- && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
- functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
- go_assert(FUNCTION_POINTER_TYPE_P(functype));
- functype = TREE_TYPE(functype);
-
- // In the struct, the function type always has a trailing
- // closure argument. Here we are referring to the function
- // code directly, and we know it is not a function literal,
- // and we know it is not a wrapper created to store in a
- // descriptor. Remove that trailing argument.
- tree old_params = TYPE_ARG_TYPES(functype);
- go_assert(old_params != NULL_TREE && old_params != void_list_node);
- tree new_params = NULL_TREE;
- tree *pp = &new_params;
- while (TREE_CHAIN (old_params) != void_list_node)
- {
- tree p = TREE_VALUE(old_params);
- go_assert(TYPE_P(p));
- *pp = tree_cons(NULL_TREE, p, NULL_TREE);
- pp = &TREE_CHAIN(*pp);
- old_params = TREE_CHAIN (old_params);
- }
- *pp = void_list_node;
- functype = build_function_type(TREE_TYPE(functype), new_params);
- }
-
- tree decl;
- if (functype == error_mark_node)
- decl = error_mark_node;
- else
- {
- decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, id,
- functype);
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
+ std::string asm_name;
+ if (this->asm_name_.empty())
+ {
+ asm_name = (no->package() == NULL
+ ? gogo->pkgpath_symbol()
+ : no->package()->pkgpath_symbol());
+ asm_name.append(1, '.');
+ asm_name.append(Gogo::unpack_hidden_name(no->name()));
+ if (this->fntype_->is_method())
+ {
+ asm_name.append(1, '.');
+ Type* rtype = this->fntype_->receiver()->type();
+ asm_name.append(rtype->mangled_name(gogo));
+ }
+ }
- if (this->asm_name_.empty())
- {
- std::string asm_name = (no->package() == NULL
- ? gogo->pkgpath_symbol()
- : no->package()->pkgpath_symbol());
- asm_name.append(1, '.');
- asm_name.append(Gogo::unpack_hidden_name(no->name()));
- if (this->fntype_->is_method())
- {
- asm_name.append(1, '.');
- Type* rtype = this->fntype_->receiver()->type();
- asm_name.append(rtype->mangled_name(gogo));
- }
- SET_DECL_ASSEMBLER_NAME(decl,
- get_identifier_from_string(asm_name));
- }
- }
- this->fndecl_ = decl;
- go_preserve_from_gc(decl);
+ Btype* functype = this->fntype_->get_backend_fntype(gogo);
+ this->fndecl_ =
+ gogo->backend()->function(functype, no->get_id(gogo), asm_name,
+ true, true, true, false, false,
+ this->location());
}
+
return this->fndecl_;
}
+// Return the function's decl after it has been built.
+
+tree
+Function::get_decl() const
+{
+ go_assert(this->fndecl_ != NULL);
+ return function_to_tree(this->fndecl_);
+}
+
// We always pass the receiver to a method as a pointer. If the
// receiver is actually declared as a non-pointer type, then we copy
// the value into a local variable, so that it has the right type. In
@@ -1572,7 +1363,7 @@ Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree var_decl)
void
Function::build_tree(Gogo* gogo, Named_object* named_function)
{
- tree fndecl = this->fndecl_;
+ tree fndecl = this->get_decl();
go_assert(fndecl != NULL_TREE);
tree params = NULL_TREE;
@@ -1659,8 +1450,13 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
}
}
- // The closure variable is passed last, if this is a function
- // literal or a descriptor wrapper.
+ *pp = NULL_TREE;
+
+ DECL_ARGUMENTS(fndecl) = params;
+
+ // If we need a closure variable, fetch it by calling a runtime
+ // function. The caller will have called __go_set_closure before
+ // the function call.
if (this->closure_var_ != NULL)
{
Bvariable* bvar =
@@ -1668,25 +1464,25 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
tree var_decl = var_to_tree(bvar);
if (var_decl != error_mark_node)
{
- go_assert(TREE_CODE(var_decl) == PARM_DECL);
- *pp = var_decl;
- pp = &DECL_CHAIN(*pp);
+ go_assert(TREE_CODE(var_decl) == VAR_DECL);
+ static tree get_closure_fndecl;
+ tree get_closure = Gogo::call_builtin(&get_closure_fndecl,
+ this->location_,
+ "__go_get_closure",
+ 0,
+ ptr_type_node);
+
+ // Mark the __go_get_closure function as pure, since it
+ // depends only on the global variable g.
+ DECL_PURE_P(get_closure_fndecl) = 1;
+
+ get_closure = fold_convert_loc(this->location_.gcc_location(),
+ TREE_TYPE(var_decl), get_closure);
+ DECL_INITIAL(var_decl) = get_closure;
+ DECL_CHAIN(var_decl) = declare_vars;
+ declare_vars = var_decl;
}
}
- else if (this->enclosing_ != NULL || this->is_descriptor_wrapper_)
- {
- tree parm_decl = build_decl(this->location_.gcc_location(), PARM_DECL,
- get_identifier("$closure"),
- const_ptr_type_node);
- DECL_CONTEXT(parm_decl) = current_function_decl;
- DECL_ARG_TYPE(parm_decl) = const_ptr_type_node;
- *pp = parm_decl;
- pp = &DECL_CHAIN(*pp);
- }
-
- *pp = NULL_TREE;
-
- DECL_ARGUMENTS(fndecl) = params;
if (this->block_ != NULL)
{
@@ -1805,7 +1601,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
set = NULL_TREE;
else
set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
- DECL_RESULT(this->fndecl_), retval);
+ DECL_RESULT(this->get_decl()), retval);
tree ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
void_type_node, set);
append_to_statement_list(ret_stmt, &stmt_list);
@@ -1860,7 +1656,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
retval = this->return_value(gogo, named_function, end_loc,
&stmt_list);
set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
- DECL_RESULT(this->fndecl_), retval);
+ DECL_RESULT(this->get_decl()), retval);
ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
void_type_node, set);
@@ -1878,7 +1674,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
*fini = stmt_list;
}
-// Return the value to assign to DECL_RESULT(this->fndecl_). This may
+// Return the value to assign to DECL_RESULT(this->get_decl()). This may
// also add statements to STMT_LIST, which need to be executed before
// the assignment. This is used for a return statement with no
// explicit values.
@@ -1911,7 +1707,7 @@ Function::return_value(Gogo* gogo, Named_object* named_function,
}
else
{
- tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_));
+ tree rettype = TREE_TYPE(DECL_RESULT(this->get_decl()));
retval = create_tmp_var(rettype, "RESULT");
tree field = TYPE_FIELDS(rettype);
int index = 0;
@@ -2332,18 +2128,14 @@ Gogo::interface_method_table_for_type(const Interface_type* interface,
go_assert(m != NULL);
Named_object* no = m->named_object();
-
- tree fnid = no->get_id(this);
-
- tree fndecl;
+ Bfunction* bf;
if (no->is_function())
- fndecl = no->func_value()->get_or_make_decl(this, no, fnid);
+ bf = no->func_value()->get_or_make_decl(this, no);
else if (no->is_function_declaration())
- fndecl = no->func_declaration_value()->get_or_make_decl(this, no,
- fnid);
+ bf = no->func_declaration_value()->get_or_make_decl(this, no);
else
go_unreachable();
- fndecl = build_fold_addr_expr(fndecl);
+ tree fndecl = build_fold_addr_expr(function_to_tree(bf));
elt = pointers->quick_push(empty);
elt->index = size_int(i);
@@ -2362,10 +2154,11 @@ Gogo::interface_method_table_for_type(const Interface_type* interface,
TREE_CONSTANT(decl) = 1;
DECL_INITIAL(decl) = constructor;
- // If the interface type has hidden methods, then this is the only
- // definition of the table. Otherwise it is a comdat table which
- // may be defined in multiple packages.
- if (has_hidden_methods)
+ // If the interface type has hidden methods, and the table is for a
+ // named type, then this is the only definition of the table.
+ // Otherwise it is a comdat table which may be defined in multiple
+ // packages.
+ if (has_hidden_methods && type->named_type() != NULL)
TREE_PUBLIC(decl) = 1;
else
{
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index a21493a786c..e16b0d3a59e 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1192,6 +1192,27 @@ Gogo::record_interface_type(Interface_type* itype)
this->interface_types_.push_back(itype);
}
+// Return an erroneous name that indicates that an error has already
+// been reported.
+
+std::string
+Gogo::erroneous_name()
+{
+ static int erroneous_count;
+ char name[50];
+ snprintf(name, sizeof name, "$erroneous%d", erroneous_count);
+ ++erroneous_count;
+ return name;
+}
+
+// Return whether a name is an erroneous name.
+
+bool
+Gogo::is_erroneous_name(const std::string& name)
+{
+ return name.compare(0, 10, "$erroneous") == 0;
+}
+
// Return a name for a thunk object.
std::string
@@ -1770,8 +1791,8 @@ Create_function_descriptors::function(Named_object* no)
if (no->is_function()
&& no->func_value()->enclosing() == NULL
&& !no->func_value()->is_method()
- && !no->func_value()->is_descriptor_wrapper()
- && !Gogo::is_hidden_name(no->name()))
+ && !Gogo::is_hidden_name(no->name())
+ && !Gogo::is_thunk(no))
no->func_value()->descriptor(this->gogo_, no);
return TRAVERSE_CONTINUE;
@@ -2367,7 +2388,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut)
Block* retblock = new Block(enclosing, loc);
retblock->set_end_location(loc);
- Temporary_statement* ts = Statement::make_temporary(Type::lookup_bool_type(),
+ Temporary_statement* ts = Statement::make_temporary(shortcut->type(),
left, loc);
retblock->add_statement(ts);
@@ -2541,13 +2562,38 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
return TRAVERSE_CONTINUE;
// If there is only one expression with a side-effect, we can
- // usually leave it in place. However, for an assignment statement,
- // we need to evaluate an expression on the right hand side before
- // we evaluate any index expression on the left hand side, so for
- // that case we always move the expression. Otherwise we mishandle
- // m[0] = len(m) where m is a map.
- if (c == 1 && s->classification() != Statement::STATEMENT_ASSIGNMENT)
- return TRAVERSE_CONTINUE;
+ // usually leave it in place.
+ if (c == 1)
+ {
+ switch (s->classification())
+ {
+ case Statement::STATEMENT_ASSIGNMENT:
+ // For an assignment statement, we need to evaluate an
+ // expression on the right hand side before we evaluate any
+ // index expression on the left hand side, so for that case
+ // we always move the expression. Otherwise we mishandle
+ // m[0] = len(m) where m is a map.
+ break;
+
+ case Statement::STATEMENT_EXPRESSION:
+ {
+ // If this is a call statement that doesn't return any
+ // values, it will not have been counted as a value to
+ // move. We need to move any subexpressions in case they
+ // are themselves call statements that require passing a
+ // closure.
+ Expression* expr = s->expression_statement()->expr();
+ if (expr->call_expression() != NULL
+ && expr->call_expression()->result_count() == 0)
+ break;
+ return TRAVERSE_CONTINUE;
+ }
+
+ default:
+ // We can leave the expression in place.
+ return TRAVERSE_CONTINUE;
+ }
+ }
bool is_thunk = s->thunk_statement() != NULL;
for (Find_eval_ordering::const_iterator p = find_eval_ordering.begin();
@@ -2776,7 +2822,10 @@ Build_recover_thunks::function(Named_object* orig_no)
if (orig_fntype->is_varargs())
new_fntype->set_is_varargs();
- std::string name = orig_no->name() + "$recover";
+ std::string name = orig_no->name();
+ if (orig_fntype->is_method())
+ name += "$" + orig_fntype->receiver()->type()->mangled_name(gogo);
+ name += "$recover";
Named_object *new_no = gogo->start_function(name, new_fntype, false,
location);
Function *new_func = new_no->func_value();
@@ -2803,7 +2852,7 @@ Build_recover_thunks::function(Named_object* orig_no)
Named_object* orig_closure_no = orig_func->closure_var();
Variable* orig_closure_var = orig_closure_no->var_value();
Variable* new_var = new Variable(orig_closure_var->type(), NULL, false,
- true, false, location);
+ false, false, location);
snprintf(buf, sizeof buf, "closure.%u", count);
++count;
Named_object* new_closure_no = Named_object::make_variable(buf, NULL,
@@ -2870,7 +2919,25 @@ Build_recover_thunks::function(Named_object* orig_no)
&& !orig_rec_no->var_value()->is_receiver());
orig_rec_no->var_value()->set_is_receiver();
- const std::string& new_receiver_name(orig_fntype->receiver()->name());
+ std::string new_receiver_name(orig_fntype->receiver()->name());
+ if (new_receiver_name.empty())
+ {
+ // Find the receiver. It was named "r.NNN" in
+ // Gogo::start_function.
+ for (Bindings::const_definitions_iterator p =
+ new_bindings->begin_definitions();
+ p != new_bindings->end_definitions();
+ ++p)
+ {
+ const std::string& pname((*p)->name());
+ if (pname[0] == 'r' && pname[1] == '.')
+ {
+ new_receiver_name = pname;
+ break;
+ }
+ }
+ go_assert(!new_receiver_name.empty());
+ }
Named_object* new_rec_no = new_bindings->lookup_local(new_receiver_name);
if (new_rec_no == NULL)
go_assert(saw_errors());
@@ -3133,7 +3200,8 @@ Check_return_statements_traverse::function(Named_object* no)
return TRAVERSE_CONTINUE;
if (func->block()->may_fall_through())
- error_at(func->location(), "control reaches end of non-void function");
+ error_at(func->block()->end_location(),
+ "missing return at end of function");
return TRAVERSE_CONTINUE;
}
@@ -3273,8 +3341,9 @@ Function::Function(Function_type* type, Function* enclosing, Block* block,
closure_var_(NULL), block_(block), location_(location), labels_(),
local_type_count_(0), descriptor_(NULL), fndecl_(NULL), defer_stack_(NULL),
is_sink_(false), results_are_named_(false), nointerface_(false),
- calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false),
- in_unique_section_(false), is_descriptor_wrapper_(false)
+ is_unnamed_type_stub_method_(false), calls_recover_(false),
+ is_recover_thunk_(false), has_recover_thunk_(false),
+ in_unique_section_(false)
{
}
@@ -3356,9 +3425,9 @@ Function::closure_var()
Struct_field_list* sfl = new Struct_field_list;
Type* struct_type = Type::make_struct_type(sfl, loc);
Variable* var = new Variable(Type::make_pointer_type(struct_type),
- NULL, false, true, false, loc);
+ NULL, false, false, false, loc);
var->set_is_used();
- this->closure_var_ = Named_object::make_variable("closure", NULL, var);
+ this->closure_var_ = Named_object::make_variable("$closure", NULL, var);
// Note that the new variable is not in any binding contour.
}
return this->closure_var_;
@@ -3380,7 +3449,7 @@ Function::set_closure_type()
st->push_field(Struct_field(Typed_identifier(".$f", voidptr_type,
this->location_)));
- unsigned int index = 0;
+ unsigned int index = 1;
for (Closure_fields::const_iterator p = this->closure_fields_.begin();
p != this->closure_fields_.end();
++p, ++index)
@@ -3561,93 +3630,16 @@ Function::determine_types()
this->block_->determine_types();
}
-// Build a wrapper function for a function descriptor. A function
-// descriptor refers to a function that takes a closure as its last
-// argument. In this case there will be no closure, but an indirect
-// call will pass nil as the last argument. We need to build a
-// wrapper function that accepts and discards that last argument, so
-// that cases like -mrtd will work correctly. In most cases the
-// wrapper function will simply be a jump.
-
-Named_object*
-Function::make_descriptor_wrapper(Gogo* gogo, Named_object* no,
- Function_type* orig_fntype)
-{
- Location loc = no->location();
-
- Type* vt = Type::make_pointer_type(Type::make_void_type());
- Function_type* new_fntype = orig_fntype->copy_with_closure(vt);
-
- std::string name = no->name() + "$descriptorfn";
- Named_object* dno = gogo->start_function(name, new_fntype, false, loc);
- dno->func_value()->is_descriptor_wrapper_ = true;
-
- gogo->start_block(loc);
-
- Expression* fn = Expression::make_func_reference(no, NULL, loc);
-
- // Call the function begin wrapped, passing all of the arguments
- // except for the last one (the last argument is the ignored
- // closure).
- const Typed_identifier_list* orig_params = orig_fntype->parameters();
- Expression_list* args;
- if (orig_params == NULL || orig_params->empty())
- args = NULL;
- else
- {
- const Typed_identifier_list* new_params = new_fntype->parameters();
- args = new Expression_list();
- for (Typed_identifier_list::const_iterator p = new_params->begin();
- p + 1 != new_params->end();
- ++p)
- {
- Named_object* p_no = gogo->lookup(p->name(), NULL);
- go_assert(p_no != NULL
- && p_no->is_variable()
- && p_no->var_value()->is_parameter());
- args->push_back(Expression::make_var_reference(p_no, loc));
- }
- }
-
- Call_expression* call = Expression::make_call(fn, args,
- orig_fntype->is_varargs(),
- loc);
- call->set_varargs_are_lowered();
-
- Statement* s = Statement::make_return_from_call(call, loc);
- gogo->add_statement(s);
- Block* b = gogo->finish_block(loc);
- gogo->add_block(b, loc);
- gogo->lower_block(dno, b);
- gogo->finish_function(loc);
-
- return dno;
-}
-
// Return the function descriptor, the value you get when you refer to
// the function in Go code without calling it.
Expression*
-Function::descriptor(Gogo* gogo, Named_object* no)
+Function::descriptor(Gogo*, Named_object* no)
{
go_assert(!this->is_method());
go_assert(this->closure_var_ == NULL);
- go_assert(!this->is_descriptor_wrapper_);
if (this->descriptor_ == NULL)
- {
- // Make and record the descriptor first, so that when we lower
- // the descriptor wrapper we don't try to make it again.
- Func_descriptor_expression* descriptor =
- Expression::make_func_descriptor(no);
- this->descriptor_ = descriptor;
- if (no->package() == NULL
- && !Linemap::is_predeclared_location(no->location()))
- {
- Named_object* dno = Function::make_descriptor_wrapper(gogo, no,
- this->type_);
- descriptor->set_descriptor_wrapper(dno);
- }
- }
+ this->descriptor_ = Expression::make_func_descriptor(no);
return this->descriptor_;
}
@@ -3849,6 +3841,81 @@ Function::import_func(Import* imp, std::string* pname,
*presults = results;
}
+// Get the backend representation.
+
+Bfunction*
+Function::get_or_make_decl(Gogo* gogo, Named_object* no)
+{
+ if (this->fndecl_ == NULL)
+ {
+ std::string asm_name;
+ bool is_visible = false;
+ if (no->package() != NULL)
+ ;
+ else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
+ ;
+ else if (Gogo::unpack_hidden_name(no->name()) == "init"
+ && !this->type_->is_method())
+ ;
+ else if (Gogo::unpack_hidden_name(no->name()) == "main"
+ && gogo->is_main_package())
+ is_visible = true;
+ // Methods have to be public even if they are hidden because
+ // they can be pulled into type descriptors when using
+ // anonymous fields.
+ else if (!Gogo::is_hidden_name(no->name())
+ || this->type_->is_method())
+ {
+ if (!this->is_unnamed_type_stub_method_)
+ is_visible = true;
+ std::string pkgpath = gogo->pkgpath_symbol();
+ if (this->type_->is_method()
+ && Gogo::is_hidden_name(no->name())
+ && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath())
+ {
+ // This is a method we created for an unexported
+ // method of an imported embedded type. We need to
+ // use the pkgpath of the imported package to avoid
+ // a possible name collision. See bug478 for a test
+ // case.
+ pkgpath = Gogo::hidden_name_pkgpath(no->name());
+ pkgpath = Gogo::pkgpath_for_symbol(pkgpath);
+ }
+
+ asm_name = pkgpath;
+ asm_name.append(1, '.');
+ asm_name.append(Gogo::unpack_hidden_name(no->name()));
+ if (this->type_->is_method())
+ {
+ asm_name.append(1, '.');
+ Type* rtype = this->type_->receiver()->type();
+ asm_name.append(rtype->mangled_name(gogo));
+ }
+ }
+
+ // If a function calls the predeclared recover function, we
+ // can't inline it, because recover behaves differently in a
+ // function passed directly to defer. If this is a recover
+ // thunk that we built to test whether a function can be
+ // recovered, we can't inline it, because that will mess up
+ // our return address comparison.
+ bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_);
+
+ // If this is a thunk created to call a function which calls
+ // the predeclared recover function, we need to disable
+ // stack splitting for the thunk.
+ bool disable_split_stack = this->is_recover_thunk_;
+
+ Btype* functype = this->type_->get_backend_fntype(gogo);
+ this->fndecl_ =
+ gogo->backend()->function(functype, no->get_id(gogo), asm_name,
+ is_visible, false, is_inlinable,
+ disable_split_stack,
+ this->in_unique_section_, this->location());
+ }
+ return this->fndecl_;
+}
+
// Class Block.
Block::Block(Block* enclosing, Location location)
@@ -4186,24 +4253,11 @@ Bindings_snapshot::check_goto_defs(Location loc, const Block* block,
// Return the function descriptor.
Expression*
-Function_declaration::descriptor(Gogo* gogo, Named_object* no)
+Function_declaration::descriptor(Gogo*, Named_object* no)
{
go_assert(!this->fntype_->is_method());
if (this->descriptor_ == NULL)
- {
- // Make and record the descriptor first, so that when we lower
- // the descriptor wrapper we don't try to make it again.
- Func_descriptor_expression* descriptor =
- Expression::make_func_descriptor(no);
- this->descriptor_ = descriptor;
- if (no->package() == NULL
- && !Linemap::is_predeclared_location(no->location()))
- {
- Named_object* dno = Function::make_descriptor_wrapper(gogo, no,
- this->fntype_);
- descriptor->set_descriptor_wrapper(dno);
- }
- }
+ this->descriptor_ = Expression::make_func_descriptor(no);
return this->descriptor_;
}
@@ -5153,6 +5207,75 @@ Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
go_unreachable();
}
+
+// Return the external identifier for this object.
+
+std::string
+Named_object::get_id(Gogo* gogo)
+{
+ go_assert(!this->is_variable() && !this->is_result_variable());
+ std::string decl_name;
+ if (this->is_function_declaration()
+ && !this->func_declaration_value()->asm_name().empty())
+ decl_name = this->func_declaration_value()->asm_name();
+ else if (this->is_type()
+ && Linemap::is_predeclared_location(this->type_value()->location()))
+ {
+ // We don't need the package name for builtin types.
+ decl_name = Gogo::unpack_hidden_name(this->name_);
+ }
+ else
+ {
+ std::string package_name;
+ if (this->package_ == NULL)
+ package_name = gogo->package_name();
+ else
+ package_name = this->package_->package_name();
+
+ // Note that this will be misleading if this is an unexported
+ // method generated for an embedded imported type. In that case
+ // the unexported method should have the package name of the
+ // package from which it is imported, but we are going to give
+ // it our package name. Fixing this would require knowing the
+ // package name, but we only know the package path. It might be
+ // better to use package paths here anyhow. This doesn't affect
+ // the assembler code, because we always set that name in
+ // Function::get_or_make_decl anyhow. FIXME.
+
+ decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
+
+ Function_type* fntype;
+ if (this->is_function())
+ fntype = this->func_value()->type();
+ else if (this->is_function_declaration())
+ fntype = this->func_declaration_value()->type();
+ else
+ fntype = NULL;
+ if (fntype != NULL && fntype->is_method())
+ {
+ decl_name.push_back('.');
+ decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
+ }
+ }
+ if (this->is_type())
+ {
+ unsigned int index;
+ const Named_object* in_function = this->type_value()->in_function(&index);
+ if (in_function != NULL)
+ {
+ decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+ if (index > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", index);
+ decl_name += '$';
+ decl_name += buf;
+ }
+ }
+ }
+ return decl_name;
+}
+
// Class Bindings.
Bindings::Bindings(Bindings* enclosing)
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index b6e9e45a1cb..31b258d62d6 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -48,6 +48,7 @@ class Bstatement;
class Bblock;
class Bvariable;
class Blabel;
+class Bfunction;
// This file declares the basic classes used to hold the internal
// representation of Go which is built by the parser.
@@ -387,6 +388,16 @@ class Gogo
void
mark_locals_used();
+ // Return a name to use for an error case. This should only be used
+ // after reporting an error, and is used to avoid useless knockon
+ // errors.
+ static std::string
+ erroneous_name();
+
+ // Return whether the name indicates an error.
+ static bool
+ is_erroneous_name(const std::string&);
+
// Return a name to use for a thunk function. A thunk function is
// one we create during the compilation, for a go statement or a
// defer statement or a method expression.
@@ -942,6 +953,15 @@ class Function
this->nointerface_ = true;
}
+ // Record that this function is a stub method created for an unnamed
+ // type.
+ void
+ set_is_unnamed_type_stub_method()
+ {
+ go_assert(this->is_method());
+ this->is_unnamed_type_stub_method_ = true;
+ }
+
// Add a new field to the closure variable.
void
add_closure_field(Named_object* var, Location loc)
@@ -1050,12 +1070,6 @@ class Function
set_in_unique_section()
{ this->in_unique_section_ = true; }
- // Whether this function was created as a descriptor wrapper for
- // another function.
- bool
- is_descriptor_wrapper() const
- { return this->is_descriptor_wrapper_; }
-
// Swap with another function. Used only for the thunk which calls
// recover.
void
@@ -1085,21 +1099,13 @@ class Function
this->descriptor_ = descriptor;
}
- // Build a descriptor wrapper function.
- static Named_object*
- make_descriptor_wrapper(Gogo*, Named_object*, Function_type*);
-
- // Return the function's decl given an identifier.
- tree
- get_or_make_decl(Gogo*, Named_object*, tree id);
+ // Return the backend representation.
+ Bfunction*
+ get_or_make_decl(Gogo*, Named_object*);
// Return the function's decl after it has been built.
tree
- get_decl() const
- {
- go_assert(this->fndecl_ != NULL);
- return this->fndecl_;
- }
+ get_decl() const;
// Set the function decl to hold a tree of the function code.
void
@@ -1170,7 +1176,7 @@ class Function
// The function descriptor, if any.
Expression* descriptor_;
// The function decl.
- tree fndecl_;
+ Bfunction* fndecl_;
// The defer stack variable. A pointer to this variable is used to
// distinguish the defer stack for one function from another. This
// is NULL unless we actually need a defer stack.
@@ -1181,6 +1187,9 @@ class Function
bool results_are_named_ : 1;
// True if this method should not be included in the type descriptor.
bool nointerface_ : 1;
+ // True if this function is a stub method created for an unnamed
+ // type.
+ bool is_unnamed_type_stub_method_ : 1;
// True if this function calls the predeclared recover function.
bool calls_recover_ : 1;
// True if this a thunk built for a function which calls recover.
@@ -1190,9 +1199,6 @@ class Function
// True if this function should be put in a unique section. This is
// turned on for field tracking.
bool in_unique_section_ : 1;
- // True if this is a function wrapper created to put in a function
- // descriptor.
- bool is_descriptor_wrapper_ : 1;
};
// A snapshot of the current binding state.
@@ -1268,9 +1274,9 @@ class Function_declaration
has_descriptor() const
{ return this->descriptor_ != NULL; }
- // Return a decl for the function given an identifier.
- tree
- get_or_make_decl(Gogo*, Named_object*, tree id);
+ // Return a backend representation.
+ Bfunction*
+ get_or_make_decl(Gogo*, Named_object*);
// If there is a descriptor, build it into the backend
// representation.
@@ -1293,7 +1299,7 @@ class Function_declaration
// The function descriptor, if any.
Expression* descriptor_;
// The function decl if needed.
- tree fndecl_;
+ Bfunction* fndecl_;
};
// A variable.
@@ -2184,8 +2190,8 @@ class Named_object
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
- // Return a tree for the external identifier for this object.
- tree
+ // Return the external identifier for this object.
+ std::string
get_id(Gogo*);
// Return a tree representing this object.
diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h
index c6844cda8a5..9917937e4d3 100644
--- a/gcc/go/gofrontend/import.h
+++ b/gcc/go/gofrontend/import.h
@@ -149,6 +149,11 @@ class Import
location() const
{ return this->location_; }
+ // Return the package we are importing.
+ Package*
+ package() const
+ { return this->package_; }
+
// Return the next character.
int
peek_char()
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index 22a1f6e2a0c..16169634733 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -873,7 +873,28 @@ Lex::gather_identifier()
&& (cc < 'a' || cc > 'z')
&& cc != '_'
&& (cc < '0' || cc > '9'))
- break;
+ {
+ // Check for an invalid character here, as we get better
+ // error behaviour if we swallow them as part of the
+ // identifier we are building.
+ if ((cc >= ' ' && cc < 0x7f)
+ || cc == '\t'
+ || cc == '\r'
+ || cc == '\n')
+ break;
+
+ this->lineoff_ = p - this->linebuf_;
+ error_at(this->location(),
+ "invalid character 0x%x in identifier",
+ cc);
+ if (!has_non_ascii_char)
+ {
+ buf.assign(pstart, p - pstart);
+ has_non_ascii_char = true;
+ }
+ if (!Lex::is_invalid_identifier(buf))
+ buf.append("$INVALID$");
+ }
++p;
if (is_first)
{
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 429d91bafe2..9c7d8277efa 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -213,7 +213,7 @@ Parse::qualified_ident(std::string* pname, Named_object** ppackage)
if (name == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = "blank";
+ name = Gogo::erroneous_name();
}
if (package->name() == this->gogo_->package_name())
@@ -744,6 +744,8 @@ Parse::signature(Typed_identifier* receiver, Location location)
return NULL;
Parse::Names names;
+ if (receiver != NULL)
+ names[receiver->name()] = receiver;
if (params != NULL)
this->check_signature_names(params, &names);
if (results != NULL)
@@ -1940,12 +1942,9 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
{
if (this->gogo_->in_global_scope())
return this->create_dummy_global(type, init, location);
- else if (type == NULL)
- this->gogo_->add_statement(Statement::make_statement(init, true));
else
{
- // With both a type and an initializer, create a dummy
- // variable so that we will check whether the
+ // Create a dummy variable so that we will check whether the
// initializer can be assigned to the type.
Variable* var = new Variable(type, init, false, false, false,
location);
@@ -2693,15 +2692,17 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
this->advance_token();
return Expression::make_composite_literal(type, depth, false, NULL,
- location);
+ false, location);
}
bool has_keys = false;
+ bool all_are_names = true;
Expression_list* vals = new Expression_list;
while (true)
{
Expression* val;
bool is_type_omitted = false;
+ bool is_name = false;
const Token* token = this->peek_token();
@@ -2722,6 +2723,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
location);
+ is_name = true;
}
else
{
@@ -2747,6 +2749,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
if (has_keys)
vals->push_back(NULL);
+ is_name = false;
}
else
{
@@ -2793,6 +2796,9 @@ Parse::composite_lit(Type* type, int depth, Location location)
vals->push_back(val);
+ if (!is_name)
+ all_are_names = false;
+
if (token->is_op(OPERATOR_COMMA))
{
if (this->advance_token()->is_op(OPERATOR_RCURLY))
@@ -2833,7 +2839,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
}
return Expression::make_composite_literal(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// FunctionLit = "func" Signature Block .
@@ -3107,7 +3113,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
if (token->identifier() == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = this->gogo_->pack_hidden_name("blank", false);
+ name = Gogo::erroneous_name();
}
this->advance_token();
return Expression::make_selector(left, name, location);
@@ -4932,7 +4938,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
*varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
@@ -4968,7 +4974,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
if (recv_var != "_")
@@ -5266,7 +5272,8 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
no->var_value()->set_type_from_range_value();
if (is_new)
any_new = true;
- p_range_clause->value = Expression::make_var_reference(no, location);
+ if (!Gogo::is_sink_name(pti->name()))
+ p_range_clause->value = Expression::make_var_reference(no, location);
}
if (!any_new)
@@ -5504,7 +5511,7 @@ Parse::package_clause()
if (name == "_")
{
error_at(this->location(), "invalid package name _");
- name = "blank";
+ name = Gogo::erroneous_name();
}
this->advance_token();
}
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index ecc508d0dcc..3b0f1880758 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -42,6 +42,8 @@ enum Runtime_function_type
RFT_RUNE,
// Go type float64, C type double.
RFT_FLOAT64,
+ // Go type complex64, C type __complex float.
+ RFT_COMPLEX64,
// Go type complex128, C type __complex double.
RFT_COMPLEX128,
// Go type string, C type struct __go_string.
@@ -126,6 +128,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_float_type("float64");
break;
+ case RFT_COMPLEX64:
+ t = Type::lookup_complex_type("complex64");
+ break;
+
case RFT_COMPLEX128:
t = Type::lookup_complex_type("complex128");
break;
@@ -216,6 +222,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_UINTPTR:
case RFT_RUNE:
case RFT_FLOAT64:
+ case RFT_COMPLEX64:
case RFT_COMPLEX128:
case RFT_STRING:
case RFT_POINTER:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 0d3fd3c43f1..a303a50410f 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -68,6 +68,12 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
P1(STRING), R1(SLICE))
+// Complex division.
+DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div",
+ P2(COMPLEX64, COMPLEX64), R1(COMPLEX64))
+DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
+ P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
+
// Make a slice.
DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index ca1ad07af6c..a5102c0c450 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -594,6 +594,15 @@ Assignment_statement::do_check_types(Gogo*)
Type* lhs_type = this->lhs_->type();
Type* rhs_type = this->rhs_->type();
+
+ // Invalid assignment of nil to the blank identifier.
+ if (lhs_type->is_sink_type()
+ && rhs_type->is_nil_type())
+ {
+ this->report_error(_("use of untyped nil"));
+ return;
+ }
+
std::string reason;
bool ok;
if (this->are_hidden_fields_ok_)
@@ -975,7 +984,10 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
if ((*plhs)->is_sink_expression())
{
- b->add_statement(Statement::make_statement(*prhs, true));
+ if ((*prhs)->type()->is_nil_type())
+ this->report_error(_("use of untyped nil"));
+ else
+ b->add_statement(Statement::make_statement(*prhs, true));
continue;
}
@@ -1658,46 +1670,23 @@ Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
location);
}
-// An expression statement.
-
-class Expression_statement : public Statement
-{
- public:
- Expression_statement(Expression* expr, bool is_ignored)
- : Statement(STATEMENT_EXPRESSION, expr->location()),
- expr_(expr), is_ignored_(is_ignored)
- { }
-
- Expression*
- expr()
- { return this->expr_; }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return this->traverse_expression(traverse, &this->expr_); }
-
- void
- do_determine_types()
- { this->expr_->determine_type_no_context(); }
-
- void
- do_check_types(Gogo*);
+// Class Expression_statement.
- bool
- do_may_fall_through() const;
+// Constructor.
- Bstatement*
- do_get_backend(Translate_context* context);
+Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
+ : Statement(STATEMENT_EXPRESSION, expr->location()),
+ expr_(expr), is_ignored_(is_ignored)
+{
+}
- void
- do_dump_statement(Ast_dump_context*) const;
+// Determine types.
- private:
- Expression* expr_;
- // Whether the value of this expression is being explicitly ignored.
- bool is_ignored_;
-};
+void
+Expression_statement::do_determine_types()
+{
+ this->expr_->determine_type_no_context();
+}
// Check the types of an expression statement. The only check we do
// is to possibly give an error about discarding the value of the
@@ -4093,6 +4082,16 @@ Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
bool
Type_case_clauses::Type_case_clause::may_fall_through() const
{
+ if (this->is_fallthrough_)
+ {
+ // This case means that we automatically fall through to the
+ // next case (it's used for T1 in case T1, T2:). It does not
+ // mean that we fall through to the end of the type switch as a
+ // whole. There is sure to be a next case and that next case
+ // will determine whether we fall through to the statements
+ // after the type switch.
+ return false;
+ }
if (this->statements_ == NULL)
return true;
return this->statements_->may_fall_through();
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index fb2ae334293..b128fa0a8eb 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -17,6 +17,7 @@ class Function;
class Unnamed_label;
class Temporary_statement;
class Variable_declaration_statement;
+class Expression_statement;
class Return_statement;
class Thunk_statement;
class Label_statement;
@@ -329,6 +330,14 @@ class Statement
STATEMENT_VARIABLE_DECLARATION>();
}
+ // If this is an expression statement, return it. Otherwise return
+ // NULL.
+ Expression_statement*
+ expression_statement()
+ {
+ return this->convert<Expression_statement, STATEMENT_EXPRESSION>();
+ }
+
// If this is a return statement, return it. Otherwise return NULL.
Return_statement*
return_statement()
@@ -636,6 +645,43 @@ class Return_statement : public Statement
bool is_lowered_;
};
+// An expression statement.
+
+class Expression_statement : public Statement
+{
+ public:
+ Expression_statement(Expression* expr, bool is_ignored);
+
+ Expression*
+ expr()
+ { return this->expr_; }
+
+ protected:
+ int
+ do_traverse(Traverse* traverse)
+ { return this->traverse_expression(traverse, &this->expr_); }
+
+ void
+ do_determine_types();
+
+ void
+ do_check_types(Gogo*);
+
+ bool
+ do_may_fall_through() const;
+
+ Bstatement*
+ do_get_backend(Translate_context* context);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
+ private:
+ Expression* expr_;
+ // Whether the value of this expression is being explicitly ignored.
+ bool is_ignored_;
+};
+
// A send statement.
class Send_statement : public Statement
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 0a86d472062..b95017c1afd 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1834,7 +1834,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
bloc);
gogo->start_block(bloc);
- if (this->struct_type() != NULL)
+ if (name != NULL && name->real_type()->named_type() != NULL)
+ this->write_named_hash(gogo, name, hash_fntype, equal_fntype);
+ else if (this->struct_type() != NULL)
this->struct_type()->write_hash_function(gogo, name, hash_fntype,
equal_fntype);
else if (this->array_type() != NULL)
@@ -1852,7 +1854,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
false, bloc);
gogo->start_block(bloc);
- if (this->struct_type() != NULL)
+ if (name != NULL && name->real_type()->named_type() != NULL)
+ this->write_named_equal(gogo, name);
+ else if (this->struct_type() != NULL)
this->struct_type()->write_equal_function(gogo, name);
else if (this->array_type() != NULL)
this->array_type()->write_equal_function(gogo, name);
@@ -1865,6 +1869,100 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
gogo->finish_function(bloc);
}
+// Write a hash function that simply calls the hash function for a
+// named type. This is used when one named type is defined as
+// another. This ensures that this case works when the other named
+// type is defined in another package and relies on calling hash
+// functions defined only in that package.
+
+void
+Type::write_named_hash(Gogo* gogo, Named_type* name,
+ Function_type* hash_fntype, Function_type* equal_fntype)
+{
+ Location bloc = Linemap::predeclared_location();
+
+ Named_type* base_type = name->real_type()->named_type();
+ go_assert(base_type != NULL);
+
+ // The pointer to the type we are going to hash. This is an
+ // unsafe.Pointer.
+ Named_object* key_arg = gogo->lookup("key", NULL);
+ go_assert(key_arg != NULL);
+
+ // The size of the type we are going to hash.
+ Named_object* keysz_arg = gogo->lookup("key_size", NULL);
+ go_assert(keysz_arg != NULL);
+
+ Named_object* hash_fn;
+ Named_object* equal_fn;
+ name->real_type()->type_functions(gogo, base_type, hash_fntype, equal_fntype,
+ &hash_fn, &equal_fn);
+
+ // Call the hash function for the base type.
+ Expression* key_ref = Expression::make_var_reference(key_arg, bloc);
+ Expression* keysz_ref = Expression::make_var_reference(keysz_arg, bloc);
+ Expression_list* args = new Expression_list();
+ args->push_back(key_ref);
+ args->push_back(keysz_ref);
+ Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
+ Expression* call = Expression::make_call(func, args, false, bloc);
+
+ // Return the hash of the base type.
+ Expression_list* vals = new Expression_list();
+ vals->push_back(call);
+ Statement* s = Statement::make_return_statement(vals, bloc);
+ gogo->add_statement(s);
+}
+
+// Write an equality function that simply calls the equality function
+// for a named type. This is used when one named type is defined as
+// another. This ensures that this case works when the other named
+// type is defined in another package and relies on calling equality
+// functions defined only in that package.
+
+void
+Type::write_named_equal(Gogo* gogo, Named_type* name)
+{
+ Location bloc = Linemap::predeclared_location();
+
+ // The pointers to the types we are going to compare. These have
+ // type unsafe.Pointer.
+ Named_object* key1_arg = gogo->lookup("key1", NULL);
+ Named_object* key2_arg = gogo->lookup("key2", NULL);
+ go_assert(key1_arg != NULL && key2_arg != NULL);
+
+ Named_type* base_type = name->real_type()->named_type();
+ go_assert(base_type != NULL);
+
+ // Build temporaries with the base type.
+ Type* pt = Type::make_pointer_type(base_type);
+
+ Expression* ref = Expression::make_var_reference(key1_arg, bloc);
+ ref = Expression::make_cast(pt, ref, bloc);
+ Temporary_statement* p1 = Statement::make_temporary(pt, ref, bloc);
+ gogo->add_statement(p1);
+
+ ref = Expression::make_var_reference(key2_arg, bloc);
+ ref = Expression::make_cast(pt, ref, bloc);
+ Temporary_statement* p2 = Statement::make_temporary(pt, ref, bloc);
+ gogo->add_statement(p2);
+
+ // Compare the values for equality.
+ Expression* t1 = Expression::make_temporary_reference(p1, bloc);
+ t1 = Expression::make_unary(OPERATOR_MULT, t1, bloc);
+
+ Expression* t2 = Expression::make_temporary_reference(p2, bloc);
+ t2 = Expression::make_unary(OPERATOR_MULT, t2, bloc);
+
+ Expression* cond = Expression::make_binary(OPERATOR_EQEQ, t1, t2, bloc);
+
+ // Return the equality comparison.
+ Expression_list* vals = new Expression_list();
+ vals->push_back(cond);
+ Statement* s = Statement::make_return_statement(vals, bloc);
+ gogo->add_statement(s);
+}
+
// Return a composite literal for the type descriptor for a plain type
// of kind RUNTIME_TYPE_KIND named NAME.
@@ -2164,26 +2262,9 @@ Type::method_constructor(Gogo*, Type* method_type,
++p;
go_assert(p->is_field_name("typ"));
- if (!only_value_methods && m->is_value_method())
- {
- // This is a value method on a pointer type. Change the type of
- // the method to use a pointer receiver. The implementation
- // always uses a pointer receiver anyhow.
- Type* rtype = mtype->receiver()->type();
- Type* prtype = Type::make_pointer_type(rtype);
- Typed_identifier* receiver =
- new Typed_identifier(mtype->receiver()->name(), prtype,
- mtype->receiver()->location());
- mtype = Type::make_function_type(receiver,
- (mtype->parameters() == NULL
- ? NULL
- : mtype->parameters()->copy()),
- (mtype->results() == NULL
- ? NULL
- : mtype->results()->copy()),
- mtype->location());
- }
- vals->push_back(Expression::make_type_descriptor(mtype, bloc));
+ bool want_pointer_receiver = !only_value_methods && m->is_value_method();
+ nonmethod_type = mtype->copy_with_receiver_as_param(want_pointer_receiver);
+ vals->push_back(Expression::make_type_descriptor(nonmethod_type, bloc));
++p;
go_assert(p->is_field_name("tfn"));
@@ -2288,9 +2369,7 @@ Type::is_backend_type_size_known(Gogo* gogo)
}
case TYPE_NAMED:
- // Begin converting this type to the backend representation.
- // This will create a placeholder if necessary.
- this->get_backend(gogo);
+ this->named_type()->convert(gogo);
return this->named_type()->is_named_backend_type_size_known();
case TYPE_FORWARD:
@@ -3385,82 +3464,83 @@ Function_type::do_hash_for_method(Gogo* gogo) const
// Get the backend representation for a function type.
Btype*
+Function_type::get_backend_fntype(Gogo* gogo)
+{
+ if (this->fnbtype_ == NULL)
+ {
+ Backend::Btyped_identifier breceiver;
+ if (this->receiver_ != NULL)
+ {
+ breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name());
+
+ // We always pass the address of the receiver parameter, in
+ // order to make interface calls work with unknown types.
+ Type* rtype = this->receiver_->type();
+ if (rtype->points_to() == NULL)
+ rtype = Type::make_pointer_type(rtype);
+ breceiver.btype = rtype->get_backend(gogo);
+ breceiver.location = this->receiver_->location();
+ }
+
+ std::vector<Backend::Btyped_identifier> bparameters;
+ if (this->parameters_ != NULL)
+ {
+ bparameters.resize(this->parameters_->size());
+ size_t i = 0;
+ for (Typed_identifier_list::const_iterator p =
+ this->parameters_->begin(); p != this->parameters_->end();
+ ++p, ++i)
+ {
+ bparameters[i].name = Gogo::unpack_hidden_name(p->name());
+ bparameters[i].btype = p->type()->get_backend(gogo);
+ bparameters[i].location = p->location();
+ }
+ go_assert(i == bparameters.size());
+ }
+
+ std::vector<Backend::Btyped_identifier> bresults;
+ if (this->results_ != NULL)
+ {
+ bresults.resize(this->results_->size());
+ size_t i = 0;
+ for (Typed_identifier_list::const_iterator p =
+ this->results_->begin(); p != this->results_->end();
+ ++p, ++i)
+ {
+ bresults[i].name = Gogo::unpack_hidden_name(p->name());
+ bresults[i].btype = p->type()->get_backend(gogo);
+ bresults[i].location = p->location();
+ }
+ go_assert(i == bresults.size());
+ }
+
+ this->fnbtype_ = gogo->backend()->function_type(breceiver, bparameters,
+ bresults,
+ this->location());
+
+ }
+
+ return this->fnbtype_;
+}
+
+// Get the backend representation for a Go function type.
+
+Btype*
Function_type::do_get_backend(Gogo* gogo)
{
// When we do anything with a function value other than call it, it
// is represented as a pointer to a struct whose first field is the
// actual function. So that is what we return as the type of a Go
- // function. The function stored in the first field always that
- // takes one additional trailing argument: the closure pointer. For
- // a top-level function, this additional argument will only be
- // passed when invoking the function indirectly, via the struct.
+ // function.
Location loc = this->location();
Btype* struct_type =
gogo->backend()->placeholder_struct_type("__go_descriptor", loc);
Btype* ptr_struct_type = gogo->backend()->pointer_type(struct_type);
- Backend::Btyped_identifier breceiver;
- if (this->receiver_ != NULL)
- {
- breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name());
-
- // We always pass the address of the receiver parameter, in
- // order to make interface calls work with unknown types.
- Type* rtype = this->receiver_->type();
- if (rtype->points_to() == NULL)
- rtype = Type::make_pointer_type(rtype);
- breceiver.btype = rtype->get_backend(gogo);
- breceiver.location = this->receiver_->location();
- }
-
- std::vector<Backend::Btyped_identifier> bparameters;
- size_t last;
- if (this->parameters_ == NULL)
- {
- bparameters.resize(1);
- last = 0;
- }
- else
- {
- bparameters.resize(this->parameters_->size() + 1);
- size_t i = 0;
- for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
- p != this->parameters_->end();
- ++p, ++i)
- {
- bparameters[i].name = Gogo::unpack_hidden_name(p->name());
- bparameters[i].btype = p->type()->get_backend(gogo);
- bparameters[i].location = p->location();
- }
- last = i;
- }
- go_assert(last + 1 == bparameters.size());
- bparameters[last].name = "$closure";
- bparameters[last].btype = ptr_struct_type;
- bparameters[last].location = loc;
-
- std::vector<Backend::Btyped_identifier> bresults;
- if (this->results_ != NULL)
- {
- bresults.resize(this->results_->size());
- size_t i = 0;
- for (Typed_identifier_list::const_iterator p = this->results_->begin();
- p != this->results_->end();
- ++p, ++i)
- {
- bresults[i].name = Gogo::unpack_hidden_name(p->name());
- bresults[i].btype = p->type()->get_backend(gogo);
- bresults[i].location = p->location();
- }
- go_assert(i == bresults.size());
- }
-
- Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
- bresults, loc);
std::vector<Backend::Btyped_identifier> fields(1);
fields[0].name = "code";
- fields[0].btype = fntype;
+ fields[0].btype = this->get_backend_fntype(gogo);
fields[0].location = loc;
if (!gogo->backend()->set_placeholder_struct_type(struct_type, fields))
return gogo->backend()->error_type();
@@ -3836,11 +3916,37 @@ Function_type::copy_with_receiver(Type* receiver_type) const
return ret;
}
+// Make a copy of a function type with the receiver as the first
+// parameter.
+
+Function_type*
+Function_type::copy_with_receiver_as_param(bool want_pointer_receiver) const
+{
+ go_assert(this->is_method());
+ Typed_identifier_list* new_params = new Typed_identifier_list();
+ Type* rtype = this->receiver_->type();
+ if (want_pointer_receiver)
+ rtype = Type::make_pointer_type(rtype);
+ Typed_identifier receiver(this->receiver_->name(), rtype,
+ this->receiver_->location());
+ new_params->push_back(receiver);
+ const Typed_identifier_list* orig_params = this->parameters_;
+ if (orig_params != NULL && !orig_params->empty())
+ {
+ for (Typed_identifier_list::const_iterator p = orig_params->begin();
+ p != orig_params->end();
+ ++p)
+ new_params->push_back(*p);
+ }
+ return Type::make_function_type(NULL, new_params, this->results_,
+ this->location_);
+}
+
// Make a copy of a function type ignoring any receiver and adding a
// closure parameter.
Function_type*
-Function_type::copy_with_closure(Type* closure_type) const
+Function_type::copy_with_names() const
{
Typed_identifier_list* new_params = new Typed_identifier_list();
const Typed_identifier_list* orig_params = this->parameters_;
@@ -3858,8 +3964,6 @@ Function_type::copy_with_closure(Type* closure_type) const
p->location()));
}
}
- new_params->push_back(Typed_identifier("closure.0", closure_type,
- this->location_));
const Typed_identifier_list* orig_results = this->results_;
Typed_identifier_list* new_results;
@@ -4212,7 +4316,8 @@ Struct_field::is_field_name(const std::string& name) const
// This is a horrible hack caused by the fact that we don't pack
// the names of builtin types. FIXME.
- if (nt != NULL
+ if (!this->is_imported_
+ && nt != NULL
&& nt->is_builtin()
&& nt->name() == Gogo::unpack_hidden_name(name))
return true;
@@ -4221,6 +4326,52 @@ Struct_field::is_field_name(const std::string& name) const
}
}
+// Return whether this field is an unexported field named NAME.
+
+bool
+Struct_field::is_unexported_field_name(Gogo* gogo,
+ const std::string& name) const
+{
+ const std::string& field_name(this->field_name());
+ if (Gogo::is_hidden_name(field_name)
+ && name == Gogo::unpack_hidden_name(field_name)
+ && gogo->pack_hidden_name(name, false) != field_name)
+ return true;
+
+ // Check for the name of a builtin type. This is like the test in
+ // is_field_name, only there we return false if this->is_imported_,
+ // and here we return true.
+ if (this->is_imported_ && this->is_anonymous())
+ {
+ Type* t = this->typed_identifier_.type();
+ if (t->points_to() != NULL)
+ t = t->points_to();
+ Named_type* nt = t->named_type();
+ if (nt != NULL
+ && nt->is_builtin()
+ && nt->name() == Gogo::unpack_hidden_name(name))
+ return true;
+ }
+
+ return false;
+}
+
+// Return whether this field is an embedded built-in type.
+
+bool
+Struct_field::is_embedded_builtin(Gogo* gogo) const
+{
+ const std::string& name(this->field_name());
+ // We know that a field is an embedded type if it is anonymous.
+ // We can decide if it is a built-in type by checking to see if it is
+ // registered globally under the field's name.
+ // This allows us to distinguish between embedded built-in types and
+ // embedded types that are aliases to built-in types.
+ return (this->is_anonymous()
+ && !Gogo::is_hidden_name(name)
+ && gogo->lookup_global(name.c_str()) != NULL);
+}
+
// Class Struct_type.
// A hash table used to find identical unnamed structs so that they
@@ -4228,6 +4379,11 @@ Struct_field::is_field_name(const std::string& name) const
Struct_type::Identical_structs Struct_type::identical_structs;
+// A hash table used to merge method sets for identical unnamed
+// structs.
+
+Struct_type::Struct_method_tables Struct_type::struct_method_tables;
+
// Traversal.
int
@@ -4260,12 +4416,7 @@ Struct_type::do_verify()
++p)
{
Type* t = p->type();
- if (t->is_undefined())
- {
- error_at(p->location(), "struct field type is incomplete");
- p->set_type(Type::make_error_type());
- }
- else if (p->is_anonymous())
+ if (p->is_anonymous())
{
if (t->named_type() != NULL && t->points_to() != NULL)
{
@@ -4637,13 +4788,8 @@ Struct_type::is_unexported_local_field(Gogo* gogo,
for (Struct_field_list::const_iterator pf = fields->begin();
pf != fields->end();
++pf)
- {
- const std::string& field_name(pf->field_name());
- if (Gogo::is_hidden_name(field_name)
- && name == Gogo::unpack_hidden_name(field_name)
- && gogo->pack_hidden_name(name, false) != field_name)
- return true;
- }
+ if (pf->is_unexported_field_name(gogo, name))
+ return true;
}
return false;
}
@@ -4692,9 +4838,24 @@ Struct_type::interface_method_table(Gogo* gogo,
const Interface_type* interface,
bool is_pointer)
{
+ std::pair<Struct_type*, Struct_type::Struct_method_table_pair*>
+ val(this, NULL);
+ std::pair<Struct_type::Struct_method_tables::iterator, bool> ins =
+ Struct_type::struct_method_tables.insert(val);
+
+ Struct_method_table_pair* smtp;
+ if (!ins.second)
+ smtp = ins.first->second;
+ else
+ {
+ smtp = new Struct_method_table_pair();
+ smtp->first = NULL;
+ smtp->second = NULL;
+ ins.first->second = smtp;
+ }
+
return Type::interface_method_table(gogo, this, interface, is_pointer,
- &this->interface_method_tables_,
- &this->pointer_interface_method_tables_);
+ &smtp->first, &smtp->second);
}
// Convert struct fields to the backend representation. This is not
@@ -4835,11 +4996,16 @@ Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
++q;
go_assert(q->is_field_name("pkgPath"));
- if (!Gogo::is_hidden_name(pf->field_name()))
- fvals->push_back(Expression::make_nil(bloc));
+ bool is_embedded_builtin = pf->is_embedded_builtin(gogo);
+ if (!Gogo::is_hidden_name(pf->field_name()) && !is_embedded_builtin)
+ fvals->push_back(Expression::make_nil(bloc));
else
{
- std::string n = Gogo::hidden_name_pkgpath(pf->field_name());
+ std::string n;
+ if (is_embedded_builtin)
+ n = gogo->package_name();
+ else
+ n = Gogo::hidden_name_pkgpath(pf->field_name());
Expression* s = Expression::make_string(n, bloc);
fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
}
@@ -5226,6 +5392,7 @@ Struct_type::do_import(Import* imp)
Type* ftype = imp->read_type();
Struct_field sf(Typed_identifier(name, ftype, imp->location()));
+ sf.set_is_imported();
if (imp->peek_char() == ' ')
{
@@ -5641,8 +5808,10 @@ Array_type::get_length_tree(Gogo* gogo)
t = Type::lookup_integer_type("int");
else if (t->is_abstract())
t = t->make_non_abstract_type();
- tree tt = type_to_tree(t->get_backend(gogo));
- this->length_tree_ = Expression::integer_constant_tree(val, tt);
+ Btype* btype = t->get_backend(gogo);
+ Bexpression* iexpr =
+ gogo->backend()->integer_constant_expression(btype, val);
+ this->length_tree_ = expr_to_tree(iexpr);
mpz_clear(val);
}
else
@@ -8996,6 +9165,8 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
fntype->is_varargs(), location);
gogo->finish_function(fntype->location());
+ if (type->named_type() == NULL && stub->is_function())
+ stub->func_value()->set_is_unnamed_type_stub_method();
if (m->nointerface() && stub->is_function())
stub->func_value()->set_nointerface();
}
@@ -9245,7 +9416,11 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
}
else
{
- if (!ambig1.empty())
+ if (Gogo::is_erroneous_name(name))
+ {
+ // An error was already reported.
+ }
+ else if (!ambig1.empty())
error_at(location, "%qs is ambiguous via %qs and %qs",
Gogo::message_name(name).c_str(), ambig1.c_str(),
ambig2.c_str());
@@ -9259,7 +9434,9 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
else
{
bool is_unexported;
- if (!Gogo::is_hidden_name(name))
+ // The test for 'a' and 'z' is to handle builtin names,
+ // which are not hidden.
+ if (!Gogo::is_hidden_name(name) && (name[0] < 'a' || name[0] > 'z'))
is_unexported = false;
else
{
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 56626f1960e..0c712aaf539 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1138,6 +1138,13 @@ class Type
Function_type* equal_fntype, Named_object** hash_fn,
Named_object** equal_fn);
+ void
+ write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
+ Function_type* equal_fntype);
+
+ void
+ write_named_equal(Gogo*, Named_type*);
+
// Build a composite literal for the uncommon type information.
Expression*
uncommon_type_constructor(Gogo*, Type* uncommon_type,
@@ -1717,7 +1724,8 @@ class Function_type : public Type
Typed_identifier_list* results, Location location)
: Type(TYPE_FUNCTION),
receiver_(receiver), parameters_(parameters), results_(results),
- location_(location), is_varargs_(false), is_builtin_(false)
+ location_(location), is_varargs_(false), is_builtin_(false),
+ fnbtype_(NULL)
{ }
// Get the receiver.
@@ -1789,15 +1797,26 @@ class Function_type : public Type
Function_type*
copy_with_receiver(Type*) const;
- // Return a copy of this type ignoring any receiver and adding a
- // final closure parameter of type CLOSURE_TYPE. This is used when
- // creating descriptors.
+ // Return a copy of this type with the receiver treated as the first
+ // parameter. If WANT_POINTER_RECEIVER is true, the receiver is
+ // forced to be a pointer.
+ Function_type*
+ copy_with_receiver_as_param(bool want_pointer_receiver) const;
+
+ // Return a copy of this type ignoring any receiver and using dummy
+ // names for all parameters. This is used for thunks for method
+ // values.
Function_type*
- copy_with_closure(Type* closure_type) const;
+ copy_with_names() const;
static Type*
make_function_type_descriptor_type();
+ // Return the backend representation of this function type. This is used
+ // as the real type of a backend function declaration or defintion.
+ Btype*
+ get_backend_fntype(Gogo*);
+
protected:
int
do_traverse(Traverse*);
@@ -1851,6 +1870,9 @@ class Function_type : public Type
// Whether this is a special builtin function which can not simply
// be called. This is used for len, cap, etc.
bool is_builtin_;
+ // The backend representation of this type for backend function
+ // declarations and definitions.
+ Btype* fnbtype_;
};
// The type of a pointer.
@@ -1915,7 +1937,7 @@ class Struct_field
{
public:
explicit Struct_field(const Typed_identifier& typed_identifier)
- : typed_identifier_(typed_identifier), tag_(NULL)
+ : typed_identifier_(typed_identifier), tag_(NULL), is_imported_(false)
{ }
// The field name.
@@ -1926,6 +1948,14 @@ class Struct_field
bool
is_field_name(const std::string& name) const;
+ // Return whether this struct field is an unexported field named NAME.
+ bool
+ is_unexported_field_name(Gogo*, const std::string& name) const;
+
+ // Return whether this struct field is an embedded built-in type.
+ bool
+ is_embedded_builtin(Gogo*) const;
+
// The field type.
Type*
type() const
@@ -1959,6 +1989,11 @@ class Struct_field
set_tag(const std::string& tag)
{ this->tag_ = new std::string(tag); }
+ // Record that this field is defined in an imported struct.
+ void
+ set_is_imported()
+ { this->is_imported_ = true; }
+
// Set the type. This is only used in error cases.
void
set_type(Type* type)
@@ -1969,6 +2004,8 @@ class Struct_field
Typed_identifier typed_identifier_;
// The field tag. This is NULL if the field has no tag.
std::string* tag_;
+ // Whether this field is defined in an imported struct.
+ bool is_imported_;
};
// A list of struct fields.
@@ -2037,8 +2074,7 @@ class Struct_type : public Type
public:
Struct_type(Struct_field_list* fields, Location location)
: Type(TYPE_STRUCT),
- fields_(fields), location_(location), all_methods_(NULL),
- interface_method_tables_(NULL), pointer_interface_method_tables_(NULL)
+ fields_(fields), location_(location), all_methods_(NULL)
{ }
// Return the field NAME. This only looks at local fields, not at
@@ -2196,6 +2232,16 @@ class Struct_type : public Type
static Identical_structs identical_structs;
+ // Used to manage method tables for identical unnamed structs.
+ typedef std::pair<Interface_method_tables*, Interface_method_tables*>
+ Struct_method_table_pair;
+
+ typedef Unordered_map_hash(Struct_type*, Struct_method_table_pair*,
+ Type_hash_identical, Type_identical)
+ Struct_method_tables;
+
+ static Struct_method_tables struct_method_tables;
+
// Used to avoid infinite loops in field_reference_depth.
struct Saw_named_type
{
@@ -2214,13 +2260,6 @@ class Struct_type : public Type
Location location_;
// If this struct is unnamed, a list of methods.
Methods* all_methods_;
- // A mapping from interfaces to the associated interface method
- // tables for this type. Only used if this struct is unnamed.
- Interface_method_tables* interface_method_tables_;
- // A mapping from interfaces to the associated interface method
- // tables for pointers to this type. Only used if this struct is
- // unnamed.
- Interface_method_tables* pointer_interface_method_tables_;
};
// The type of an array.
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 88967a6c248..e3353a5f26b 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -115,7 +115,11 @@ count_bb_insns (const_basic_block bb)
while (1)
{
- if (CALL_P (insn) || NONJUMP_INSN_P (insn))
+ if ((CALL_P (insn) || NONJUMP_INSN_P (insn))
+ /* Don't count USE/CLOBBER insns, flow_find_cross_jump etc.
+ don't count them either and we need consistency. */
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER)
count++;
if (insn == BB_END (bb))
@@ -505,7 +509,10 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
n_insns -= 2 * n_matching;
}
- if (then_start && else_start)
+ if (then_start
+ && else_start
+ && then_n_insns > n_matching
+ && else_n_insns > n_matching)
{
int longest_match = MIN (then_n_insns - n_matching,
else_n_insns - n_matching);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index c62dc68a2b0..3053aa058b7 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -623,16 +623,22 @@ parm_preserved_before_stmt_p (struct param_analysis_info *parm_ainfo,
if (parm_ainfo && parm_ainfo->parm_modified)
return false;
- gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
- ao_ref_init (&refd, parm_load);
- /* We can cache visited statements only when parm_ainfo is available and when
- we are looking at a naked load of the whole parameter. */
- if (!parm_ainfo || TREE_CODE (parm_load) != PARM_DECL)
- visited_stmts = NULL;
+ if (optimize)
+ {
+ gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
+ ao_ref_init (&refd, parm_load);
+ /* We can cache visited statements only when parm_ainfo is available and
+ when we are looking at a naked load of the whole parameter. */
+ if (!parm_ainfo || TREE_CODE (parm_load) != PARM_DECL)
+ visited_stmts = NULL;
+ else
+ visited_stmts = &parm_ainfo->parm_visited_statements;
+ walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified,
+ visited_stmts);
+ }
else
- visited_stmts = &parm_ainfo->parm_visited_statements;
- walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified,
- visited_stmts);
+ modified = true;
+
if (parm_ainfo && modified)
parm_ainfo->parm_modified = true;
return !modified;
@@ -740,7 +746,7 @@ static bool
ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
struct param_analysis_info *parms_ainfo, gimple stmt,
tree op, int *index_p, HOST_WIDE_INT *offset_p,
- bool *by_ref_p)
+ HOST_WIDE_INT *size_p, bool *by_ref_p)
{
int index;
HOST_WIDE_INT size, max_size;
@@ -758,6 +764,8 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
{
*index_p = index;
*by_ref_p = false;
+ if (size_p)
+ *size_p = size;
return true;
}
return false;
@@ -800,6 +808,8 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
{
*index_p = index;
*by_ref_p = true;
+ if (size_p)
+ *size_p = size;
return true;
}
return false;
@@ -814,7 +824,7 @@ ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
bool *by_ref_p)
{
return ipa_load_from_parm_agg_1 (info->descriptors, NULL, stmt, op, index_p,
- offset_p, by_ref_p);
+ offset_p, NULL, by_ref_p);
}
/* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
@@ -1462,6 +1472,9 @@ ipa_compute_jump_functions (struct cgraph_node *node,
{
struct cgraph_edge *cs;
+ if (!optimize)
+ return;
+
for (cs = node->callees; cs; cs = cs->next_callee)
{
struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee,
@@ -1646,7 +1659,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
if (gimple_assign_single_p (def)
&& ipa_load_from_parm_agg_1 (info->descriptors, parms_ainfo, def,
gimple_assign_rhs1 (def), &index, &offset,
- &by_ref))
+ NULL, &by_ref))
{
struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
cs->indirect_info->offset = offset;
@@ -1847,8 +1860,7 @@ ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
passed in DATA. */
static bool
-visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
- tree op, void *data)
+visit_ref_for_mod_analysis (gimple, tree op, tree, void *data)
{
struct ipa_node_params *info = (struct ipa_node_params *) data;
@@ -2126,7 +2138,6 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
we may create the first reference to the object in the unit. */
if (!callee || callee->global.inlined_to)
{
- struct cgraph_node *first_clone = callee;
/* We are better to ensure we can refer to it.
In the case of static functions we are out of luck, since we already
@@ -2142,31 +2153,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid);
return NULL;
}
-
- /* Create symbol table node. Even if inline clone exists, we can not take
- it as a target of non-inlined call. */
- callee = cgraph_create_node (target);
-
- /* OK, we previously inlined the function, then removed the offline copy and
- now we want it back for external call. This can happen when devirtualizing
- while inlining function called once that happens after extern inlined and
- virtuals are already removed. In this case introduce the external node
- and make it available for call. */
- if (first_clone)
- {
- first_clone->clone_of = callee;
- callee->clones = first_clone;
- symtab_prevail_in_asm_name_hash ((symtab_node)callee);
- symtab_insert_node_to_hashtable ((symtab_node)callee);
- if (dump_file)
- fprintf (dump_file, "ipa-prop: Introduced new external node "
- "(%s/%i) and turned into root of the clone tree.\n",
- xstrdup (cgraph_node_name (callee)), callee->uid);
- }
- else if (dump_file)
- fprintf (dump_file, "ipa-prop: Introduced new external node "
- "(%s/%i).\n",
- xstrdup (cgraph_node_name (callee)), callee->uid);
+ callee = cgraph_get_create_real_symbol_node (target);
}
ipa_check_create_node_params ();
@@ -3902,7 +3889,7 @@ ipcp_transform_function (struct cgraph_node *node)
struct ipa_agg_replacement_value *v;
gimple stmt = gsi_stmt (gsi);
tree rhs, val, t;
- HOST_WIDE_INT offset;
+ HOST_WIDE_INT offset, size;
int index;
bool by_ref, vce;
@@ -3929,13 +3916,15 @@ ipcp_transform_function (struct cgraph_node *node)
continue;
if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt,
- rhs, &index, &offset, &by_ref))
+ rhs, &index, &offset, &size, &by_ref))
continue;
for (v = aggval; v; v = v->next)
if (v->index == index
&& v->offset == offset)
break;
- if (!v || v->by_ref != by_ref)
+ if (!v
+ || v->by_ref != by_ref
+ || tree_low_cst (TYPE_SIZE (TREE_TYPE (v->value)), 0) != size)
continue;
gcc_checking_assert (is_gimple_ip_invariant (v->value));
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 94c7315c124..bedc28a8c39 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -588,7 +588,7 @@ check_call (funct_state local, gimple call, bool ipa)
/* Wrapper around check_decl for loads in local more. */
static bool
-check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_load (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, false, false);
@@ -600,7 +600,7 @@ check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for stores in local more. */
static bool
-check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_store (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, true, false);
@@ -612,7 +612,7 @@ check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for loads in ipa mode. */
static bool
-check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_load (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, false, true);
@@ -624,7 +624,7 @@ check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for stores in ipa mode. */
static bool
-check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_store (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, true, true);
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index e7d469d7442..f18ce82fef7 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -136,7 +136,7 @@ static tree find_retval (basic_block return_bb);
variable, check it if it is present in bitmap passed via DATA. */
static bool
-test_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+test_nonssa_use (gimple, tree t, tree, void *data)
{
t = get_base_address (t);
@@ -229,7 +229,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
}
if (gimple_code (stmt) == GIMPLE_LABEL
&& test_nonssa_use (stmt, gimple_label_label (stmt),
- non_ssa_vars))
+ NULL_TREE, non_ssa_vars))
{
ok = false;
goto done;
@@ -258,7 +258,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
if (virtual_operand_p (gimple_phi_result (stmt)))
continue;
if (TREE_CODE (op) != SSA_NAME
- && test_nonssa_use (stmt, op, non_ssa_vars))
+ && test_nonssa_use (stmt, op, op, non_ssa_vars))
{
ok = false;
goto done;
@@ -670,7 +670,7 @@ find_retval (basic_block return_bb)
Return true when access to T prevents splitting the function. */
static bool
-mark_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+mark_nonssa_use (gimple, tree t, tree, void *data)
{
t = get_base_address (t);
@@ -830,7 +830,7 @@ visit_bb (basic_block bb, basic_block return_bb,
if (TREE_CODE (op) == SSA_NAME)
bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
else
- can_split &= !mark_nonssa_use (stmt, op, non_ssa_vars);
+ can_split &= !mark_nonssa_use (stmt, op, op, non_ssa_vars);
}
}
return can_split;
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index c0f24b85005..d16146f85e5 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index be2e0f4123c..4c34007b44a 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -425,7 +425,9 @@ iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
&& !iv->first_special)
{
rtx val = get_iv_value (iv, const0_rtx);
- val = lowpart_subreg (mode, val, iv->extend_mode);
+ val = lowpart_subreg (mode, val,
+ iv->extend == IV_UNKNOWN_EXTEND
+ ? iv->mode : iv->extend_mode);
iv->base = val;
iv->extend = IV_UNKNOWN_EXTEND;
@@ -465,8 +467,14 @@ iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, enum machine_mode mode
&& !iv->first_special)
{
rtx val = get_iv_value (iv, const0_rtx);
+ if (iv->extend_mode != iv->mode
+ && iv->extend != IV_UNKNOWN_EXTEND
+ && iv->extend != extend)
+ val = lowpart_subreg (iv->mode, val, iv->extend_mode);
val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode,
- val, iv->extend_mode);
+ val,
+ iv->extend == extend
+ ? iv->extend_mode : iv->mode);
iv->base = val;
iv->extend = IV_UNKNOWN_EXTEND;
iv->mode = iv->extend_mode = mode;
diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c
index 6a12952cc99..d3b16b89862 100644
--- a/gcc/loop-unswitch.c
+++ b/gcc/loop-unswitch.c
@@ -191,6 +191,7 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
if (!test)
return NULL_RTX;
+ mode = VOIDmode;
for (i = 0; i < 2; i++)
{
op[i] = XEXP (test, i);
@@ -205,11 +206,15 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
return NULL_RTX;
op[i] = get_iv_value (&iv, const0_rtx);
+ if (iv.extend != IV_UNKNOWN_EXTEND
+ && iv.mode != iv.extend_mode)
+ op[i] = lowpart_subreg (iv.mode, op[i], iv.extend_mode);
+ if (mode == VOIDmode)
+ mode = iv.mode;
+ else
+ gcc_assert (mode == iv.mode);
}
- mode = GET_MODE (op[0]);
- if (mode == VOIDmode)
- mode = GET_MODE (op[1]);
if (GET_MODE_CLASS (mode) == MODE_CC)
{
if (at != BB_END (bb))
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index b2045138b91..bb18c68cc5a 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -116,6 +116,11 @@ struct regno_assign_info
/* Map regno to the corresponding regno assignment info. */
static struct regno_assign_info *regno_assign_info;
+/* All inherited, subreg or optional pseudos created before last spill
+ sub-pass. Such pseudos are permitted to get memory instead of hard
+ regs. */
+static bitmap_head non_reload_pseudos;
+
/* Process a pseudo copy with execution frequency COPY_FREQ connecting
REGNO1 and REGNO2 to form threads. */
static void
@@ -194,6 +199,15 @@ reload_pseudo_compare_func (const void *v1p, const void *v2p)
if ((diff = (ira_class_hard_regs_num[cl1]
- ira_class_hard_regs_num[cl2])) != 0)
return diff;
+ if ((diff
+ = (ira_reg_class_max_nregs[cl2][lra_reg_info[r2].biggest_mode]
+ - ira_reg_class_max_nregs[cl1][lra_reg_info[r1].biggest_mode])) != 0
+ /* The code below executes rarely as nregs == 1 in most cases.
+ So we should not worry about using faster data structures to
+ check reload pseudos. */
+ && ! bitmap_bit_p (&non_reload_pseudos, r1)
+ && ! bitmap_bit_p (&non_reload_pseudos, r2))
+ return diff;
if ((diff = (regno_assign_info[regno_assign_info[r2].first].freq
- regno_assign_info[regno_assign_info[r1].first].freq)) != 0)
return diff;
@@ -1156,7 +1170,6 @@ assign_by_spills (void)
rtx insn;
basic_block bb;
bitmap_head changed_insns, do_not_assign_nonreload_pseudos;
- bitmap_head non_reload_pseudos;
unsigned int u;
bitmap_iterator bi;
bool reload_p;
@@ -1265,7 +1278,7 @@ assign_by_spills (void)
}
}
}
- lra_assert (asm_p);
+ gcc_assert (asm_p);
break;
}
/* This is a very rare event. We can not assign a hard
diff --git a/gcc/lra-coalesce.c b/gcc/lra-coalesce.c
index 859e02f0dba..01748c08e3d 100644
--- a/gcc/lra-coalesce.c
+++ b/gcc/lra-coalesce.c
@@ -221,9 +221,12 @@ lra_coalesce (void)
basic_block bb;
rtx mv, set, insn, next, *sorted_moves;
int i, mv_num, sregno, dregno;
+ unsigned int regno;
int coalesced_moves;
int max_regno = max_reg_num ();
bitmap_head involved_insns_bitmap;
+ bitmap_head result_pseudo_vals_bitmap;
+ bitmap_iterator bi;
timevar_push (TV_LRA_COALESCE);
@@ -318,6 +321,34 @@ lra_coalesce (void)
}
}
}
+ /* If we have situation after inheritance pass:
+
+ r1 <- ... insn originally setting p1
+ i1 <- r1 setting inheritance i1 from reload r1
+ ...
+ ... <- ... p2 ... dead p2
+ ..
+ p1 <- i1
+ r2 <- i1
+ ...<- ... r2 ...
+
+ And we are coalescing p1 and p2 using p1. In this case i1 and p1
+ should have different values, otherwise they can get the same
+ hard reg and this is wrong for insn using p2 before coalescing.
+ So invalidate such inheritance pseudo values. */
+ bitmap_initialize (&result_pseudo_vals_bitmap, &reg_obstack);
+ EXECUTE_IF_SET_IN_BITMAP (&coalesced_pseudos_bitmap, 0, regno, bi)
+ bitmap_set_bit (&result_pseudo_vals_bitmap,
+ lra_reg_info[first_coalesced_pseudo[regno]].val);
+ EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi)
+ if (bitmap_bit_p (&result_pseudo_vals_bitmap, lra_reg_info[regno].val))
+ {
+ lra_set_regno_unique_value (regno);
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file,
+ " Make unique value for inheritance r%d\n", regno);
+ }
+ bitmap_clear (&result_pseudo_vals_bitmap);
bitmap_clear (&used_pseudos_bitmap);
bitmap_clear (&involved_insns_bitmap);
bitmap_clear (&coalesced_pseudos_bitmap);
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index dfbe93a8037..32e8c45f287 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1388,7 +1388,7 @@ process_alt_operands (int only_alternative)
for (nalt = 0; nalt < n_alternatives; nalt++)
{
/* Loop over operands for one constraint alternative. */
-#ifdef HAVE_ATTR_enabled
+#if HAVE_ATTR_enabled
if (curr_id->alternative_enabled_p != NULL
&& ! curr_id->alternative_enabled_p[nalt])
continue;
@@ -4396,7 +4396,7 @@ update_ebb_live_info (rtx head, rtx tail)
bitmap_clear_bit (&live_regs, reg->regno);
/* Mark each used value as live. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
- if (reg->type == OP_IN
+ if (reg->type != OP_OUT
&& bitmap_bit_p (&check_only_regs, reg->regno))
bitmap_set_bit (&live_regs, reg->regno);
/* It is quite important to remove dead move insns because it
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index d4ae0f9a87f..e179310f129 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c
index 2bcb154d22b..5dd9627c36e 100644
--- a/gcc/mode-switching.c
+++ b/gcc/mode-switching.c
@@ -568,12 +568,15 @@ optimize_mode_switching (void)
info[bb->index].computing = last_mode;
/* Check for blocks without ANY mode requirements.
- N.B. because of MODE_AFTER, last_mode might still be different
- from no_mode. */
+ N.B. because of MODE_AFTER, last_mode might still
+ be different from no_mode, in which case we need to
+ mark the block as nontransparent. */
if (!any_set_required)
{
ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now);
add_seginfo (info + bb->index, ptr);
+ if (last_mode != no_mode)
+ bitmap_clear_bit (transp[bb->index], j);
}
}
#if defined (MODE_ENTRY) && defined (MODE_EXIT)
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 5d784dda2b4..508874cec3e 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 4d86a7d95b8..51c37e4a4f9 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-05-31 Release Manager
* GCC 4.8.1 released.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 7440bef22b0..95d1168617b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -836,6 +836,7 @@ copy_var_decl (tree var, tree name, tree type)
DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
DECL_CONTEXT (copy) = DECL_CONTEXT (var);
+ TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
TREE_USED (copy) = 1;
DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
@@ -5009,8 +5010,7 @@ expand_omp_sections (struct omp_region *region)
{
/* If we are not inside a combined parallel+sections region,
call GOMP_sections_start. */
- t = build_int_cst (unsigned_type_node,
- exit_reachable ? len - 1 : len);
+ t = build_int_cst (unsigned_type_node, len - 1);
u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
stmt = gimple_build_call (u, 1, t);
}
diff --git a/gcc/optabs.c b/gcc/optabs.c
index a3051ad9d9a..afb9b5f6971 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4558,8 +4558,11 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
if (!COMPARISON_P (comparison))
return NULL_RTX;
- do_pending_stack_adjust ();
+ /* State variables we need to save and restore if cmove can't be used. */
+ int save_pending_stack_adjust = pending_stack_adjust;
+ int save_stack_pointer_delta = stack_pointer_delta;
last = get_last_insn ();
+ do_pending_stack_adjust ();
prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
&comparison, &cmode);
@@ -4579,6 +4582,8 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
}
}
delete_insns_since (last);
+ pending_stack_adjust = save_pending_stack_adjust;
+ stack_pointer_delta = save_stack_pointer_delta;
return NULL_RTX;
}
@@ -6233,7 +6238,7 @@ init_tree_optimization_optabs (tree optnode)
/* If the optabs changed, record it. */
if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
- TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs;
+ TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
else
{
TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
@@ -7035,8 +7040,7 @@ maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
create_output_operand (&ops[0], target, mode);
create_fixed_operand (&ops[1], mem);
- /* VAL may have been promoted to a wider mode. Shrink it if so. */
- create_convert_operand_to (&ops[2], val, mode, true);
+ create_input_operand (&ops[2], val, mode);
create_integer_operand (&ops[3], model);
if (maybe_expand_insn (icode, 4, ops))
return ops[0].value;
@@ -7075,8 +7079,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
struct expand_operand ops[3];
create_output_operand (&ops[0], target, mode);
create_fixed_operand (&ops[1], mem);
- /* VAL may have been promoted to a wider mode. Shrink it if so. */
- create_convert_operand_to (&ops[2], val, mode, true);
+ create_input_operand (&ops[2], val, mode);
if (maybe_expand_insn (icode, 3, ops))
return ops[0].value;
}
@@ -7118,8 +7121,6 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
{
if (!target || !register_operand (target, mode))
target = gen_reg_rtx (mode);
- if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
- val = convert_modes (mode, GET_MODE (val), val, 1);
if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
return target;
}
@@ -7331,8 +7332,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
create_output_operand (&ops[0], target_bool, bool_mode);
create_output_operand (&ops[1], target_oval, mode);
create_fixed_operand (&ops[2], mem);
- create_convert_operand_to (&ops[3], expected, mode, true);
- create_convert_operand_to (&ops[4], desired, mode, true);
+ create_input_operand (&ops[3], expected, mode);
+ create_input_operand (&ops[4], desired, mode);
create_integer_operand (&ops[5], is_weak);
create_integer_operand (&ops[6], succ_model);
create_integer_operand (&ops[7], fail_model);
@@ -7353,8 +7354,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
create_output_operand (&ops[0], target_oval, mode);
create_fixed_operand (&ops[1], mem);
- create_convert_operand_to (&ops[2], expected, mode, true);
- create_convert_operand_to (&ops[3], desired, mode, true);
+ create_input_operand (&ops[2], expected, mode);
+ create_input_operand (&ops[3], desired, mode);
if (!maybe_expand_insn (icode, 4, ops))
return false;
diff --git a/gcc/passes.c b/gcc/passes.c
index 8390223e88e..22d843aa5e8 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1398,6 +1398,7 @@ init_optimization_passes (void)
/* After CCP we rewrite no longer addressed locals into SSA
form if possible. */
NEXT_PASS (pass_forwprop);
+ NEXT_PASS (pass_object_sizes);
/* pass_build_alias is a dummy pass that ensures that we
execute TODO_rebuild_alias at this point. */
NEXT_PASS (pass_build_alias);
@@ -1435,7 +1436,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_dce);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
- NEXT_PASS (pass_object_sizes);
NEXT_PASS (pass_strlen);
NEXT_PASS (pass_ccp);
/* After CCP we rewrite no longer addressed locals into SSA
@@ -1531,18 +1531,21 @@ init_optimization_passes (void)
/* Perform simple scalar cleanup which is constant/copy propagation. */
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_object_sizes);
+ /* Fold remaining builtins. */
+ NEXT_PASS (pass_fold_builtins);
/* Copy propagation also copy-propagates constants, this is necessary
- to forward object-size results properly. */
+ to forward object-size and builtin folding results properly. */
NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_dce);
NEXT_PASS (pass_asan);
NEXT_PASS (pass_tsan);
NEXT_PASS (pass_rename_ssa_copies);
- NEXT_PASS (pass_dce);
- /* Fold remaining builtins. */
- NEXT_PASS (pass_fold_builtins);
/* ??? We do want some kind of loop invariant motion, but we possibly
need to adjust LIM to be more friendly towards preserving accurate
debug information here. */
+ /* Split critical edges before late uninit warning to reduce the
+ number of false positives from it. */
+ NEXT_PASS (pass_split_crit_edges);
NEXT_PASS (pass_late_warn_uninitialized);
NEXT_PASS (pass_uncprop);
NEXT_PASS (pass_local_pure_const);
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 883bcc2f8a1..a01b6cbdc39 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
2013-07-11 Joseph Myers <joseph@codesourcery.com>
* fi.po: Update.
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 3793109aa01..31e6fb5aff9 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -582,6 +582,8 @@ print_rtx (const_rtx in_rtx)
if (MEM_EXPR (in_rtx))
print_mem_expr (outfile, MEM_EXPR (in_rtx));
+ else
+ fputc (' ', outfile);
if (MEM_OFFSET_KNOWN_P (in_rtx))
fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
diff --git a/gcc/recog.c b/gcc/recog.c
index ae394b9b118..ad096301c9e 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -3061,6 +3061,9 @@ peep2_reg_dead_p (int ofs, rtx reg)
return 1;
}
+/* Regno offset to be used in the register search. */
+static int search_ofs;
+
/* Try to find a hard register of mode MODE, matching the register class in
CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
@@ -3076,7 +3079,6 @@ rtx
peep2_find_free_register (int from, int to, const char *class_str,
enum machine_mode mode, HARD_REG_SET *reg_set)
{
- static int search_ofs;
enum reg_class cl;
HARD_REG_SET live;
df_ref *def_rec;
@@ -3120,32 +3122,53 @@ peep2_find_free_register (int from, int to, const char *class_str,
regno = raw_regno;
#endif
- /* Don't allocate fixed registers. */
- if (fixed_regs[regno])
- continue;
- /* Don't allocate global registers. */
- if (global_regs[regno])
- continue;
- /* Make sure the register is of the right class. */
- if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
- continue;
- /* And can support the mode we need. */
+ /* Can it support the mode we need? */
if (! HARD_REGNO_MODE_OK (regno, mode))
continue;
- /* And that we don't create an extra save/restore. */
- if (! call_used_regs[regno] && ! df_regs_ever_live_p (regno))
- continue;
- if (! targetm.hard_regno_scratch_ok (regno))
- continue;
-
- /* And we don't clobber traceback for noreturn functions. */
- if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
- && (! reload_completed || frame_pointer_needed))
- continue;
success = 1;
- for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
+ for (j = 0; success && j < hard_regno_nregs[regno][mode]; j++)
{
+ /* Don't allocate fixed registers. */
+ if (fixed_regs[regno + j])
+ {
+ success = 0;
+ break;
+ }
+ /* Don't allocate global registers. */
+ if (global_regs[regno + j])
+ {
+ success = 0;
+ break;
+ }
+ /* Make sure the register is of the right class. */
+ if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno + j))
+ {
+ success = 0;
+ break;
+ }
+ /* And that we don't create an extra save/restore. */
+ if (! call_used_regs[regno + j] && ! df_regs_ever_live_p (regno + j))
+ {
+ success = 0;
+ break;
+ }
+
+ if (! targetm.hard_regno_scratch_ok (regno + j))
+ {
+ success = 0;
+ break;
+ }
+
+ /* And we don't clobber traceback for noreturn functions. */
+ if ((regno + j == FRAME_POINTER_REGNUM
+ || regno + j == HARD_FRAME_POINTER_REGNUM)
+ && (! reload_completed || frame_pointer_needed))
+ {
+ success = 0;
+ break;
+ }
+
if (TEST_HARD_REG_BIT (*reg_set, regno + j)
|| TEST_HARD_REG_BIT (live, regno + j))
{
@@ -3153,6 +3176,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
break;
}
}
+
if (success)
{
add_to_hard_reg_set (reg_set, mode, regno);
@@ -3519,6 +3543,7 @@ peephole2_optimize (void)
/* Initialize the regsets we're going to use. */
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
peep2_insn_data[i].live_before = BITMAP_ALLOC (&reg_obstack);
+ search_ofs = 0;
live = BITMAP_ALLOC (&reg_obstack);
FOR_EACH_BB_REVERSE (bb)
diff --git a/gcc/recog.h b/gcc/recog.h
index 67ad0f70d33..27e3b7c71db 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -256,7 +256,57 @@ extern struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALT
typedef int (*insn_operand_predicate_fn) (rtx, enum machine_mode);
typedef const char * (*insn_output_fn) (rtx *, rtx);
-typedef rtx (*insn_gen_fn) (rtx, ...);
+
+struct insn_gen_fn
+{
+ typedef rtx (*f0) (void);
+ typedef rtx (*f1) (rtx);
+ typedef rtx (*f2) (rtx, rtx);
+ typedef rtx (*f3) (rtx, rtx, rtx);
+ typedef rtx (*f4) (rtx, rtx, rtx, rtx);
+ typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+ typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+
+ typedef f0 stored_funcptr;
+
+ rtx operator () (void) const { return ((f0)func) (); }
+ rtx operator () (rtx a0) const { return ((f1)func) (a0); }
+ rtx operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
+ rtx operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+
+ // This is for compatibility of code that invokes functions like
+ // (*funcptr) (arg)
+ insn_gen_fn operator * (void) const { return *this; }
+
+ // The wrapped function pointer must be public and there must not be any
+ // constructors. Otherwise the insn_data_d struct initializers generated
+ // by genoutput.c will result in static initializer functions, which defeats
+ // the purpose of the generated insn_data_d array.
+ stored_funcptr func;
+};
struct insn_operand_data
{
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 896902f3012..8bfb64e40cb 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -747,6 +747,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
int n_ops, i, alt, predicated;
bool is_asm, any_replacements;
rtx set;
+ rtx link;
bool replaced[MAX_RECOG_OPERANDS];
bool changed = false;
struct kill_set_value_data ksvd;
@@ -815,6 +816,23 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
if (recog_op_alt[i][alt].earlyclobber)
kill_value (recog_data.operand[i], vd);
+ /* If we have dead sets in the insn, then we need to note these as we
+ would clobbers. */
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ {
+ if (REG_NOTE_KIND (link) == REG_UNUSED)
+ {
+ kill_value (XEXP (link, 0), vd);
+ /* Furthermore, if the insn looked like a single-set,
+ but the dead store kills the source value of that
+ set, then we can no-longer use the plain move
+ special case below. */
+ if (set
+ && reg_overlap_mentioned_p (XEXP (link, 0), SET_SRC (set)))
+ set = NULL;
+ }
+ }
+
/* Special-case plain move instructions, since we may well
be able to do the move from a different register class. */
if (set && REG_P (SET_SRC (set)))
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 0153cd9d8ec..f9447747d77 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -620,40 +620,35 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned) hard_regno_nregs[regno][mode] == nregs
&& HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+ && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
found_mode = mode;
- if (found_mode != VOIDmode)
- return found_mode;
-
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned) hard_regno_nregs[regno][mode] == nregs
&& HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+ && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
found_mode = mode;
- if (found_mode != VOIDmode)
- return found_mode;
-
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned) hard_regno_nregs[regno][mode] == nregs
&& HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+ && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
found_mode = mode;
- if (found_mode != VOIDmode)
- return found_mode;
-
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned) hard_regno_nregs[regno][mode] == nregs
&& HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+ && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
found_mode = mode;
if (found_mode != VOIDmode)
diff --git a/gcc/reorg.c b/gcc/reorg.c
index c19fb4c4262..e7cb112b483 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -1105,6 +1105,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
int used_annul = 0;
int i;
struct resources cc_set;
+ bool *redundant;
/* We can't do anything if there are more delay slots in SEQ than we
can handle, or if we don't know that it will be a taken branch.
@@ -1145,6 +1146,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
return delay_list;
#endif
+ redundant = XALLOCAVEC (bool, XVECLEN (seq, 0));
for (i = 1; i < XVECLEN (seq, 0); i++)
{
rtx trial = XVECEXP (seq, 0, i);
@@ -1166,7 +1168,8 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
/* If this insn was already done (usually in a previous delay slot),
pretend we put it in our delay slot. */
- if (redundant_insn (trial, insn, new_delay_list))
+ redundant[i] = redundant_insn (trial, insn, new_delay_list);
+ if (redundant[i])
continue;
/* We will end up re-vectoring this branch, so compute flags
@@ -1199,6 +1202,12 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
return delay_list;
}
+ /* Record the effect of the instructions that were redundant and which
+ we therefore decided not to copy. */
+ for (i = 1; i < XVECLEN (seq, 0); i++)
+ if (redundant[i])
+ update_block (XVECEXP (seq, 0, i), insn);
+
/* Show the place to which we will be branching. */
*pnew_thread = first_active_target_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
@@ -1262,6 +1271,7 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq,
/* If this insn was already done, we don't need it. */
if (redundant_insn (trial, insn, delay_list))
{
+ update_block (trial, insn);
delete_from_delay_slot (trial);
continue;
}
@@ -3266,6 +3276,7 @@ relax_delay_slots (rtx first)
to reprocess this insn. */
if (redundant_insn (XVECEXP (pat, 0, 1), delay_insn, 0))
{
+ update_block (XVECEXP (pat, 0, 1), insn);
delete_from_delay_slot (XVECEXP (pat, 0, 1));
next = prev_active_insn (next);
continue;
@@ -3385,6 +3396,7 @@ relax_delay_slots (rtx first)
&& redirect_with_delay_slots_safe_p (delay_insn, target_label,
insn))
{
+ update_block (XVECEXP (PATTERN (trial), 0, 1), insn);
reorg_redirect_jump (delay_insn, target_label);
next = insn;
continue;
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 43e794ebd07..50dc9646a25 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -639,11 +639,16 @@ simplify_truncation (enum machine_mode mode, rtx op,
XEXP (op, 0), origmode);
}
- /* Simplify (truncate:SI (op:DI (x:DI) (y:DI)))
- to (op:SI (truncate:SI (x:DI)) (truncate:SI (x:DI))). */
- if (GET_CODE (op) == PLUS
- || GET_CODE (op) == MINUS
- || GET_CODE (op) == MULT)
+ /* If the machine can perform operations in the truncated mode, distribute
+ the truncation, i.e. simplify (truncate:QI (op:SI (x:SI) (y:SI))) into
+ (op:QI (truncate:QI (x:SI)) (truncate:QI (y:SI))). */
+ if (1
+#ifdef WORD_REGISTER_OPERATIONS
+ && precision >= BITS_PER_WORD
+#endif
+ && (GET_CODE (op) == PLUS
+ || GET_CODE (op) == MINUS
+ || GET_CODE (op) == MULT))
{
rtx op0 = simplify_gen_unary (TRUNCATE, mode, XEXP (op, 0), op_mode);
if (op0)
diff --git a/gcc/stmt.c b/gcc/stmt.c
index ca58786c43c..7bdc9329bdf 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -613,6 +613,9 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
CLOBBERS is a list of STRING_CST nodes each naming a hard register
that is clobbered by this insn.
+ LABELS is a list of labels, and if LABELS is non-NULL, FALLTHRU_BB
+ should be the fallthru basic block of the asm goto.
+
Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
Some elements of OUTPUTS may be replaced with trees representing temporary
values. The caller should copy those temporary values to the originally
@@ -622,7 +625,8 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
static void
expand_asm_operands (tree string, tree outputs, tree inputs,
- tree clobbers, tree labels, int vol, location_t locus)
+ tree clobbers, tree labels, basic_block fallthru_bb,
+ int vol, location_t locus)
{
rtvec argvec, constraintvec, labelvec;
rtx body;
@@ -643,6 +647,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
enum machine_mode *inout_mode = XALLOCAVEC (enum machine_mode, noutputs);
const char **constraints = XALLOCAVEC (const char *, noutputs + ninputs);
int old_generating_concat_p = generating_concat_p;
+ rtx fallthru_label = NULL_RTX;
/* An ASM with no outputs needs to be treated as volatile, for now. */
if (noutputs == 0)
@@ -942,8 +947,24 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
/* Copy labels to the vector. */
for (i = 0, tail = labels; i < nlabels; ++i, tail = TREE_CHAIN (tail))
- ASM_OPERANDS_LABEL (body, i)
- = gen_rtx_LABEL_REF (Pmode, label_rtx (TREE_VALUE (tail)));
+ {
+ rtx r;
+ /* If asm goto has any labels in the fallthru basic block, use
+ a label that we emit immediately after the asm goto. Expansion
+ may insert further instructions into the same basic block after
+ asm goto and if we don't do this, insertion of instructions on
+ the fallthru edge might misbehave. See PR58670. */
+ if (fallthru_bb
+ && label_to_block_fn (cfun, TREE_VALUE (tail)) == fallthru_bb)
+ {
+ if (fallthru_label == NULL_RTX)
+ fallthru_label = gen_label_rtx ();
+ r = fallthru_label;
+ }
+ else
+ r = label_rtx (TREE_VALUE (tail));
+ ASM_OPERANDS_LABEL (body, i) = gen_rtx_LABEL_REF (Pmode, r);
+ }
generating_concat_p = old_generating_concat_p;
@@ -1067,6 +1088,9 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
emit_insn (body);
}
+ if (fallthru_label)
+ emit_label (fallthru_label);
+
/* For any outputs that needed reloading into registers, spill them
back to where they belong. */
for (i = 0; i < noutputs; ++i)
@@ -1087,6 +1111,7 @@ expand_asm_stmt (gimple stmt)
const char *s;
tree str, out, in, cl, labels;
location_t locus = gimple_location (stmt);
+ basic_block fallthru_bb = NULL;
/* Meh... convert the gimple asm operands into real tree lists.
Eventually we should make all routines work on the vectors instead
@@ -1122,6 +1147,9 @@ expand_asm_stmt (gimple stmt)
n = gimple_asm_nlabels (stmt);
if (n > 0)
{
+ edge fallthru = find_fallthru_edge (gimple_bb (stmt)->succs);
+ if (fallthru)
+ fallthru_bb = fallthru->dest;
t = labels = gimple_asm_label_op (stmt, 0);
for (i = 1; i < n; i++)
t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i);
@@ -1147,7 +1175,7 @@ expand_asm_stmt (gimple stmt)
/* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
OUTPUTS some trees for where the values were actually stored. */
- expand_asm_operands (str, outputs, in, cl, labels,
+ expand_asm_operands (str, outputs, in, cl, labels, fallthru_bb,
gimple_asm_volatile_p (stmt), locus);
/* Copy all the intermediate outputs into the specified outputs. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 89b307df7a2..e4906a3b311 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1007 @@
+2014-01-16 Marek Polacek <polacek@redhat.com>
+
+ Backported from mainline
+ 2014-01-16 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/59827
+ * gcc.dg/pr59827.c: New test.
+
+2014-01-15 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/59803
+ * gcc.c-torture/compile/pr59803.c: New testcase.
+
+2014-01-10 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * gcc.target/arm/neon/vst1Q_laneu64-1.c: New test.
+
+2014-01-10 Hans-Peter Nilsson <hp@axis.com>
+
+ * gcc.dg/pr46309.c: Disable for cris*-*-*.
+
+2014-01-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/56060
+ PR c++/59730
+ * g++.dg/cpp0x/variadic144.C: New.
+ * g++.dg/cpp0x/variadic145.C: Likewise.
+
+2014-01-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59715
+ * gcc.dg/torture/pr59715.c: New testcase.
+
+2014-01-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/bswap-1.c, gcc.target/mips/bswap-2.c,
+ gcc.target/mips/bswap-3.c, gcc.target/mips/bswap-4.c,
+ gcc.target/mips/bswap-5.c, gcc.target/mips/bswap-6.c: New tests.
+
+2014-01-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR rtl-optimization/59137
+ * gcc.target/mips/pr59137.c: New test.
+
+2014-01-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59125
+ PR tree-optimization/54570
+ * gcc.dg/builtin-object-size-8.c: Un-xfail.
+ * gcc.dg/builtin-object-size-14.c: New testcase.
+ * gcc.dg/strlenopt-14gf.c: Adjust.
+ * gcc.dg/strlenopt-1f.c: Likewise.
+ * gcc.dg/strlenopt-4gf.c: Likewise.
+
+ 2013-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59362
+ * gcc.c-torture/compile/pr59362.c: New test.
+
+2014-01-09 Richard Earnshaw <rearnsha@arm.com>
+
+ PR rtl-optimization/54300
+ * gcc.target/arm/pr54300.C: New test.
+
+2014-01-08 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/59610
+ * gcc.dg/ipa/pr59610.c: New test.
+
+2014-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58668
+ * gcc.dg/pr58668.c: New test.
+
+ Backported from mainline
+ 2013-12-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58956
+ PR middle-end/59470
+ * gcc.target/i386/pr59470.c: New test.
+
+2014-01-04 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2014-01-02 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/59654
+ * gfortran.dg/dynamic_dispatch_12.f90: New.
+
+2014-01-03 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.target/powerpc/rs6000-ldouble-3.c: New test.
+
+2014-01-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/59625
+ * gcc.target/i386/pr59625.c: New test.
+
+2014-01-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/59647
+ * g++.dg/opt/pr59647.C: New test.
+
+2013-12-31 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-12-30 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58998
+ * gfortran.dg/generic_28.f90: New.
+
+2013-12-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59255
+ * g++.dg/tree-prof/pr59255.C: New test.
+
+2013-12-19 James Greenhalgh <james.greenhalgh@arm.com>
+
+ Backport from Mainline
+ 2013-05-01 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * gcc.target/aarch64/scalar_intrinsics.c (force_simd): New.
+ (test_vceqd_s64): Force arguments to SIMD registers.
+ (test_vceqzd_s64): Likewise.
+ (test_vcged_s64): Likewise.
+ (test_vcled_s64): Likewise.
+ (test_vcgezd_s64): Likewise.
+ (test_vcged_u64): Likewise.
+ (test_vcgtd_s64): Likewise.
+ (test_vcltd_s64): Likewise.
+ (test_vcgtzd_s64): Likewise.
+ (test_vcgtd_u64): Likewise.
+ (test_vclezd_s64): Likewise.
+ (test_vcltzd_s64): Likewise.
+ (test_vtst_s64): Likewise.
+ (test_vtst_u64): Likewise.
+
+2013-12-19 Dominik Vogt <vogt@linux.vnet.ibm.com>
+ Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ Backport from mainline
+ 2013-12-19 Dominik Vogt <vogt@linux.vnet.ibm.com>
+ * gcc/testsuite/gcc.target/s390/hotpatch-1.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-2.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-3.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-4.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-5.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-6.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-7.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-8.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-9.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-10.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-11.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-12.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c: New test
+ * gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c: New test
+
+2013-12-18 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-12-15 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/59493
+ * gfortran.dg/unlimited_polymorphic_15.f90: New.
+
+2013-12-15 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/58630
+ * gcc.target/i386/pr43662.c (dg-options):
+ Add -maccumulate-outgoing-args.
+ * gcc.target/i386/pr43869.c (dg-options): Ditto.
+ * gcc.target/i386/pr57003.c (dg-options): Ditto.
+ * gcc.target/i386/avx-vzeroupper-16.c (dg-options):
+ Remove -mtune=generic and add -maccumulate-outgoing-args instead.
+ * gcc.target/i386/avx-vzeroupper-17.c (dg-options): Ditto.
+ * gcc.target/i386/avx-vzeroupper-18.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/func-1.c (dg-options):
+ Add -maccumulate-outgoing-args.
+ * gcc.target/x86_64/abi/callabi/func-2a.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/func-2b.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/func-indirect.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/func-indirect-2a.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/func-indirect-2b.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/leaf-1.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/leaf-2.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/pr38891.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-1.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-2.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-3.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-4a.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-4b.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-5a.c (dg-options): Ditto.
+ * gcc.target/x86_64/abi/callabi/vaarg-5b.c (dg-options): Ditto.
+
+2013-12-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/59470
+ * g++.dg/opt/pr59470.C: New test.
+
+ PR libgomp/59467
+ * gfortran.dg/gomp/pr59467.f90: New test.
+ * c-c++-common/gomp/pr59467.c: New test.
+
+2013-12-12 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-12-12 Ryan Mansfield <rmansfield@qnx.com>
+
+ PR testsuite/59442
+ * gcc.target/i386/sse2-movapd-1.c: Fix alignment attributes.
+ * gcc.target/i386/sse2-movapd-2.c: Likewise.
+ * gcc.target/i386/avx-vmovapd-256-1.c: Likewise.
+ * gcc.target/i386/avx-vmovapd-256-2.c: Likewise.
+
+2013-12-08 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-12-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59405
+ * gcc.target/i386/pr59405.c: New test.
+
+2013-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59388
+ * gcc.c-torture/execute/pr59388.c: New test.
+
+2013-12-06 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59330
+ * gcc.dg/torture/pr59330.c: New testcase.
+
+2013-12-06 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59288
+ * gcc.dg/torture/pr59288.c: New testcase.
+
+ 2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59164
+ * gcc.dg/torture/pr59164.c: New testcase.
+
+ 2013-09-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58137
+ * gcc.target/i386/pr58137.c: New testcase.
+
+2013-12-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ PR target/59343
+ * gcc.target/sh/pr51244-19.c: Adjust test case.
+
+2013-12-05 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58956
+ * gcc.dg/torture/pr58956.c: New testcase.
+
+2013-12-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59268
+ * g++.dg/cpp0x/constexpr-template6.C: New test.
+
+ PR rtl-optimization/58726
+ * gcc.c-torture/execute/pr58726.c: New test.
+
+ PR target/59163
+ * g++.dg/torture/pr59163.C: New test.
+
+2013-12-03 Marek Polacek <polacek@redhat.com>
+
+ Backport from mainline
+ 2013-12-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/59351
+ * gcc.dg/pr59351.c: New test.
+
+2013-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/59011
+ * gcc.dg/pr59011.c: New test.
+
+ PR target/58864
+ * g++.dg/opt/pr58864.C: New test.
+
+2013-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59358
+ * gcc.c-torture/execute/pr59358.c: New test.
+
+2013-12-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59139
+ * gcc.dg/torture/pr59139.c: New testcase.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/59032
+ * c-c++-common/pr59032.c: New testcase.
+
+2013-11-27 Tom de Vries <tom@codesourcery.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ PR middle-end/59037
+ * c-c++-common/pr59037.c: New testcase.
+
+2013-11-30 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/57445
+ * gfortran.dg/optional_class_1.f90 : New test
+
+2013-11-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/59280
+ * c-c++-common/pr59280.c: New test.
+
+2013-11-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59297
+ * g++.dg/gomp/pr59297.C: New test.
+
+2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ Backport from mainline
+ 2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/arm/vrinta-ce.c: New testcase.
+
+2013-11-28 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-11-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/56788
+ * config/i386/i386.c (bdesc_multi_arg) <IX86_BUILTIN_VFRCZSS>:
+ Declare as MULTI_ARG_1_SF instruction.
+ <IX86_BUILTIN_VFRCZSD>: Decleare as MULTI_ARG_1_DF instruction.
+ * config/i386/sse.md (*xop_vmfrcz<mode>2): Rename
+ from *xop_vmfrcz_<mode>.
+ * config/i386/xopintrin.h (_mm_frcz_ss): Use __builtin_ia32_movss
+ to merge scalar result with __A.
+ (_mm_frcz_sd): Use __builtin_ia32_movsd to merge scalar
+ result with __A.
+
+2013-11-28 Terry Guo <terry.guo@arm.com>
+
+ Backport mainline r205391
+ 2013-11-26 Terry Guo <terry.guo@arm.com>
+
+ * gcc.target/arm/thumb1-pic-high-reg.c: New case.
+ * gcc.target/arm/thumb1-pic-single-base.c: New case.
+
+2013-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59014
+ * gcc.c-torture/execute/pr59014-2.c: New test.
+
+ 2013-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59014
+ * gcc.c-torture/execute/pr59014.c: New test.
+
+2013-11-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/20131127-1.c: New test.
+
+2013-11-25 Vidya Praveen <vidyapraveen@arm.com>
+
+ Backport from mainline
+ 2013-10-21 Vidya Praveen <vidyapraveen@arm.com>
+
+ * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort().
+ * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort() and exit().
+
+2013-11-20 Dominik Vogt <vogt@linux.vnet.ibm.com>
+
+ Backport from mainline
+ * gcc.target/s390/htm-1.c: Rename to ...
+ * gcc/testsuite/gcc.target/s390/htm-builtins-compile-1.c: ... this
+ one.
+ * gcc.target/s390/htm-xl-intrin-1.c: Rename to ...
+ * gcc.target/s390/htm-builtins-compile-3.c: ... this one.
+ * gcc.target/s390/htm-builtins-compile-2.c: New testcase.
+ * gcc.target/s390/htm-builtins-1.c: New testcase.
+ * gcc.target/s390/htm-builtins-2.c: New testcase.
+ * gcc.target/s390/s390.exp: Add check for htm machine.
+
+2013-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57517
+ * gfortran.fortran-torture/compile/pr57517.f90: New testcase.
+ * gcc.dg/torture/pr57517.c: Likewise.
+
+2013-11-19 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58941
+ * gcc.dg/torture/pr58941.c: New testcase.
+
+2013-11-18 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58794
+ * c-c++-common/torture/pr58794-1.c: New testcase.
+ * c-c++-common/torture/pr58794-2.c: Likewise.
+
+ 2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58742
+ * c-c++-common/fold-divmul-1.c: New testcase.
+
+ 2013-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58653
+ * gcc.dg/tree-ssa/predcom-6.c: New testcase.
+ * gcc.dg/tree-ssa/predcom-7.c: Likewise.
+
+ PR tree-optimization/59047
+ * gcc.dg/torture/pr59047.c: New testcase.
+
+ 2013-10-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58143
+ * gcc.dg/torture/pr58143-1.c: New testcase.
+ * gcc.dg/torture/pr58143-2.c: Likewise.
+ * gcc.dg/torture/pr58143-3.c: Likewise.
+
+2013-11-17 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-11-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58471
+ * gfortran.dg/constructor_9.f90: New.
+
+2013-11-16 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-09-20 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58099
+ * gfortran.dg/proc_ptr_43.f90: New.
+
+2013-11-16 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58771
+ * gfortran.dg/derived_external_function_1.f90 : New test
+
+2013-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-11-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59021
+ * gcc.target/i386/pr59021.c: New test.
+
+2013-11-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/59101
+ * gcc.c-torture/execute/pr59101.c: New test.
+
+2013-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58970
+ * gcc.c-torture/compile/pr58970-1.c: New test.
+ * gcc.c-torture/compile/pr58970-2.c: New test.
+
+ 2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58997
+ * gcc.c-torture/compile/pr58997.c: New test.
+
+2013-11-10 Wei Mi <wmi@google.com>
+
+ * gcc.dg/pr57518.c: Backport regex fix from r200720.
+
+2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59034
+ * gcc.target/i386/pr59034-1.c: New test.
+ * gcc.target/i386/pr59034-2.c: Likewise.
+
+2013-11-06 Wei Mi <wmi@google.com>
+
+ PR regression/58985
+ * gcc.dg/pr57518.c: Add subreg in regexp pattern.
+
+2013-11-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/58989
+ * gfortran.dg/reshape_6.f90: New test.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58984
+ * gcc.c-torture/execute/pr58984.c: New test.
+
+2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ Backport from mainline
+ 2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58979
+ * g++.dg/diagnostic/pr58979.C: New test.
+
+2013-11-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2013-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/58690
+ * gcc.target/i386/pr58690.c: New test
+
+2013-11-02 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from mainline
+ 2013-09-23 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58355
+ * gfortran.dg/extends_15.f90: New.
+
+2013-10-29 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-08 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR rtl-optimization/58079
+ * gcc.dg/torture/pr58079.c: New test.
+
+2013-10-28 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/arm/require-pic-register-loc.c: New test.
+
+2013-10-26 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-10-22 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58779
+ * gcc.target/i386/pr30315.c: Remove MINUSCC, DECCC, MINUSCCONLY
+ and MINUSCCZEXT defines. Update scan-assembler dg directive.
+ * gcc.dg/torture/pr58779.c: New test.
+
+2013-10-25 Richard Henderson <rth@redhat.com>
+
+ PR rtl/58542
+ * gcc.dg/atomic-store-6.c: New.
+
+2013-10-25 Tom de Vries <tom@codesourcery.com>
+
+ PR c++/58282
+ * g++.dg/tm/noexcept-6.C: New test.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/pr58831.c: New test.
+
+2013-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/58805
+ * gcc.dg/pr58805.c: New test.
+
+2013-10-23 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/torture/pr58830.c: New testcase.
+
+ Backport from mainline
+ 2013-06-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57488
+ * gcc.dg/torture/pr57488.c: New testcase.
+
+2013-10-19 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * gcc.target/sh/pr54089-3.c: Fix test for load of constant 31.
+
+2013-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58596
+ * g++.dg/cpp0x/lambda/lambda-nsdmi5.C: New
+
+2013-10-16 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58633
+ * g++.dg/cpp0x/decltype57.C: New.
+ * g++.dg/cpp0x/enum18.C: Revert r174385 changes.
+
+2013-10-16 Release Manager
+
+ * GCC 4.8.2 released.
+
+2013-10-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.dg/torture/pr58670.c (ASM_STR) [__i386__ || __x86_64__]: Use
+ btsl.
+
+2013-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58670
+ * gcc.dg/torture/pr58670.c: New test.
+
+2013-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ Backport from mainline
+ 2013-09-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58539
+ * gcc.dg/torture/pr58539.c: New testcase.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58568
+ * g++.dg/cpp0x/lambda/lambda-ice10.C: New.
+ * g++.old-deja/g++.mike/misc9.C: Adjust.
+
+2013-10-08 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-nofloat-2.c: Add -mzarch to asm options.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-nofloat-2.c: New testcase.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ Backport from mainline
+ 2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-1.c: New file.
+ * gcc.target/s390/htm-nofloat-1.c: New file.
+ * gcc.target/s390/htm-xl-intrin-1.c: New file.
+
+2013-10-04 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/57697
+ PR fortran/58469
+ * gfortran.dg/defined_assignment_8.f90: New.
+ * gfortran.dg/defined_assignment_9.f90: New.
+ * gfortran.dg/defined_assignment_10.f90: New.
+ * gfortran.dg/defined_assignment_11.f90: New.
+
+2013-10-04 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ Backport from mainline.
+
+ PR target/58460
+ * gcc.target/aarch64/pr58460.c: New file.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58535
+ * g++.dg/parse/crash62.C: New.
+
+2013-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/58574
+ * gcc.c-torture/execute/pr58574.c: New test.
+
+2013-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58564
+ * gcc.c-torture/execute/pr58564.c: New test.
+
+2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt28.ad[sb]: New test.
+ * gnat.dg/opt28_pkg.ads: New helper.
+
+2013-09-23 Alan Modra <amodra@gmail.com>
+
+ * gcc.target/powerpc/pr58330.c: New.
+
+2013-09-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58457
+ * g++.dg/parse/using4.C: New.
+
+2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/array_bounds_test2.adb: New test.
+
+2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/in_out_parameter4.adb: New test.
+
+2013-09-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/58088
+ * gcc.c-torture/compile/pr58088.c: New test.
+
+2013-09-13 Christian Bruel <christian.bruel@st.com>
+
+ PR target/58314
+ * gcc.target/sh/torture/pr58314.c: New test.
+
+2013-09-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58377
+ * g++.dg/uninit-pred-4.C: New testcase.
+
+2013-09-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58385
+ * gcc.c-torture/execute/pr58385.c: New test.
+
+2013-09-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58365
+ * gcc.c-torture/execute/pr58365.c: New test.
+
+2013-09-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/58325
+ * g++.dg/warn/Wunused-var-21.C: New test.
+
+ PR tree-optimization/58364
+ * gcc.c-torture/execute/pr58364.c: New test.
+
+2013-09-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/57735
+ * g++.dg/ext/pr57735.C: New test.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57521
+ * gcc.dg/torture/pr57521.c: New testcase.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-09-03 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57656
+ * gcc.dg/torture/pr57656.c: New testcase.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57685
+ * gcc.dg/torture/pr57685.c: New testcase.
+
+2013-09-09 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58223
+ * gcc.dg/torture/pr58223.c: New testcase.
+ * gcc.dg/tree-ssa/ldist-16.c: Flip expected behavior.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58246
+ * gcc.dg/torture/pr58246.c: New testcase.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58228
+ * gcc.dg/torture/pr58228.c: New testcase.
+
+2013-09-03 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58010
+ * gcc.dg/pr58010.c: New testcase.
+
+2013-08-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58277
+ * gcc.c-torture/execute/pr58277-1.c: New test.
+ * gcc.c-torture/execute/pr58277-2.c: New test.
+
+2013-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2013-07-22 Georg-Johann Lay <avr@gjlay.de>
+
+ PR testsuite/52641
+ * gcc.dg/torture/pr57381.c: Add dg-require-effective-target int32plus.
+
+ 2013-05-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/57417
+ * gcc.dg/torture/pr57417.c: New testcase.
+
+ PR tree-optimization/57396
+ * gfortran.fortran-torture/execute/pr57396.f90: New testcase.
+
+ PR tree-optimization/57343
+ * gcc.dg/torture/pr57343.c: New testcase.
+
+ 2013-05-23 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57381
+ * gcc.dg/torture/pr57381.c: New testcase.
+
+2013-08-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58257
+ * c-c++-common/gomp/pr58257.c: New test.
+
+2013-08-28 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2013-06-24 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/56977
+ * gcc.dg/pr56977.c: New testcase.
+
+2013-08-24 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/57798
+ * gfortran.dg/inline_sum_5.f90: New.
+
+2013-08-24 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from trunk:
+ 2013-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58185
+ * gfortran.dg/select_type_34.f90: New.
+
+2013-08-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/58218
+ * gcc.target/i386/pr58218.c: New test.
+
+ PR tree-optimization/58209
+ * gcc.c-torture/execute/pr58209.c: New test.
+
+2013-08-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58190
+ * g++.dg/pr57878.C: Use __SIZE_TYPE__.
+
+2013-08-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58006
+ * g++.dg/opt/pr58006.C: New test.
+
+2013-08-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58164
+ * gcc.c-torture/compile/pr58164.c: New test.
+
+ PR tree-optimization/58165
+ * g++.dg/opt/pr58165.C: New test.
+
+2013-08-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58145
+ * gcc.dg/pr58145-1.c: New test.
+ * gcc.dg/pr58145-2.c: New test.
+
+2013-08-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/56417
+ * gcc.dg/asan/pr56417.c: New test.
+
+2013-08-13 Vladimir Makarov <vmakarov@redhat.com>
+
+ Backport from mainline
+ 2013-06-06 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/57459
+ * gcc.target/i386/pr57459.c: New test.
+
+2013-08-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/loop_optimization16.adb: New test.
+ * gnat.dg/loop_optimization16_pkg.ad[sb]: New helper.
+
+2013-08-13 Marek Polacek <polacek@redhat.com>
+
+ PR tree-optimization/57980
+ * gcc.dg/pr57980.c: New test.
+
+2013-08-13 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2013-08-12 Perez Read <netfirewall@gmail.com>
+
+ PR target/58132
+ * gcc.target/i386/movabs-1.c: New test.
+
+2013-08-11 Janus Weil <janus@gcc.gnu.org>
+
+ Backport from trunk:
+ 2013-08-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58058
+ * gfortran.dg/transfer_intrinsic_6.f90: New.
+
+2013-08-09 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ Backport from mainline:
+ 2013-08-09 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * gcc.target/arm/lp1189445.c: New testcase.
+
+2013-08-06 Martin Jambor <mjambor@suse.cz>
+ Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * gcc.dg/torture/pr58041.c (foo): Accept z by reference.
+ (a): Fix constructor.
+
+2013-08-06 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/58041
+ * gcc.dg/torture/pr58041.c: New test.
+ * gcc.target/arm/pr58041.c: Likewise.
+
+2013-07-28 Tobias Burnus <burnus@net-b.de>
+
+ Backport from mainline
+ 2013-05-28 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/57435
+ * gfortran.dg/use_29.f90: New.
+
+2013-07-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/57981
+ * g++.dg/cpp0x/pr57981.C: New.
+
+2013-07-25 Terry Guo <terry.guo@arm.com>
+
+ Backport from mainline:
+ 2013-07-25 Terry Guo <terry.guo@arm.com>
+
+ * gcc.target/arm/thumb1-Os-mult.c: New test case.
+
+2013-07-19 Wei Mi <wmi@google.com>
+
+ Backport from mainline:
+ 2013-07-18 Wei Mi <wmi@google.com>
+
+ PR rtl-optimization/57878
+ * g++.dg/pr57878.C: New test.
+
+2013-07-19 Georg-Johann Lay <avr@gjlay.de>
+
+ Backport from 2013-07-19 trunk r201051.
+
+ PR target/57516
+ * gcc.target/avr/torture/builtins-4-roundfx.c (test2hr, test2k):
+ Adjust to corrected rounding.
+
+2013-07-19 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/bmi-1.c: Extend with new instrinsics.
+ Fix scan patterns.
+ * gcc.target/i386/bmi-2.c: Ditto.
+ * gcc.target/i386/bmi-bextr-4.c: New.
+ * gcc.target/i386/bmi-bextr-5.c: Ditto.
+
2013-07-16 Iain Sandoe <iain@codesourcery.com>
PR target/55656
@@ -111,7 +1115,7 @@
2013-06-19 Wei Mi <wmi@google.com>
PR rtl-optimization/57518
- * testsuite/gcc.dg/pr57518.c: New test.
+ * gcc.dg/pr57518.c: New test.
2013-06-11 Tobias Burnus <burnus@net-b.de>
@@ -240,8 +1244,8 @@
2013-05-09 Martin Jambor <mjambor@suse.cz>
- PR middle-end/56988
- * gcc.dg/ipa/pr56988.c: New test.
+ PR middle-end/56988
+ * gcc.dg/ipa/pr56988.c: New test.
2013-05-08 Marc Glisse <marc.glisse@inria.fr>
@@ -318,7 +1322,7 @@
2013-04-25 Marek Polacek <polacek@redhat.com>
PR tree-optimization/57066
- * gcc.dg/torture/builtin-logb-1.c: Adjust testcase.
+ * gcc.dg/torture/builtin-logb-1.c: Adjust testcase.
2013-05-02 Jakub Jelinek <jakub@redhat.com>
@@ -344,32 +1348,32 @@
Backport from mainline
2013-04-24 Vladimir Makarov <vmakarov@redhat.com>
- PR rtl-optimizations/57046
- * gcc.target/i386/pr57046.c: New test.
+ PR rtl-optimizations/57046
+ * gcc.target/i386/pr57046.c: New test.
2013-05-02 Vladimir Makarov <vmakarov@redhat.com>
Backport from mainline
2013-04-22 Vladimir Makarov <vmakarov@redhat.com>
- PR target/57018
- * gcc.target/i386/pr57018.c: New test.
+ PR target/57018
+ * gcc.target/i386/pr57018.c: New test.
2013-05-02 Vladimir Makarov <vmakarov@redhat.com>
Backport from mainline
2013-04-18 Jakub Jelinek <jakub@redhat.com>
- PR rtl-optimization/56999
- * g++.dg/opt/pr56999.C: New test.
+ PR rtl-optimization/56999
+ * g++.dg/opt/pr56999.C: New test.
2013-05-02 Vladimir Makarov <vmakarov@redhat.com>
Backport from mainline
2013-04-19 Vladimir Makarov <vmakarov@redhat.com>
- PR rtl-optimization/56847
- * gcc.dg/pr56847.c: New test.
+ PR rtl-optimization/56847
+ * gcc.dg/pr56847.c: New test.
2013-05-02 Ian Bolton <ian.bolton@arm.com>
@@ -719,7 +1723,7 @@
2013-03-29 Tobias Burnus <burnus@net-b.de>
PR fortran/56737
- * testsuite/gfortran.dg/fmt_cache_3.f90: New.
+ * gfortran.dg/fmt_cache_3.f90: New.
2013-04-02 Richard Biener <rguenther@suse.de>
@@ -1253,7 +2257,7 @@
2013-02-20 Jan Hubicka <jh@suse.cz>
PR tree-optimization/56265
- * testsuite/g++.dg/ipa/devirt-11.C: New testcase.
+ * g++.dg/ipa/devirt-11.C: New testcase.
2013-02-20 Richard Biener <rguenther@suse.de>
@@ -1440,11 +2444,9 @@
Avoid instrumenting duplicated memory access in the same basic block
* c-c++-common/asan/no-redundant-instrumentation-1.c: New test.
- * testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c:
- Likewise.
- * testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c:
- Likewise.
- * testsuite/c-c++-common/asan/inc.c: Likewise.
+ * c-c++-common/asan/no-redundant-instrumentation-2.c: Likewise.
+ * c-c++-common/asan/no-redundant-instrumentation-3.c: Likewise.
+ * c-c++-common/asan/inc.c: Likewise.
2013-02-12 Vladimir Makarov <vmakarov@redhat.com>
diff --git a/gcc/testsuite/ChangeLog.ibm b/gcc/testsuite/ChangeLog.ibm
index f1151ec2920..43ca1442e73 100644
--- a/gcc/testsuite/ChangeLog.ibm
+++ b/gcc/testsuite/ChangeLog.ibm
@@ -1,3 +1,344 @@
+2014-02-15 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline r207808.
+ 2014-02-15 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/60203
+ * gcc.target/powerpc/pr60203.c: New testsuite.
+
+2014-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline r207699.
+ 2014-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/60137
+ * gcc.target/powerpc/pr60137.c: New file.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207521
+ 2014-02-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/sum2s.c: New.
+ * gcc.dg/vmx/sum2s-be-order.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207520
+ 2014-02-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/pack.c: New.
+ * gcc.dg/vmx/pack-be-order.c: New.
+ * gcc.dg/vmx/unpack.c: New.
+ * gcc.dg/vmx/unpack-be-order.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207415
+ 2014-02-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/3b-15.c: Remove special handling for little endian.
+ * gcc.dg/vmx/perm.c: New.
+ * gcc.dg/vmx/perm-be-order.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207414
+ 2014-02-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/vsums.c: New.
+ * gcc.dg/vmx/vsums-be-order.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207318
+ 2014-01-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/splat.c: New.
+ * gcc.dg/vmx/splat-vsx.c: New.
+ * gcc.dg/vmx/splat-be-order.c: New.
+ * gcc.dg/vmx/splat-vsx-be-order.c: New.
+ * gcc.dg/vmx/eg-5.c: Remove special casing for little endian.
+ * gcc.dg/vmx/sn7153.c: Add special casing for little endian.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r207262
+ 2014-01-29 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/merge-be-order.c: New.
+ * gcc.dg/vmx/merge.c: New.
+ * gcc.dg/vmx/merge-vsx-be-order.c: New.
+ * gcc.dg/vmx/merge-vsx.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206926
+ 2014-01-22 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/insert-vsx-be-order.c: New.
+ * gcc.dg/vmx/extract-vsx.c: New.
+ * gcc.dg/vmx/extract-vsx-be-order.c: New.
+ * gcc.dg/vmx/insert-vsx.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206641
+ 2014-01-15 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * gcc.dg/vmx/mult-even-odd.c: New.
+ * gcc.dg/vmx/mult-even-odd-be-order.c: New.
+
+2014-02-06 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r206590
+ 2014-01-13 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/insert.c: New.
+ * gcc.dg/vmx/insert-be-order.c: New.
+ * gcc.dg/vmx/extract.c: New.
+ * gcc.dg/vmx/extract-be-order.c: New.
+
+2014-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from mainline
+ 2014-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59909
+ * gcc.target/powerpc/quad-atomic.c: New file to test power8 quad
+ word atomic functions at runtime.
+
+2014-01-14 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline
+
+ 2013-10-23 Pat Haugen <pthaugen@us.ibm.com>
+
+ * gcc.target/powerpc/direct-move.h: Fix header for executable tests.
+
+2013-12-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205638
+ 2013-12-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c: Skip for little
+ endian.
+
+2013-11-27 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205464
+ 2013-11-27 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gfortran.dg/nan_7.f90: Disable for little endian PowerPC.
+
+2013-11-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-11-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59054
+ * gcc.target/powerpc/direct-move.h (VSX_REG_ATTR): Allow test to
+ specify an appropriate register class for VSX operations.
+ (load_vsx): Use it.
+ (load_gpr_to_vsx): Likewise.
+ (load_vsx_to_gpr): Likewise.
+ * gcc.target/powerpc/direct-move-vint1.c: Use an appropriate
+ register class for VSX registers that the type can handle. Remove
+ checks for explicit number of instructions generated, just check
+ if the instruction is generated.
+ * gcc.target/powerpc/direct-move-vint2.c: Likewise.
+ * gcc.target/powerpc/direct-move-float1.c: Likewise.
+ * gcc.target/powerpc/direct-move-float2.c: Likewise.
+ * gcc.target/powerpc/direct-move-double1.c: Likewise.
+ * gcc.target/powerpc/direct-move-double2.c: Likewise.
+ * gcc.target/powerpc/direct-move-long1.c: Likewise.
+ * gcc.target/powerpc/direct-move-long2.c: Likewise.
+
+ * gcc.target/powerpc/bool3-av.c: Limit to 64-bit mode for now.
+ * gcc.target/powerpc/bool3-p7.c: Likewise.
+ * gcc.target/powerpc/bool3-p8.c: Likewise.
+
+ * gcc.target/powerpc/p8vector-ldst.c: Just check that the
+ appropriate instructions are generated, don't check the count.
+
+ 2013-11-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/59054
+ * gcc.target/powerpc/pr59054.c: New test.
+
+2013-11-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r205146
+ 2013-11-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pr48258-1.c: Skip for little endian.
+
+2013-11-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r205106:
+
+ 2013-11-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * gcc.target/powerpc/darwin-longlong.c (msw): Make endian-safe.
+
+2013-11-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r205046:
+
+ 2013-11-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * gcc.target/powerpc/ppc64-abi-2.c (MAKE_SLOT): New macro to
+ construct parameter slot value in endian-independent way.
+ (fcevv, fciievv, fcvevv): Use it.
+
+2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204862
+ 2013-11-15 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/3b-15.c: Revise for little endian.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204808:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * gcc.target/powerpc/ppc64-abi-1.c (stack_frame_t): Remove
+ compiler and linker field if _CALL_ELF == 2.
+ * gcc.target/powerpc/ppc64-abi-2.c (stack_frame_t): Likewise.
+ * gcc.target/powerpc/ppc64-abi-dfp-1.c (stack_frame_t): Likewise.
+ * gcc.dg/stack-usage-1.c (SIZE): Update value for _CALL_ELF == 2.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * gcc.target/powerpc/ppc64-abi-dfp-1.c (FUNC_START): New macro.
+ (WRAPPER): Use it.
+ * gcc.target/powerpc/no-r11-1.c: Skip on powerpc_elfv2.
+ * gcc.target/powerpc/no-r11-2.c: Skip on powerpc_elfv2.
+ * gcc.target/powerpc/no-r11-3.c: Skip on powerpc_elfv2.
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * lib/target-supports.exp (check_effective_target_powerpc_elfv2):
+ New function.
+ * gcc.target/powerpc/pr57949-1.c: Disable for powerpc_elfv2.
+ * gcc.target/powerpc/pr57949-2.c: Likewise.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r204799:
+
+ 2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * g++.dg/eh/ppc64-sighandle-cr.C: New test.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r201750.
+ Note: Default setting of -mcompat-align-parm inverted!
+
+ 2013-08-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR target/57949
+ * gcc.target/powerpc/pr57949-1.c: New.
+ * gcc.target/powerpc/pr57949-2.c: New.
+
+2013-11-15 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ Backport from mainline r201040 and r201929:
+
+ 2013-08-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pr57744.c: Declare abort.
+
+ 2013-07-18 Pat Haugen <pthaugen@us.ibm.com>
+
+ * gcc.target/powerpc/pr57744.c: Fix typo.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204321
+ 2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * gcc.dg/vmx/vec-set.c: New.
+
+2013-11-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r204138
+ 2013-10-28 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/gcc-bug-i.c: Add little endian variant.
+ * gcc.dg/vmx/eg-5.c: Likewise.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203930
+ 2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com>
+
+ * gcc.target/powerpc/altivec-perm-1.c: Move the two vector pack
+ tests into...
+ * gcc.target/powerpc/altivec-perm-3.c: ...this new test, which is
+ restricted to big-endian targets.
+
+2013-11-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline r203246
+ 2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pr43154.c: Skip for ppc64 little endian.
+ * gcc.target/powerpc/fusion.c: Likewise.
+
+2013-10-21 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2013-04-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR target/56843
+ * gcc.target/powerpc/recip-1.c: Modify expected output.
+ * gcc.target/powerpc/recip-3.c: Likewise.
+ * gcc.target/powerpc/recip-4.c: Likewise.
+ * gcc.target/powerpc/recip-5.c: Add expected output for iterations.
+
+2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from mainline
+ 2013-10-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/p8vector-fp.c: New test for floating point
+ scalar operations when using -mupper-regs-sf and -mupper-regs-df.
+ * gcc.target/powerpc/ppc-target-1.c: Update tests to allow either
+ VSX scalar operations or the traditional floating point form of
+ the instruction.
+ * gcc.target/powerpc/ppc-target-2.c: Likewise.
+ * gcc.target/powerpc/recip-3.c: Likewise.
+ * gcc.target/powerpc/recip-5.c: Likewise.
+ * gcc.target/powerpc/pr72747.c: Likewise.
+ * gcc.target/powerpc/vsx-builtin-3.c: Likewise.
+
+ Back port from mainline
+ 2013-09-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/p8vector-ldst.c: New test for -mupper-regs-sf
+ and -mupper-regs-df.
+
+ Back port from mainline
+ 2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58673
+ * gcc.target/powerpc/pr58673-1.c: New file to test whether
+ -mquad-word + -mno-vsx-timode causes errors.
+ * gcc.target/powerpc/pr58673-2.c: Likewise.
+
+2013-08-19 Peter Bergner <bergner@vnet.ibm.com>
+
+ Back port from mainline
+ 2013-08-19 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gcc.target/powerpc/dfp-dd-2.c: New test.
+ * gcc.target/powerpc/dfp-td-2.c: Likewise.
+ * gcc.target/powerpc/dfp-td-3.c: Likewise.
+
2013-08-16 Michael Meissner <meissner@linux.vnet.ibm.com>
Backport from trunk.
diff --git a/gcc/testsuite/c-c++-common/fold-divmul-1.c b/gcc/testsuite/c-c++-common/fold-divmul-1.c
new file mode 100644
index 00000000000..5c867923d2e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fold-divmul-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original" } */
+
+int *
+fx (int *b, int *e)
+{
+ return b + (e - b);
+}
+
+/* { dg-final { scan-tree-dump-not "/\\\[ex\\\]" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/pr58257.c b/gcc/testsuite/c-c++-common/gomp/pr58257.c
new file mode 100644
index 00000000000..8f8d24a998a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr58257.c
@@ -0,0 +1,15 @@
+/* PR middle-end/58257 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp -Wall" } */
+
+int
+foo (int n)
+{
+ int a[10][10];
+ int x, y;
+#pragma omp parallel for collapse(2) /* { dg-bogus "may be used uninitialized in this function" } */
+ for (x = 0; x < n; x++) /* { dg-bogus "may be used uninitialized in this function" } */
+ for (y = 0; y < n; y++)
+ a[x][y] = x + y * y;
+ return a[0][0];
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr59467.c b/gcc/testsuite/c-c++-common/gomp/pr59467.c
new file mode 100644
index 00000000000..475182a6236
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr59467.c
@@ -0,0 +1,68 @@
+/* PR libgomp/59467 */
+
+int v;
+
+void
+foo (void)
+{
+ int x = 0, y = 0;
+ #pragma omp parallel
+ {
+ int z;
+ #pragma omp single copyprivate (x) /* { dg-error "is not threadprivate or private in outer context" } */
+ {
+ #pragma omp atomic write
+ x = 6;
+ }
+ #pragma omp atomic read
+ z = x;
+ #pragma omp atomic
+ y += z;
+ }
+ #pragma omp parallel
+ {
+ int z;
+ #pragma omp single copyprivate (v) /* { dg-error "is not threadprivate or private in outer context" } */
+ {
+ #pragma omp atomic write
+ v = 6;
+ }
+ #pragma omp atomic read
+ z = v;
+ #pragma omp atomic
+ y += z;
+ }
+ #pragma omp parallel private (x)
+ {
+ int z;
+ #pragma omp single copyprivate (x)
+ {
+ #pragma omp atomic write
+ x = 6;
+ }
+ #pragma omp atomic read
+ z = x;
+ #pragma omp atomic
+ y += z;
+ }
+ x = 0;
+ #pragma omp parallel reduction (+:x)
+ {
+ #pragma omp single copyprivate (x)
+ {
+ #pragma omp atomic write
+ x = 6;
+ }
+ #pragma omp atomic
+ y += x;
+ }
+ #pragma omp single copyprivate (x)
+ {
+ x = 7;
+ }
+ #pragma omp single copyprivate (v) /* { dg-error "is not threadprivate or private in outer context" } */
+ {
+ #pragma omp atomic write
+ v = 6;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/pr59032.c b/gcc/testsuite/c-c++-common/pr59032.c
new file mode 100644
index 00000000000..327f5aeb6bc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr59032.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo()
+{
+ float v __attribute__((vector_size(8)));
+ v++;
+}
+
+void
+foo2 ()
+{
+ float v __attribute__((vector_size(8)));
+ ++v;
+}
+
+void
+foo3 ()
+{
+ float v __attribute__((vector_size(8)));
+ v--;
+}
+
+void
+foo4 ()
+{
+ float v __attribute__((vector_size(8)));
+ --v;
+}
diff --git a/gcc/testsuite/c-c++-common/pr59037.c b/gcc/testsuite/c-c++-common/pr59037.c
new file mode 100644
index 00000000000..fae13c2fa94
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr59037.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+int
+main (int argc, char** argv)
+{
+ v4si x = {0,1,2,3};
+ x = (v4si) {(x)[3], (x)[2], (x)[1], (x)[0]};
+ return x[4];
+}
diff --git a/gcc/testsuite/c-c++-common/pr59280.c b/gcc/testsuite/c-c++-common/pr59280.c
new file mode 100644
index 00000000000..779f0fb858f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr59280.c
@@ -0,0 +1,4 @@
+/* PR c/59280 */
+/* { dg-do compile } */
+
+void bar (char *) __attribute__((constructor(foo))); /* { dg-error "constructor priorities must be integers|was not declared|constructor priorities are not supported" } */
diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-1.c b/gcc/testsuite/c-c++-common/torture/pr58794-1.c
new file mode 100644
index 00000000000..175629fec90
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr58794-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+struct S0
+{
+ int f;
+};
+
+struct S1
+{
+ struct S0 f1;
+ volatile int f2;
+};
+
+struct S2
+{
+ struct S1 g;
+} a, b;
+
+static int *c[1][2] = {{0, (int *)&a.g.f2}};
+static int d;
+
+int
+main ()
+{
+ for (d = 0; d < 1; d++)
+ for (b.g.f1.f = 0; b.g.f1.f < 1; b.g.f1.f++)
+ *c[b.g.f1.f][d + 1] = 0;
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-2.c b/gcc/testsuite/c-c++-common/torture/pr58794-2.c
new file mode 100644
index 00000000000..767798806db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr58794-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+struct S
+{
+ volatile int f;
+} a;
+
+unsigned int b;
+
+static int *c[1][2] = {{0, (int *)&a.f}};
+static unsigned int d;
+
+int
+main ()
+{
+ for (; d < 1; d++)
+ for (; b < 1; b++)
+ *c[b][d + 1] = 0;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/access02.C b/gcc/testsuite/g++.dg/cpp0x/access02.C
new file mode 100644
index 00000000000..74960a66a61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/access02.C
@@ -0,0 +1,39 @@
+// PR c++/58954
+// { dg-require-effective-target c++11 }
+
+template<class T>
+T&& declval();
+
+template<class T>
+struct foo_argument
+{
+ template<class Ret, class C, class Arg>
+ static Arg test(Ret (C::*)(Arg));
+
+ typedef decltype(test(&T::template foo<>)) type;
+};
+
+template<class T, class>
+struct dependent { typedef T type; };
+
+template<class T>
+struct base
+{
+ template<class Ignore = void>
+ auto foo(int i) -> decltype(declval<
+ typename dependent<T&, Ignore>::type
+ >().foo_impl(i));
+};
+
+struct derived : base<derived>
+{
+ friend struct base<derived>;
+private:
+ int foo_impl(int i);
+};
+
+int main()
+{
+ foo_argument<derived>::type var = 0;
+ return var;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template6.C
new file mode 100644
index 00000000000..eac6004aeb3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template6.C
@@ -0,0 +1,20 @@
+// PR c++/59268
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+template <typename>
+struct A
+{
+ constexpr A (int) {}
+ virtual void foo ()
+ {
+ constexpr A<void> a (0);
+ }
+};
+
+void
+bar ()
+{
+ A<int> a (3);
+ a.foo ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C
new file mode 100644
index 00000000000..1fc3738554e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C
@@ -0,0 +1,16 @@
+// PR c++/57901
+// { dg-require-effective-target c++11 }
+
+struct Z {
+ Z() = default;
+ Z(Z const&) = default;
+ constexpr Z(Z&&) {} /* non-trivial (constexpr) move ctor */
+};
+
+template<typename T>
+constexpr int fn0(T v) { return 0; }
+template<typename T>
+constexpr int fn (T v) { return fn0(v); }
+
+constexpr auto t0 = fn0(Z()); // OK!
+constexpr auto t = fn (Z()); // error! (GCC 4.8.1)
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype57.C b/gcc/testsuite/g++.dg/cpp0x/decltype57.C
new file mode 100644
index 00000000000..353cc72c335
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype57.C
@@ -0,0 +1,8 @@
+// PR c++/58633
+// { dg-do compile { target c++11 } }
+
+void foo(int i)
+{
+ typedef int I;
+ decltype(i.I::~I())* p;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum18.C b/gcc/testsuite/g++.dg/cpp0x/enum18.C
index 306ed8259f9..7361595c00e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum18.C
@@ -4,5 +4,5 @@
int main(void) {
enum e {};
e ev;
- ev.e::~e_u(); // { dg-error "e_u. has not been declared" }
+ ev.e::~e_u(); // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C
new file mode 100644
index 00000000000..d85918dd07b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C
@@ -0,0 +1,30 @@
+// PR c++/58083
+// { dg-do compile { target c++11 } }
+
+namespace details {
+struct iterator_concept_checker
+{
+ typedef char yes_type;
+ typedef char (&no_type)[2];
+
+ template <typename T>
+ static no_type test(...);
+
+ template <typename T>
+ static yes_type test(
+ int*
+ , void (*)(T) = [](T it)
+ {
+ auto copy = T{it}; // copy constructible
+ copy = it; // copy assignable
+ copy.~T(); // destroyable
+ ++it; // incrementable
+ }
+ );
+};
+}
+
+int main()
+{
+ details::iterator_concept_checker::test<int>(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C
new file mode 100644
index 00000000000..1ea59c21c84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C
@@ -0,0 +1,8 @@
+// PR c++/58568
+// { dg-do compile { target c++11 } }
+
+template<int> struct A
+{
+ static const int i;
+ template<int N> const int A<N>::i = []{ return 0; }(); // { dg-error "invalid use" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C
new file mode 100644
index 00000000000..1d2778fb5ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C
@@ -0,0 +1,7 @@
+// PR c++/58596
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ int i = [] { return decltype(i)(); }();
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C
new file mode 100644
index 00000000000..febe0ecac46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C
@@ -0,0 +1,13 @@
+// PR c++/58162
+// { dg-require-effective-target c++11 }
+
+struct A {
+ A();
+ A(A&&);
+};
+
+struct B {
+ A const a = A();
+};
+
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr57981.C b/gcc/testsuite/g++.dg/cpp0x/pr57981.C
new file mode 100644
index 00000000000..5ee1f0ed6ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr57981.C
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++11 -Wall -Wextra" }
+
+template<class T>
+void f(T t, void* = 0) // { dg-warning "unused parameter" }
+{
+}
+
+template<class T>
+auto g(T t) -> decltype(f(t))
+{
+ f(t);
+}
+
+int main()
+{
+ g(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual14.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual14.C
new file mode 100644
index 00000000000..8e55551aeb2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual14.C
@@ -0,0 +1,18 @@
+// PR c++/57825
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+struct target_class
+{};
+
+template<typename Class, typename Ret, typename... Args>
+struct target_class<Ret (Class::*)(Args...)>
+{};
+
+template<typename Class, typename Ret, typename... Args>
+struct target_class<Ret (Class::*)(Args...) &>
+{};
+
+template<typename Class, typename Ret, typename... Args>
+struct target_class<Ret (Class::*)(Args...) &&>
+{};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic144.C b/gcc/testsuite/g++.dg/cpp0x/variadic144.C
new file mode 100644
index 00000000000..5d05d3d52bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic144.C
@@ -0,0 +1,15 @@
+// PR c++/56060
+// { dg-do compile { target c++11 } }
+
+template<typename T> struct baz { };
+template<typename T> T bar();
+
+template<typename T, typename ... U>
+baz<decltype(bar<T>()(bar<U> ...))> // { dg-error "cannot be used" }
+foo();
+
+int main()
+{
+ foo<int>(); // { dg-error "no matching" }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic145.C b/gcc/testsuite/g++.dg/cpp0x/variadic145.C
new file mode 100644
index 00000000000..65edda59fd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic145.C
@@ -0,0 +1,13 @@
+// PR c++/59730
+// { dg-do compile { target c++11 } }
+
+template <typename> void declval();
+template <typename> void forward();
+template <typename> class D;
+template <typename _Functor, typename... _Bound_args>
+class D <_Functor(_Bound_args...)> {
+ template <typename... _Args, decltype(declval<_Functor>)>
+ void operator()(...) {
+ 0(forward<_Args>...);
+ }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr58979.C b/gcc/testsuite/g++.dg/diagnostic/pr58979.C
new file mode 100644
index 00000000000..6be3f143693
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr58979.C
@@ -0,0 +1,4 @@
+// PR c++/58979
+// { dg-do compile }
+
+int i = 0->*0; // { dg-error "invalid type argument of" }
diff --git a/gcc/testsuite/g++.dg/eh/ppc64-sighandle-cr.C b/gcc/testsuite/g++.dg/eh/ppc64-sighandle-cr.C
new file mode 100644
index 00000000000..32561736077
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/ppc64-sighandle-cr.C
@@ -0,0 +1,54 @@
+// { dg-do run { target { powerpc64*-*-linux* } } }
+// { dg-options "-fexceptions -fnon-call-exceptions" }
+
+#include <signal.h>
+#include <stdlib.h>
+#include <fenv.h>
+
+#define SET_CR(R,V) __asm__ __volatile__ ("mtcrf %0,%1" : : "n" (1<<(7-R)), "r" (V<<(4*(7-R))) : "cr" #R)
+#define GET_CR(R) ({ int tmp; __asm__ __volatile__ ("mfcr %0" : "=r" (tmp)); (tmp >> 4*(7-R)) & 15; })
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+ SET_CR(2, 3);
+ SET_CR(3, 2);
+ SET_CR(4, 1);
+
+ throw 0;
+}
+
+float test (float a, float b) __attribute__ ((__noinline__));
+float test (float a, float b)
+{
+ float x;
+ asm ("mtcrf %1,%2" : "=f" (x) : "n" (1 << (7-3)), "r" (0), "0" (b) : "cr3");
+ return a / x;
+}
+
+int main ()
+{
+ struct sigaction sa;
+ int status;
+
+ sa.sa_sigaction = sighandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ status = sigaction (SIGFPE, & sa, NULL);
+
+ feenableexcept (FE_DIVBYZERO);
+
+ SET_CR(2, 6);
+ SET_CR(3, 9);
+ SET_CR(4, 12);
+
+ try {
+ test (1, 0);
+ }
+ catch (...) {
+ return GET_CR(2) != 6 || GET_CR(3) != 9 || GET_CR(4) != 12;
+ }
+
+ return 1;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/ext/pr57362.C b/gcc/testsuite/g++.dg/ext/pr57362.C
new file mode 100644
index 00000000000..67f96857e8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr57362.C
@@ -0,0 +1,199 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target("default")))
+int foo(void) { return 1; }
+__attribute__((target("128bit-long-double")))
+int foo(void) { return 1; }
+__attribute__((target("80387")))
+int foo(void) { return 1; }
+__attribute__((target("96bit-long-double")))
+int foo(void) { return 1; }
+__attribute__((target("long-double-80")))
+int foo(void) { return 1; }
+__attribute__((target("long-double-64")))
+int foo(void) { return 1; }
+__attribute__((target("accumulate-outgoing-args")))
+int foo(void) { return 1; }
+__attribute__((target("align-double")))
+int foo(void) { return 1; }
+__attribute__((target("align-stringops")))
+int foo(void) { return 1; }
+__attribute__((target("fancy-math-387")))
+int foo(void) { return 1; }
+__attribute__((target("force-drap")))
+int foo(void) { return 1; }
+__attribute__((target("fp-ret-in-387")))
+int foo(void) { return 1; }
+__attribute__((target("hard-float")))
+int foo(void) { return 1; }
+__attribute__((target("ieee-fp")))
+int foo(void) { return 1; }
+__attribute__((target("inline-all-stringops")))
+int foo(void) { return 1; }
+__attribute__((target("inline-stringops-dynamically")))
+int foo(void) { return 1; }
+__attribute__((target("intel-syntax")))
+int foo(void) { return 1; }
+__attribute__((target("ms-bitfields")))
+int foo(void) { return 1; }
+__attribute__((target("no-align-stringops")))
+int foo(void) { return 1; }
+__attribute__((target("no-fancy-math-387")))
+int foo(void) { return 1; }
+__attribute__((target("no-push-args")))
+int foo(void) { return 1; }
+__attribute__((target("no-red-zone")))
+int foo(void) { return 1; }
+__attribute__((target("omit-leaf-frame-pointer")))
+int foo(void) { return 1; }
+__attribute__((target("pc32")))
+int foo(void) { return 1; }
+__attribute__((target("pc64")))
+int foo(void) { return 1; }
+__attribute__((target("pc80")))
+int foo(void) { return 1; }
+__attribute__((target("push-args")))
+int foo(void) { return 1; }
+__attribute__((target("red-zone")))
+int foo(void) { return 1; }
+__attribute__((target("rtd")))
+int foo(void) { return 1; }
+__attribute__((target("soft-float")))
+int foo(void) { return 1; }
+__attribute__((target("sseregparm")))
+int foo(void) { return 1; }
+__attribute__((target("stackrealign")))
+int foo(void) { return 1; }
+__attribute__((target("stack-arg-probe")))
+int foo(void) { return 1; }
+__attribute__((target("tls-direct-seg-refs")))
+int foo(void) { return 1; }
+__attribute__((target("vect8-ret-in-mem")))
+int foo(void) { return 1; }
+__attribute__((target("recip")))
+int foo(void) { return 1; }
+__attribute__((target("cld")))
+int foo(void) { return 1; }
+__attribute__((target("vzeroupper")))
+int foo(void) { return 1; }
+__attribute__((target("dispatch-scheduler")))
+int foo(void) { return 1; }
+__attribute__((target("prefer-avx128")))
+int foo(void) { return 1; }
+__attribute__((target("32")))
+int foo(void) { return 1; }
+__attribute__((target("64")))
+int foo(void) { return 1; }
+__attribute__((target("x32")))
+int foo(void) { return 1; }
+__attribute__((target("mmx")))
+int foo(void) { return 1; }
+__attribute__((target("3dnow")))
+int foo(void) { return 1; }
+__attribute__((target("3dnowa")))
+int foo(void) { return 1; }
+__attribute__((target("sse")))
+int foo(void) { return 1; }
+__attribute__((target("sse2")))
+int foo(void) { return 1; }
+__attribute__((target("sse3")))
+int foo(void) { return 1; }
+__attribute__((target("ssse3")))
+int foo(void) { return 1; }
+__attribute__((target("sse4.1")))
+int foo(void) { return 1; }
+__attribute__((target("sse4.2")))
+int foo(void) { return 1; }
+__attribute__((target("sse4")))
+int foo(void) { return 1; }
+__attribute__((target("no-sse4")))
+int foo(void) { return 1; }
+__attribute__((target("sse5")))
+int foo(void) { return 1; }
+__attribute__((target("avx")))
+int foo(void) { return 1; }
+__attribute__((target("avx2")))
+int foo(void) { return 1; }
+__attribute__((target("fma")))
+int foo(void) { return 1; }
+__attribute__((target("sse4a")))
+int foo(void) { return 1; }
+__attribute__((target("fma4")))
+int foo(void) { return 1; }
+__attribute__((target("xop")))
+int foo(void) { return 1; }
+__attribute__((target("lwp")))
+int foo(void) { return 1; }
+__attribute__((target("abm")))
+int foo(void) { return 1; }
+__attribute__((target("popcnt")))
+int foo(void) { return 1; }
+__attribute__((target("bmi")))
+int foo(void) { return 1; }
+__attribute__((target("bmi2")))
+int foo(void) { return 1; }
+__attribute__((target("lzcnt")))
+int foo(void) { return 1; }
+__attribute__((target("hle")))
+int foo(void) { return 1; }
+__attribute__((target("rdseed")))
+int foo(void) { return 1; }
+__attribute__((target("prfchw")))
+int foo(void) { return 1; }
+__attribute__((target("adx")))
+int foo(void) { return 1; }
+__attribute__((target("fxsr")))
+int foo(void) { return 1; }
+__attribute__((target("xsave")))
+int foo(void) { return 1; }
+__attribute__((target("xsaveopt")))
+int foo(void) { return 1; }
+__attribute__((target("tbm")))
+int foo(void) { return 1; }
+__attribute__((target("cx16")))
+int foo(void) { return 1; }
+__attribute__((target("sahf")))
+int foo(void) { return 1; }
+__attribute__((target("movbe")))
+int foo(void) { return 1; }
+__attribute__((target("crc32")))
+int foo(void) { return 1; }
+__attribute__((target("aes")))
+int foo(void) { return 1; }
+__attribute__((target("pclmul")))
+int foo(void) { return 1; }
+__attribute__((target("sse2avx")))
+int foo(void) { return 1; }
+__attribute__((target("fsgsbase")))
+int foo(void) { return 1; }
+__attribute__((target("rdrnd")))
+int foo(void) { return 1; }
+__attribute__((target("f16c")))
+int foo(void) { return 1; }
+__attribute__((target("fentry")))
+int foo(void) { return 1; }
+__attribute__((target("8bit-idiv")))
+int foo(void) { return 1; }
+__attribute__((target("avx256-split-unaligned-load")))
+int foo(void) { return 1; }
+__attribute__((target("avx256-split-unaligned-store")))
+int foo(void) { return 1; }
+__attribute__((target("rtm")))
+int foo(void) { return 1; }
+//---------------
+
+#include <stdio.h>
+ int main (void)
+ {
+ int result;
+ result = foo();
+ printf("Result is %d\n", result);
+ return result;
+ }
+
+/* { dg-prune-output "attribute.* is unknown" } */
+/* { dg-prune-output "redefinition of int foo" } */
+/* { dg-prune-output "previous declaration of int foo" } */
+/* { dg-prune-output "int foo.* previously defined here" } */
+/* { dg-prune-output "No dispatcher found for" } */
diff --git a/gcc/testsuite/g++.dg/ext/pr57735.C b/gcc/testsuite/g++.dg/ext/pr57735.C
new file mode 100644
index 00000000000..0eb95006dda
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr57735.C
@@ -0,0 +1,145 @@
+/* { dg-do compile { target arm*-*-* } } */
+/* { dg-options "-march=armv5te -marm -mtune=xscale -mfloat-abi=soft -O1" } */
+
+typedef unsigned int size_t;
+__extension__
+typedef long long int int64_t;
+namespace WTF {
+ template<typename T> class RefPtr {
+ public:
+ inline T* operator->() const { return m_ptr; }
+ T* m_ptr;
+ };
+}
+using WTF::RefPtr;
+namespace JSC {
+ class ExecState;
+ class JSString;
+ typedef int64_t EncodedJSValue;
+ class JSValue {
+ public:
+ static EncodedJSValue encode(JSValue);
+ JSString* toString(ExecState*) const;
+ };
+}
+typedef unsigned char LChar;
+ typedef short unsigned int UChar;
+namespace WTF {
+ template<typename T, size_t inlineCapacity = 0>
+ class Vector {
+ public:
+ template<typename U> bool tryAppend(const U*, size_t);
+ };
+}
+using WTF::Vector;
+namespace WTF {
+template<typename CharType> inline bool isASCIIDigit(CharType c)
+{
+}
+template<typename CharType> inline bool isASCIIHexDigit(CharType c)
+{
+ return isASCIIDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
+}
+ class StringImpl;
+}
+using WTF::StringImpl;
+namespace WTF {
+class StringImpl {
+public:
+ unsigned length() const { return m_length; }
+ unsigned m_length;
+};
+}
+namespace JSC {
+ class Register {
+ };
+class UString {
+public:
+ unsigned length() const
+ {
+ return m_impl->length();
+ }
+ const LChar* characters8() const
+ {
+ }
+ RefPtr<StringImpl> m_impl;
+};
+ class ExecState : private Register {
+ public:
+ JSValue argument(size_t argument)
+ {
+ }
+ };
+ class JSCell {
+ };
+ class JSString : public JSCell {
+ public:
+ const UString& value(ExecState*) const;
+ };
+class JSStringBuilder {
+public:
+ void append(const UChar u)
+ {
+ m_okay &= buffer16.tryAppend(&u, 1);
+ }
+ Vector<UChar, 64> buffer16;
+ bool m_okay;
+};
+template <typename T>
+class Lexer {
+public:
+ static unsigned char convertHex(int c1, int c2);
+};
+}
+namespace WTF {
+namespace Unicode {
+ int UTF8SequenceLength(char);
+ int decodeUTF8Sequence(const char*);
+}
+}
+using namespace WTF;
+using namespace Unicode;
+namespace JSC {
+template <typename CharType>
+static JSValue decode(ExecState* exec, const CharType* characters, int length, const char* doNotUnescape, bool strict)
+{
+ JSStringBuilder builder;
+ int k = 0;
+ UChar u = 0;
+ while (k < length) {
+ const CharType* p = characters + k;
+ CharType c = *p;
+ if (c == '%') {
+ int charLen = 0;
+ if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
+ const char b0 = Lexer<CharType>::convertHex(p[1], p[2]);
+ const int sequenceLen = UTF8SequenceLength(b0);
+ if (sequenceLen && k <= length - sequenceLen * 3) {
+ charLen = sequenceLen * 3;
+ char sequence[5];
+ if (charLen != 0) {
+ const int character = decodeUTF8Sequence(sequence);
+ if (character < 0 || character >= 0x110000)
+ charLen = 0;
+ else if (character >= 0x10000) {
+ builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
+ } else
+ u = static_cast<UChar>(character);
+ }
+ }
+ }
+ }
+ }
+}
+static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
+{
+ UString str = exec->argument(0).toString(exec)->value(exec);
+ return decode(exec, str.characters8(), str.length(), doNotUnescape, strict);
+}
+EncodedJSValue globalFuncDecodeURI(ExecState* exec)
+{
+ static const char do_not_unescape_when_decoding_URI[] =
+ "#$&+,/:;=?@";
+ return JSValue::encode(decode(exec, do_not_unescape_when_decoding_URI, true));
+}
+}
diff --git a/gcc/testsuite/g++.dg/gomp/pr59297.C b/gcc/testsuite/g++.dg/gomp/pr59297.C
new file mode 100644
index 00000000000..330ed2e00b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/pr59297.C
@@ -0,0 +1,25 @@
+// PR c++/59297
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+template <typename T>
+struct A
+{
+ ~A ();
+ const T &operator[] (int) const;
+};
+
+struct B
+{
+ int &operator () (A <int>);
+};
+
+void
+foo (B &x, int &z)
+{
+ A<A<int> > y;
+ #pragma omp atomic
+ x (y[0]) += 1;
+ #pragma omp atomic
+ z += x(y[1]);
+}
diff --git a/gcc/testsuite/g++.dg/inherit/virtual11.C b/gcc/testsuite/g++.dg/inherit/virtual11.C
new file mode 100644
index 00000000000..04c24129343
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/virtual11.C
@@ -0,0 +1,17 @@
+// PR c++/59031
+// { dg-do compile }
+// { dg-options "-fdump-tree-gimple " }
+class B {
+ public:
+ virtual int add (int a, int b) {return a+ b;}
+};
+
+class D : public B {
+};
+
+int foo (int a, int b) {
+ D d;
+ return d.add(a, b);
+}
+// { dg-final { scan-tree-dump-not "OBJ_TYPE_REF" "gimple" } }
+// { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/g++.dg/opt/pr58006.C b/gcc/testsuite/g++.dg/opt/pr58006.C
new file mode 100644
index 00000000000..fd3b7bebd8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr58006.C
@@ -0,0 +1,22 @@
+// PR tree-optimization/58006
+// { dg-do compile }
+// { dg-require-effective-target pthread }
+// { dg-options "-Ofast -ftree-parallelize-loops=2" }
+
+extern "C" float sqrtf (float);
+
+struct S
+{
+ float i, j;
+ float foo () const { return sqrtf (i * i + j * j); }
+ S () : i (1), j (1) {}
+};
+
+void
+bar (int a, int b)
+{
+ int i;
+ float f;
+ for (i = a; i < b; i++)
+ f = S ().foo ();
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr58165.C b/gcc/testsuite/g++.dg/opt/pr58165.C
new file mode 100644
index 00000000000..d758e370050
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr58165.C
@@ -0,0 +1,14 @@
+// PR tree-optimization/58165
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" float sqrtf (float);
+
+struct A { A (); ~A (); };
+
+void
+foo (double d)
+{
+ A a;
+ sqrtf (d);
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr58864.C b/gcc/testsuite/g++.dg/opt/pr58864.C
new file mode 100644
index 00000000000..b8587f298a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr58864.C
@@ -0,0 +1,21 @@
+// PR target/58864
+// { dg-do compile }
+// { dg-options "-Os" }
+// { dg-additional-options "-march=i686" { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+
+struct A { A (); ~A (); };
+struct B { B (); };
+
+float d, e;
+
+void
+foo ()
+{
+ A a;
+ float c = d;
+ while (1)
+ {
+ B b;
+ e = c ? -c : 0;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr59470.C b/gcc/testsuite/g++.dg/opt/pr59470.C
new file mode 100644
index 00000000000..4698ab717d2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr59470.C
@@ -0,0 +1,188 @@
+// PR middle-end/59470
+// { dg-do run }
+// { dg-options "-O2 -fstack-protector" }
+// { dg-additional-options "-fPIC" { target fpic } }
+// { dg-require-effective-target fstack_protector }
+
+struct A
+{
+ int a1;
+ A () throw () : a1 (0) {}
+};
+
+struct B
+{
+ unsigned int b1 () throw ();
+};
+
+__attribute__((noinline, noclone)) unsigned int
+B::b1 () throw ()
+{
+ asm volatile ("" : : : "memory");
+ return 0;
+}
+
+struct C
+{
+ const A **c1;
+ void c2 (const A *, unsigned int);
+};
+
+__attribute__((noinline, noclone)) void
+C::c2 (const A *, unsigned int)
+{
+ asm volatile ("" : : : "memory");
+}
+
+struct D
+{
+ C *d1;
+};
+
+struct E
+{
+ int e1;
+ int e2;
+ D e3;
+};
+
+struct F
+{
+ virtual int f1 (const char * s, int n);
+};
+
+struct G
+{
+ F *g1;
+ bool g2;
+ G & g3 (const char * ws, int len)
+ {
+ if (__builtin_expect (!g2, true)
+ && __builtin_expect (this->g1->f1 (ws, len) != len, false))
+ g2 = true;
+ return *this;
+ }
+};
+
+struct H : public A
+{
+ const char *h1;
+ unsigned int h2;
+ bool h3;
+ const char *h4;
+ char h5;
+ char h6;
+ char h7[31];
+ bool h8;
+ H () : h1 (0), h2 (0), h4 (0), h5 (0), h6 (0), h8 (false) {}
+ void h9 (const D &) __attribute__((noinline, noclone));
+};
+
+void
+H::h9 (const D &)
+{
+ h3 = true;
+ __builtin_memset (h7, 0, sizeof (h7));
+ asm volatile ("" : : : "memory");
+};
+
+B b;
+
+inline const H *
+foo (const D &x)
+{
+ const unsigned int i = b.b1 ();
+ const A **j = x.d1->c1;
+ if (!j[i])
+ {
+ H *k = 0;
+ try
+ {
+ k = new H;
+ k->h9 (x);
+ }
+ catch (...)
+ {
+ }
+ x.d1->c2 (k, i);
+ }
+ return static_cast <const H *>(j[i]);
+}
+
+__attribute__((noinline, noclone)) int
+bar (char *x, unsigned long v, const char *y, int z, bool w)
+{
+ asm volatile ("" : : "r" (x), "r" (v), "r" (y) : "memory");
+ asm volatile ("" : : "r" (z), "r" (w) : "memory");
+ return 8;
+}
+
+__attribute__((noinline, noclone)) void
+baz (void *z, const char *g, unsigned int h, char s, E &e, char *n, char *c, int &l)
+{
+ asm volatile ("" : : "r" (z), "r" (g), "r" (h) : "memory");
+ asm volatile ("" : : "r" (s), "r" (&e), "r" (n) : "memory");
+ asm volatile ("" : : "r" (c), "r" (&l) : "memory");
+ if (n == c)
+ __builtin_abort ();
+ int i = 0;
+ asm ("" : "+r" (i));
+ if (i == 0)
+ __builtin_exit (0);
+}
+
+__attribute__((noinline, noclone)) G
+test (void *z, G s, E &x, char, long v)
+{
+ const D &d = x.e3;
+ const H *h = foo (d);
+ const char *q = h->h7;
+ const int f = x.e2;
+ const int i = 5 * sizeof (long);
+ char *c = static_cast <char *>(__builtin_alloca (i));
+ const int b = f & 74;
+ const bool e = (b != 64 && b != 8);
+ const unsigned long u = ((v > 0 || !e) ? (unsigned long) v : -(unsigned long) v);
+ int l = bar (c + i, u, q, f, e);
+ c += i - l;
+ if (h->h3)
+ {
+ char *c2 = static_cast <char *>(__builtin_alloca ((l + 1) * 2));
+ baz (z, h->h1, h->h2, h->h6, x, c2 + 2, c, l);
+ c = c2 + 2;
+ }
+ if (__builtin_expect (e, true))
+ {
+ }
+ else if ((f & 4096) && v)
+ {
+ {
+ const bool m = f & 176;
+ *--c = q[m];
+ *--c = q[1];
+ }
+ }
+ const int w = x.e1;
+ if (w > l)
+ {
+ char * c3 = static_cast <char *>(__builtin_alloca (w));
+ c = c3;
+ }
+ return s.g3 (c, l);
+}
+
+int
+main ()
+{
+ H h;
+ const A *j[1];
+ C c;
+ G g;
+ E e;
+ h.h9 (e.e3);
+ j[0] = &h;
+ c.c1 = j;
+ e.e3.d1 = &c;
+ test (0, g, e, 0, 0);
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr59647.C b/gcc/testsuite/g++.dg/opt/pr59647.C
new file mode 100644
index 00000000000..1fc5067d83f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr59647.C
@@ -0,0 +1,32 @@
+// PR rtl-optimization/59647
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-vrp" }
+// { dg-additional-options "-msse2 -mfpmath=sse" { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+
+void f1 (int);
+void f2 ();
+double f3 (int);
+
+struct A
+{
+ int f4 () const
+ {
+ if (a == 0)
+ return 1;
+ return 0;
+ }
+ unsigned f5 ()
+ {
+ if (!f4 ())
+ f2 ();
+ return a;
+ }
+ int a;
+};
+
+void
+f6 (A *x)
+{
+ unsigned b = x->f5 ();
+ f1 (b - 1 - f3 (x->f5 () - 1U));
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash62.C b/gcc/testsuite/g++.dg/parse/crash62.C
new file mode 100644
index 00000000000..04154f40cd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash62.C
@@ -0,0 +1,6 @@
+// PR c++/58535
+
+struct A
+{
+ template<int> virtual void foo(); // { dg-error "templates" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/using4.C b/gcc/testsuite/g++.dg/parse/using4.C
new file mode 100644
index 00000000000..2abe399f8dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/using4.C
@@ -0,0 +1,20 @@
+// PR c++/58457
+
+struct allocator
+{
+ void operator delete (void*);
+ void* operator new (__SIZE_TYPE__, void*);
+};
+
+struct type : public allocator
+{
+ type() {}
+ using allocator::operator new;
+ using allocator::operator delete;
+};
+
+int main()
+{
+ new (0) type;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pr57878.C b/gcc/testsuite/g++.dg/pr57878.C
new file mode 100644
index 00000000000..da4fc4bb563
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr57878.C
@@ -0,0 +1,226 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-m32 -O2 -fno-omit-frame-pointer -fPIC -std=gnu++11" } */
+
+typedef int int32;
+typedef long long int64;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+namespace std {
+ typedef __SIZE_TYPE__ size_t;
+ template<class _CharT>
+ struct char_traits;
+ template<typename _Tp>
+ inline _Tp* __addressof(_Tp& __r) noexcept {
+ return reinterpret_cast<_Tp*> (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
+ }
+ template<typename _Tp>
+ struct remove_reference {
+ typedef _Tp type;
+ };
+ template<typename _Tp>
+ constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept {
+ return static_cast<_Tp&&>(__t);
+ }
+}
+typedef __SIZE_TYPE__ size_t;
+extern "C++" {
+ inline void* operator new(std::size_t, void* __p) noexcept {
+ return __p;
+ }
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Tp>
+ class new_allocator {
+ public:
+ typedef size_t size_type;
+ typedef _Tp* pointer;
+ };
+}
+namespace std {
+ template<typename _Tp>
+ using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
+ template<typename _Tp>
+ class allocator
+ : public __allocator_base<_Tp> {
+ public:
+ typedef size_t size_type;
+ template<typename _Tp1>
+ struct rebind {
+ typedef allocator<_Tp1> other;
+ };
+ };
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ class __sso_string_base;
+ template<typename _CharT, typename _Traits = std::char_traits<_CharT>, typename _Alloc = std::allocator<_CharT>, template <typename, typename, typename> class _Base = __sso_string_base>
+ class __versa_string;
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ struct __vstring_utility {
+ typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
+ template<typename _Alloc1>
+ struct _Alloc_hider
+ : public _Alloc1 {
+ _Alloc_hider(const _Alloc1& __a, _CharT* __ptr)
+ : _Alloc1(__a), _M_p(__ptr) {
+ }
+ _CharT* _M_p;
+ };
+ };
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ class __sso_string_base
+ : protected __vstring_utility<_CharT, _Traits, _Alloc> {
+ typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
+ typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+ private:
+ typename _Util_Base::template _Alloc_hider<_CharT_alloc_type>
+ _M_dataplus;
+ size_type _M_string_length;
+ enum {
+ _S_local_capacity = 15 };
+ union {
+ _CharT _M_local_data[_S_local_capacity + 1];
+ };
+ template<typename _InIterator>
+ void _M_construct(_InIterator __beg, _InIterator __end);
+ public:
+ size_type _M_max_size() const;
+ _CharT* _M_data() const {
+ return _M_dataplus._M_p;
+ }
+ size_type _M_length() const {
+ return _M_string_length;
+ }
+ __sso_string_base(const __sso_string_base& __rcs);
+ const _CharT_alloc_type& _M_get_allocator() const {
+ }
+ };
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ __sso_string_base<_CharT, _Traits, _Alloc>:: __sso_string_base(const __sso_string_base& __rcs)
+ : _M_dataplus(__rcs._M_get_allocator(), _M_local_data) {
+ _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length());
+ }
+ template<typename _CharT, typename _Traits, typename _Alloc, template <typename, typename, typename> class _Base>
+ class __versa_string
+ : private _Base<_CharT, _Traits, _Alloc> {
+ };
+}
+template<typename _CharT, typename _Traits = std::char_traits<_CharT>, typename _Alloc = std::allocator<_CharT> >
+class basic_string
+ : public __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc> {
+};
+typedef basic_string<char> string;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Alloc, typename _Tp>
+ class __alloctr_rebind_helper {
+ public:
+ static const bool __value = true;
+ };
+ template<typename _Alloc, typename _Tp, bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value>
+ struct __alloctr_rebind;
+ template<typename _Alloc, typename _Tp> struct __alloctr_rebind<_Alloc, _Tp, true>
+ {
+ typedef typename _Alloc::template rebind<_Tp>::other __type;
+ };
+ template<typename _Alloc>
+ struct allocator_traits {
+ private:
+ template<typename _Tp>
+ static typename _Tp::pointer _S_pointer_helper(_Tp*);
+ typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;
+ public:
+ typedef __pointer pointer;
+ template<typename _Tp>
+ using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
+ };
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Alloc> struct __alloc_traits
+ : std::allocator_traits<_Alloc>
+ {
+ typedef std::allocator_traits<_Alloc> _Base_type;
+ template<typename _Tp>
+ struct rebind {
+ typedef typename _Base_type::template rebind_alloc<_Tp>
+ other;
+ };
+ };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _T1, typename... _Args>
+ inline void _Construct(_T1* __p, _Args&&... __args) {
+ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...);
+ }
+ template<typename _Tp, typename _Alloc>
+ struct _Vector_base {
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer;
+ struct _Vector_impl
+ : public _Tp_alloc_type {
+ pointer _M_start;
+ pointer _M_finish;
+ };
+ public:
+ _Vector_impl _M_impl;
+ };
+ template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
+ class vector
+ : protected _Vector_base<_Tp, _Alloc> {
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ public:
+ typedef _Tp value_type;
+ typedef typename _Base::pointer pointer;
+ typedef size_t size_type;
+ size_type size() const;
+ void push_back(const value_type& __x) {
+ _M_emplace_back_aux(__x);
+ }
+ template<typename... _Args>
+ void _M_emplace_back_aux(_Args&&... __args);
+ size_type _M_check_len();
+ };
+ template<typename _Tp, typename _Alloc> template<typename... _Args>
+ void vector<_Tp, _Alloc>:: _M_emplace_back_aux(_Args&&... __args) {
+ const size_type __len = _M_check_len();
+ pointer __new_start(static_cast<pointer>(::operator new(__len * sizeof(_Tp))));
+ pointer __new_temp(__new_start + size());
+ ::new((void *)__new_temp) _Tp(std::forward<_Args>(__args)...);
+ pointer __cur = __new_start;
+ pointer __first = this->_M_impl._M_start;
+ pointer __last = this->_M_impl._M_finish;
+ for (;
+ __first != __last;
+ ++__first, ++__cur) std::_Construct(std::__addressof(*__cur), *__first);
+ }
+}
+using std::vector;
+class DL {
+public:
+ struct ChunkId {
+ int64 disk_id;
+ uint64 handle;
+ uint64 version;
+ string capability;
+ ChunkId();
+ };
+ struct ChunkInfo {
+ ChunkId id;
+ uint64 mtime;
+ uint32 length;
+ int32 space_used;
+ };
+};
+class FDB {
+ void CollectChunk(const DL::ChunkInfo& chunk, const int& location);
+private:
+ struct ChunkData {
+ int location;
+ DL::ChunkInfo chunk_info;
+ };
+ vector<ChunkData> chunk_data_;
+};
+void FDB::CollectChunk(const DL::ChunkInfo& chunk, const int& location) {
+ ChunkData chunk_data;
+ chunk_data_.push_back( chunk_data);
+}
diff --git a/gcc/testsuite/g++.dg/template/abstract1.C b/gcc/testsuite/g++.dg/template/abstract1.C
new file mode 100644
index 00000000000..20bbf5a911f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/abstract1.C
@@ -0,0 +1,12 @@
+// PR c++/58022
+
+template <class T> struct A { };
+template <class T> A<T> & operator<< (A<T>&, T);
+template <class T> class foo;
+template <class T> A<char> & operator<<(A<char>& o, const foo<T>& l);
+template <class T> class foo {
+ friend A<char>& operator<< <T> (A<char>& o, const foo<T>& l);
+};
+class bar;
+foo<bar> fb;
+class bar { virtual void baz()=0; };
diff --git a/gcc/testsuite/g++.dg/template/delete2.C b/gcc/testsuite/g++.dg/template/delete2.C
new file mode 100644
index 00000000000..b6ab380c9f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/delete2.C
@@ -0,0 +1,26 @@
+// PR c++/58119
+
+template <class T>
+struct A
+{
+ operator T*();
+ template <class U>
+ operator A<U>();
+};
+
+template <class T>
+struct B
+{
+ operator T*();
+ template <class U>
+ operator A<U>*();
+};
+
+int main()
+{
+ A<int> a;
+ delete a;
+
+ B<int> b;
+ delete b; // { dg-error "template|delete" }
+}
diff --git a/gcc/testsuite/g++.dg/template/inherit9.C b/gcc/testsuite/g++.dg/template/inherit9.C
new file mode 100644
index 00000000000..926343b4e23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/inherit9.C
@@ -0,0 +1,15 @@
+// PR c++/58273
+
+class A {};
+class B
+{
+ int goo(A);
+};
+template<typename E>
+class D : public B
+{
+ void foo(A t)
+ {
+ int const i(B::goo(t));
+ }
+};
diff --git a/gcc/testsuite/g++.dg/template/partial14.C b/gcc/testsuite/g++.dg/template/partial14.C
new file mode 100644
index 00000000000..3870164f0ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial14.C
@@ -0,0 +1,16 @@
+// PR c++/59044
+
+template <class T>
+class C {
+private:
+ template <T a, T b>
+ struct Implementation {};
+public:
+ typedef typename Implementation<0, 0>::Typedef Type;
+};
+
+template <class T>
+template <T b>
+struct C<T>::Implementation<0, b> { typedef void Typedef; };
+
+template class C<unsigned>;
diff --git a/gcc/testsuite/g++.dg/tm/noexcept-6.C b/gcc/testsuite/g++.dg/tm/noexcept-6.C
new file mode 100644
index 00000000000..4391159e235
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/noexcept-6.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-fno-exceptions -fgnu-tm -O -std=c++0x -fdump-tree-tmlower" }
+
+struct TrueFalse
+{
+ static constexpr bool v() { return true; }
+};
+
+int global;
+
+template<typename T> int foo()
+{
+ return __transaction_atomic noexcept(T::v()) (global + 1);
+}
+
+int f1()
+{
+ return foo<TrueFalse>();
+}
+
+/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 0 "tmlower" } } */
+/* { dg-final { scan-tree-dump-times "__transaction_atomic" 1 "tmlower" } } */
+/* { dg-final { cleanup-tree-dump "tmlower" } } */
diff --git a/gcc/testsuite/g++.dg/torture/pr59163.C b/gcc/testsuite/g++.dg/torture/pr59163.C
new file mode 100644
index 00000000000..2f9a9997078
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr59163.C
@@ -0,0 +1,30 @@
+// PR target/59163
+// { dg-do run }
+
+struct A { float a[4]; };
+struct B { int b; A a; };
+
+__attribute__((noinline, noclone)) void
+bar (A &a)
+{
+ if (a.a[0] != 36.0f || a.a[1] != 42.0f || a.a[2] != 48.0f || a.a[3] != 54.0f)
+ __builtin_abort ();
+}
+
+__attribute__((noinline, noclone)) void
+foo (A &a)
+{
+ int i;
+ A c = a;
+ for (i = 0; i < 4; i++)
+ c.a[i] *= 6.0f;
+ a = c;
+ bar (a);
+}
+
+int
+main ()
+{
+ B b = { 5, { 6, 7, 8, 9 } };
+ foo (b.a);
+}
diff --git a/gcc/testsuite/g++.dg/tree-prof/pr59255.C b/gcc/testsuite/g++.dg/tree-prof/pr59255.C
new file mode 100644
index 00000000000..eb2b51f7e25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-prof/pr59255.C
@@ -0,0 +1,29 @@
+// PR c++/59255
+// { dg-options "-O2 -std=c++11" }
+
+struct S
+{
+ __attribute__((noinline, noclone)) ~S () noexcept (true)
+ {
+ if (fn)
+ fn (1);
+ }
+ void (*fn) (int);
+};
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+ if (x != 1)
+ throw 1;
+}
+
+int
+main ()
+{
+ for (int i = 0; i < 100; i++)
+ {
+ S s;
+ s.fn = foo;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/uninit-pred-4.C b/gcc/testsuite/g++.dg/uninit-pred-4.C
new file mode 100644
index 00000000000..94ab13c50d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/uninit-pred-4.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Og" } */
+
+int pop ();
+int pop_first_bucket;
+
+int my_pop ()
+{
+ int out; // { dg-bogus "uninitialized" "uninitialized variable warning" }
+
+ while (pop_first_bucket)
+ if (pop_first_bucket && (out = pop()))
+ return out;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-21.C b/gcc/testsuite/g++.dg/warn/Wunused-var-21.C
new file mode 100644
index 00000000000..d279e598033
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-var-21.C
@@ -0,0 +1,31 @@
+// PR c++/58325
+// { dg-do compile }
+// { dg-options "-Wunused" }
+
+void
+f1 ()
+{
+ int *volatile a = new int[1];
+ delete[] a;
+}
+
+void
+f2 ()
+{
+ int *b = new int[1];
+ delete[] b;
+}
+
+void
+f3 ()
+{
+ int *volatile c = new int;
+ delete c;
+}
+
+void
+f4 ()
+{
+ int *d = new int;
+ delete d;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/misc9.C b/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
index 3d8858cf64a..7b9a86cbf4a 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
@@ -8,6 +8,6 @@ class bee {
class foo {
public:
- int bee::bar; // { dg-error "not derived" } you cannot do this
+ int bee::bar; // { dg-error "invalid use" } you cannot do this
int me();
};
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58088.c b/gcc/testsuite/gcc.c-torture/compile/pr58088.c
new file mode 100644
index 00000000000..07a9c68a7ff
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58088.c
@@ -0,0 +1,5 @@
+int
+bar (int i)
+{
+ return 1 | ((i * 2) & 254);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58164.c b/gcc/testsuite/gcc.c-torture/compile/pr58164.c
new file mode 100644
index 00000000000..7fe24fa439f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58164.c
@@ -0,0 +1,8 @@
+/* PR tree-optimization/58164 */
+
+int
+foo (void)
+{
+ int x = 0;
+ goto *&x;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c
new file mode 100644
index 00000000000..45aad2b2e65
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c
@@ -0,0 +1,11 @@
+/* PR middle-end/58970 */
+
+struct T { int b : 1; };
+struct S { struct T t[1]; };
+
+void
+foo (int x, struct S *s)
+{
+ if (x == -1)
+ s->t[x].b = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c
new file mode 100644
index 00000000000..3103b31e179
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c
@@ -0,0 +1,11 @@
+/* PR middle-end/58970 */
+
+struct T { char a : 8; char b : 1; };
+struct S { char x; struct T t[1]; };
+
+void
+foo (int x, struct S *s)
+{
+ if (x == -1)
+ s->t[x].b = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58997.c b/gcc/testsuite/gcc.c-torture/compile/pr58997.c
new file mode 100644
index 00000000000..2c7a0f82c8a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58997.c
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/58997 */
+
+int a, b, c, e;
+short d;
+char h;
+
+void
+foo ()
+{
+ while (b)
+ {
+ d = a ? c : 1 % a;
+ c = d;
+ h = d;
+ if (!h)
+ while (e)
+ ;
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59362.c b/gcc/testsuite/gcc.c-torture/compile/pr59362.c
new file mode 100644
index 00000000000..3e78f76bc5f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr59362.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/59362 */
+
+char *
+foo (char *r, int s)
+{
+ r = __builtin___stpcpy_chk (r, "abc", __builtin_object_size (r, 1));
+ if (s)
+ r = __builtin___stpcpy_chk (r, "d", __builtin_object_size (r, 1));
+ return r;
+}
+
+char *a;
+long int b;
+
+void
+bar (void)
+{
+ b = __builtin_object_size (0, 0);
+ a = __builtin___stpcpy_chk (0, "", b);
+ b = __builtin_object_size (a, 0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59803.c b/gcc/testsuite/gcc.c-torture/compile/pr59803.c
new file mode 100644
index 00000000000..d2b5d2098f5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr59803.c
@@ -0,0 +1,27 @@
+/* PR target/59803 */
+
+extern void baz (void) __attribute__ ((__noreturn__));
+struct A { int g, h; };
+extern struct A a;
+struct B { unsigned char i, j, k, l, m; };
+int c, d, e;
+static int f;
+
+void
+foo (void)
+{
+ f = 1;
+}
+
+void
+bar (struct B *x)
+{
+ x->i = e;
+ x->k = c;
+ x->l = d;
+ x->j = a.h;
+ x->m = f;
+ if (x->i != e) baz ();
+ if (x->k != c) baz ();
+ if (x->j != a.h) baz ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20131127-1.c b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c
new file mode 100644
index 00000000000..8ec49657741
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c
@@ -0,0 +1,34 @@
+/* PR middle-end/59138 */
+/* Testcase by John Regehr <regehr@cs.utah.edu> */
+
+extern void abort (void);
+
+#pragma pack(1)
+
+struct S0 {
+ int f0;
+ int f1;
+ int f2;
+ short f3;
+};
+
+short a = 1;
+
+struct S0 b = { 1 }, c, d, e;
+
+struct S0 fn1() { return c; }
+
+void fn2 (void)
+{
+ b = fn1 ();
+ a = 0;
+ d = e;
+}
+
+int main (void)
+{
+ fn2 ();
+ if (a != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58209.c b/gcc/testsuite/gcc.c-torture/execute/pr58209.c
new file mode 100644
index 00000000000..78743bfb959
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58209.c
@@ -0,0 +1,32 @@
+/* PR tree-optimization/58209 */
+
+extern void abort (void);
+typedef __INTPTR_TYPE__ T;
+T buf[1024];
+
+T *
+foo (T n)
+{
+ if (n == 0)
+ return (T *) buf;
+ T s = (T) foo (n - 1);
+ return (T *) (s + sizeof (T));
+}
+
+T *
+bar (T n)
+{
+ if (n == 0)
+ return buf;
+ return foo (n - 1) + 1;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 27; i++)
+ if (foo (i) != buf + i || bar (i) != buf + i)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58277-1.c b/gcc/testsuite/gcc.c-torture/execute/pr58277-1.c
new file mode 100644
index 00000000000..811988f4371
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58277-1.c
@@ -0,0 +1,102 @@
+/* PR tree-optimization/58277 */
+
+extern void abort (void);
+static int a[2];
+int b, c, d, *e, f, g, h, **i = &e, k, l = 1, n, o, p;
+static int **volatile j = &e;
+const int m;
+char u;
+
+int
+bar ()
+{
+ u = 0;
+ return m;
+}
+
+__attribute__((noinline, noclone)) void
+baz ()
+{
+ asm ("");
+}
+
+static int
+foo ()
+{
+ int t1;
+ g = bar ();
+ if (l)
+ ;
+ else
+ for (;; h++)
+ {
+ *i = 0;
+ o = *e = 0;
+ if (p)
+ {
+ f = 0;
+ return 0;
+ }
+ for (;; k++)
+ {
+ int *t2 = 0;
+ int *const *t3[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, &t2, 0, 0, &t2, &t2, &t2,
+ &t2, &t2, 0, 0, 0, 0, 0, 0, 0, &t2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, &t2, 0, 0, 0, 0, 0, 0, 0, &t2, &t2,
+ &t2, &t2, &t2, 0, 0, 0, 0, 0, 0, 0, &t2, 0, 0, 0,
+ &t2, 0, 0, 0, &t2, 0, &t2, 0, 0, &t2, 0, 0, 0, 0,
+ 0, &t2, 0, 0, 0, 0, &t2, &t2, 0, 0, 0, 0, &t2, 0,
+ 0, 0, 0, 0, 0, 0, &t2, 0, 0, 0, 0, 0, &t2, 0, 0, 0,
+ &t2, &t2
+ };
+ int *const **t4[] = {&t3[0]};
+ **i = 0;
+ if (**j)
+ break;
+ u = 0;
+ }
+ *i = *j;
+ t1 = 0;
+ for (; t1 < 5; t1++)
+ *i = *j;
+ }
+ *j = 0;
+ return 1;
+}
+
+int
+main ()
+{
+ int t5;
+ a[0] = 1;
+ {
+ int *t6[6] = {&d, &d};
+ for (n = 1; n; n--)
+ if (foo())
+ {
+ int *t7[] = {0};
+ d = 0;
+ for (; u < 1; u++)
+ *i = *j;
+ *i = 0;
+ *i = 0;
+ int t8[5] = {0};
+ *i = &t8[0];
+ int *const *t9 = &t6[0];
+ int *const **t10 = &t9;
+ *t10 = &t7[0];
+ }
+ }
+ u = 0;
+ for (; b; b++)
+ for (t5 = 0; t5 < 10; t5++)
+ c = a[a[a[a[a[a[a[a[c]]]]]]]];
+
+ baz ();
+
+ if (!a[a[a[a[a[a[a[a[a[a[a[a[a[a[a[u]]]]]]]]]]]]]]])
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58277-2.c b/gcc/testsuite/gcc.c-torture/execute/pr58277-2.c
new file mode 100644
index 00000000000..d919c2f3f80
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58277-2.c
@@ -0,0 +1,98 @@
+/* PR tree-optimization/58277 */
+
+extern void abort (void);
+static int a[1], b, c, e, i, j, k, m, q[] = { 1, 1 }, t;
+int volatile d;
+int **r;
+static int ***volatile s = &r;
+int f, g, o, x;
+static int *volatile h = &f, *p;
+char n;
+
+static void
+fn1 ()
+{
+ b = a[a[a[a[a[a[a[a[b]]]]]]]];
+ b = a[a[a[a[a[a[a[a[b]]]]]]]];
+ b = a[a[b]];
+ b = a[a[a[a[a[a[a[a[b]]]]]]]];
+ b = a[a[a[a[a[a[a[a[b]]]]]]]];
+}
+
+static int
+fn2 ()
+{
+ n = 0;
+ for (; g; t++)
+ {
+ for (;; m++)
+ {
+ d;
+ int *u;
+ int **v[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, &u, 0, 0, 0, 0, &u, &u, &u, &u, &u, &u, &u, 0,
+ &u, 0, &u, &u, &u, 0, &u, &u, 0, &u, &u, &u, &u, 0, &u, &u, &u,
+ &u, &u, 0, &u, &u, 0, &u, 0, &u, &u, 0, &u, &u, &u, &u, &u, 0,
+ &u, 0, 0, 0, &u, &u, &u, 0, 0, &u, &u, &u, 0, &u, 0, &u, &u
+ };
+ int ***w[] = { &v[0] };
+ if (*p)
+ break;
+ return 0;
+ }
+ *h = 0;
+ }
+ return 1;
+}
+
+static void
+fn3 ()
+{
+ int *y[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ for (; i; i++)
+ x = 0;
+ if (fn2 ())
+ {
+ int *z[6] = { };
+ for (; n < 1; n++)
+ *h = 0;
+ int t1[7];
+ for (; c; c++)
+ o = t1[0];
+ for (; e; e--)
+ {
+ int **t2 = &y[0];
+ int ***t3 = &t2;
+ *t3 = &z[0];
+ }
+ }
+ *s = 0;
+ for (n = 0;; n = 0)
+ {
+ int t4 = 0;
+ if (q[n])
+ break;
+ *r = &t4;
+ }
+}
+
+int
+main ()
+{
+ for (; j; j--)
+ a[0] = 0;
+ fn3 ();
+ for (; k; k++)
+ fn1 ();
+ fn1 ();
+
+ if (n)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58364.c b/gcc/testsuite/gcc.c-torture/execute/pr58364.c
new file mode 100644
index 00000000000..59ad7b47a16
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58364.c
@@ -0,0 +1,17 @@
+/* PR tree-optimization/58364 */
+
+int a = 1, b, c;
+
+int
+foo (int x)
+{
+ return x < 0 ? 1 : x;
+}
+
+int
+main ()
+{
+ if (foo (a > c == (b = 0)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58365.c b/gcc/testsuite/gcc.c-torture/execute/pr58365.c
new file mode 100644
index 00000000000..1e6079d8429
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58365.c
@@ -0,0 +1,35 @@
+/* PR rtl-optimization/58365 */
+
+extern void abort (void);
+
+struct S
+{
+ volatile int a;
+ int b, c, d, e;
+} f;
+static struct S g, h;
+int i = 1;
+
+char
+foo (void)
+{
+ return i;
+}
+
+static struct S
+bar (void)
+{
+ if (foo ())
+ return f;
+ return g;
+}
+
+int
+main ()
+{
+ h = bar ();
+ f.b = 1;
+ if (h.b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58385.c b/gcc/testsuite/gcc.c-torture/execute/pr58385.c
new file mode 100644
index 00000000000..8d7da6fc972
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58385.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/58385 */
+
+extern void abort (void);
+
+int a, b = 1;
+
+int
+foo ()
+{
+ b = 0;
+ return 0;
+}
+
+int
+main ()
+{
+ ((0 || a) & foo () >= 0) <= 1 && 1;
+ if (b)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58564.c b/gcc/testsuite/gcc.c-torture/execute/pr58564.c
new file mode 100644
index 00000000000..967ee95d4ab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58564.c
@@ -0,0 +1,14 @@
+/* PR middle-end/58564 */
+
+extern void abort (void);
+int a, b;
+short *c, **d = &c;
+
+int
+main ()
+{
+ b = (0, 0 > ((&c == d) & (1 && (a ^ 1)))) | 0U;
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58574.c b/gcc/testsuite/gcc.c-torture/execute/pr58574.c
new file mode 100644
index 00000000000..44827eb7819
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58574.c
@@ -0,0 +1,219 @@
+/* PR target/58574 */
+
+__attribute__((noinline, noclone)) double
+foo (double x)
+{
+ double t;
+ switch ((int) x)
+ {
+ case 0:
+ t = 2 * x - 1;
+ return 0.70878e-3 + (0.71234e-3 + (0.35779e-5 + (0.17403e-7 + (0.81710e-10 + (0.36885e-12 + 0.15917e-14 * t) * t) * t) * t) * t) * t;
+ case 1:
+ t = 2 * x - 3;
+ return 0.21479e-2 + (0.72686e-3 + (0.36843e-5 + (0.18071e-7 + (0.85496e-10 + (0.38852e-12 + 0.16868e-14 * t) * t) * t) * t) * t) * t;
+ case 2:
+ t = 2 * x - 5;
+ return 0.36165e-2 + (0.74182e-3 + (0.37948e-5 + (0.18771e-7 + (0.89484e-10 + (0.40935e-12 + 0.17872e-14 * t) * t) * t) * t) * t) * t;
+ case 3:
+ t = 2 * x - 7;
+ return 0.51154e-2 + (0.75722e-3 + (0.39096e-5 + (0.19504e-7 + (0.93687e-10 + (0.43143e-12 + 0.18939e-14 * t) * t) * t) * t) * t) * t;
+ case 4:
+ t = 2 * x - 9;
+ return 0.66457e-2 + (0.77310e-3 + (0.40289e-5 + (0.20271e-7 + (0.98117e-10 + (0.45484e-12 + 0.20076e-14 * t) * t) * t) * t) * t) * t;
+ case 5:
+ t = 2 * x - 11;
+ return 0.82082e-2 + (0.78946e-3 + (0.41529e-5 + (0.21074e-7 + (0.10278e-9 + (0.47965e-12 + 0.21285e-14 * t) * t) * t) * t) * t) * t;
+ case 6:
+ t = 2 * x - 13;
+ return 0.98039e-2 + (0.80633e-3 + (0.42819e-5 + (0.21916e-7 + (0.10771e-9 + (0.50595e-12 + 0.22573e-14 * t) * t) * t) * t) * t) * t;
+ case 7:
+ t = 2 * x - 15;
+ return 0.11433e-1 + (0.82372e-3 + (0.44160e-5 + (0.22798e-7 + (0.11291e-9 + (0.53386e-12 + 0.23944e-14 * t) * t) * t) * t) * t) * t;
+ case 8:
+ t = 2 * x - 17;
+ return 0.13099e-1 + (0.84167e-3 + (0.45555e-5 + (0.23723e-7 + (0.11839e-9 + (0.56346e-12 + 0.25403e-14 * t) * t) * t) * t) * t) * t;
+ case 9:
+ t = 2 * x - 19;
+ return 0.14800e-1 + (0.86018e-3 + (0.47008e-5 + (0.24694e-7 + (0.12418e-9 + (0.59486e-12 + 0.26957e-14 * t) * t) * t) * t) * t) * t;
+ case 10:
+ t = 2 * x - 21;
+ return 0.16540e-1 + (0.87928e-3 + (0.48520e-5 + (0.25711e-7 + (0.13030e-9 + (0.62820e-12 + 0.28612e-14 * t) * t) * t) * t) * t) * t;
+ case 11:
+ t = 2 * x - 23;
+ return 0.18318e-1 + (0.89900e-3 + (0.50094e-5 + (0.26779e-7 + (0.13675e-9 + (0.66358e-12 + 0.30375e-14 * t) * t) * t) * t) * t) * t;
+ case 12:
+ t = 2 * x - 25;
+ return 0.20136e-1 + (0.91936e-3 + (0.51734e-5 + (0.27900e-7 + (0.14357e-9 + (0.70114e-12 + 0.32252e-14 * t) * t) * t) * t) * t) * t;
+ case 13:
+ t = 2 * x - 27;
+ return 0.21996e-1 + (0.94040e-3 + (0.53443e-5 + (0.29078e-7 + (0.15078e-9 + (0.74103e-12 + 0.34251e-14 * t) * t) * t) * t) * t) * t;
+ case 14:
+ t = 2 * x - 29;
+ return 0.23898e-1 + (0.96213e-3 + (0.55225e-5 + (0.30314e-7 + (0.15840e-9 + (0.78340e-12 + 0.36381e-14 * t) * t) * t) * t) * t) * t;
+ case 15:
+ t = 2 * x - 31;
+ return 0.25845e-1 + (0.98459e-3 + (0.57082e-5 + (0.31613e-7 + (0.16646e-9 + (0.82840e-12 + 0.38649e-14 * t) * t) * t) * t) * t) * t;
+ case 16:
+ t = 2 * x - 33;
+ return 0.27837e-1 + (0.10078e-2 + (0.59020e-5 + (0.32979e-7 + (0.17498e-9 + (0.87622e-12 + 0.41066e-14 * t) * t) * t) * t) * t) * t;
+ case 17:
+ t = 2 * x - 35;
+ return 0.29877e-1 + (0.10318e-2 + (0.61041e-5 + (0.34414e-7 + (0.18399e-9 + (0.92703e-12 + 0.43639e-14 * t) * t) * t) * t) * t) * t;
+ case 18:
+ t = 2 * x - 37;
+ return 0.31965e-1 + (0.10566e-2 + (0.63151e-5 + (0.35924e-7 + (0.19353e-9 + (0.98102e-12 + 0.46381e-14 * t) * t) * t) * t) * t) * t;
+ case 19:
+ t = 2 * x - 39;
+ return 0.34104e-1 + (0.10823e-2 + (0.65354e-5 + (0.37512e-7 + (0.20362e-9 + (0.10384e-11 + 0.49300e-14 * t) * t) * t) * t) * t) * t;
+ case 20:
+ t = 2 * x - 41;
+ return 0.36295e-1 + (0.11089e-2 + (0.67654e-5 + (0.39184e-7 + (0.21431e-9 + (0.10994e-11 + 0.52409e-14 * t) * t) * t) * t) * t) * t;
+ case 21:
+ t = 2 * x - 43;
+ return 0.38540e-1 + (0.11364e-2 + (0.70058e-5 + (0.40943e-7 + (0.22563e-9 + (0.11642e-11 + 0.55721e-14 * t) * t) * t) * t) * t) * t;
+ case 22:
+ t = 2 * x - 45;
+ return 0.40842e-1 + (0.11650e-2 + (0.72569e-5 + (0.42796e-7 + (0.23761e-9 + (0.12332e-11 + 0.59246e-14 * t) * t) * t) * t) * t) * t;
+ case 23:
+ t = 2 * x - 47;
+ return 0.43201e-1 + (0.11945e-2 + (0.75195e-5 + (0.44747e-7 + (0.25030e-9 + (0.13065e-11 + 0.63000e-14 * t) * t) * t) * t) * t) * t;
+ case 24:
+ t = 2 * x - 49;
+ return 0.45621e-1 + (0.12251e-2 + (0.77941e-5 + (0.46803e-7 + (0.26375e-9 + (0.13845e-11 + 0.66996e-14 * t) * t) * t) * t) * t) * t;
+ case 25:
+ t = 2 * x - 51;
+ return 0.48103e-1 + (0.12569e-2 + (0.80814e-5 + (0.48969e-7 + (0.27801e-9 + (0.14674e-11 + 0.71249e-14 * t) * t) * t) * t) * t) * t;
+ case 26:
+ t = 2 * x - 59;
+ return 0.58702e-1 + (0.13962e-2 + (0.93714e-5 + (0.58882e-7 + (0.34414e-9 + (0.18552e-11 + 0.91160e-14 * t) * t) * t) * t) * t) * t;
+ case 30:
+ t = 2 * x - 79;
+ return 0.90908e-1 + (0.18544e-2 + (0.13903e-4 + (0.95549e-7 + (0.59752e-9 + (0.33656e-11 + 0.16815e-13 * t) * t) * t) * t) * t) * t;
+ case 40:
+ t = 2 * x - 99;
+ return 0.13443e0 + (0.25474e-2 + (0.21385e-4 + (0.15996e-6 + (0.10585e-8 + (0.61258e-11 + 0.30412e-13 * t) * t) * t) * t) * t) * t;
+ case 50:
+ t = 2 * x - 119;
+ return 0.19540e0 + (0.36342e-2 + (0.34096e-4 + (0.27479e-6 + (0.18934e-8 + (0.11021e-10 + 0.52931e-13 * t) * t) * t) * t) * t) * t;
+ case 60:
+ t = 2 * x - 121;
+ return 0.20281e0 + (0.37739e-2 + (0.35791e-4 + (0.29038e-6 + (0.20068e-8 + (0.11673e-10 + 0.55790e-13 * t) * t) * t) * t) * t) * t;
+ case 61:
+ t = 2 * x - 123;
+ return 0.21050e0 + (0.39206e-2 + (0.37582e-4 + (0.30691e-6 + (0.21270e-8 + (0.12361e-10 + 0.58770e-13 * t) * t) * t) * t) * t) * t;
+ case 62:
+ t = 2 * x - 125;
+ return 0.21849e0 + (0.40747e-2 + (0.39476e-4 + (0.32443e-6 + (0.22542e-8 + (0.13084e-10 + 0.61873e-13 * t) * t) * t) * t) * t) * t;
+ case 63:
+ t = 2 * x - 127;
+ return 0.22680e0 + (0.42366e-2 + (0.41477e-4 + (0.34300e-6 + (0.23888e-8 + (0.13846e-10 + 0.65100e-13 * t) * t) * t) * t) * t) * t;
+ case 64:
+ t = 2 * x - 129;
+ return 0.23545e0 + (0.44067e-2 + (0.43594e-4 + (0.36268e-6 + (0.25312e-8 + (0.14647e-10 + 0.68453e-13 * t) * t) * t) * t) * t) * t;
+ case 65:
+ t = 2 * x - 131;
+ return 0.24444e0 + (0.45855e-2 + (0.45832e-4 + (0.38352e-6 + (0.26819e-8 + (0.15489e-10 + 0.71933e-13 * t) * t) * t) * t) * t) * t;
+ case 66:
+ t = 2 * x - 133;
+ return 0.25379e0 + (0.47735e-2 + (0.48199e-4 + (0.40561e-6 + (0.28411e-8 + (0.16374e-10 + 0.75541e-13 * t) * t) * t) * t) * t) * t;
+ case 67:
+ t = 2 * x - 135;
+ return 0.26354e0 + (0.49713e-2 + (0.50702e-4 + (0.42901e-6 + (0.30095e-8 + (0.17303e-10 + 0.79278e-13 * t) * t) * t) * t) * t) * t;
+ case 68:
+ t = 2 * x - 137;
+ return 0.27369e0 + (0.51793e-2 + (0.53350e-4 + (0.45379e-6 + (0.31874e-8 + (0.18277e-10 + 0.83144e-13 * t) * t) * t) * t) * t) * t;
+ case 69:
+ t = 2 * x - 139;
+ return 0.28426e0 + (0.53983e-2 + (0.56150e-4 + (0.48003e-6 + (0.33752e-8 + (0.19299e-10 + 0.87139e-13 * t) * t) * t) * t) * t) * t;
+ case 70:
+ t = 2 * x - 141;
+ return 0.29529e0 + (0.56288e-2 + (0.59113e-4 + (0.50782e-6 + (0.35735e-8 + (0.20369e-10 + 0.91262e-13 * t) * t) * t) * t) * t) * t;
+ case 71:
+ t = 2 * x - 143;
+ return 0.30679e0 + (0.58714e-2 + (0.62248e-4 + (0.53724e-6 + (0.37827e-8 + (0.21490e-10 + 0.95513e-13 * t) * t) * t) * t) * t) * t;
+ case 72:
+ t = 2 * x - 145;
+ return 0.31878e0 + (0.61270e-2 + (0.65564e-4 + (0.56837e-6 + (0.40035e-8 + (0.22662e-10 + 0.99891e-13 * t) * t) * t) * t) * t) * t;
+ case 73:
+ t = 2 * x - 147;
+ return 0.33130e0 + (0.63962e-2 + (0.69072e-4 + (0.60133e-6 + (0.42362e-8 + (0.23888e-10 + 0.10439e-12 * t) * t) * t) * t) * t) * t;
+ case 74:
+ t = 2 * x - 149;
+ return 0.34438e0 + (0.66798e-2 + (0.72783e-4 + (0.63619e-6 + (0.44814e-8 + (0.25168e-10 + 0.10901e-12 * t) * t) * t) * t) * t) * t;
+ case 75:
+ t = 2 * x - 151;
+ return 0.35803e0 + (0.69787e-2 + (0.76710e-4 + (0.67306e-6 + (0.47397e-8 + (0.26505e-10 + 0.11376e-12 * t) * t) * t) * t) * t) * t;
+ case 76:
+ t = 2 * x - 153;
+ return 0.37230e0 + (0.72938e-2 + (0.80864e-4 + (0.71206e-6 + (0.50117e-8 + (0.27899e-10 + 0.11862e-12 * t) * t) * t) * t) * t) * t;
+ case 77:
+ t = 2 * x - 155;
+ return 0.38722e0 + (0.76260e-2 + (0.85259e-4 + (0.75329e-6 + (0.52979e-8 + (0.29352e-10 + 0.12360e-12 * t) * t) * t) * t) * t) * t;
+ case 78:
+ t = 2 * x - 157;
+ return 0.40282e0 + (0.79762e-2 + (0.89909e-4 + (0.79687e-6 + (0.55989e-8 + (0.30866e-10 + 0.12868e-12 * t) * t) * t) * t) * t) * t;
+ case 79:
+ t = 2 * x - 159;
+ return 0.41914e0 + (0.83456e-2 + (0.94827e-4 + (0.84291e-6 + (0.59154e-8 + (0.32441e-10 + 0.13387e-12 * t) * t) * t) * t) * t) * t;
+ case 80:
+ t = 2 * x - 161;
+ return 0.43621e0 + (0.87352e-2 + (0.10002e-3 + (0.89156e-6 + (0.62480e-8 + (0.34079e-10 + 0.13917e-12 * t) * t) * t) * t) * t) * t;
+ case 81:
+ t = 2 * x - 163;
+ return 0.45409e0 + (0.91463e-2 + (0.10553e-3 + (0.94293e-6 + (0.65972e-8 + (0.35782e-10 + 0.14455e-12 * t) * t) * t) * t) * t) * t;
+ case 82:
+ t = 2 * x - 165;
+ return 0.47282e0 + (0.95799e-2 + (0.11135e-3 + (0.99716e-6 + (0.69638e-8 + (0.37549e-10 + 0.15003e-12 * t) * t) * t) * t) * t) * t;
+ case 83:
+ t = 2 * x - 167;
+ return 0.49243e0 + (0.10037e-1 + (0.11750e-3 + (0.10544e-5 + (0.73484e-8 + (0.39383e-10 + 0.15559e-12 * t) * t) * t) * t) * t) * t;
+ case 84:
+ t = 2 * x - 169;
+ return 0.51298e0 + (0.10520e-1 + (0.12400e-3 + (0.11147e-5 + (0.77517e-8 + (0.41283e-10 + 0.16122e-12 * t) * t) * t) * t) * t) * t;
+ case 85:
+ t = 2 * x - 171;
+ return 0.53453e0 + (0.11030e-1 + (0.13088e-3 + (0.11784e-5 + (0.81743e-8 + (0.43252e-10 + 0.16692e-12 * t) * t) * t) * t) * t) * t;
+ case 86:
+ t = 2 * x - 173;
+ return 0.55712e0 + (0.11568e-1 + (0.13815e-3 + (0.12456e-5 + (0.86169e-8 + (0.45290e-10 + 0.17268e-12 * t) * t) * t) * t) * t) * t;
+ case 87:
+ t = 2 * x - 175;
+ return 0.58082e0 + (0.12135e-1 + (0.14584e-3 + (0.13164e-5 + (0.90803e-8 + (0.47397e-10 + 0.17850e-12 * t) * t) * t) * t) * t) * t;
+ case 88:
+ t = 2 * x - 177;
+ return 0.60569e0 + (0.12735e-1 + (0.15396e-3 + (0.13909e-5 + (0.95651e-8 + (0.49574e-10 + 0.18435e-12 * t) * t) * t) * t) * t) * t;
+ case 89:
+ t = 2 * x - 179;
+ return 0.63178e0 + (0.13368e-1 + (0.16254e-3 + (0.14695e-5 + (0.10072e-7 + (0.51822e-10 + 0.19025e-12 * t) * t) * t) * t) * t) * t;
+ case 90:
+ t = 2 * x - 181;
+ return 0.65918e0 + (0.14036e-1 + (0.17160e-3 + (0.15521e-5 + (0.10601e-7 + (0.54140e-10 + 0.19616e-12 * t) * t) * t) * t) * t) * t;
+ case 91:
+ t = 2 * x - 183;
+ return 0.68795e0 + (0.14741e-1 + (0.18117e-3 + (0.16392e-5 + (0.11155e-7 + (0.56530e-10 + 0.20209e-12 * t) * t) * t) * t) * t) * t;
+ case 92:
+ t = 2 * x - 185;
+ return 0.71818e0 + (0.15486e-1 + (0.19128e-3 + (0.17307e-5 + (0.11732e-7 + (0.58991e-10 + 0.20803e-12 * t) * t) * t) * t) * t) * t;
+ case 93:
+ t = 2 * x - 187;
+ return 0.74993e0 + (0.16272e-1 + (0.20195e-3 + (0.18269e-5 + (0.12335e-7 + (0.61523e-10 + 0.21395e-12 * t) * t) * t) * t) * t) * t;
+ }
+ return 1.0;
+}
+
+int
+main ()
+{
+#ifdef __s390x__
+ {
+ register unsigned long r5 __asm ("r5");
+ r5 = 0xdeadbeefUL;
+ asm volatile ("":"+r" (r5));
+ }
+#endif
+ double d = foo (78.4);
+ if (d < 0.38 || d > 0.42)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58726.c b/gcc/testsuite/gcc.c-torture/execute/pr58726.c
new file mode 100644
index 00000000000..9fa8b6953f1
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58726.c
@@ -0,0 +1,26 @@
+/* PR rtl-optimization/58726 */
+
+int a, c;
+union { int f1; int f2 : 1; } b;
+
+short
+foo (short p)
+{
+ return p < 0 ? p : a;
+}
+
+int
+main ()
+{
+ if (sizeof (short) * __CHAR_BIT__ != 16
+ || sizeof (int) * __CHAR_BIT__ != 32)
+ return 0;
+ b.f1 = 56374;
+ unsigned short d;
+ int e = b.f2;
+ d = e == 0 ? b.f1 : 0;
+ c = foo (d);
+ if (c != (short) 56374)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58831.c b/gcc/testsuite/gcc.c-torture/execute/pr58831.c
new file mode 100644
index 00000000000..a40cd54d222
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58831.c
@@ -0,0 +1,40 @@
+#include <assert.h>
+
+int a, *b, c, d, f, **i, p, q, *r;
+short o, j;
+
+static int __attribute__((noinline, noclone))
+fn1 (int *p1, int **p2)
+{
+ int **e = &b;
+ for (; p; p++)
+ *p1 = 1;
+ *e = *p2 = &d;
+
+ assert (r);
+
+ return c;
+}
+
+static int ** __attribute__((noinline, noclone))
+fn2 (void)
+{
+ for (f = 0; f != 42; f++)
+ {
+ int *g[3] = {0, 0, 0};
+ for (o = 0; o; o--)
+ for (; a > 1;)
+ {
+ int **h[1] = { &g[2] };
+ }
+ }
+ return &r;
+}
+
+int
+main (void)
+{
+ i = fn2 ();
+ fn1 (b, i);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58984.c b/gcc/testsuite/gcc.c-torture/execute/pr58984.c
new file mode 100644
index 00000000000..e0f7669c78d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58984.c
@@ -0,0 +1,57 @@
+/* PR tree-optimization/58984 */
+
+struct S { int f0 : 8; int : 6; int f1 : 5; };
+struct T { char f0; int : 6; int f1 : 5; };
+
+int a, *c = &a, e, n, b, m;
+
+static int
+foo (struct S p)
+{
+ const unsigned short *f[36];
+ for (; e < 2; e++)
+ {
+ const unsigned short **i = &f[0];
+ *c ^= 1;
+ if (p.f1)
+ {
+ *i = 0;
+ return b;
+ }
+ }
+ return 0;
+}
+
+static int
+bar (struct T p)
+{
+ const unsigned short *f[36];
+ for (; e < 2; e++)
+ {
+ const unsigned short **i = &f[0];
+ *c ^= 1;
+ if (p.f1)
+ {
+ *i = 0;
+ return b;
+ }
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ struct S o = { 1, 1 };
+ foo (o);
+ m = n || o.f0;
+ if (a != 1)
+ __builtin_abort ();
+ e = 0;
+ struct T p = { 1, 1 };
+ bar (p);
+ m |= n || p.f0;
+ if (a != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c b/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c
new file mode 100644
index 00000000000..18da0059eab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/59014 */
+
+__attribute__((noinline, noclone)) long long int
+foo (long long int x, long long int y)
+{
+ if (((int) x | (int) y) != 0)
+ return 6;
+ return x + y;
+}
+
+int
+main ()
+{
+ if (sizeof (long long) == sizeof (int))
+ return 0;
+ int shift_half = sizeof (int) * __CHAR_BIT__ / 2;
+ long long int x = (3LL << shift_half) << shift_half;
+ long long int y = (5LL << shift_half) << shift_half;
+ long long int z = foo (x, y);
+ if (z != ((8LL << shift_half) << shift_half))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59014.c b/gcc/testsuite/gcc.c-torture/execute/pr59014.c
new file mode 100644
index 00000000000..10bf81a462f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59014.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/59014 */
+
+int a = 2, b, c, d;
+
+int
+foo ()
+{
+ for (;; c++)
+ if ((b > 0) | (a & 1))
+ ;
+ else
+ {
+ d = a;
+ return 0;
+ }
+}
+
+int
+main ()
+{
+ foo ();
+ if (d != 2)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59101.c b/gcc/testsuite/gcc.c-torture/execute/pr59101.c
new file mode 100644
index 00000000000..ed6a7e8fa31
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59101.c
@@ -0,0 +1,15 @@
+/* PR target/59101 */
+
+__attribute__((noinline, noclone)) int
+foo (int a)
+{
+ return (~a & 4102790424LL) > 0 | 6;
+}
+
+int
+main ()
+{
+ if (foo (0) != 7)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59358.c b/gcc/testsuite/gcc.c-torture/execute/pr59358.c
new file mode 100644
index 00000000000..674026d6258
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59358.c
@@ -0,0 +1,44 @@
+/* PR tree-optimization/59358 */
+
+__attribute__((noinline, noclone)) int
+foo (int *x, int y)
+{
+ int z = *x;
+ if (y > z && y <= 16)
+ while (y > z)
+ z *= 2;
+ return z;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 1; i < 17; i++)
+ {
+ int j = foo (&i, 16);
+ int k;
+ if (i >= 8 && i <= 15)
+ k = 16 + (i - 8) * 2;
+ else if (i >= 4 && i <= 7)
+ k = 16 + (i - 4) * 4;
+ else if (i == 3)
+ k = 24;
+ else
+ k = 16;
+ if (j != k)
+ __builtin_abort ();
+ j = foo (&i, 7);
+ if (i >= 7)
+ k = i;
+ else if (i >= 4)
+ k = 8 + (i - 4) * 2;
+ else if (i == 3)
+ k = 12;
+ else
+ k = 8;
+ if (j != k)
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59388.c b/gcc/testsuite/gcc.c-torture/execute/pr59388.c
new file mode 100644
index 00000000000..de3648a003e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr59388.c
@@ -0,0 +1,11 @@
+/* PR tree-optimization/59388 */
+
+int a;
+struct S { unsigned int f:1; } b;
+
+int
+main ()
+{
+ a = (0 < b.f) | b.f;
+ return a;
+}
diff --git a/gcc/testsuite/gcc.dg/20050922-1.c b/gcc/testsuite/gcc.dg/20050922-1.c
index ed5a3c63e9d..982f82011ba 100644
--- a/gcc/testsuite/gcc.dg/20050922-1.c
+++ b/gcc/testsuite/gcc.dg/20050922-1.c
@@ -4,7 +4,7 @@
/* { dg-do run } */
/* { dg-options "-O1 -std=c99" } */
-#include <stdlib.h>
+extern void abort (void);
#if __INT_MAX__ == 2147483647
typedef unsigned int uint32_t;
diff --git a/gcc/testsuite/gcc.dg/20050922-2.c b/gcc/testsuite/gcc.dg/20050922-2.c
index c2974d03d9c..2e8db829e29 100644
--- a/gcc/testsuite/gcc.dg/20050922-2.c
+++ b/gcc/testsuite/gcc.dg/20050922-2.c
@@ -4,7 +4,8 @@
/* { dg-do run } */
/* { dg-options "-O1 -std=c99" } */
-#include <stdlib.h>
+extern void abort (void);
+extern void exit (int);
#if __INT_MAX__ == 2147483647
typedef unsigned int uint32_t;
diff --git a/gcc/testsuite/gcc.dg/asan/pr56417.c b/gcc/testsuite/gcc.dg/asan/pr56417.c
new file mode 100644
index 00000000000..b7eabf125aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr56417.c
@@ -0,0 +1,9 @@
+/* PR sanitizer/56417 */
+/* { dg-do compile } */
+/* { dg-options "-w" } */
+
+int
+foo (void)
+{
+ return __builtin_strlen (&foo);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic-store-6.c b/gcc/testsuite/gcc.dg/atomic-store-6.c
new file mode 100644
index 00000000000..81499cd716b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-store-6.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
+
+__int128_t i;
+
+int main()
+{
+ __atomic_store_16(&i, -1, 0);
+ if (i != -1)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-14.c b/gcc/testsuite/gcc.dg/builtin-object-size-14.c
new file mode 100644
index 00000000000..085011eda52
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-14.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+extern char *strncpy(char *, const char *, __SIZE_TYPE__);
+
+union u {
+ struct {
+ char vi[8];
+ char pi[16];
+ };
+ char all[8+16+4];
+};
+
+void __attribute__((noinline,noclone))
+f(union u *u)
+{
+ char vi[8+1];
+ __builtin_strncpy(vi, u->vi, sizeof(u->vi));
+ if (__builtin_object_size (u->all, 1) != -1)
+ abort ();
+}
+int main()
+{
+ union u u;
+ f (&u);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-8.c b/gcc/testsuite/gcc.dg/builtin-object-size-8.c
index 7af64d3ab7a..f2d88f9d591 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-8.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-8.c
@@ -1,4 +1,4 @@
-/* { dg-do run { xfail *-*-* } } */
+/* { dg-do run } */
/* { dg-options "-O2" } */
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/ipa/pr59610.c b/gcc/testsuite/gcc.dg/ipa/pr59610.c
new file mode 100644
index 00000000000..fc0933441e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr59610.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct A { int a; };
+extern void *y;
+
+__attribute__((optimize (0))) void
+foo (void *p, struct A x)
+{
+ foo (y, x);
+}
diff --git a/gcc/testsuite/gcc.dg/pr46309.c b/gcc/testsuite/gcc.dg/pr46309.c
index ee154ccd2f3..9275015049e 100644
--- a/gcc/testsuite/gcc.dg/pr46309.c
+++ b/gcc/testsuite/gcc.dg/pr46309.c
@@ -1,5 +1,5 @@
/* PR tree-optimization/46309 */
-/* { dg-do compile } */
+/* { dg-do compile { target { ! { cris*-*-* } } } } */
/* { dg-options "-O2 -fdump-tree-reassoc-details" } */
/* The transformation depends on BRANCH_COST being greater than 1
(see the notes in the PR), so try to force that. */
diff --git a/gcc/testsuite/gcc.dg/pr56977.c b/gcc/testsuite/gcc.dg/pr56977.c
new file mode 100644
index 00000000000..fde88afed1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56977.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Og" } */
+
+__attribute__((__error__("error"))) void error ();
+
+void f (int i) {
+ if (__builtin_constant_p (i)) {
+ error ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr57518.c b/gcc/testsuite/gcc.dg/pr57518.c
index 4c84a856b5d..8eb714d8c55 100644
--- a/gcc/testsuite/gcc.dg/pr57518.c
+++ b/gcc/testsuite/gcc.dg/pr57518.c
@@ -1,8 +1,8 @@
-/* PR rtl-optimization/57130 */
+/* PR rtl-optimization/57518 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-rtl-ira" } */
-/* { dg-final { scan-rtl-dump-not "REG_EQUIV.*mem.*\"ip\"" "ira" } } */
+/* { dg-final { scan-rtl-dump-not "REG_EQUIV\[^\n\]*mem\[^\n\]*\"ip\".*subreg" "ira" } } */
char ip[10];
int total;
diff --git a/gcc/testsuite/gcc.dg/pr57980.c b/gcc/testsuite/gcc.dg/pr57980.c
new file mode 100644
index 00000000000..be83536c5f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr57980.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/57980 */
+/* { dg-do compile } */
+/* { dg-options "-O -foptimize-sibling-calls -w" } */
+
+typedef int V __attribute__ ((vector_size (2 * sizeof (int))));
+extern V f (void);
+
+V
+bar (void)
+{
+ return -f ();
+}
+
+V
+foo (void)
+{
+ V v = { };
+ return v - f ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr58010.c b/gcc/testsuite/gcc.dg/pr58010.c
new file mode 100644
index 00000000000..a0fbd31f495
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58010.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -funswitch-loops -ftree-vectorize" } */
+
+short a, b, c, d;
+
+void f(void)
+{
+ short e;
+
+ for(; e; e++)
+ for(; b; b++);
+
+ for(d = 0; d < 4; d++)
+ a ^= (e ^= 1) || c ? : e;
+}
diff --git a/gcc/testsuite/gcc.dg/pr58145-1.c b/gcc/testsuite/gcc.dg/pr58145-1.c
new file mode 100644
index 00000000000..0e236c0456d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58145-1.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/58145 */
+/* { dg-do compile { target { int32plus } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct S { unsigned int data : 32; };
+struct T { unsigned int data; };
+volatile struct S s2;
+
+void
+f1 (int val)
+{
+ struct S s = { .data = val };
+ *(volatile struct S *) 0x880000UL = s;
+}
+
+void
+f2 (int val)
+{
+ struct T t = { .data = val };
+ *(volatile struct T *) 0x880000UL = t;
+}
+
+void
+f3 (int val)
+{
+ *(volatile unsigned int *) 0x880000UL = val;
+}
+
+void
+f4 (int val)
+{
+ struct S s = { .data = val };
+ s2 = s;
+}
+
+/* { dg-final { scan-tree-dump-times " ={v} " 4 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58145-2.c b/gcc/testsuite/gcc.dg/pr58145-2.c
new file mode 100644
index 00000000000..840e9828972
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58145-2.c
@@ -0,0 +1,51 @@
+/* PR tree-optimization/58145 */
+/* { dg-do compile { target { int32plus } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct S { unsigned int data : 32; };
+struct T { unsigned int data; };
+volatile struct S s2;
+
+static inline void
+f1 (int val)
+{
+ struct S s = { .data = val };
+ *(volatile struct S *) 0x880000UL = s;
+}
+
+static inline void
+f2 (int val)
+{
+ struct T t = { .data = val };
+ *(volatile struct T *) 0x880000UL = t;
+}
+
+static inline void
+f3 (int val)
+{
+ *(volatile unsigned int *) 0x880000UL = val;
+}
+
+static inline void
+f4 (int val)
+{
+ struct S s = { .data = val };
+ s2 = s;
+}
+
+void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ f1 (0);
+ for (i = 0; i < 100; i++)
+ f2 (0);
+ for (i = 0; i < 100; i++)
+ f3 (0);
+ for (i = 0; i < 100; i++)
+ f4 (0);
+}
+
+/* { dg-final { scan-tree-dump-times " ={v} " 4 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58463.c b/gcc/testsuite/gcc.dg/pr58463.c
new file mode 100644
index 00000000000..e2b44119347
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58463.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-ealias-details -O2" } */
+
+typedef struct
+{
+ int data16;
+}
+list_data;
+void
+fn1 (list_data * p1)
+{
+ p1->data16 = p1->data16 & 1 & p1->data16 >> 1;
+}
+
+/* { dg-final { cleanup-tree-dump "ealias" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58668.c b/gcc/testsuite/gcc.dg/pr58668.c
new file mode 100644
index 00000000000..3e09508dc16
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58668.c
@@ -0,0 +1,25 @@
+/* PR rtl-optimization/58668 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-mthumb" { target { { arm*-*-* } && arm_thumb2_ok } } } */
+
+void *fn1 (void *);
+void *fn2 (void *, const char *);
+void fn3 (void *);
+void fn4 (void *, int);
+
+void *
+test (void *x)
+{
+ void *a, *b;
+ if (!(a = fn1 (x)))
+ return (void *) 0;
+ if (!(b = fn2 (a, "w")))
+ {
+ fn3 (a);
+ return (void *) 0;
+ }
+ fn3 (a);
+ fn4 (b, 1);
+ return b;
+}
diff --git a/gcc/testsuite/gcc.dg/pr58805.c b/gcc/testsuite/gcc.dg/pr58805.c
new file mode 100644
index 00000000000..dda0e4bdf4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58805.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */
+
+/* Type that matches the 'p' constraint. */
+#define TYPE void *
+
+static inline
+void bar (TYPE *r)
+{
+ TYPE t;
+ __asm__ ("" : "=&p" (t), "=p" (*r));
+}
+
+void
+foo (int n, TYPE *x, TYPE *y)
+{
+ if (n == 0)
+ bar (x);
+ else
+ bar (y);
+}
+
+/* { dg-final { scan-tree-dump-times "__asm__" 2 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr59011.c b/gcc/testsuite/gcc.dg/pr59011.c
new file mode 100644
index 00000000000..2fb8187ad55
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59011.c
@@ -0,0 +1,22 @@
+/* PR middle-end/59011 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+void
+foo (int m)
+{
+ int a[m];
+ void
+ bar (void)
+ {
+ {
+ int
+ baz (void)
+ {
+ return a[0];
+ }
+ }
+ a[0] = 42;
+ }
+ bar ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr59351.c b/gcc/testsuite/gcc.dg/pr59351.c
new file mode 100644
index 00000000000..384058f4041
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59351.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wpedantic" } */
+
+unsigned int
+foo (void)
+{
+ return sizeof ((int[]) {}); /* { dg-warning "ISO C forbids empty initializer braces" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr59827.c b/gcc/testsuite/gcc.dg/pr59827.c
new file mode 100644
index 00000000000..77e1e9ca206
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr59827.c
@@ -0,0 +1,15 @@
+/* PR middle-end/59827 */
+/* { dg-do compile } */
+
+int
+foo (int p[2][]) /* { dg-error "array type has incomplete element type" } */
+{
+ return p[0][0];
+}
+
+void
+bar (void)
+{
+ int p[2][1];
+ foo (p); /* { dg-error "type of formal parameter 1 is incomplete" } */
+}
diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
index b6524f9a125..3e44dabf953 100644
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -38,7 +38,11 @@
# endif
#elif defined (__powerpc64__) || defined (__ppc64__) || defined (__POWERPC64__) \
|| defined (__PPC64__)
-# define SIZE 180
+# if _CALL_ELF == 2
+# define SIZE 208
+# else
+# define SIZE 180
+# endif
#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
# if defined (__ALTIVEC__)
diff --git a/gcc/testsuite/gcc.dg/strlenopt-14gf.c b/gcc/testsuite/gcc.dg/strlenopt-14gf.c
index 999759e86f6..bc7fc1f5c9c 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-14gf.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-14gf.c
@@ -11,14 +11,14 @@
memcpy. */
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 2 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 3 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-1f.c b/gcc/testsuite/gcc.dg/strlenopt-1f.c
index 4b0207fd4f7..f5d85710ed6 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-1f.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-1f.c
@@ -6,13 +6,13 @@
#include "strlenopt-1.c"
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 3 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-4gf.c b/gcc/testsuite/gcc.dg/strlenopt-4gf.c
index cf99212a152..f6088d60c89 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-4gf.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-4gf.c
@@ -7,13 +7,13 @@
#include "strlenopt-4.c"
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 4 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 5 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr57343.c b/gcc/testsuite/gcc.dg/torture/pr57343.c
new file mode 100644
index 00000000000..b05bad5cb43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57343.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+int c = 0;
+
+int
+main ()
+{
+ int i, f = 1;
+ for (i = 0; i < 5; i++)
+ {
+ --c;
+ unsigned char h = c * 100;
+ if (h == 0)
+ {
+ f = 0;
+ break;
+ }
+ }
+ if (f != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57381.c b/gcc/testsuite/gcc.dg/torture/pr57381.c
new file mode 100644
index 00000000000..ff6550a6d5f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57381.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target int32plus } */
+
+struct S0 { int f0, f1, f2; };
+
+struct S1 {
+ int f0;
+ volatile struct S0 f2;
+};
+
+static struct S1 s = {0x47BED265,{0x06D4EB3E,5,0U}};
+
+int foo(struct S0 p)
+{
+ for (s.f2.f2 = 0; (s.f2.f2 <= 12); s.f2.f2++)
+ {
+ volatile int *l_61[5][2][2] = {{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,(void*)0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{(void*)0,&s.f2.f0}}};
+
+ volatile int **l_68 = &l_61[0][0][1];
+ volatile int *l_76 = &s.f2.f0;
+ (*l_68) = l_61[0][0][0];
+ if ((*l_76 = (p.f2 % 5))) ;
+ }
+ return p.f0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57417.c b/gcc/testsuite/gcc.dg/torture/pr57417.c
new file mode 100644
index 00000000000..6eac6f932b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57417.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int a, b;
+volatile int *c;
+
+void foo ()
+{
+ volatile int d[1];
+ b = 0;
+ for (;; a--)
+ c = &d[b];
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57488.c b/gcc/testsuite/gcc.dg/torture/pr57488.c
new file mode 100644
index 00000000000..7eda36476e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57488.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int i, j, *pj = &j, **ppj = &pj;
+int x, *px = &x;
+
+short s, *ps = &s, k;
+
+unsigned short u, *pu = &u, **ppu = &pu;
+
+char c, *pc = &c;
+
+unsigned char v = 48;
+
+static int
+bar (int p)
+{
+ p = k;
+ *px = **ppu = i;
+ *ppj = &p;
+ if (**ppj)
+ *pj = p;
+ return p;
+}
+
+void __attribute__((noinline))
+foo ()
+{
+ for (; i <= 3; i++)
+ for (; j; j--);
+
+ u ^= bar (*pj);
+
+ for (k = 1; k >= 0; k--)
+ {
+ int l;
+ bar (0);
+ for (l = 1; l < 5; l++)
+ {
+ int m;
+ for (m = 6; m; m--)
+ {
+ v--;
+ *ps = *pc;
+ }
+ }
+ }
+}
+
+int
+main ()
+{
+ foo ();
+ if (v != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57517.c b/gcc/testsuite/gcc.dg/torture/pr57517.c
new file mode 100644
index 00000000000..2422d8ee64a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57517.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+int x[1024], y[1024], z[1024], w[1024];
+void foo (void)
+{
+ int i;
+ for (i = 1; i < 1024; ++i)
+ {
+ int a = x[i];
+ int b = y[i];
+ int c = x[i-1];
+ int d = y[i-1];
+ if (w[i])
+ z[i] = (a + b) + (c + d);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57521.c b/gcc/testsuite/gcc.dg/torture/pr57521.c
new file mode 100644
index 00000000000..e7832cb00e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57521.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-ftree-loop-if-convert" } */
+
+void abort (void);
+
+int a, b, c, d, o = 1, p;
+short e;
+
+int
+fn1 (int * p1)
+{
+ int f, g, h, j = 0, k = 0, l = 0;
+ unsigned int i;
+ int *m[1] = { &l };
+ for (; b >= 0; b--)
+ {
+ if (*p1)
+ if (j >= 0)
+ {
+ int n = 1;
+ e = 1;
+ h = a ? a : 1 % n;
+ g = h > 0 ? 0 : h + 1;
+ k = c + g;
+ }
+ else
+ continue;
+ else
+ {
+
+ f = d > 0 ? 0 : d + 1;
+ i = f;
+ j = 1 + i;
+ }
+ l++;
+ }
+ return k;
+}
+
+int
+main ()
+{
+ for (;; p++)
+ {
+ fn1 (&o);
+ break;
+ }
+ if (e != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57656.c b/gcc/testsuite/gcc.dg/torture/pr57656.c
new file mode 100644
index 00000000000..4f3645e4693
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57656.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fstrict-overflow" } */
+
+int main (void)
+{
+ int a = -1;
+ int b = __INT_MAX__;
+ int c = 2;
+ int t = 1 - ((a - b) / c); // t = 1 - ( __INT_MIN__ / 2 )
+ if (t != (1 - (-1 - __INT_MAX__) / 2))
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57685.c b/gcc/testsuite/gcc.dg/torture/pr57685.c
new file mode 100644
index 00000000000..75973f2a493
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57685.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+unsigned f(void)
+{
+ unsigned a;
+ int b, c, d, e;
+
+ for(c = 27; c < 40; c++)
+ b |= d |= b;
+
+ if(b)
+ a = e;
+
+ return a;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58041.c b/gcc/testsuite/gcc.dg/torture/pr58041.c
new file mode 100644
index 00000000000..169a71ae7e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58041.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+
+typedef long long V
+ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+struct s
+{
+ char u;
+ V v[2];
+} __attribute__((packed,aligned(1)));
+
+__attribute__((noinline, noclone))
+long long foo(struct s *x, int y, V *z)
+{
+ V a = x->v[y];
+ x->v[y] = *z;
+ return a[1];
+}
+
+struct s a = {0,{{0,0},{0,0}}};
+int main()
+{
+ V v1 = {0,1};
+ V v2 = {0,2};
+
+ if (foo(&a,0,&v1) != 0)
+ __builtin_abort();
+ if (foo(&a,0,&v2) != 1)
+ __builtin_abort();
+ if (foo(&a,1,&v1) != 0)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58079.c b/gcc/testsuite/gcc.dg/torture/pr58079.c
new file mode 100644
index 00000000000..99a30181f1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58079.c
@@ -0,0 +1,107 @@
+/* { dg-options "-mlong-calls" { target mips*-*-* } } */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int __kernel_size_t;
+typedef __kernel_size_t size_t;
+struct list_head {
+ struct list_head *next;
+};
+
+struct dmx_ts_feed {
+ int is_filtering;
+};
+struct dmx_section_feed {
+ u16 secbufp;
+ u16 seclen;
+ u16 tsfeedp;
+};
+
+typedef int (*dmx_ts_cb) (
+ const u8 * buffer1,
+ size_t buffer1_length,
+ const u8 * buffer2,
+ size_t buffer2_length
+);
+
+struct dvb_demux_feed {
+ union {
+ struct dmx_ts_feed ts;
+ struct dmx_section_feed sec;
+ } feed;
+ union {
+ dmx_ts_cb ts;
+ } cb;
+ int type;
+ u16 pid;
+ int ts_type;
+ struct list_head list_head;
+};
+
+struct dvb_demux {
+ int (*stop_feed)(struct dvb_demux_feed *feed);
+ struct list_head feed_list;
+};
+
+
+static
+inline
+__attribute__((always_inline))
+u8
+payload(const u8 *tsp)
+{
+ if (tsp[3] & 0x20) {
+ return 184 - 1 - tsp[4];
+ }
+ return 184;
+}
+
+static
+inline
+__attribute__((always_inline))
+int
+dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, const u8 *buf)
+{
+ int count = payload(buf);
+ int p;
+ if (count == 0)
+ return -1;
+ return feed->cb.ts(&buf[p], count, ((void *)0), 0);
+}
+
+static
+inline
+__attribute__((always_inline))
+void
+dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf)
+{
+ switch (feed->type) {
+ case 0:
+ if (feed->ts_type & 1) {
+ dvb_dmx_swfilter_payload(feed, buf);
+ }
+ if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
+ feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
+ }
+}
+
+static
+void
+dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
+{
+ struct dvb_demux_feed *feed;
+ int dvr_done = 0;
+
+ for (feed = ({ const typeof( ((typeof(*feed) *)0)->list_head ) *__mptr = ((&demux->feed_list)->next); (typeof(*feed) *)( (char *)__mptr - __builtin_offsetof(typeof(*feed),list_head) );}); __builtin_prefetch(feed->list_head.next), &feed->list_head != (&demux->feed_list); feed = ({ const typeof( ((typeof(*feed) *)0)->list_head ) *__mptr = (feed->list_head.next); (typeof(*feed) *)( (char *)__mptr - __builtin_offsetof(typeof(*feed),list_head) );})) {
+ if (((((feed)->type == 0) && ((feed)->feed.ts.is_filtering) && (((feed)->ts_type & (1 | 8)) == 1))) && (dvr_done++))
+ dvb_dmx_swfilter_packet_type(feed, buf);
+ else if (feed->pid == 0x2000)
+ feed->cb.ts(buf, 188, ((void *)0), 0);
+ }
+}
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+ while (count--) {
+ dvb_dmx_swfilter_packet(demux, buf);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-1.c b/gcc/testsuite/gcc.dg/torture/pr58143-1.c
new file mode 100644
index 00000000000..855515edb97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+extern void abort (void);
+
+int a, b, c, d, e, f, g, h = 1, i;
+
+int foo (int p)
+{
+ return p < 0 && a < - __INT_MAX__ - 1 - p ? 0 : 1;
+}
+
+int *bar ()
+{
+ int j;
+ i = h ? 0 : 1 % h;
+ for (j = 0; j < 1; j++)
+ for (d = 0; d; d++)
+ for (e = 1; e;)
+ return 0;
+ return 0;
+}
+
+int baz ()
+{
+ for (; b >= 0; b--)
+ for (c = 1; c >= 0; c--)
+ {
+ int *k = &c;
+ for (;;)
+ {
+ for (f = 0; f < 1; f++)
+ {
+ g = foo (*k);
+ bar ();
+ }
+ if (*k)
+ break;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int main ()
+{
+ baz ();
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-2.c b/gcc/testsuite/gcc.dg/torture/pr58143-2.c
new file mode 100644
index 00000000000..dd0dae1efe0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-2.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+int a, b, d, e, f, *g, h, i;
+volatile int c;
+
+char foo (unsigned char p)
+{
+ return p + 1;
+}
+
+int bar ()
+{
+ for (h = 0; h < 3; h = foo (h))
+ {
+ c;
+ for (f = 0; f < 1; f++)
+ {
+ i = a && 0 < -__INT_MAX__ - h ? 0 : 1;
+ if (e)
+ for (; d;)
+ b = 0;
+ else
+ g = 0;
+ }
+ }
+ return 0;
+}
+
+int main ()
+{
+ bar ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-3.c b/gcc/testsuite/gcc.dg/torture/pr58143-3.c
new file mode 100644
index 00000000000..23ae9cd39ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-3.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+int a, b, c, d, e;
+
+int
+main ()
+{
+ for (b = 4; b > -30; b--)
+ for (; c;)
+ for (;;)
+ {
+ e = a > __INT_MAX__ - b;
+ if (d)
+ break;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58223.c b/gcc/testsuite/gcc.dg/torture/pr58223.c
new file mode 100644
index 00000000000..978084ad0dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58223.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int a[2], b;
+
+int main ()
+{
+ for (b = 0; b < 2; b++)
+ {
+ a[0] = 1;
+ a[b] = 0;
+ }
+ if (a[0] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58228.c b/gcc/testsuite/gcc.dg/torture/pr58228.c
new file mode 100644
index 00000000000..d12303a008d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58228.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int a[8][8] = {{1}};
+int b, c, d, e;
+
+int main ()
+{
+ for (c = 0; c < 8; c++)
+ for (b = 0; b < 2; b++)
+ a[b + 4][c] = a[c][0];
+ if (a[4][4] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58246.c b/gcc/testsuite/gcc.dg/torture/pr58246.c
new file mode 100644
index 00000000000..5417abf913d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58246.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int a, b;
+
+int main ()
+{
+ int t[2] = {1,1};
+
+ for (a = 0; a < 2; a++)
+ {
+ b ^= t[a];
+ t[a] = t[1] = 0;
+ }
+
+ if (b != 1)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58539.c b/gcc/testsuite/gcc.dg/torture/pr58539.c
new file mode 100644
index 00000000000..a016150f18e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58539.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+int a, b;
+
+extern void baz (int);
+
+int foo (int p)
+{
+ return p ? p : 1;
+}
+
+void bar ()
+{
+ int *c = &a, *d = &a;
+ for (b = 0; b < 12; b++)
+ *d |= 1;
+ foo (*c);
+ baz (*c && 1);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58670.c b/gcc/testsuite/gcc.dg/torture/pr58670.c
new file mode 100644
index 00000000000..ba9fce71f9e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58670.c
@@ -0,0 +1,47 @@
+/* PR middle-end/58670 */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+
+#if defined (__i386__) || defined (__x86_64__)
+#define ASM_STR "btsl $1, %0; jc %l[lab]"
+#endif
+
+__attribute__((noinline, noclone)) int
+foo (int a, int b)
+{
+ if (a)
+ return -3;
+#ifdef ASM_STR
+ asm volatile goto (ASM_STR : : "m" (b) : "memory" : lab);
+ return 0;
+lab:
+#endif
+ return 0;
+}
+
+int
+bar (int a, int b)
+{
+ if (a)
+ return -3;
+#ifdef ASM_STR
+ asm volatile goto (ASM_STR : : "m" (b) : "memory" : lab);
+ return 0;
+lab:
+#endif
+ return 0;
+}
+
+int
+main ()
+{
+ if (foo (1, 0) != -3
+ || foo (0, 3) != 0
+ || foo (1, 0) != -3
+ || foo (0, 0) != 0
+ || bar (1, 0) != -3
+ || bar (0, 3) != 0
+ || bar (1, 0) != -3
+ || bar (0, 0) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58779.c b/gcc/testsuite/gcc.dg/torture/pr58779.c
new file mode 100644
index 00000000000..b0c0c869513
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58779.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+
+int a, c;
+
+int main ()
+{
+ int e = -1;
+ short d = (c <= 0) ^ e;
+ if ((unsigned int) a - (a || d) <= (unsigned int) a)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58830.c b/gcc/testsuite/gcc.dg/torture/pr58830.c
new file mode 100644
index 00000000000..8081f8b2c27
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58830.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-pre -ftree-partial-pre" } */
+
+extern void abort (void);
+
+int b, c, d, f, g, h, i, j[6], *l = &b, *m, n, *o, r;
+char k;
+
+static int
+foo ()
+{
+ char *p = &k;
+
+ for (; d; d++)
+ if (i)
+ h = 0;
+ else
+ h = c || (r = 0);
+
+ for (f = 0; f < 2; f++)
+ {
+ unsigned int q;
+ *l = 0;
+ if (n)
+ *m = g;
+ if (g)
+ o = 0;
+ for (q = -8; q >= 5; q++)
+ (*p)--;
+ }
+
+ return 0;
+}
+
+int
+main ()
+{
+ foo ();
+ if (j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] ^ (k & 15)] != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58941.c b/gcc/testsuite/gcc.dg/torture/pr58941.c
new file mode 100644
index 00000000000..c0eea073165
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58941.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+typedef struct {
+ int msgLength;
+ unsigned char data[1000];
+} SMsg;
+
+typedef struct {
+ int dummy;
+ int d[0];
+} SData;
+
+int condition = 3;
+
+int main()
+{
+ SMsg msg;
+ SData *pData = (SData*)(msg.data);
+ unsigned int i = 0;
+ for (i = 0; i < 1; i++)
+ {
+ pData->d[i] = 0;
+ if(condition & 1)
+ pData->d[i] |= 0x55;
+ if(condition & 2)
+ pData->d[i] |= 0xaa;
+ }
+ if (pData->d[0] != 0xff)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58956.c b/gcc/testsuite/gcc.dg/torture/pr58956.c
new file mode 100644
index 00000000000..7576ba7fb5c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58956.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct S
+{
+ int f0;
+} a = {1}, b, g, *c = &b, **f = &c;
+
+int *d, **e = &d, h;
+
+struct S
+foo ()
+{
+ *e = &h;
+ if (!d)
+ __builtin_unreachable ();
+ *f = &g;
+ return a;
+}
+
+int
+main ()
+{
+ struct S *i = c;
+ *i = foo ();
+ if (b.f0 != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59047.c b/gcc/testsuite/gcc.dg/torture/pr59047.c
new file mode 100644
index 00000000000..fcedfcba870
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59047.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct
+{
+ int f0;
+ int f1:1;
+ int f2:2;
+} a = {0, 0, 1};
+
+int b, c, *d, e, f;
+
+int
+fn1 ()
+{
+ for (; b < 1; ++b)
+ {
+ for (e = 0; e < 1; e = 1)
+ {
+ int **g = &d;
+ *g = &c;
+ }
+ *d = 0;
+ f = a.f1;
+ if (f)
+ return 0;
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ fn1 ();
+ if (b != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59139.c b/gcc/testsuite/gcc.dg/torture/pr59139.c
new file mode 100644
index 00000000000..4ec9177ffe7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59139.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+int a, b, c, d, e;
+int fn1(p1, p2) { return p2 == 0 ? p1 : 1 % p2; }
+
+void fn2()
+{
+ c = 0;
+ for (;; c = (unsigned short)c)
+ {
+ b = 2;
+ for (; b; b = a)
+ {
+ e = fn1(2, c && 1);
+ d = c == 0 ? e : c;
+ if (d)
+ return;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59164.c b/gcc/testsuite/gcc.dg/torture/pr59164.c
new file mode 100644
index 00000000000..1ec69610c21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59164.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int a, d, e;
+long b[10];
+int c[10][8];
+
+int fn1(p1)
+{
+ return 1 >> p1;
+}
+
+void fn2(void)
+{
+ int f;
+ for (a=1; a <= 4; a++)
+ {
+ f = fn1(0 < c[a][0]);
+ if (f || d)
+ e = b[a] = 1;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59288.c b/gcc/testsuite/gcc.dg/torture/pr59288.c
new file mode 100644
index 00000000000..8331e73289c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59288.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+void
+baz (int *d)
+{
+ long int i, j, k;
+ for (i = 0, j = 0, k = 0; i < 512; i = (int) i + 1, j = (int) j + 1, k = (int) k + 3)
+ d[i] = j ^ (i * 3) ^ (2 * k + 2);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59330.c b/gcc/testsuite/gcc.dg/torture/pr59330.c
new file mode 100644
index 00000000000..74b832ea314
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59330.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+
+void free(void *ptr)
+{
+}
+
+void *foo(void)
+{
+ return 0;
+}
+
+int main(void)
+{
+ void *p = foo();
+ free(p);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59715.c b/gcc/testsuite/gcc.dg/torture/pr59715.c
new file mode 100644
index 00000000000..19c09de55d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59715.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int a = 2, b;
+
+int
+main ()
+{
+ int c;
+ if (!b)
+ {
+ b = a;
+ c = a == 0 ? 1 : 1 % a;
+ if (c)
+ b = 0;
+ }
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c
index a26999e8905..53a9fa4f9e3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c
@@ -14,8 +14,8 @@ void foo (int n)
}
}
-/* We should apply loop distribution and generate a memset (0). */
+/* We should not apply loop distribution and not generate a memset (0). */
-/* { dg-final { scan-tree-dump "distributed: split to 2" "ldist" } } */
-/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump "Loop 1 is the same" "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset zero" 0 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c
new file mode 100644
index 00000000000..0af24381485
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+int a, c, e[5][2];
+unsigned int d;
+
+int
+main ()
+{
+ for (d = 0; d < 2; d++)
+ if (a ? 0 : e[c + 3][d] & e[c + 4][d])
+ break;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
new file mode 100644
index 00000000000..e7ae87ccc7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-tree-pcom-details" } */
+
+int b, f, d[5][2];
+unsigned int c;
+
+int
+main ()
+{
+ for (c = 0; c < 2; c++)
+ if (d[b + 3][c] & d[b + 4][c])
+ if (f)
+ break;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Executing predictive commoning" "pcom" } } */
+/* { dg-final { cleanup-tree-dump "pcom" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c
index 376c7e4ee07..f3d169b0324 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-skip-if "cost too high" { powerpc*le-*-* } { "*" } { "" } } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vmx/eg-5.c b/gcc/testsuite/gcc.dg/vmx/eg-5.c
index 0b37e69d194..eb4b4e02836 100644
--- a/gcc/testsuite/gcc.dg/vmx/eg-5.c
+++ b/gcc/testsuite/gcc.dg/vmx/eg-5.c
@@ -6,12 +6,10 @@ matvecmul4 (vector float c0, vector float c1, vector float c2,
{
/* Set result to a vector of f32 0's */
vector float result = ((vector float){0.,0.,0.,0.});
-
result = vec_madd (c0, vec_splat (v, 0), result);
result = vec_madd (c1, vec_splat (v, 1), result);
result = vec_madd (c2, vec_splat (v, 2), result);
result = vec_madd (c3, vec_splat (v, 3), result);
-
return result;
}
diff --git a/gcc/testsuite/gcc.dg/vmx/extract-be-order.c b/gcc/testsuite/gcc.dg/vmx/extract-be-order.c
new file mode 100644
index 00000000000..5c09471d99b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/extract-be-order.c
@@ -0,0 +1,33 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char va = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vb = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vc = {0,1,2,3,4,5,6,7};
+ vector signed short vd = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int ve = {0,1,2,3};
+ vector signed int vf = {-2,-1,0,1};
+ vector float vg = {-2.0f,-1.0f,0.0f,1.0f};
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ check (vec_extract (va, 5) == 10, "vec_extract (va, 5)");
+ check (vec_extract (vb, 0) == 7, "vec_extract (vb, 0)");
+ check (vec_extract (vc, 7) == 0, "vec_extract (vc, 7)");
+ check (vec_extract (vd, 3) == 0, "vec_extract (vd, 3)");
+ check (vec_extract (ve, 2) == 1, "vec_extract (ve, 2)");
+ check (vec_extract (vf, 1) == 0, "vec_extract (vf, 1)");
+ check (vec_extract (vg, 0) == 1.0f, "vec_extract (vg, 0)");
+#else
+ check (vec_extract (va, 5) == 5, "vec_extract (va, 5)");
+ check (vec_extract (vb, 0) == -8, "vec_extract (vb, 0)");
+ check (vec_extract (vc, 7) == 7, "vec_extract (vc, 7)");
+ check (vec_extract (vd, 3) == -1, "vec_extract (vd, 3)");
+ check (vec_extract (ve, 2) == 2, "vec_extract (ve, 2)");
+ check (vec_extract (vf, 1) == -1, "vec_extract (vf, 1)");
+ check (vec_extract (vg, 0) == -2.0f, "vec_extract (vg, 0)");
+#endif
+}
+
diff --git a/gcc/testsuite/gcc.dg/vmx/extract-vsx-be-order.c b/gcc/testsuite/gcc.dg/vmx/extract-vsx-be-order.c
new file mode 100644
index 00000000000..fbeda7b5a62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/extract-vsx-be-order.c
@@ -0,0 +1,19 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector long vl = {0, 1};
+ vector double vd = {0.0, 1.0};
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ check (vec_extract (vl, 0) == 1, "vl, 0");
+ check (vec_extract (vd, 1) == 0.0, "vd, 1");
+#else
+ check (vec_extract (vl, 0) == 0, "vl, 0");
+ check (vec_extract (vd, 1) == 1.0, "vd, 1");
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/extract-vsx.c b/gcc/testsuite/gcc.dg/vmx/extract-vsx.c
new file mode 100644
index 00000000000..68f0909c155
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/extract-vsx.c
@@ -0,0 +1,16 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector long vl = {0, 1};
+ vector double vd = {0.0, 1.0};
+
+ check (vec_extract (vl, 0) == 0, "vec_extract, vl, 0");
+ check (vec_extract (vd, 1) == 1.0, "vec_extract, vd, 1");
+ check (vl[0] == 0, "[], vl, 0");
+ check (vd[1] == 1.0, "[], vd, 0");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/extract.c b/gcc/testsuite/gcc.dg/vmx/extract.c
new file mode 100644
index 00000000000..6fc47255702
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/extract.c
@@ -0,0 +1,21 @@
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char va = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vb = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vc = {0,1,2,3,4,5,6,7};
+ vector signed short vd = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int ve = {0,1,2,3};
+ vector signed int vf = {-2,-1,0,1};
+ vector float vg = {-2.0f,-1.0f,0.0f,1.0f};
+
+ check (vec_extract (va, 5) == 5, "vec_extract (va, 5)");
+ check (vec_extract (vb, 0) == -8, "vec_extract (vb, 0)");
+ check (vec_extract (vc, 7) == 7, "vec_extract (vc, 7)");
+ check (vec_extract (vd, 3) == -1, "vec_extract (vd, 3)");
+ check (vec_extract (ve, 2) == 2, "vec_extract (ve, 2)");
+ check (vec_extract (vf, 1) == -1, "vec_extract (vf, 1)");
+ check (vec_extract (vg, 0) == -2.0f, "vec_extract (vg, 0)");
+}
+
diff --git a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
index 97ef1448819..3e0e6a0793e 100644
--- a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
+++ b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
@@ -13,12 +13,27 @@
#define DO_INLINE __attribute__ ((always_inline))
#define DONT_INLINE __attribute__ ((noinline))
+#ifdef __LITTLE_ENDIAN__
+static inline DO_INLINE int inline_me(vector signed short data)
+{
+ union {vector signed short v; signed short s[8];} u;
+ signed short x;
+ unsigned char x1, x2;
+
+ u.v = data;
+ x = u.s[7];
+ x1 = (x >> 8) & 0xff;
+ x2 = x & 0xff;
+ return ((x2 << 8) | x1);
+}
+#else
static inline DO_INLINE int inline_me(vector signed short data)
{
union {vector signed short v; signed short s[8];} u;
u.v = data;
return u.s[7];
}
+#endif
static DONT_INLINE int foo(vector signed short data)
{
diff --git a/gcc/testsuite/gcc.dg/vmx/insert-be-order.c b/gcc/testsuite/gcc.dg/vmx/insert-be-order.c
new file mode 100644
index 00000000000..592ef28c0fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/insert-be-order.c
@@ -0,0 +1,65 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char va = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vb = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vc = {0,1,2,3,4,5,6,7};
+ vector signed short vd = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int ve = {0,1,2,3};
+ vector signed int vf = {-2,-1,0,1};
+ vector float vg = {-2.0f,-1.0f,0.0f,1.0f};
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ check (vec_all_eq (vec_insert (16, va, 5),
+ ((vector unsigned char)
+ {0,1,2,3,4,5,6,7,8,9,16,11,12,13,14,15})),
+ "vec_insert (va LE)");
+ check (vec_all_eq (vec_insert (-16, vb, 0),
+ ((vector signed char)
+ {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,-16})),
+ "vec_insert (vb LE)");
+ check (vec_all_eq (vec_insert (16, vc, 7),
+ ((vector unsigned short){16,1,2,3,4,5,6,7})),
+ "vec_insert (vc LE)");
+ check (vec_all_eq (vec_insert (-16, vd, 3),
+ ((vector signed short){-4,-3,-2,-1,-16,1,2,3})),
+ "vec_insert (vd LE)");
+ check (vec_all_eq (vec_insert (16, ve, 2),
+ ((vector unsigned int){0,16,2,3})),
+ "vec_insert (ve LE)");
+ check (vec_all_eq (vec_insert (-16, vf, 1),
+ ((vector signed int){-2,-1,-16,1})),
+ "vec_insert (vf LE)");
+ check (vec_all_eq (vec_insert (-16.0f, vg, 0),
+ ((vector float){-2.0f,-1.0f,0.0f,-16.0f})),
+ "vec_insert (vg LE)");
+#else
+ check (vec_all_eq (vec_insert (16, va, 5),
+ ((vector unsigned char)
+ {0,1,2,3,4,16,6,7,8,9,10,11,12,13,14,15})),
+ "vec_insert (va BE)");
+ check (vec_all_eq (vec_insert (-16, vb, 0),
+ ((vector signed char)
+ {-16,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7})),
+ "vec_insert (vb BE)");
+ check (vec_all_eq (vec_insert (16, vc, 7),
+ ((vector unsigned short){0,1,2,3,4,5,6,16})),
+ "vec_insert (vc BE)");
+ check (vec_all_eq (vec_insert (-16, vd, 3),
+ ((vector signed short){-4,-3,-2,-16,0,1,2,3})),
+ "vec_insert (vd BE)");
+ check (vec_all_eq (vec_insert (16, ve, 2),
+ ((vector unsigned int){0,1,16,3})),
+ "vec_insert (ve BE)");
+ check (vec_all_eq (vec_insert (-16, vf, 1),
+ ((vector signed int){-2,-16,0,1})),
+ "vec_insert (vf BE)");
+ check (vec_all_eq (vec_insert (-16.0f, vg, 0),
+ ((vector float){-16.0f,-1.0f,0.0f,1.0f})),
+ "vec_insert (vg BE)");
+#endif
+}
+
diff --git a/gcc/testsuite/gcc.dg/vmx/insert-vsx-be-order.c b/gcc/testsuite/gcc.dg/vmx/insert-vsx-be-order.c
new file mode 100644
index 00000000000..375c8ff18f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/insert-vsx-be-order.c
@@ -0,0 +1,34 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static int vec_long_eq (vector long x, vector long y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static int vec_dbl_eq (vector double x, vector double y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static void test()
+{
+ vector long vl = {0, 1};
+ vector double vd = {0.0, 1.0};
+ vector long vlr = vec_insert (2, vl, 0);
+ vector double vdr = vec_insert (2.0, vd, 1);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector long vler = {0, 2};
+ vector double vder = {2.0, 1.0};
+#else
+ vector long vler = {2, 1};
+ vector double vder = {0.0, 2.0};
+#endif
+
+ check (vec_long_eq (vlr, vler), "vl");
+ check (vec_dbl_eq (vdr, vder), "vd");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/insert-vsx.c b/gcc/testsuite/gcc.dg/vmx/insert-vsx.c
new file mode 100644
index 00000000000..bda6b6ccdae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/insert-vsx.c
@@ -0,0 +1,28 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static int vec_long_eq (vector long x, vector long y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static int vec_dbl_eq (vector double x, vector double y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static void test()
+{
+ vector long vl = {0, 1};
+ vector double vd = {0.0, 1.0};
+ vector long vlr = vec_insert (2, vl, 0);
+ vector double vdr = vec_insert (2.0, vd, 1);
+ vector long vler = {2, 1};
+ vector double vder = {0.0, 2.0};
+
+ check (vec_long_eq (vlr, vler), "vl");
+ check (vec_dbl_eq (vdr, vder), "vd");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/insert.c b/gcc/testsuite/gcc.dg/vmx/insert.c
new file mode 100644
index 00000000000..39cd75d879c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/insert.c
@@ -0,0 +1,37 @@
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char va = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vb = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vc = {0,1,2,3,4,5,6,7};
+ vector signed short vd = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int ve = {0,1,2,3};
+ vector signed int vf = {-2,-1,0,1};
+ vector float vg = {-2.0f,-1.0f,0.0f,1.0f};
+
+ check (vec_all_eq (vec_insert (16, va, 5),
+ ((vector unsigned char)
+ {0,1,2,3,4,16,6,7,8,9,10,11,12,13,14,15})),
+ "vec_insert (va)");
+ check (vec_all_eq (vec_insert (-16, vb, 0),
+ ((vector signed char)
+ {-16,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7})),
+ "vec_insert (vb)");
+ check (vec_all_eq (vec_insert (16, vc, 7),
+ ((vector unsigned short){0,1,2,3,4,5,6,16})),
+ "vec_insert (vc)");
+ check (vec_all_eq (vec_insert (-16, vd, 3),
+ ((vector signed short){-4,-3,-2,-16,0,1,2,3})),
+ "vec_insert (vd)");
+ check (vec_all_eq (vec_insert (16, ve, 2),
+ ((vector unsigned int){0,1,16,3})),
+ "vec_insert (ve)");
+ check (vec_all_eq (vec_insert (-16, vf, 1),
+ ((vector signed int){-2,-16,0,1})),
+ "vec_insert (vf)");
+ check (vec_all_eq (vec_insert (-16.0f, vg, 0),
+ ((vector float){-16.0f,-1.0f,0.0f,1.0f})),
+ "vec_insert (vg)");
+}
+
diff --git a/gcc/testsuite/gcc.dg/vmx/merge-be-order.c b/gcc/testsuite/gcc.dg/vmx/merge-be-order.c
new file mode 100644
index 00000000000..2de888fa444
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/merge-be-order.c
@@ -0,0 +1,96 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb
+ = {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+ vector signed char vsca
+ = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed char vscb = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector float vfa = {-4.0,-3.0,-2.0,-1.0};
+ vector float vfb = {0.0,1.0,2.0,3.0};
+
+ /* Result vectors. */
+ vector unsigned char vuch, vucl;
+ vector signed char vsch, vscl;
+ vector unsigned short vush, vusl;
+ vector signed short vssh, vssl;
+ vector unsigned int vuih, vuil;
+ vector signed int vsih, vsil;
+ vector float vfh, vfl;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector unsigned char vucrh = {24,8,25,9,26,10,27,11,28,12,29,13,30,14,31,15};
+ vector unsigned char vucrl = {16,0,17,1,18,2,19,3,20,4,21,5,22,6,23,7};
+ vector signed char vscrh = {8,-8,9,-7,10,-6,11,-5,12,-4,13,-3,14,-2,15,-1};
+ vector signed char vscrl = {0,-16,1,-15,2,-14,3,-13,4,-12,5,-11,6,-10,7,-9};
+ vector unsigned short vusrh = {12,4,13,5,14,6,15,7};
+ vector unsigned short vusrl = {8,0,9,1,10,2,11,3};
+ vector signed short vssrh = {4,-4,5,-3,6,-2,7,-1};
+ vector signed short vssrl = {0,-8,1,-7,2,-6,3,-5};
+ vector unsigned int vuirh = {6,2,7,3};
+ vector unsigned int vuirl = {4,0,5,1};
+ vector signed int vsirh = {2,-2,3,-1};
+ vector signed int vsirl = {0,-4,1,-3};
+ vector float vfrh = {2.0,-2.0,3.0,-1.0};
+ vector float vfrl = {0.0,-4.0,1.0,-3.0};
+#else
+ vector unsigned char vucrh = {0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23};
+ vector unsigned char vucrl = {8,24,9,25,10,26,11,27,12,28,13,29,14,30,15,31};
+ vector signed char vscrh = {-16,0,-15,1,-14,2,-13,3,-12,4,-11,5,-10,6,-9,7};
+ vector signed char vscrl = {-8,8,-7,9,-6,10,-5,11,-4,12,-3,13,-2,14,-1,15};
+ vector unsigned short vusrh = {0,8,1,9,2,10,3,11};
+ vector unsigned short vusrl = {4,12,5,13,6,14,7,15};
+ vector signed short vssrh = {-8,0,-7,1,-6,2,-5,3};
+ vector signed short vssrl = {-4,4,-3,5,-2,6,-1,7};
+ vector unsigned int vuirh = {0,4,1,5};
+ vector unsigned int vuirl = {2,6,3,7};
+ vector signed int vsirh = {-4,0,-3,1};
+ vector signed int vsirl = {-2,2,-1,3};
+ vector float vfrh = {-4.0,0.0,-3.0,1.0};
+ vector float vfrl = {-2.0,2.0,-1.0,3.0};
+#endif
+
+ vuch = vec_mergeh (vuca, vucb);
+ vucl = vec_mergel (vuca, vucb);
+ vsch = vec_mergeh (vsca, vscb);
+ vscl = vec_mergel (vsca, vscb);
+ vush = vec_mergeh (vusa, vusb);
+ vusl = vec_mergel (vusa, vusb);
+ vssh = vec_mergeh (vssa, vssb);
+ vssl = vec_mergel (vssa, vssb);
+ vuih = vec_mergeh (vuia, vuib);
+ vuil = vec_mergel (vuia, vuib);
+ vsih = vec_mergeh (vsia, vsib);
+ vsil = vec_mergel (vsia, vsib);
+ vfh = vec_mergeh (vfa, vfb );
+ vfl = vec_mergel (vfa, vfb );
+
+ check (vec_all_eq (vuch, vucrh), "vuch");
+ check (vec_all_eq (vucl, vucrl), "vucl");
+ check (vec_all_eq (vsch, vscrh), "vsch");
+ check (vec_all_eq (vscl, vscrl), "vscl");
+ check (vec_all_eq (vush, vusrh), "vush");
+ check (vec_all_eq (vusl, vusrl), "vusl");
+ check (vec_all_eq (vssh, vssrh), "vssh");
+ check (vec_all_eq (vssl, vssrl), "vssl");
+ check (vec_all_eq (vuih, vuirh), "vuih");
+ check (vec_all_eq (vuil, vuirl), "vuil");
+ check (vec_all_eq (vsih, vsirh), "vsih");
+ check (vec_all_eq (vsil, vsirl), "vsil");
+ check (vec_all_eq (vfh, vfrh), "vfh");
+ check (vec_all_eq (vfl, vfrl), "vfl");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c b/gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c
new file mode 100644
index 00000000000..92cdabff0cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/merge-vsx-be-order.c
@@ -0,0 +1,46 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static int vec_long_eq (vector long x, vector long y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static void test()
+{
+ /* Input vectors. */
+ vector long vla = {-2,-1};
+ vector long vlb = {0,1};
+ vector double vda = {-2.0,-1.0};
+ vector double vdb = {0.0,1.0};
+
+ /* Result vectors. */
+ vector long vlh, vll;
+ vector double vdh, vdl;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector long vlrh = {1,-1};
+ vector long vlrl = {0,-2};
+ vector double vdrh = {1.0,-1.0};
+ vector double vdrl = {0.0,-2.0};
+#else
+ vector long vlrh = {-2,0};
+ vector long vlrl = {-1,1};
+ vector double vdrh = {-2.0,0.0};
+ vector double vdrl = {-1.0,1.0};
+#endif
+
+ vlh = vec_mergeh (vla, vlb);
+ vll = vec_mergel (vla, vlb);
+ vdh = vec_mergeh (vda, vdb);
+ vdl = vec_mergel (vda, vdb);
+
+ check (vec_long_eq (vlh, vlrh), "vlh");
+ check (vec_long_eq (vll, vlrl), "vll");
+ check (vec_all_eq (vdh, vdrh), "vdh" );
+ check (vec_all_eq (vdl, vdrl), "vdl" );
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/merge-vsx.c b/gcc/testsuite/gcc.dg/vmx/merge-vsx.c
new file mode 100644
index 00000000000..51e45746843
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/merge-vsx.c
@@ -0,0 +1,39 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static int vec_long_eq (vector long x, vector long y)
+{
+ return (x[0] == y[0] && x[1] == y[1]);
+}
+
+static void test()
+{
+ /* Input vectors. */
+ vector long vla = {-2,-1};
+ vector long vlb = {0,1};
+ vector double vda = {-2.0,-1.0};
+ vector double vdb = {0.0,1.0};
+
+ /* Result vectors. */
+ vector long vlh, vll;
+ vector double vdh, vdl;
+
+ /* Expected result vectors. */
+ vector long vlrh = {-2,0};
+ vector long vlrl = {-1,1};
+ vector double vdrh = {-2.0,0.0};
+ vector double vdrl = {-1.0,1.0};
+
+ vlh = vec_mergeh (vla, vlb);
+ vll = vec_mergel (vla, vlb);
+ vdh = vec_mergeh (vda, vdb);
+ vdl = vec_mergel (vda, vdb);
+
+ check (vec_long_eq (vlh, vlrh), "vlh");
+ check (vec_long_eq (vll, vlrl), "vll");
+ check (vec_all_eq (vdh, vdrh), "vdh" );
+ check (vec_all_eq (vdl, vdrl), "vdl" );
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/merge.c b/gcc/testsuite/gcc.dg/vmx/merge.c
new file mode 100644
index 00000000000..84b14fea744
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/merge.c
@@ -0,0 +1,77 @@
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb
+ = {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+ vector signed char vsca
+ = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed char vscb = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector float vfa = {-4.0,-3.0,-2.0,-1.0};
+ vector float vfb = {0.0,1.0,2.0,3.0};
+
+ /* Result vectors. */
+ vector unsigned char vuch, vucl;
+ vector signed char vsch, vscl;
+ vector unsigned short vush, vusl;
+ vector signed short vssh, vssl;
+ vector unsigned int vuih, vuil;
+ vector signed int vsih, vsil;
+ vector float vfh, vfl;
+
+ /* Expected result vectors. */
+ vector unsigned char vucrh = {0,16,1,17,2,18,3,19,4,20,5,21,6,22,7,23};
+ vector unsigned char vucrl = {8,24,9,25,10,26,11,27,12,28,13,29,14,30,15,31};
+ vector signed char vscrh = {-16,0,-15,1,-14,2,-13,3,-12,4,-11,5,-10,6,-9,7};
+ vector signed char vscrl = {-8,8,-7,9,-6,10,-5,11,-4,12,-3,13,-2,14,-1,15};
+ vector unsigned short vusrh = {0,8,1,9,2,10,3,11};
+ vector unsigned short vusrl = {4,12,5,13,6,14,7,15};
+ vector signed short vssrh = {-8,0,-7,1,-6,2,-5,3};
+ vector signed short vssrl = {-4,4,-3,5,-2,6,-1,7};
+ vector unsigned int vuirh = {0,4,1,5};
+ vector unsigned int vuirl = {2,6,3,7};
+ vector signed int vsirh = {-4,0,-3,1};
+ vector signed int vsirl = {-2,2,-1,3};
+ vector float vfrh = {-4.0,0.0,-3.0,1.0};
+ vector float vfrl = {-2.0,2.0,-1.0,3.0};
+
+ vuch = vec_mergeh (vuca, vucb);
+ vucl = vec_mergel (vuca, vucb);
+ vsch = vec_mergeh (vsca, vscb);
+ vscl = vec_mergel (vsca, vscb);
+ vush = vec_mergeh (vusa, vusb);
+ vusl = vec_mergel (vusa, vusb);
+ vssh = vec_mergeh (vssa, vssb);
+ vssl = vec_mergel (vssa, vssb);
+ vuih = vec_mergeh (vuia, vuib);
+ vuil = vec_mergel (vuia, vuib);
+ vsih = vec_mergeh (vsia, vsib);
+ vsil = vec_mergel (vsia, vsib);
+ vfh = vec_mergeh (vfa, vfb );
+ vfl = vec_mergel (vfa, vfb );
+
+ check (vec_all_eq (vuch, vucrh), "vuch");
+ check (vec_all_eq (vucl, vucrl), "vucl");
+ check (vec_all_eq (vsch, vscrh), "vsch");
+ check (vec_all_eq (vscl, vscrl), "vscl");
+ check (vec_all_eq (vush, vusrh), "vush");
+ check (vec_all_eq (vusl, vusrl), "vusl");
+ check (vec_all_eq (vssh, vssrh), "vssh");
+ check (vec_all_eq (vssl, vssrl), "vssl");
+ check (vec_all_eq (vuih, vuirh), "vuih");
+ check (vec_all_eq (vuil, vuirl), "vuil");
+ check (vec_all_eq (vsih, vsirh), "vsih");
+ check (vec_all_eq (vsil, vsirl), "vsil");
+ check (vec_all_eq (vfh, vfrh), "vfh");
+ check (vec_all_eq (vfl, vfrl), "vfl");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/mult-even-odd-be-order.c b/gcc/testsuite/gcc.dg/vmx/mult-even-odd-be-order.c
new file mode 100644
index 00000000000..ff3047486cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/mult-even-odd-be-order.c
@@ -0,0 +1,64 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb = {2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3};
+ vector signed char vsca = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector signed char vscb = {2,-3,2,-3,2,-3,2,-3,2,-3,2,-3,2,-3,2,-3};
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {2,3,2,3,2,3,2,3};
+ vector signed short vssa = {-4,-3,-2,-1,0,1,2,3};
+ vector signed short vssb = {2,-3,2,-3,2,-3,2,-3};
+ vector unsigned short vuse, vuso;
+ vector signed short vsse, vsso;
+ vector unsigned int vuie, vuio;
+ vector signed int vsie, vsio;
+
+ vuse = vec_mule (vuca, vucb);
+ vuso = vec_mulo (vuca, vucb);
+ vsse = vec_mule (vsca, vscb);
+ vsso = vec_mulo (vsca, vscb);
+ vuie = vec_mule (vusa, vusb);
+ vuio = vec_mulo (vusa, vusb);
+ vsie = vec_mule (vssa, vssb);
+ vsio = vec_mulo (vssa, vssb);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ check (vec_all_eq (vuse,
+ ((vector unsigned short){3,9,15,21,27,33,39,45})),
+ "vuse");
+ check (vec_all_eq (vuso,
+ ((vector unsigned short){0,4,8,12,16,20,24,28})),
+ "vuso");
+ check (vec_all_eq (vsse,
+ ((vector signed short){21,15,9,3,-3,-9,-15,-21})),
+ "vsse");
+ check (vec_all_eq (vsso,
+ ((vector signed short){-16,-12,-8,-4,0,4,8,12})),
+ "vsso");
+ check (vec_all_eq (vuie, ((vector unsigned int){3,9,15,21})), "vuie");
+ check (vec_all_eq (vuio, ((vector unsigned int){0,4,8,12})), "vuio");
+ check (vec_all_eq (vsie, ((vector signed int){9,3,-3,-9})), "vsie");
+ check (vec_all_eq (vsio, ((vector signed int){-8,-4,0,4})), "vsio");
+#else
+ check (vec_all_eq (vuse,
+ ((vector unsigned short){0,4,8,12,16,20,24,28})),
+ "vuse");
+ check (vec_all_eq (vuso,
+ ((vector unsigned short){3,9,15,21,27,33,39,45})),
+ "vuso");
+ check (vec_all_eq (vsse,
+ ((vector signed short){-16,-12,-8,-4,0,4,8,12})),
+ "vsse");
+ check (vec_all_eq (vsso,
+ ((vector signed short){21,15,9,3,-3,-9,-15,-21})),
+ "vsso");
+ check (vec_all_eq (vuie, ((vector unsigned int){0,4,8,12})), "vuie");
+ check (vec_all_eq (vuio, ((vector unsigned int){3,9,15,21})), "vuio");
+ check (vec_all_eq (vsie, ((vector signed int){-8,-4,0,4})), "vsie");
+ check (vec_all_eq (vsio, ((vector signed int){9,3,-3,-9})), "vsio");
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/mult-even-odd.c b/gcc/testsuite/gcc.dg/vmx/mult-even-odd.c
new file mode 100644
index 00000000000..34b72e90040
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/mult-even-odd.c
@@ -0,0 +1,43 @@
+#include "harness.h"
+
+static void test()
+{
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb = {2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3};
+ vector signed char vsca = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector signed char vscb = {2,-3,2,-3,2,-3,2,-3,2,-3,2,-3,2,-3,2,-3};
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {2,3,2,3,2,3,2,3};
+ vector signed short vssa = {-4,-3,-2,-1,0,1,2,3};
+ vector signed short vssb = {2,-3,2,-3,2,-3,2,-3};
+ vector unsigned short vuse, vuso;
+ vector signed short vsse, vsso;
+ vector unsigned int vuie, vuio;
+ vector signed int vsie, vsio;
+
+ vuse = vec_mule (vuca, vucb);
+ vuso = vec_mulo (vuca, vucb);
+ vsse = vec_mule (vsca, vscb);
+ vsso = vec_mulo (vsca, vscb);
+ vuie = vec_mule (vusa, vusb);
+ vuio = vec_mulo (vusa, vusb);
+ vsie = vec_mule (vssa, vssb);
+ vsio = vec_mulo (vssa, vssb);
+
+ check (vec_all_eq (vuse,
+ ((vector unsigned short){0,4,8,12,16,20,24,28})),
+ "vuse");
+ check (vec_all_eq (vuso,
+ ((vector unsigned short){3,9,15,21,27,33,39,45})),
+ "vuso");
+ check (vec_all_eq (vsse,
+ ((vector signed short){-16,-12,-8,-4,0,4,8,12})),
+ "vsse");
+ check (vec_all_eq (vsso,
+ ((vector signed short){21,15,9,3,-3,-9,-15,-21})),
+ "vsso");
+ check (vec_all_eq (vuie, ((vector unsigned int){0,4,8,12})), "vuie");
+ check (vec_all_eq (vuio, ((vector unsigned int){3,9,15,21})), "vuio");
+ check (vec_all_eq (vsie, ((vector signed int){-8,-4,0,4})), "vsie");
+ check (vec_all_eq (vsio, ((vector signed int){9,3,-3,-9})), "vsio");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/pack-be-order.c b/gcc/testsuite/gcc.dg/vmx/pack-be-order.c
new file mode 100644
index 00000000000..c400fc882dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/pack-be-order.c
@@ -0,0 +1,136 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+#define BIG 4294967295
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector bool short vbsa = {0,65535,65535,0,0,0,65535,0};
+ vector bool short vbsb = {65535,0,0,65535,65535,65535,0,65535};
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector bool int vbia = {0,BIG,BIG,BIG};
+ vector bool int vbib = {BIG,0,0,0};
+ vector unsigned int vipa = {(0<<24) + (2<<19) + (3<<11) + (4<<3),
+ (1<<24) + (5<<19) + (6<<11) + (7<<3),
+ (0<<24) + (8<<19) + (9<<11) + (10<<3),
+ (1<<24) + (11<<19) + (12<<11) + (13<<3)};
+ vector unsigned int vipb = {(1<<24) + (14<<19) + (15<<11) + (16<<3),
+ (0<<24) + (17<<19) + (18<<11) + (19<<3),
+ (1<<24) + (20<<19) + (21<<11) + (22<<3),
+ (0<<24) + (23<<19) + (24<<11) + (25<<3)};
+ vector unsigned short vusc = {0,256,1,257,2,258,3,259};
+ vector unsigned short vusd = {4,260,5,261,6,262,7,263};
+ vector signed short vssc = {-1,-128,0,127,-2,-129,1,128};
+ vector signed short vssd = {-3,-130,2,129,-4,-131,3,130};
+ vector unsigned int vuic = {0,65536,1,65537};
+ vector unsigned int vuid = {2,65538,3,65539};
+ vector signed int vsic = {-1,-32768,0,32767};
+ vector signed int vsid = {-2,-32769,1,32768};
+
+ /* Result vectors. */
+ vector unsigned char vucr;
+ vector signed char vscr;
+ vector bool char vbcr;
+ vector unsigned short vusr;
+ vector signed short vssr;
+ vector bool short vbsr;
+ vector pixel vpr;
+ vector unsigned char vucsr;
+ vector signed char vscsr;
+ vector unsigned short vussr;
+ vector signed short vsssr;
+ vector unsigned char vucsur1, vucsur2;
+ vector unsigned short vussur1, vussur2;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector unsigned char vucer = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7};
+ vector signed char vscer = {0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1};
+ vector bool char vbcer = {255,0,0,255,255,255,0,255,0,255,255,0,0,0,255,0};
+ vector unsigned short vuser = {4,5,6,7,0,1,2,3};
+ vector signed short vsser = {0,1,2,3,-4,-3,-2,-1};
+ vector bool short vbser = {65535,0,0,0,0,65535,65535,65535};
+ vector pixel vper = {(1<<15) + (14<<10) + (15<<5) + 16,
+ (0<<15) + (17<<10) + (18<<5) + 19,
+ (1<<15) + (20<<10) + (21<<5) + 22,
+ (0<<15) + (23<<10) + (24<<5) + 25,
+ (0<<15) + (2<<10) + (3<<5) + 4,
+ (1<<15) + (5<<10) + (6<<5) + 7,
+ (0<<15) + (8<<10) + (9<<5) + 10,
+ (1<<15) + (11<<10) + (12<<5) + 13};
+ vector unsigned char vucser = {4,255,5,255,6,255,7,255,0,255,1,255,2,255,3,255};
+ vector signed char vscser = {-3,-128,2,127,-4,-128,3,127,
+ -1,-128,0,127,-2,-128,1,127};
+ vector unsigned short vusser = {2,65535,3,65535,0,65535,1,65535};
+ vector signed short vssser = {-2,-32768,1,32767,-1,-32768,0,32767};
+ vector unsigned char vucsuer1 = {4,255,5,255,6,255,7,255,0,255,1,255,2,255,3,255};
+ vector unsigned char vucsuer2 = {0,0,2,129,0,0,3,130,0,0,0,127,0,0,1,128};
+ vector unsigned short vussuer1 = {2,65535,3,65535,0,65535,1,65535};
+ vector unsigned short vussuer2 = {0,0,1,32768,0,0,0,32767};
+#else
+ vector unsigned char vucer = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vscer = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector bool char vbcer = {0,255,255,0,0,0,255,0,255,0,0,255,255,255,0,255};
+ vector unsigned short vuser = {0,1,2,3,4,5,6,7};
+ vector signed short vsser = {-4,-3,-2,-1,0,1,2,3};
+ vector bool short vbser = {0,65535,65535,65535,65535,0,0,0};
+ vector pixel vper = {(0<<15) + (2<<10) + (3<<5) + 4,
+ (1<<15) + (5<<10) + (6<<5) + 7,
+ (0<<15) + (8<<10) + (9<<5) + 10,
+ (1<<15) + (11<<10) + (12<<5) + 13,
+ (1<<15) + (14<<10) + (15<<5) + 16,
+ (0<<15) + (17<<10) + (18<<5) + 19,
+ (1<<15) + (20<<10) + (21<<5) + 22,
+ (0<<15) + (23<<10) + (24<<5) + 25};
+ vector unsigned char vucser = {0,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255};
+ vector signed char vscser = {-1,-128,0,127,-2,-128,1,127,
+ -3,-128,2,127,-4,-128,3,127};
+ vector unsigned short vusser = {0,65535,1,65535,2,65535,3,65535};
+ vector signed short vssser = {-1,-32768,0,32767,-2,-32768,1,32767};
+ vector unsigned char vucsuer1 = {0,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255};
+ vector unsigned char vucsuer2 = {0,0,0,127,0,0,1,128,0,0,2,129,0,0,3,130};
+ vector unsigned short vussuer1 = {0,65535,1,65535,2,65535,3,65535};
+ vector unsigned short vussuer2 = {0,0,0,32767,0,0,1,32768};
+#endif
+
+ vucr = vec_pack (vusa, vusb);
+ vscr = vec_pack (vssa, vssb);
+ vbcr = vec_pack (vbsa, vbsb);
+ vusr = vec_pack (vuia, vuib);
+ vssr = vec_pack (vsia, vsib);
+ vbsr = vec_pack (vbia, vbib);
+ vpr = vec_packpx (vipa, vipb);
+ vucsr = vec_packs (vusc, vusd);
+ vscsr = vec_packs (vssc, vssd);
+ vussr = vec_packs (vuic, vuid);
+ vsssr = vec_packs (vsic, vsid);
+ vucsur1 = vec_packsu (vusc, vusd);
+ vucsur2 = vec_packsu (vssc, vssd);
+ vussur1 = vec_packsu (vuic, vuid);
+ vussur2 = vec_packsu (vsic, vsid);
+
+ check (vec_all_eq (vucr, vucer), "vucr");
+ check (vec_all_eq (vscr, vscer), "vscr");
+ check (vec_all_eq (vbcr, vbcer), "vbcr");
+ check (vec_all_eq (vusr, vuser), "vusr");
+ check (vec_all_eq (vssr, vsser), "vssr");
+ check (vec_all_eq (vbsr, vbser), "vbsr");
+ check (vec_all_eq (vpr, vper ), "vpr" );
+ check (vec_all_eq (vucsr, vucser), "vucsr");
+ check (vec_all_eq (vscsr, vscser), "vscsr");
+ check (vec_all_eq (vussr, vusser), "vussr");
+ check (vec_all_eq (vsssr, vssser), "vsssr");
+ check (vec_all_eq (vucsur1, vucsuer1), "vucsur1");
+ check (vec_all_eq (vucsur2, vucsuer2), "vucsur2");
+ check (vec_all_eq (vussur1, vussuer1), "vussur1");
+ check (vec_all_eq (vussur2, vussuer2), "vussur2");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/pack.c b/gcc/testsuite/gcc.dg/vmx/pack.c
new file mode 100644
index 00000000000..d1b49f0a62a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/pack.c
@@ -0,0 +1,108 @@
+#include "harness.h"
+
+#define BIG 4294967295
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector bool short vbsa = {0,65535,65535,0,0,0,65535,0};
+ vector bool short vbsb = {65535,0,0,65535,65535,65535,0,65535};
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector bool int vbia = {0,BIG,BIG,BIG};
+ vector bool int vbib = {BIG,0,0,0};
+ vector unsigned int vipa = {(0<<24) + (2<<19) + (3<<11) + (4<<3),
+ (1<<24) + (5<<19) + (6<<11) + (7<<3),
+ (0<<24) + (8<<19) + (9<<11) + (10<<3),
+ (1<<24) + (11<<19) + (12<<11) + (13<<3)};
+ vector unsigned int vipb = {(1<<24) + (14<<19) + (15<<11) + (16<<3),
+ (0<<24) + (17<<19) + (18<<11) + (19<<3),
+ (1<<24) + (20<<19) + (21<<11) + (22<<3),
+ (0<<24) + (23<<19) + (24<<11) + (25<<3)};
+ vector unsigned short vusc = {0,256,1,257,2,258,3,259};
+ vector unsigned short vusd = {4,260,5,261,6,262,7,263};
+ vector signed short vssc = {-1,-128,0,127,-2,-129,1,128};
+ vector signed short vssd = {-3,-130,2,129,-4,-131,3,130};
+ vector unsigned int vuic = {0,65536,1,65537};
+ vector unsigned int vuid = {2,65538,3,65539};
+ vector signed int vsic = {-1,-32768,0,32767};
+ vector signed int vsid = {-2,-32769,1,32768};
+
+ /* Result vectors. */
+ vector unsigned char vucr;
+ vector signed char vscr;
+ vector bool char vbcr;
+ vector unsigned short vusr;
+ vector signed short vssr;
+ vector bool short vbsr;
+ vector pixel vpr;
+ vector unsigned char vucsr;
+ vector signed char vscsr;
+ vector unsigned short vussr;
+ vector signed short vsssr;
+ vector unsigned char vucsur1, vucsur2;
+ vector unsigned short vussur1, vussur2;
+
+ /* Expected result vectors. */
+ vector unsigned char vucer = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vscer = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector bool char vbcer = {0,255,255,0,0,0,255,0,255,0,0,255,255,255,0,255};
+ vector unsigned short vuser = {0,1,2,3,4,5,6,7};
+ vector signed short vsser = {-4,-3,-2,-1,0,1,2,3};
+ vector bool short vbser = {0,65535,65535,65535,65535,0,0,0};
+ vector pixel vper = {(0<<15) + (2<<10) + (3<<5) + 4,
+ (1<<15) + (5<<10) + (6<<5) + 7,
+ (0<<15) + (8<<10) + (9<<5) + 10,
+ (1<<15) + (11<<10) + (12<<5) + 13,
+ (1<<15) + (14<<10) + (15<<5) + 16,
+ (0<<15) + (17<<10) + (18<<5) + 19,
+ (1<<15) + (20<<10) + (21<<5) + 22,
+ (0<<15) + (23<<10) + (24<<5) + 25};
+ vector unsigned char vucser = {0,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255};
+ vector signed char vscser = {-1,-128,0,127,-2,-128,1,127,
+ -3,-128,2,127,-4,-128,3,127};
+ vector unsigned short vusser = {0,65535,1,65535,2,65535,3,65535};
+ vector signed short vssser = {-1,-32768,0,32767,-2,-32768,1,32767};
+ vector unsigned char vucsuer1 = {0,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255};
+ vector unsigned char vucsuer2 = {0,0,0,127,0,0,1,128,0,0,2,129,0,0,3,130};
+ vector unsigned short vussuer1 = {0,65535,1,65535,2,65535,3,65535};
+ vector unsigned short vussuer2 = {0,0,0,32767,0,0,1,32768};
+
+ vucr = vec_pack (vusa, vusb);
+ vscr = vec_pack (vssa, vssb);
+ vbcr = vec_pack (vbsa, vbsb);
+ vusr = vec_pack (vuia, vuib);
+ vssr = vec_pack (vsia, vsib);
+ vbsr = vec_pack (vbia, vbib);
+ vpr = vec_packpx (vipa, vipb);
+ vucsr = vec_packs (vusc, vusd);
+ vscsr = vec_packs (vssc, vssd);
+ vussr = vec_packs (vuic, vuid);
+ vsssr = vec_packs (vsic, vsid);
+ vucsur1 = vec_packsu (vusc, vusd);
+ vucsur2 = vec_packsu (vssc, vssd);
+ vussur1 = vec_packsu (vuic, vuid);
+ vussur2 = vec_packsu (vsic, vsid);
+
+ check (vec_all_eq (vucr, vucer), "vucr");
+ check (vec_all_eq (vscr, vscer), "vscr");
+ check (vec_all_eq (vbcr, vbcer), "vbcr");
+ check (vec_all_eq (vusr, vuser), "vusr");
+ check (vec_all_eq (vssr, vsser), "vssr");
+ check (vec_all_eq (vbsr, vbser), "vbsr");
+ check (vec_all_eq (vpr, vper ), "vpr" );
+ check (vec_all_eq (vucsr, vucser), "vucsr");
+ check (vec_all_eq (vscsr, vscser), "vscsr");
+ check (vec_all_eq (vussr, vusser), "vussr");
+ check (vec_all_eq (vsssr, vssser), "vsssr");
+ check (vec_all_eq (vucsur1, vucsuer1), "vucsur1");
+ check (vec_all_eq (vucsur2, vucsuer2), "vucsur2");
+ check (vec_all_eq (vussur1, vussuer1), "vussur1");
+ check (vec_all_eq (vussur2, vussuer2), "vussur2");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/perm-be-order.c b/gcc/testsuite/gcc.dg/vmx/perm-be-order.c
new file mode 100644
index 00000000000..604f63dc95f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/perm-be-order.c
@@ -0,0 +1,74 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb = {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+ vector signed char vsca = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed char vscb = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector float vfa = {-4.0,-3.0,-2.0,-1.0};
+ vector float vfb = {0.0,1.0,2.0,3.0};
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector unsigned char vucp = {15,16,14,17,13,18,12,19,11,20,10,21,9,22,8,23};
+ vector unsigned char vscp = {15,16,14,17,13,18,12,19,11,20,10,21,9,22,8,23};
+ vector unsigned char vusp = {15,14,17,16,13,12,19,18,11,10,21,20,9,8,23,22};
+ vector unsigned char vssp = {15,14,17,16,13,12,19,18,11,10,21,20,9,8,23,22};
+ vector unsigned char vuip = {15,14,13,12,19,18,17,16,11,10,9,8,23,22,21,20};
+ vector unsigned char vsip = {15,14,13,12,19,18,17,16,11,10,9,8,23,22,21,20};
+ vector unsigned char vfp = {15,14,13,12,19,18,17,16,11,10,9,8,23,22,21,20};
+#else
+ vector unsigned char vucp = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+ vector unsigned char vscp = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+ vector unsigned char vusp = {0,1,30,31,2,3,28,29,4,5,26,27,6,7,24,25};
+ vector unsigned char vssp = {0,1,30,31,2,3,28,29,4,5,26,27,6,7,24,25};
+ vector unsigned char vuip = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+ vector unsigned char vsip = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+ vector unsigned char vfp = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+#endif
+
+ /* Result vectors. */
+ vector unsigned char vuc;
+ vector signed char vsc;
+ vector unsigned short vus;
+ vector signed short vss;
+ vector unsigned int vui;
+ vector signed int vsi;
+ vector float vf;
+
+ /* Expected result vectors. */
+ vector unsigned char vucr = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+ vector signed char vscr = {-16,15,-15,14,-14,13,-13,12,-12,11,-11,10,-10,9,-9,8};
+ vector unsigned short vusr = {0,15,1,14,2,13,3,12};
+ vector signed short vssr = {-8,7,-7,6,-6,5,-5,4};
+ vector unsigned int vuir = {0,7,1,6};
+ vector signed int vsir = {-4,3,-3,2};
+ vector float vfr = {-4.0,3.0,-3.0,2.0};
+
+ vuc = vec_perm (vuca, vucb, vucp);
+ vsc = vec_perm (vsca, vscb, vscp);
+ vus = vec_perm (vusa, vusb, vusp);
+ vss = vec_perm (vssa, vssb, vssp);
+ vui = vec_perm (vuia, vuib, vuip);
+ vsi = vec_perm (vsia, vsib, vsip);
+ vf = vec_perm (vfa, vfb, vfp );
+
+ check (vec_all_eq (vuc, vucr), "vuc");
+ check (vec_all_eq (vsc, vscr), "vsc");
+ check (vec_all_eq (vus, vusr), "vus");
+ check (vec_all_eq (vss, vssr), "vss");
+ check (vec_all_eq (vui, vuir), "vui");
+ check (vec_all_eq (vsi, vsir), "vsi");
+ check (vec_all_eq (vf, vfr), "vf" );
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/perm.c b/gcc/testsuite/gcc.dg/vmx/perm.c
new file mode 100644
index 00000000000..be6bf3422c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/perm.c
@@ -0,0 +1,69 @@
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vucb
+ = {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+ vector unsigned char vucp = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+
+ vector signed char vsca
+ = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed char vscb = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector unsigned char vscp = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+
+ vector unsigned short vusa = {0,1,2,3,4,5,6,7};
+ vector unsigned short vusb = {8,9,10,11,12,13,14,15};
+ vector unsigned char vusp = {0,1,30,31,2,3,28,29,4,5,26,27,6,7,24,25};
+
+ vector signed short vssa = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vssb = {0,1,2,3,4,5,6,7};
+ vector unsigned char vssp = {0,1,30,31,2,3,28,29,4,5,26,27,6,7,24,25};
+
+ vector unsigned int vuia = {0,1,2,3};
+ vector unsigned int vuib = {4,5,6,7};
+ vector unsigned char vuip = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+
+ vector signed int vsia = {-4,-3,-2,-1};
+ vector signed int vsib = {0,1,2,3};
+ vector unsigned char vsip = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+
+ vector float vfa = {-4.0,-3.0,-2.0,-1.0};
+ vector float vfb = {0.0,1.0,2.0,3.0};
+ vector unsigned char vfp = {0,1,2,3,28,29,30,31,4,5,6,7,24,25,26,27};
+
+ /* Result vectors. */
+ vector unsigned char vuc;
+ vector signed char vsc;
+ vector unsigned short vus;
+ vector signed short vss;
+ vector unsigned int vui;
+ vector signed int vsi;
+ vector float vf;
+
+ /* Expected result vectors. */
+ vector unsigned char vucr = {0,31,1,30,2,29,3,28,4,27,5,26,6,25,7,24};
+ vector signed char vscr = {-16,15,-15,14,-14,13,-13,12,-12,11,-11,10,-10,9,-9,8};
+ vector unsigned short vusr = {0,15,1,14,2,13,3,12};
+ vector signed short vssr = {-8,7,-7,6,-6,5,-5,4};
+ vector unsigned int vuir = {0,7,1,6};
+ vector signed int vsir = {-4,3,-3,2};
+ vector float vfr = {-4.0,3.0,-3.0,2.0};
+
+ vuc = vec_perm (vuca, vucb, vucp);
+ vsc = vec_perm (vsca, vscb, vscp);
+ vus = vec_perm (vusa, vusb, vusp);
+ vss = vec_perm (vssa, vssb, vssp);
+ vui = vec_perm (vuia, vuib, vuip);
+ vsi = vec_perm (vsia, vsib, vsip);
+ vf = vec_perm (vfa, vfb, vfp );
+
+ check (vec_all_eq (vuc, vucr), "vuc");
+ check (vec_all_eq (vsc, vscr), "vsc");
+ check (vec_all_eq (vus, vusr), "vus");
+ check (vec_all_eq (vss, vssr), "vss");
+ check (vec_all_eq (vui, vuir), "vui");
+ check (vec_all_eq (vsi, vsir), "vsi");
+ check (vec_all_eq (vf, vfr), "vf" );
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/sn7153.c b/gcc/testsuite/gcc.dg/vmx/sn7153.c
index a498a862006..2381a891cd3 100644
--- a/gcc/testsuite/gcc.dg/vmx/sn7153.c
+++ b/gcc/testsuite/gcc.dg/vmx/sn7153.c
@@ -34,7 +34,11 @@ main()
void validate_sat()
{
+#ifdef __LITTLE_ENDIAN__
+ if (vec_any_ne(vec_splat(vec_mfvscr(), 0), ((vector unsigned short){1,1,1,1,1,1,1,1})))
+#else
if (vec_any_ne(vec_splat(vec_mfvscr(), 7), ((vector unsigned short){1,1,1,1,1,1,1,1})))
+#endif
{
union {vector unsigned short v; unsigned short s[8];} u;
u.v = vec_mfvscr();
diff --git a/gcc/testsuite/gcc.dg/vmx/splat-be-order.c b/gcc/testsuite/gcc.dg/vmx/splat-be-order.c
new file mode 100644
index 00000000000..e265ae4be20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/splat-be-order.c
@@ -0,0 +1,59 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuc = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vsc = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vus = {0,1,2,3,4,5,6,7};
+ vector signed short vss = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int vui = {0,1,2,3};
+ vector signed int vsi = {-2,-1,0,1};
+ vector float vf = {-2.0,-1.0,0.0,1.0};
+
+ /* Result vectors. */
+ vector unsigned char vucr;
+ vector signed char vscr;
+ vector unsigned short vusr;
+ vector signed short vssr;
+ vector unsigned int vuir;
+ vector signed int vsir;
+ vector float vfr;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector unsigned char vucer = {14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14};
+ vector signed char vscer = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
+ vector unsigned short vuser = {0,0,0,0,0,0,0,0};
+ vector signed short vsser = {3,3,3,3,3,3,3,3};
+ vector unsigned int vuier = {1,1,1,1};
+ vector signed int vsier = {-2,-2,-2,-2};
+ vector float vfer = {0.0,0.0,0.0,0.0};
+#else
+ vector unsigned char vucer = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+ vector signed char vscer = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ vector unsigned short vuser = {7,7,7,7,7,7,7,7};
+ vector signed short vsser = {-4,-4,-4,-4,-4,-4,-4,-4};
+ vector unsigned int vuier = {2,2,2,2};
+ vector signed int vsier = {1,1,1,1};
+ vector float vfer = {-1.0,-1.0,-1.0,-1.0};
+#endif
+
+ vucr = vec_splat (vuc, 1);
+ vscr = vec_splat (vsc, 8);
+ vusr = vec_splat (vus, 7);
+ vssr = vec_splat (vss, 0);
+ vuir = vec_splat (vui, 2);
+ vsir = vec_splat (vsi, 3);
+ vfr = vec_splat (vf, 1);
+
+ check (vec_all_eq (vucr, vucer), "vuc");
+ check (vec_all_eq (vscr, vscer), "vsc");
+ check (vec_all_eq (vusr, vuser), "vus");
+ check (vec_all_eq (vssr, vsser), "vss");
+ check (vec_all_eq (vuir, vuier), "vui");
+ check (vec_all_eq (vsir, vsier), "vsi");
+ check (vec_all_eq (vfr, vfer ), "vf");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/splat-vsx-be-order.c b/gcc/testsuite/gcc.dg/vmx/splat-vsx-be-order.c
new file mode 100644
index 00000000000..cd389bd0f66
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/splat-vsx-be-order.c
@@ -0,0 +1,37 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned int vui = {0,1,2,3};
+ vector signed int vsi = {-2,-1,0,1};
+ vector float vf = {-2.0,-1.0,0.0,1.0};
+
+ /* Result vectors. */
+ vector unsigned int vuir;
+ vector signed int vsir;
+ vector float vfr;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector unsigned int vuier = {1,1,1,1};
+ vector signed int vsier = {-2,-2,-2,-2};
+ vector float vfer = {0.0,0.0,0.0,0.0};
+#else
+ vector unsigned int vuier = {2,2,2,2};
+ vector signed int vsier = {1,1,1,1};
+ vector float vfer = {-1.0,-1.0,-1.0,-1.0};
+#endif
+
+ vuir = vec_splat (vui, 2);
+ vsir = vec_splat (vsi, 3);
+ vfr = vec_splat (vf, 1);
+
+ check (vec_all_eq (vuir, vuier), "vui");
+ check (vec_all_eq (vsir, vsier), "vsi");
+ check (vec_all_eq (vfr, vfer ), "vf");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/splat-vsx.c b/gcc/testsuite/gcc.dg/vmx/splat-vsx.c
new file mode 100644
index 00000000000..5a6e7dfe46c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/splat-vsx.c
@@ -0,0 +1,31 @@
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec -mabi=altivec -std=gnu99 -mvsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned int vui = {0,1,2,3};
+ vector signed int vsi = {-2,-1,0,1};
+ vector float vf = {-2.0,-1.0,0.0,1.0};
+
+ /* Result vectors. */
+ vector unsigned int vuir;
+ vector signed int vsir;
+ vector float vfr;
+
+ /* Expected result vectors. */
+ vector unsigned int vuier = {2,2,2,2};
+ vector signed int vsier = {1,1,1,1};
+ vector float vfer = {-1.0,-1.0,-1.0,-1.0};
+
+ vuir = vec_splat (vui, 2);
+ vsir = vec_splat (vsi, 3);
+ vfr = vec_splat (vf, 1);
+
+ check (vec_all_eq (vuir, vuier), "vui");
+ check (vec_all_eq (vsir, vsier), "vsi");
+ check (vec_all_eq (vfr, vfer ), "vf");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/splat.c b/gcc/testsuite/gcc.dg/vmx/splat.c
new file mode 100644
index 00000000000..e45974ac910
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/splat.c
@@ -0,0 +1,47 @@
+#include "harness.h"
+
+static void test()
+{
+ /* Input vectors. */
+ vector unsigned char vuc = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ vector signed char vsc = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector unsigned short vus = {0,1,2,3,4,5,6,7};
+ vector signed short vss = {-4,-3,-2,-1,0,1,2,3};
+ vector unsigned int vui = {0,1,2,3};
+ vector signed int vsi = {-2,-1,0,1};
+ vector float vf = {-2.0,-1.0,0.0,1.0};
+
+ /* Result vectors. */
+ vector unsigned char vucr;
+ vector signed char vscr;
+ vector unsigned short vusr;
+ vector signed short vssr;
+ vector unsigned int vuir;
+ vector signed int vsir;
+ vector float vfr;
+
+ /* Expected result vectors. */
+ vector unsigned char vucer = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+ vector signed char vscer = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ vector unsigned short vuser = {7,7,7,7,7,7,7,7};
+ vector signed short vsser = {-4,-4,-4,-4,-4,-4,-4,-4};
+ vector unsigned int vuier = {2,2,2,2};
+ vector signed int vsier = {1,1,1,1};
+ vector float vfer = {-1.0,-1.0,-1.0,-1.0};
+
+ vucr = vec_splat (vuc, 1);
+ vscr = vec_splat (vsc, 8);
+ vusr = vec_splat (vus, 7);
+ vssr = vec_splat (vss, 0);
+ vuir = vec_splat (vui, 2);
+ vsir = vec_splat (vsi, 3);
+ vfr = vec_splat (vf, 1);
+
+ check (vec_all_eq (vucr, vucer), "vuc");
+ check (vec_all_eq (vscr, vscer), "vsc");
+ check (vec_all_eq (vusr, vuser), "vus");
+ check (vec_all_eq (vssr, vsser), "vss");
+ check (vec_all_eq (vuir, vuier), "vui");
+ check (vec_all_eq (vsir, vsier), "vsi");
+ check (vec_all_eq (vfr, vfer ), "vf");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/sum2s-be-order.c b/gcc/testsuite/gcc.dg/vmx/sum2s-be-order.c
new file mode 100644
index 00000000000..0981cc1d52b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/sum2s-be-order.c
@@ -0,0 +1,19 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector signed int vsia = {-10,1,2,3};
+ vector signed int vsib = {100,101,102,-103};
+ vector signed int vsir;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector signed int vsier = {91,0,107,0};
+#else
+ vector signed int vsier = {0,92,0,-98};
+#endif
+
+ vsir = vec_sum2s (vsia, vsib);
+
+ check (vec_all_eq (vsir, vsier), "vsir");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/sum2s.c b/gcc/testsuite/gcc.dg/vmx/sum2s.c
new file mode 100644
index 00000000000..ded05be849c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/sum2s.c
@@ -0,0 +1,13 @@
+#include "harness.h"
+
+static void test()
+{
+ vector signed int vsia = {-10,1,2,3};
+ vector signed int vsib = {100,101,102,-103};
+ vector signed int vsir;
+ vector signed int vsier = {0,92,0,-98};
+
+ vsir = vec_sum2s (vsia, vsib);
+
+ check (vec_all_eq (vsir, vsier), "vsir");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/unpack-be-order.c b/gcc/testsuite/gcc.dg/vmx/unpack-be-order.c
new file mode 100644
index 00000000000..e174433dd23
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/unpack-be-order.c
@@ -0,0 +1,88 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+#define BIG 4294967295
+
+static void test()
+{
+ /* Input vectors. */
+ vector signed char vsc = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector bool char vbc = {0,255,255,0,0,0,255,0,255,0,0,255,255,255,0,255};
+ vector pixel vp = {(0<<15) + (1<<10) + (2<<5) + 3,
+ (1<<15) + (4<<10) + (5<<5) + 6,
+ (0<<15) + (7<<10) + (8<<5) + 9,
+ (1<<15) + (10<<10) + (11<<5) + 12,
+ (1<<15) + (13<<10) + (14<<5) + 15,
+ (0<<15) + (16<<10) + (17<<5) + 18,
+ (1<<15) + (19<<10) + (20<<5) + 21,
+ (0<<15) + (22<<10) + (23<<5) + 24};
+ vector signed short vss = {-4,-3,-2,-1,0,1,2,3};
+ vector bool short vbs = {0,65535,65535,0,0,0,65535,0};
+
+ /* Result vectors. */
+ vector signed short vsch, vscl;
+ vector bool short vbsh, vbsl;
+ vector unsigned int vuih, vuil;
+ vector signed int vsih, vsil;
+ vector bool int vbih, vbil;
+
+ /* Expected result vectors. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector signed short vschr = {0,1,2,3,4,5,6,7};
+ vector signed short vsclr = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector bool short vbshr = {65535,0,0,65535,65535,65535,0,65535};
+ vector bool short vbslr = {0,65535,65535,0,0,0,65535,0};
+ vector unsigned int vuihr = {(65535<<24) + (13<<16) + (14<<8) + 15,
+ (0<<24) + (16<<16) + (17<<8) + 18,
+ (65535<<24) + (19<<16) + (20<<8) + 21,
+ (0<<24) + (22<<16) + (23<<8) + 24};
+ vector unsigned int vuilr = {(0<<24) + (1<<16) + (2<<8) + 3,
+ (65535<<24) + (4<<16) + (5<<8) + 6,
+ (0<<24) + (7<<16) + (8<<8) + 9,
+ (65535<<24) + (10<<16) + (11<<8) + 12};
+ vector signed int vsihr = {0,1,2,3};
+ vector signed int vsilr = {-4,-3,-2,-1};
+ vector bool int vbihr = {0,0,BIG,0};
+ vector bool int vbilr = {0,BIG,BIG,0};
+#else
+ vector signed short vschr = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vsclr = {0,1,2,3,4,5,6,7};
+ vector bool short vbshr = {0,65535,65535,0,0,0,65535,0};
+ vector bool short vbslr = {65535,0,0,65535,65535,65535,0,65535};
+ vector unsigned int vuihr = {(0<<24) + (1<<16) + (2<<8) + 3,
+ (65535<<24) + (4<<16) + (5<<8) + 6,
+ (0<<24) + (7<<16) + (8<<8) + 9,
+ (65535<<24) + (10<<16) + (11<<8) + 12};
+ vector unsigned int vuilr = {(65535<<24) + (13<<16) + (14<<8) + 15,
+ (0<<24) + (16<<16) + (17<<8) + 18,
+ (65535<<24) + (19<<16) + (20<<8) + 21,
+ (0<<24) + (22<<16) + (23<<8) + 24};
+ vector signed int vsihr = {-4,-3,-2,-1};
+ vector signed int vsilr = {0,1,2,3};
+ vector bool int vbihr = {0,BIG,BIG,0};
+ vector bool int vbilr = {0,0,BIG,0};
+#endif
+
+ vsch = vec_unpackh (vsc);
+ vscl = vec_unpackl (vsc);
+ vbsh = vec_unpackh (vbc);
+ vbsl = vec_unpackl (vbc);
+ vuih = vec_unpackh (vp);
+ vuil = vec_unpackl (vp);
+ vsih = vec_unpackh (vss);
+ vsil = vec_unpackl (vss);
+ vbih = vec_unpackh (vbs);
+ vbil = vec_unpackl (vbs);
+
+ check (vec_all_eq (vsch, vschr), "vsch");
+ check (vec_all_eq (vscl, vsclr), "vscl");
+ check (vec_all_eq (vbsh, vbshr), "vbsh");
+ check (vec_all_eq (vbsl, vbslr), "vbsl");
+ check (vec_all_eq (vuih, vuihr), "vuih");
+ check (vec_all_eq (vuil, vuilr), "vuil");
+ check (vec_all_eq (vsih, vsihr), "vsih");
+ check (vec_all_eq (vsil, vsilr), "vsil");
+ check (vec_all_eq (vbih, vbihr), "vbih");
+ check (vec_all_eq (vbil, vbilr), "vbil");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/unpack.c b/gcc/testsuite/gcc.dg/vmx/unpack.c
new file mode 100644
index 00000000000..3c13163cb7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/unpack.c
@@ -0,0 +1,67 @@
+#include "harness.h"
+
+#define BIG 4294967295
+
+static void test()
+{
+ /* Input vectors. */
+ vector signed char vsc = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+ vector bool char vbc = {0,255,255,0,0,0,255,0,255,0,0,255,255,255,0,255};
+ vector pixel vp = {(0<<15) + (1<<10) + (2<<5) + 3,
+ (1<<15) + (4<<10) + (5<<5) + 6,
+ (0<<15) + (7<<10) + (8<<5) + 9,
+ (1<<15) + (10<<10) + (11<<5) + 12,
+ (1<<15) + (13<<10) + (14<<5) + 15,
+ (0<<15) + (16<<10) + (17<<5) + 18,
+ (1<<15) + (19<<10) + (20<<5) + 21,
+ (0<<15) + (22<<10) + (23<<5) + 24};
+ vector signed short vss = {-4,-3,-2,-1,0,1,2,3};
+ vector bool short vbs = {0,65535,65535,0,0,0,65535,0};
+
+ /* Result vectors. */
+ vector signed short vsch, vscl;
+ vector bool short vbsh, vbsl;
+ vector unsigned int vuih, vuil;
+ vector signed int vsih, vsil;
+ vector bool int vbih, vbil;
+
+ /* Expected result vectors. */
+ vector signed short vschr = {-8,-7,-6,-5,-4,-3,-2,-1};
+ vector signed short vsclr = {0,1,2,3,4,5,6,7};
+ vector bool short vbshr = {0,65535,65535,0,0,0,65535,0};
+ vector bool short vbslr = {65535,0,0,65535,65535,65535,0,65535};
+ vector unsigned int vuihr = {(0<<24) + (1<<16) + (2<<8) + 3,
+ (65535<<24) + (4<<16) + (5<<8) + 6,
+ (0<<24) + (7<<16) + (8<<8) + 9,
+ (65535<<24) + (10<<16) + (11<<8) + 12};
+ vector unsigned int vuilr = {(65535<<24) + (13<<16) + (14<<8) + 15,
+ (0<<24) + (16<<16) + (17<<8) + 18,
+ (65535<<24) + (19<<16) + (20<<8) + 21,
+ (0<<24) + (22<<16) + (23<<8) + 24};
+ vector signed int vsihr = {-4,-3,-2,-1};
+ vector signed int vsilr = {0,1,2,3};
+ vector bool int vbihr = {0,BIG,BIG,0};
+ vector bool int vbilr = {0,0,BIG,0};
+
+ vsch = vec_unpackh (vsc);
+ vscl = vec_unpackl (vsc);
+ vbsh = vec_unpackh (vbc);
+ vbsl = vec_unpackl (vbc);
+ vuih = vec_unpackh (vp);
+ vuil = vec_unpackl (vp);
+ vsih = vec_unpackh (vss);
+ vsil = vec_unpackl (vss);
+ vbih = vec_unpackh (vbs);
+ vbil = vec_unpackl (vbs);
+
+ check (vec_all_eq (vsch, vschr), "vsch");
+ check (vec_all_eq (vscl, vsclr), "vscl");
+ check (vec_all_eq (vbsh, vbshr), "vbsh");
+ check (vec_all_eq (vbsl, vbslr), "vbsl");
+ check (vec_all_eq (vuih, vuihr), "vuih");
+ check (vec_all_eq (vuil, vuilr), "vuil");
+ check (vec_all_eq (vsih, vsihr), "vsih");
+ check (vec_all_eq (vsil, vsilr), "vsil");
+ check (vec_all_eq (vbih, vbihr), "vbih");
+ check (vec_all_eq (vbil, vbilr), "vbil");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/vec-set.c b/gcc/testsuite/gcc.dg/vmx/vec-set.c
new file mode 100644
index 00000000000..fa11c47a122
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/vec-set.c
@@ -0,0 +1,14 @@
+#include "harness.h"
+
+vector short
+vec_set (short m)
+{
+ return (vector short){m, 0, 0, 0, 0, 0, 0, 0};
+}
+
+static void test()
+{
+ check (vec_all_eq (vec_set (7),
+ ((vector short){7, 0, 0, 0, 0, 0, 0, 0})),
+ "vec_set");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/vsums-be-order.c b/gcc/testsuite/gcc.dg/vmx/vsums-be-order.c
new file mode 100644
index 00000000000..69fe3b64aaf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/vsums-be-order.c
@@ -0,0 +1,19 @@
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static void test()
+{
+ vector signed int va = {-7,11,-13,17};
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ vector signed int vb = {128,0,0,0};
+#else
+ vector signed int vb = {0,0,0,128};
+#endif
+
+ vector signed int vd = vec_sums (va, vb);
+ signed int r = vec_extract (vd, 3);
+
+ check (r == 136, "sums");
+}
diff --git a/gcc/testsuite/gcc.dg/vmx/vsums.c b/gcc/testsuite/gcc.dg/vmx/vsums.c
new file mode 100644
index 00000000000..dfbb1cc6ddc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/vsums.c
@@ -0,0 +1,12 @@
+#include "harness.h"
+
+static void test()
+{
+ vector signed int va = {-7,11,-13,17};
+ vector signed int vb = {0,0,0,128};
+
+ vector signed int vd = vec_sums (va, vb);
+ signed int r = vec_extract (vd, 3);
+
+ check (r == 136, "sums");
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr58460.c b/gcc/testsuite/gcc.target/aarch64/pr58460.c
new file mode 100644
index 00000000000..a7e149a371c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr58460.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+extern unsigned long x1;
+
+char *
+f (char *a, char *b)
+{
+ return a;
+}
+
+int
+g (char *a)
+{
+ return 2;
+}
+
+void
+h (char *p[])
+{
+ char n[x1][512];
+ char *l = f (p[1], " ");
+ if (g (p[0]))
+ n[0][0] = '\0';
+ while (l && *l)
+ {
+ }
+}
+
+unsigned long x1;
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
index 1b853084328..cad70ab6259 100644
--- a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
+++ b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
@@ -1,7 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-#include "../../../config/aarch64/arm_neon.h"
+#include <arm_neon.h>
+
+/* Used to force a variable to a SIMD register. */
+#define force_simd(V1) asm volatile ("mov %d0, %1.d[0]" \
+ : "=w"(V1) \
+ : "w"(V1) \
+ : /* No clobbers */);
/* { dg-final { scan-assembler-times "\\tadd\\tx\[0-9\]+" 2 } } */
@@ -31,7 +37,12 @@ test_vaddd_s64_2 (int64x1_t a, int64x1_t b, int64x1_t c, int64x1_t d)
uint64x1_t
test_vceqd_s64 (int64x1_t a, int64x1_t b)
{
- return vceqd_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vceqd_s64 (a, b);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmeq\\td\[0-9\]+, d\[0-9\]+, #?0" 1 } } */
@@ -39,7 +50,11 @@ test_vceqd_s64 (int64x1_t a, int64x1_t b)
uint64x1_t
test_vceqzd_s64 (int64x1_t a)
{
- return vceqzd_s64 (a);
+ uint64x1_t res;
+ force_simd (a);
+ res = vceqzd_s64 (a);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmge\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 2 } } */
@@ -47,21 +62,36 @@ test_vceqzd_s64 (int64x1_t a)
uint64x1_t
test_vcged_s64 (int64x1_t a, int64x1_t b)
{
- return vcged_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcged_s64 (a, b);
+ force_simd (res);
+ return res;
}
uint64x1_t
test_vcled_s64 (int64x1_t a, int64x1_t b)
{
- return vcled_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcled_s64 (a, b);
+ force_simd (res);
+ return res;
}
-/* { dg-final { scan-assembler-times "\\tcmge\\td\[0-9\]+, d\[0-9\]+, #?0" 1 } } */
+/* Idiom recognition will cause this testcase not to generate
+ the expected cmge instruction, so do not check for it. */
uint64x1_t
test_vcgezd_s64 (int64x1_t a)
{
- return vcgezd_s64 (a);
+ uint64x1_t res;
+ force_simd (a);
+ res = vcgezd_s64 (a);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmhs\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 1 } } */
@@ -69,7 +99,12 @@ test_vcgezd_s64 (int64x1_t a)
uint64x1_t
test_vcged_u64 (uint64x1_t a, uint64x1_t b)
{
- return vcged_u64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcged_u64 (a, b);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmgt\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 2 } } */
@@ -77,13 +112,23 @@ test_vcged_u64 (uint64x1_t a, uint64x1_t b)
uint64x1_t
test_vcgtd_s64 (int64x1_t a, int64x1_t b)
{
- return vcgtd_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcgtd_s64 (a, b);
+ force_simd (res);
+ return res;
}
uint64x1_t
test_vcltd_s64 (int64x1_t a, int64x1_t b)
{
- return vcltd_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcltd_s64 (a, b);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmgt\\td\[0-9\]+, d\[0-9\]+, #?0" 1 } } */
@@ -91,7 +136,11 @@ test_vcltd_s64 (int64x1_t a, int64x1_t b)
uint64x1_t
test_vcgtzd_s64 (int64x1_t a)
{
- return vcgtzd_s64 (a);
+ uint64x1_t res;
+ force_simd (a);
+ res = vcgtzd_s64 (a);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmhi\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 1 } } */
@@ -99,7 +148,12 @@ test_vcgtzd_s64 (int64x1_t a)
uint64x1_t
test_vcgtd_u64 (uint64x1_t a, uint64x1_t b)
{
- return vcgtd_u64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vcgtd_u64 (a, b);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tcmle\\td\[0-9\]+, d\[0-9\]+, #?0" 1 } } */
@@ -107,15 +161,24 @@ test_vcgtd_u64 (uint64x1_t a, uint64x1_t b)
uint64x1_t
test_vclezd_s64 (int64x1_t a)
{
- return vclezd_s64 (a);
+ uint64x1_t res;
+ force_simd (a);
+ res = vclezd_s64 (a);
+ force_simd (res);
+ return res;
}
-/* { dg-final { scan-assembler-times "\\tcmlt\\td\[0-9\]+, d\[0-9\]+, #?0" 1 } } */
+/* Idiom recognition will cause this testcase not to generate
+ the expected cmlt instruction, so do not check for it. */
uint64x1_t
test_vcltzd_s64 (int64x1_t a)
{
- return vcltzd_s64 (a);
+ uint64x1_t res;
+ force_simd (a);
+ res = vcltzd_s64 (a);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\tdup\\tb\[0-9\]+, v\[0-9\]+\.b" 2 } } */
@@ -179,13 +242,23 @@ test_vdupd_lane_u64 (uint64x2_t a)
int64x1_t
test_vtst_s64 (int64x1_t a, int64x1_t b)
{
- return vtstd_s64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vtstd_s64 (a, b);
+ force_simd (res);
+ return res;
}
uint64x1_t
test_vtst_u64 (uint64x1_t a, uint64x1_t b)
{
- return vtstd_u64 (a, b);
+ uint64x1_t res;
+ force_simd (a);
+ force_simd (b);
+ res = vtstd_s64 (a, b);
+ force_simd (res);
+ return res;
}
/* { dg-final { scan-assembler-times "\\taddp\\td\[0-9\]+, v\[0-9\]+\.2d" 1 } } */
@@ -722,7 +795,10 @@ test_vrshld_u64 (uint64x1_t a, uint64x1_t b)
return vrshld_u64 (a, b);
}
-/* { dg-final { scan-assembler-times "\\tasr\\tx\[0-9\]+" 1 } } */
+/* Other intrinsics can generate an asr instruction (vcltzd, vcgezd),
+ so we cannot check scan-assembler-times. */
+
+/* { dg-final { scan-assembler "\\tasr\\tx\[0-9\]+" } } */
int64x1_t
test_vshrd_n_s64 (int64x1_t a)
diff --git a/gcc/testsuite/gcc.target/arm/lp1189445.c b/gcc/testsuite/gcc.target/arm/lp1189445.c
new file mode 100644
index 00000000000..766748e5509
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/lp1189445.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon } */
+/* { dg-add-options arm_neon } */
+/* { dg-options "-O3" } */
+
+int id;
+int
+test (const long int *data)
+{
+ int i, retval;
+ retval = id;
+ for (i = 0; i < id; i++)
+ {
+ retval &= (data[i] <= 0);
+ }
+
+ return (retval);
+}
diff --git a/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c b/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c
new file mode 100644
index 00000000000..5f4c927b6e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c
@@ -0,0 +1,25 @@
+/* Test the `vst1Q_laneu64' ARM Neon intrinsic. */
+
+/* Detect ICE in the case of unaligned memory address. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+
+unsigned char dummy_store[1000];
+
+void
+foo (char* addr)
+{
+ uint8x16_t vdata = vld1q_u8 (addr);
+ vst1q_lane_u64 ((uint64_t*) &dummy_store, vreinterpretq_u64_u8 (vdata), 0);
+}
+
+uint64_t
+bar (uint64x2_t vdata)
+{
+ vdata = vld1q_lane_u64 ((uint64_t*) &dummy_store, vdata, 0);
+ return vgetq_lane_u64 (vdata, 0);
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr54300.C b/gcc/testsuite/gcc.target/arm/pr54300.C
new file mode 100644
index 00000000000..eb1a74e36cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr54300.C
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+#include <stdlib.h>
+
+struct __attribute__ ((aligned(8))) _v16u8_ {
+ uint8x16_t val;
+ _v16u8_( const int16x8_t &src) { val = vreinterpretq_u8_s16(src); }
+ operator int16x8_t () const { return vreinterpretq_s16_u8(val); }
+};
+typedef struct _v16u8_ v16u8;
+
+struct __attribute__ ((aligned(4))) _v8u8_ {
+ uint8x8_t val;
+ _v8u8_( const uint8x8_t &src) { val = src; }
+ operator int16x4_t () const { return vreinterpret_s16_u8(val); }
+};
+typedef struct _v8u8_ v8u8;
+
+typedef v16u8 v8i16;
+typedef int32x4_t v4i32;
+typedef const short cv1i16;
+typedef const unsigned char cv1u8;
+typedef const v8i16 cv8i16;
+
+static inline __attribute__((always_inline)) v8u8 zero_64(){ return vdup_n_u8( 0 ); }
+
+static inline __attribute__((always_inline)) v8i16 loadlo_8i16( cv8i16* p ){
+ return vcombine_s16( vld1_s16( (cv1i16 *)p ), zero_64() );
+}
+static inline __attribute__((always_inline)) v8i16 _loadlo_8i16( cv8i16* p, int offset ){
+ return loadlo_8i16( (cv8i16*)(&((cv1u8*)p)[offset]) );
+}
+
+void __attribute__((noinline))
+test(unsigned short *_Inp, int32_t *_Out,
+ unsigned int s1v, unsigned int dv0,
+ unsigned int smask_v)
+{
+ int32x4_t c = vdupq_n_s32(0);
+
+ for(unsigned int sv=0 ; sv!=dv0 ; sv=(sv+s1v)&smask_v )
+ {
+ int32x4_t s;
+ s = vmovl_s16( vget_low_s16( _loadlo_8i16( (cv8i16*) _Inp, sv ) ) );
+ c = vaddq_s32( c, s );
+ }
+ vst1q_s32( _Out, c );
+}
+
+main()
+{
+ unsigned short a[4] = {1, 2, 3, 4};
+ int32_t b[4] = {0, 0, 0, 0};
+ test(a, b, 1, 1, ~0);
+ if (b[0] != 1 || b[1] != 2 || b[2] != 3 || b[3] != 4)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr58041.c b/gcc/testsuite/gcc.target/arm/pr58041.c
new file mode 100644
index 00000000000..481a72b81c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58041.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mno-unaligned-access" } */
+/* { dg-final { scan-assembler "ldrb" } } */
+/* { dg-final { scan-assembler "strb" } } */
+
+struct s
+{
+ char u;
+ long long v[2];
+} __attribute__((packed,aligned(1)));
+
+__attribute__((noinline, noclone))
+long long foo(struct s *x, int y, long long z)
+{
+ long long a = x->v[y];
+ x->v[y] = z;
+ return a;
+}
+
+struct s a = {0,{0,0}};
+int main()
+{
+ if (foo(&a,0,1) != 0)
+ __builtin_abort();
+ if (foo(&a,0,2) != 1)
+ __builtin_abort();
+ if (foo(&a,1,1) != 0)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
new file mode 100644
index 00000000000..bd85e8640c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-g -fPIC" } */
+
+void *v;
+void a (void *x) { }
+void b (void) { }
+ /* line 7. */
+int /* line 8. */
+main (int argc) /* line 9. */
+{ /* line 10. */
+ if (argc == 12345) /* line 11. */
+ {
+ a (v);
+ return 1;
+ }
+ b ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "\.loc 1 7 0" } } */
+/* { dg-final { scan-assembler-not "\.loc 1 8 0" } } */
+/* { dg-final { scan-assembler-not "\.loc 1 9 0" } } */
+
+/* The loc at the start of the prologue. */
+/* { dg-final { scan-assembler-times "\.loc 1 10 0" 1 } } */
+
+/* The loc at the end of the prologue, with the first user line. */
+/* { dg-final { scan-assembler-times "\.loc 1 11 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/thumb1-Os-mult.c b/gcc/testsuite/gcc.target/arm/thumb1-Os-mult.c
new file mode 100644
index 00000000000..31b8bd69227
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb1-Os-mult.c
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "" { ! { arm_thumb1 } } } */
+
+int
+mymul3 (int x)
+{
+ return x * 0x555;
+}
+
+/* { dg-final { scan-assembler "mul\[\\t \]*r.,\[\\t \]*r." } } */
diff --git a/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c b/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c
new file mode 100644
index 00000000000..df269fc8476
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-options "-mthumb -fpic -mpic-register=9" } */
+
+int g_test;
+
+int
+foo (int par)
+{
+ g_test = par;
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c b/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c
new file mode 100644
index 00000000000..6e9b2570a4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-options "-mthumb -fpic -msingle-pic-base" } */
+
+int g_test;
+
+int
+foo (int par)
+{
+ g_test = par;
+}
diff --git a/gcc/testsuite/gcc.target/arm/vrinta-ce.c b/gcc/testsuite/gcc.target/arm/vrinta-ce.c
new file mode 100644
index 00000000000..71c5b3b0e37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vrinta-ce.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2 -marm -march=armv8-a" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double foo (double a)
+{
+ if (a > 3.0)
+ return __builtin_round (a);
+
+ return 0.0;
+}
+
+/* { dg-final { scan-assembler-times "vrinta.f64\td\[0-9\]+" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c b/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c
index 6ad0775553a..46e915a6c87 100644
--- a/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c
+++ b/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c
@@ -72,11 +72,11 @@ DEFTEST1 (long long accum, llk)
static void test2hr (void)
{
- TEST2 (hr, 1, 0x7f, 0x40);
- TEST2 (hr, 2, 0x7f, 0b1100000);
- TEST2 (hr, 3, 0x7f, 0b1110000);
- TEST2 (hr, 4, 0x7f, 0b1111000);
-
+ TEST2 (hr, 1, 0x7f, 0x7f);
+ TEST2 (hr, 2, 0x70, 0x7f);
+ TEST2 (hr, 3, 0x78, 0x7f);
+ TEST2 (hr, 4, 0x7f, 0x7f);
+
TEST2 (uhr, 1, 0x7f, 0x80);
TEST2 (uhr, 2, 0x7f, 0x80);
TEST2 (uhr, 3, 0x7f, 0x80);
@@ -85,10 +85,13 @@ static void test2hr (void)
void test2k (void)
{
- TEST2 (k, 1, 0x7fffffff, 0x7fff8000 | 0b100000000000000);
- TEST2 (k, 2, 0x7fffffff, 0x7fff8000 | 0b110000000000000);
- TEST2 (k, 3, 0x7fffffff, 0x7fff8000 | 0b111000000000000);
- TEST2 (k, 4, 0x7fffffff, 0x7fff8000 | 0b111100000000000);
+ TEST2 (k, 1, 0x7fffff00, 0x7fffffff);
+ TEST2 (k, 2, 0x7ffffff0, 0x7fffffff);
+ TEST2 (k, 2, 0x7ffff000, 0x7fffffff);
+ TEST2 (k, 3, 0x7ffff000, 0x7ffff000);
+ TEST2 (k, 3, 0x7ffff800, 0x7fffffff);
+ TEST2 (k, 3, 0x7ffff7ff, 0x7ffff000);
+ TEST2 (k, 4, 0x7ffff7ff, 0x7ffff800);
TEST2 (uk, 1, 0x7fffffff, 1ul << 31);
TEST2 (uk, 2, 0x7fffffff, 1ul << 31);
diff --git a/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-1.c b/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-1.c
index d9121228307..cc524c8a641 100644
--- a/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-1.c
@@ -15,7 +15,7 @@ void static
avx_test (void)
{
union256d u;
- double e [4] __attribute__ ((aligned (8))) = {41124.234,2344.2354,8653.65635,856.43576};
+ double e [4] __attribute__ ((aligned (32))) = {41124.234,2344.2354,8653.65635,856.43576};
u.x = test (e);
diff --git a/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-2.c b/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-2.c
index 96a664ac11e..9224484cac1 100644
--- a/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx-vmovapd-256-2.c
@@ -15,7 +15,7 @@ void static
avx_test (void)
{
union256d u;
- double e [4] __attribute__ ((aligned (8))) = {0.0};
+ double e [4] __attribute__ ((aligned (32))) = {0.0};
u.x = _mm256_set_pd (39578.467285, 7856.342941, 85632.783567, 47563.234215);
diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-16.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-16.c
index bc6e0d23c7d..b64add14e6b 100644
--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-16.c
+++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-16.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-O2 -mavx -mabi=ms -mtune=generic -dp" } */
+/* { dg-options "-O2 -mavx -mabi=ms -maccumulate-outgoing-args -dp" } */
typedef float __m256 __attribute__ ((__vector_size__ (32), __may_alias__));
diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
index 5d3aa48397c..16d29958c7e 100644
--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
+++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-17.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-O2 -mavx -mabi=ms -mtune=generic -dp" } */
+/* { dg-options "-O2 -mavx -mabi=ms -maccumulate-outgoing-args -dp" } */
typedef float __m256 __attribute__ ((__vector_size__ (32), __may_alias__));
diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-18.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-18.c
index 06307525d46..4dcb00f6f11 100644
--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-18.c
+++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-O0 -mavx -mabi=ms -mtune=generic -dp" } */
+/* { dg-options "-O0 -mavx -mabi=ms -maccumulate-outgoing-args -dp" } */
typedef float __m256 __attribute__ ((__vector_size__ (32), __may_alias__));
diff --git a/gcc/testsuite/gcc.target/i386/bmi-1.c b/gcc/testsuite/gcc.target/i386/bmi-1.c
index dc964ba3d92..c66a9d83b29 100644
--- a/gcc/testsuite/gcc.target/i386/bmi-1.c
+++ b/gcc/testsuite/gcc.target/i386/bmi-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mbmi " } */
-/* { dg-final { scan-assembler "andn\[^\\n]*(%|)eax" } } */
-/* { dg-final { scan-assembler "bextr\[^\\n]*(%|)eax" } } */
-/* { dg-final { scan-assembler "blsi\[^\\n]*(%|)eax" } } */
-/* { dg-final { scan-assembler "blsmsk\[^\\n]*(%|)eax" } } */
-/* { dg-final { scan-assembler "blsr\[^\\n]*(%|)eax" } } */
-/* { dg-final { scan-assembler "tzcntl\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "andn\[^\\n]*eax" } } */
+/* { dg-final { scan-assembler-times "bextr\[ \\t]+\[^\\n]*eax" 2 } } */
+/* { dg-final { scan-assembler-times "blsi\[^\\n]*eax" 2 } } */
+/* { dg-final { scan-assembler-times "blsmsk\[^\\n]*eax" 2 } } */
+/* { dg-final { scan-assembler-times "blsr\[^\\n]*eax" 2 } } */
+/* { dg-final { scan-assembler-times "tzcntl\[^\\n]*eax" 2 } } */
#include <x86intrin.h>
@@ -22,25 +22,57 @@ func_bextr32 (unsigned int X, unsigned int Y)
}
unsigned int
+func_bextr32_3args (unsigned int X,
+ unsigned int Y,
+ unsigned int Z)
+{
+ return _bextr_u32(X, Y, Z);
+}
+
+unsigned int
func_blsi32 (unsigned int X)
{
return __blsi_u32(X);
}
unsigned int
+func_blsi32_2 (unsigned int X)
+{
+ return _blsi_u32(X);
+}
+
+unsigned int
func_blsmsk32 (unsigned int X)
{
return __blsmsk_u32(X);
}
unsigned int
+func_blsmsk32_2 (unsigned int X)
+{
+ return _blsmsk_u32(X);
+}
+
+unsigned int
func_blsr32 (unsigned int X)
{
return __blsr_u32(X);
}
unsigned int
+func_blsr32_2 (unsigned int X)
+{
+ return _blsr_u32(X);
+}
+
+unsigned int
func_tzcnt32 (unsigned int X)
{
return __tzcnt_u32(X);
}
+
+unsigned int
+func_tzcnt32_2 (unsigned int X)
+{
+ return _tzcnt_u32(X);
+}
diff --git a/gcc/testsuite/gcc.target/i386/bmi-2.c b/gcc/testsuite/gcc.target/i386/bmi-2.c
index 56f73876d0c..6eea66aa0f6 100644
--- a/gcc/testsuite/gcc.target/i386/bmi-2.c
+++ b/gcc/testsuite/gcc.target/i386/bmi-2.c
@@ -1,11 +1,11 @@
/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-options "-O2 -mbmi " } */
-/* { dg-final { scan-assembler "andn\[^\\n]*(%|)rax" } } */
-/* { dg-final { scan-assembler "bextr\[^\\n]*(%|)rax" } } */
-/* { dg-final { scan-assembler "blsi\[^\\n]*(%|)rax" } } */
-/* { dg-final { scan-assembler "blsmsk\[^\\n]*(%|)rax" } } */
-/* { dg-final { scan-assembler "blsr\[^\\n]*(%|)rax" } } */
-/* { dg-final { scan-assembler "tzcntq\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "andn\[^\\n]*rax" } } */
+/* { dg-final { scan-assembler-times "bextr\[ \\t]+\[^\\n]*rax" 2 } } */
+/* { dg-final { scan-assembler-times "blsi\[^\\n]*rax" 2 } } */
+/* { dg-final { scan-assembler-times "blsmsk\[^\\n]*rax" 2 } } */
+/* { dg-final { scan-assembler-times "blsr\[^\\n]*rax" 2 } } */
+/* { dg-final { scan-assembler-times "tzcntq\[^\\n]*rax" 2 } } */
#include <x86intrin.h>
@@ -22,25 +22,57 @@ func_bextr64 (unsigned long long X, unsigned long long Y)
}
unsigned long long
+func_bextr64_3args (unsigned long long X,
+ unsigned long long Y,
+ unsigned long long Z)
+{
+ return _bextr_u64 (X, Y, Z);
+}
+
+unsigned long long
func_blsi64 (unsigned long long X)
{
return __blsi_u64 (X);
}
unsigned long long
+func_blsi64_2 (unsigned long long X)
+{
+ return _blsi_u64 (X);
+}
+
+unsigned long long
func_blsmsk64 (unsigned long long X)
{
return __blsmsk_u64 (X);
}
unsigned long long
+func_blsmsk64_2 (unsigned long long X)
+{
+ return _blsmsk_u64 (X);
+}
+
+unsigned long long
func_blsr64 (unsigned long long X)
{
return __blsr_u64 (X);
}
unsigned long long
+func_blsr64_2 (unsigned long long X)
+{
+ return _blsr_u64 (X);
+}
+
+unsigned long long
func_tzcnt64 (unsigned long long X)
{
return __tzcnt_u64 (X);
}
+
+unsigned long long
+func_tzcnt64_2 (unsigned long long X)
+{
+ return _tzcnt_u64 (X);
+}
diff --git a/gcc/testsuite/gcc.target/i386/movabs-1.c b/gcc/testsuite/gcc.target/i386/movabs-1.c
new file mode 100644
index 00000000000..75ef8d2a6cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/movabs-1.c
@@ -0,0 +1,10 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -masm=intel" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target masm_intel } */
+
+void
+foo (void)
+{
+ *(volatile long*)0xFFFF800000000000 = -1;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr30315.c b/gcc/testsuite/gcc.target/i386/pr30315.c
index 998d5071e5c..557b4f75174 100644
--- a/gcc/testsuite/gcc.target/i386/pr30315.c
+++ b/gcc/testsuite/gcc.target/i386/pr30315.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-times "cmp" 4 } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
extern void abort (void);
int c;
@@ -34,39 +34,10 @@ void pluscconly##t##C (T a, T b) \
}
#define PLUSCCONLY(T, t) PLUSCCONLY1(T, t, a) PLUSCCONLY1(T, t, b)
-#define MINUSCC(T, t) \
-T minuscc##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- abort (); \
- return difference; \
-}
-
-#define DECCC(T, t) \
-T deccc##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- c --; \
- return difference; \
-}
-
-#define MINUSCCONLY(T, t) \
-void minuscconly##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- abort (); \
-}
-
#define TEST(T, t) \
PLUSCC(T, t) \
PLUSCCONLY(T, t) \
- INCCC(T, t) \
- MINUSCC(T, t) \
- MINUSCCONLY(T, t) \
- DECCC(T, t)
+ INCCC(T, t)
TEST (unsigned long, l)
TEST (unsigned int, i)
@@ -84,14 +55,3 @@ unsigned long pluscczext##C (unsigned int a, unsigned int b) \
PLUSCCZEXT(a)
PLUSCCZEXT(b)
-
-#define MINUSCCZEXT \
-unsigned long minuscczext (unsigned int a, unsigned int b) \
-{ \
- unsigned int difference = a - b; \
- if (difference > a) \
- abort (); \
- return difference; \
-}
-
-MINUSCCZEXT
diff --git a/gcc/testsuite/gcc.target/i386/pr43662.c b/gcc/testsuite/gcc.target/i386/pr43662.c
index 2896a1a52c3..2d87ddfb5d9 100644
--- a/gcc/testsuite/gcc.target/i386/pr43662.c
+++ b/gcc/testsuite/gcc.target/i386/pr43662.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target lp64 } } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -maccumulate-outgoing-args" } */
void __attribute__ ((ms_abi)) foo (void)
{
diff --git a/gcc/testsuite/gcc.target/i386/pr43869.c b/gcc/testsuite/gcc.target/i386/pr43869.c
index 4157db1d168..fbcd4d97ad9 100644
--- a/gcc/testsuite/gcc.target/i386/pr43869.c
+++ b/gcc/testsuite/gcc.target/i386/pr43869.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target lp64 } } */
+/* { dg-options "-maccumulate-outgoing-args" } */
int __attribute__((__noinline__))
bugged(float f1, float f2, float f3, float f4,
diff --git a/gcc/testsuite/gcc.target/i386/pr57003.c b/gcc/testsuite/gcc.target/i386/pr57003.c
index dfa6b8b5095..91b4f5402e6 100644
--- a/gcc/testsuite/gcc.target/i386/pr57003.c
+++ b/gcc/testsuite/gcc.target/i386/pr57003.c
@@ -1,6 +1,6 @@
/* PR rtl-optimization/57003 */
/* { dg-do run } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -maccumulate-outgoing-args" } */
#define N 2001
unsigned short *b, *c, *d;
diff --git a/gcc/testsuite/gcc.target/i386/pr57459.c b/gcc/testsuite/gcc.target/i386/pr57459.c
new file mode 100644
index 00000000000..75101145afc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr57459.c
@@ -0,0 +1,60 @@
+/* PR rtl-optimization/57459 */
+/* { dg-do run } */
+/* { dg-options "-fno-inline -O2 -minline-all-stringops -fno-omit-frame-pointer" } */
+
+int total1[10], total2[10], total3[10], total4[10], total5[10], a[20];
+int len;
+
+void stackclean() {
+ void *ptr = __builtin_alloca(20000);
+ __builtin_memset(ptr, 0, 20000);
+}
+
+void foo(const char *s) {
+ int r1 = a[1];
+ int r2 = a[2];
+ int r3 = a[3];
+ int r4 = a[4];
+ int r5 = a[5];
+
+ len = __builtin_strlen(s);
+
+ if (s != 0)
+ return;
+
+ while (r1) {
+ total1[r1] = r1;
+ r1--;
+ }
+
+ while (r2) {
+ total2[r2] = r2;
+ r2--;
+ }
+
+ while (r3) {
+ total3[r3] = r3;
+ r3--;
+ }
+
+ while (r4) {
+ total4[r4] = r4;
+ r4--;
+ }
+
+ while (r5) {
+ total5[r5] = r5;
+ r5--;
+ }
+}
+
+extern void abort (void);
+
+int main() {
+ stackclean();
+ foo("abcdefgh");
+ if (len != 8)
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr58137.c b/gcc/testsuite/gcc.target/i386/pr58137.c
new file mode 100644
index 00000000000..0a7daf83cd5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58137.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx2" } */
+
+typedef unsigned int U32;
+
+struct sv {
+ void* sv_any;
+ U32 sv_refcnt;
+ U32 sv_flags;
+};
+typedef struct sv SV;
+
+struct xrv {
+ SV * xrv_rv;
+};
+typedef struct xrv XRV;
+
+extern XRV * PL_xrv_root;
+
+void
+more_xrv (void)
+{
+ register XRV* xrv;
+ register XRV* xrvend;
+ xrv = PL_xrv_root;
+ xrvend = &xrv[200 / sizeof (XRV) - 1];
+ while (xrv < xrvend)
+ {
+ xrv->xrv_rv = (SV*)(xrv + 1);
+ xrv++;
+ }
+ xrv->xrv_rv = 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58218.c b/gcc/testsuite/gcc.target/i386/pr58218.c
new file mode 100644
index 00000000000..4145242059f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58218.c
@@ -0,0 +1,5 @@
+/* PR target/58218 */
+/* { dg-do assemble { target lp64 } } */
+/* { dg-options "-mcmodel=medium" } */
+
+struct { float x[16385]; } a = { { 0.f, } };
diff --git a/gcc/testsuite/gcc.target/i386/pr58690.c b/gcc/testsuite/gcc.target/i386/pr58690.c
new file mode 100644
index 00000000000..87a87cc9c90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58690.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -mx32 -maddress-mode=short" } */
+
+struct gomp_thread
+{
+ char foo[41];
+};
+extern __thread struct gomp_thread gomp_tls_data;
+void
+foo (void)
+{
+ __builtin_memset (&gomp_tls_data, '\0', sizeof (gomp_tls_data));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59021.c b/gcc/testsuite/gcc.target/i386/pr59021.c
new file mode 100644
index 00000000000..a1df27b105e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59021.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mvzeroupper" } */
+
+extern void abort (void);
+
+struct S {
+ int i1;
+ int i2;
+ int i3;
+};
+
+typedef double v4df __attribute__ ((vector_size (32)));
+
+extern int foo (v4df, int i1, int i2, int i3, int i4, int i5, struct S s);
+
+void bar (v4df v, struct S s)
+{
+ int r = foo (v, 1, 2, 3, 4, 5, s);
+ if (r)
+ abort ();
+}
+
+/* { dg-final { scan-assembler-not "vzeroupper" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr59034-1.c b/gcc/testsuite/gcc.target/i386/pr59034-1.c
new file mode 100644
index 00000000000..1f4c4e04a23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59034-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O -mx32 -mtune=corei7 -maddress-mode=short" } */
+
+extern int foo(int, ...);
+int bar(void) {
+ long double l = 1.2345E6;
+ foo(0, l);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59034-2.c b/gcc/testsuite/gcc.target/i386/pr59034-2.c
new file mode 100644
index 00000000000..14e594ba608
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59034-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O -mx32 -mtune=corei7 -maddress-mode=long" } */
+
+extern int foo(int, ...);
+int bar(void) {
+ long double l = 1.2345E6;
+ foo(0, l);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59405.c b/gcc/testsuite/gcc.target/i386/pr59405.c
new file mode 100644
index 00000000000..1136e2e4501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59405.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-mmmx -mfpmath=387" } */
+
+#include "mmx-check.h"
+
+#include <mmintrin.h>
+
+typedef float float32x2_t __attribute__ ((vector_size (8)));
+
+float
+foo32x2_be (float32x2_t x)
+{
+ _mm_empty ();
+ return x[1];
+}
+
+static void
+mmx_test (void)
+{
+ float32x2_t b = { 0.0f, 1.0f };
+
+ if (foo32x2_be (b) != 1.0f)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59470.c b/gcc/testsuite/gcc.target/i386/pr59470.c
new file mode 100644
index 00000000000..0d9952fb4b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59470.c
@@ -0,0 +1,17 @@
+/* PR middle-end/58956 */
+/* PR middle-end/59470 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a, b, d[1024];
+
+int
+main ()
+{
+ int c = a;
+ asm ("{movl $6, (%2); movl $1, %0|mov dword ptr [%2], 6; mov %0, 1}"
+ : "=r" (d[c]) : "rm" (b), "r" (&a) : "memory");
+ if (d[0] != 1 || d[6] != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59625.c b/gcc/testsuite/gcc.target/i386/pr59625.c
new file mode 100644
index 00000000000..8e1a7794bc4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59625.c
@@ -0,0 +1,36 @@
+/* PR target/59625 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=atom" } */
+
+int
+foo (void)
+{
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ asm goto ("" : : : : lab);
+ return 0;
+lab:
+ return 1;
+}
+
+/* Verify we don't consider asm goto as a jump for four jumps limit
+ optimization. asm goto doesn't have to contain a jump at all,
+ the branching to labels can happen through different means. */
+/* { dg-final { scan-assembler-not "(p2align\[^\n\r\]*\[\n\r]*\[^\n\r\]*){8}p2align" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-movapd-1.c b/gcc/testsuite/gcc.target/i386/sse2-movapd-1.c
index b8b9dba0c20..55d9f594f55 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-movapd-1.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-movapd-1.c
@@ -25,7 +25,7 @@ static void
TEST (void)
{
union128d u;
- double e[2] __attribute__ ((aligned (8))) = {2134.3343,1234.635654};
+ double e[2] __attribute__ ((aligned (16))) = {2134.3343,1234.635654};
u.x = test (e);
diff --git a/gcc/testsuite/gcc.target/i386/sse2-movapd-2.c b/gcc/testsuite/gcc.target/i386/sse2-movapd-2.c
index 8298551baf5..87da332779a 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-movapd-2.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-movapd-2.c
@@ -25,7 +25,7 @@ static void
TEST (void)
{
union128d u;
- double e[2] __attribute__ ((aligned (8))) = {0.0};
+ double e[2] __attribute__ ((aligned (16))) = {0.0};
u.x = _mm_set_pd (2134.3343,1234.635654);
diff --git a/gcc/testsuite/gcc.target/i386/xop-frczX.c b/gcc/testsuite/gcc.target/i386/xop-frczX.c
new file mode 100644
index 00000000000..931b5ce397b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xop-frczX.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-require-effective-target xop } */
+/* { dg-options "-O2 -mxop" } */
+
+#include "xop-check.h"
+
+#include <x86intrin.h>
+
+void
+check_mm_vmfrcz_sd (__m128d __A, __m128d __B)
+{
+ union128d a, b, c;
+ double d[2];
+
+ a.x = __A;
+ b.x = __B;
+ c.x = _mm_frcz_sd (__A, __B);
+ d[0] = b.a[0] - (int)b.a[0] ;
+ d[1] = a.a[1];
+ if (check_union128d (c, d))
+ abort ();
+}
+
+void
+check_mm_vmfrcz_ss (__m128 __A, __m128 __B)
+{
+ union128 a, b, c;
+ float f[4];
+
+ a.x = __A;
+ b.x = __B;
+ c.x = _mm_frcz_ss (__A, __B);
+ f[0] = b.a[0] - (int)b.a[0] ;
+ f[1] = a.a[1];
+ f[2] = a.a[2];
+ f[3] = a.a[3];
+ if (check_union128 (c, f))
+ abort ();
+}
+
+static void
+xop_test (void)
+{
+ union128 a, b;
+ union128d c,d;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ a.a[i] = i + 3.5;
+ b.a[i] = i + 7.9;
+ }
+ for (i = 0; i < 2; i++)
+ {
+ c.a[i] = i + 3.5;
+ d.a[i] = i + 7.987654321;
+ }
+ check_mm_vmfrcz_ss (a.x, b.x);
+ check_mm_vmfrcz_sd (c.x, d.x);
+}
diff --git a/gcc/testsuite/gcc.target/mips/bswap-1.c b/gcc/testsuite/gcc.target/mips/bswap-1.c
new file mode 100644
index 00000000000..24016f26931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-1.c
@@ -0,0 +1,10 @@
+/* { dg-options "isa_rev>=2" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+NOMIPS16 unsigned short
+foo (unsigned short x)
+{
+ return ((x << 8) & 0xff00) | ((x >> 8) & 0xff);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-2.c b/gcc/testsuite/gcc.target/mips/bswap-2.c
new file mode 100644
index 00000000000..e0ca496b6d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-2.c
@@ -0,0 +1,9 @@
+/* { dg-options "isa_rev>=2" } */
+
+NOMIPS16 unsigned short
+foo (unsigned short x)
+{
+ return __builtin_bswap16 (x);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-3.c b/gcc/testsuite/gcc.target/mips/bswap-3.c
new file mode 100644
index 00000000000..5d2086fd324
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-3.c
@@ -0,0 +1,14 @@
+/* { dg-options "isa_rev>=2" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+NOMIPS16 unsigned int
+foo (unsigned int x)
+{
+ return (((x << 24) & 0xff000000)
+ | ((x << 8) & 0xff0000)
+ | ((x >> 8) & 0xff00)
+ | ((x >> 24) & 0xff));
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
+/* { dg-final { scan-assembler "\tror\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-4.c b/gcc/testsuite/gcc.target/mips/bswap-4.c
new file mode 100644
index 00000000000..ac37a011440
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-4.c
@@ -0,0 +1,10 @@
+/* { dg-options "isa_rev>=2" } */
+
+NOMIPS16 unsigned int
+foo (unsigned int x)
+{
+ return __builtin_bswap32 (x);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
+/* { dg-final { scan-assembler "\tror\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-5.c b/gcc/testsuite/gcc.target/mips/bswap-5.c
new file mode 100644
index 00000000000..45520e4ab85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-5.c
@@ -0,0 +1,20 @@
+/* { dg-options "isa_rev>=2 -mgp64" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned long long uint64_t;
+
+NOMIPS16 uint64_t
+foo (uint64_t x)
+{
+ return (((x << 56) & 0xff00000000000000ull)
+ | ((x << 40) & 0xff000000000000ull)
+ | ((x << 24) & 0xff0000000000ull)
+ | ((x << 8) & 0xff00000000ull)
+ | ((x >> 8) & 0xff000000)
+ | ((x >> 24) & 0xff0000)
+ | ((x >> 40) & 0xff00)
+ | ((x >> 56) & 0xff));
+}
+
+/* { dg-final { scan-assembler "\tdsbh\t" } } */
+/* { dg-final { scan-assembler "\tdshd\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-6.c b/gcc/testsuite/gcc.target/mips/bswap-6.c
new file mode 100644
index 00000000000..1145357fef1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-6.c
@@ -0,0 +1,12 @@
+/* { dg-options "isa_rev>=2 -mgp64" } */
+
+typedef unsigned long long uint64_t;
+
+NOMIPS16 uint64_t
+foo (uint64_t x)
+{
+ return __builtin_bswap64 (x);
+}
+
+/* { dg-final { scan-assembler "\tdsbh\t" } } */
+/* { dg-final { scan-assembler "\tdshd\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/pr59137.c b/gcc/testsuite/gcc.target/mips/pr59137.c
new file mode 100644
index 00000000000..89865065680
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr59137.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-mno-plt" } */
+
+extern void abort (void);
+
+struct lispstruct
+{
+ int e;
+ int t;
+};
+
+struct lispstruct Cnil_body;
+struct lispstruct Ct_body;
+int nvalues;
+
+struct lispstruct * __attribute__ ((noinline))
+fLlistp (struct lispstruct *x0)
+{
+ if (x0 == &Cnil_body
+ || (((unsigned long) x0 >= 0x80000000) ? 0
+ : (!x0->e ? (x0 != &Cnil_body) : x0->t)))
+ x0 = &Ct_body;
+ else
+ x0 = &Cnil_body;
+ nvalues = 1;
+ return x0;
+}
+
+int main ()
+{
+ if (fLlistp ((struct lispstruct *) 0xa0000001) != &Cnil_body)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
index ee5c5eee900..c3cf67e44f4 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
@@ -19,19 +19,6 @@ V b4(V x)
return __builtin_shuffle(x, (V){ 4,5,6,7, 4,5,6,7, 4,5,6,7, 4,5,6,7, });
}
-V p2(V x, V y)
-{
- return __builtin_shuffle(x, y,
- (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 });
-
-}
-
-V p4(V x, V y)
-{
- return __builtin_shuffle(x, y,
- (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 });
-}
-
V h1(V x, V y)
{
return __builtin_shuffle(x, y,
@@ -72,5 +59,3 @@ V l4(V x, V y)
/* { dg-final { scan-assembler "vspltb" } } */
/* { dg-final { scan-assembler "vsplth" } } */
/* { dg-final { scan-assembler "vspltw" } } */
-/* { dg-final { scan-assembler "vpkuhum" } } */
-/* { dg-final { scan-assembler "vpkuwum" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c
new file mode 100644
index 00000000000..d0b671eac77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
+/* { dg-options "-O -maltivec -mno-vsx" } */
+
+typedef unsigned char V __attribute__((vector_size(16)));
+
+V p2(V x, V y)
+{
+ return __builtin_shuffle(x, y,
+ (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 });
+
+}
+
+V p4(V x, V y)
+{
+ return __builtin_shuffle(x, y,
+ (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 });
+}
+
+/* { dg-final { scan-assembler-not "vperm" } } */
+/* { dg-final { scan-assembler "vpkuhum" } } */
+/* { dg-final { scan-assembler "vpkuwum" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-av.c b/gcc/testsuite/gcc.target/powerpc/bool3-av.c
index 4ef82c8cd97..d4aac786b2c 100644
--- a/gcc/testsuite/gcc.target/powerpc/bool3-av.c
+++ b/gcc/testsuite/gcc.target/powerpc/bool3-av.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
/* { dg-options "-O2 -mcpu=power6 -mabi=altivec -maltivec -mno-vsx" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p7.c b/gcc/testsuite/gcc.target/powerpc/bool3-p7.c
index a077ba5aea7..34e3c9e79dd 100644
--- a/gcc/testsuite/gcc.target/powerpc/bool3-p7.c
+++ b/gcc/testsuite/gcc.target/powerpc/bool3-p7.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O2 -mcpu=power7" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p8.c b/gcc/testsuite/gcc.target/powerpc/bool3-p8.c
index 361a0452d7d..e1b2dfa7ee2 100644
--- a/gcc/testsuite/gcc.target/powerpc/bool3-p8.c
+++ b/gcc/testsuite/gcc.target/powerpc/bool3-p8.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-O2 -mcpu=power8" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/darwin-longlong.c b/gcc/testsuite/gcc.target/powerpc/darwin-longlong.c
index 0692b3d8069..14b56d0828b 100644
--- a/gcc/testsuite/gcc.target/powerpc/darwin-longlong.c
+++ b/gcc/testsuite/gcc.target/powerpc/darwin-longlong.c
@@ -11,7 +11,11 @@ int msw(long long in)
int i[2];
} ud;
ud.ll = in;
+#ifdef __LITTLE_ENDIAN__
+ return ud.i[1];
+#else
return ud.i[0];
+#endif
}
int main()
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-dd-2.c b/gcc/testsuite/gcc.target/powerpc/dfp-dd-2.c
new file mode 100644
index 00000000000..fcb72bdff2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-dd-2.c
@@ -0,0 +1,26 @@
+/* Test generation of DFP instructions for POWER6. */
+/* { dg-do compile { target { powerpc*-*-linux* && powerpc_fprs } } } */
+/* { dg-options "-std=gnu99 -O1 -mcpu=power6" } */
+
+/* { dg-final { scan-assembler-times "fneg" 1 } } */
+/* { dg-final { scan-assembler-times "fabs" 1 } } */
+/* { dg-final { scan-assembler-times "fnabs" 1 } } */
+/* { dg-final { scan-assembler-times "fmr" 0 } } */
+
+_Decimal64
+func1 (_Decimal64 a, _Decimal64 b)
+{
+ return -b;
+}
+
+_Decimal64
+func2 (_Decimal64 a, _Decimal64 b)
+{
+ return __builtin_fabsd64 (b);
+}
+
+_Decimal64
+func3 (_Decimal64 a, _Decimal64 b)
+{
+ return - __builtin_fabsd64 (b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-td-2.c b/gcc/testsuite/gcc.target/powerpc/dfp-td-2.c
new file mode 100644
index 00000000000..a078cc46980
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-td-2.c
@@ -0,0 +1,29 @@
+/* Test generation of DFP instructions for POWER6. */
+/* { dg-do compile { target { powerpc*-*-linux* && powerpc_fprs } } } */
+/* { dg-options "-std=gnu99 -O1 -mcpu=power6" } */
+
+/* { dg-final { scan-assembler-times "fneg" 1 } } */
+/* { dg-final { scan-assembler-times "fabs" 1 } } */
+/* { dg-final { scan-assembler-times "fnabs" 1 } } */
+/* { dg-final { scan-assembler-times "fmr" 0 } } */
+
+/* These tests verify we only generate fneg, fabs and fnabs
+ instructions and no fmr's since these are done in place. */
+
+_Decimal128
+func1 (_Decimal128 a)
+{
+ return -a;
+}
+
+_Decimal128
+func2 (_Decimal128 a)
+{
+ return __builtin_fabsd128 (a);
+}
+
+_Decimal128
+func3 (_Decimal128 a)
+{
+ return - __builtin_fabsd128 (a);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-td-3.c b/gcc/testsuite/gcc.target/powerpc/dfp-td-3.c
new file mode 100644
index 00000000000..e825e5cad28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-td-3.c
@@ -0,0 +1,29 @@
+/* Test generation of DFP instructions for POWER6. */
+/* { dg-do compile { target { powerpc*-*-linux* && powerpc_fprs } } } */
+/* { dg-options "-std=gnu99 -O1 -mcpu=power6" } */
+
+/* { dg-final { scan-assembler-times "fneg" 1 } } */
+/* { dg-final { scan-assembler-times "fabs" 1 } } */
+/* { dg-final { scan-assembler-times "fnabs" 1 } } */
+/* { dg-final { scan-assembler-times "fmr" 3 } } */
+
+/* These tests verify we generate fneg, fabs and fnabs and
+ associated fmr's since these are not done in place. */
+
+_Decimal128
+func1 (_Decimal128 a, _Decimal128 b)
+{
+ return -b;
+}
+
+_Decimal128
+func2 (_Decimal128 a, _Decimal128 b)
+{
+ return __builtin_fabsd128 (b);
+}
+
+_Decimal128
+func3 (_Decimal128 a, _Decimal128 b)
+{
+ return - __builtin_fabsd128 (b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
index 534a04a937b..2569ac84369 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
@@ -3,13 +3,14 @@
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
-/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */
-/* { dg-final { scan-assembler-times "mfvsrd" 1 } } */
+/* { dg-final { scan-assembler "mtvsrd" } } */
+/* { dg-final { scan-assembler "mfvsrd" } } */
-/* Check code generation for direct move for long types. */
+/* Check code generation for direct move for double types. */
#define TYPE double
#define IS_FLOAT 1
#define NO_ALTIVEC 1
+#define VSX_REG_ATTR "ws"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
index 750debfc0df..c8702204b70 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
@@ -10,5 +10,6 @@
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
+#define VSX_REG_ATTR "ws"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
index ff1e97c0d43..524c0eead43 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
@@ -3,15 +3,16 @@
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
-/* { dg-final { scan-assembler-times "mtvsrd" 2 } } */
-/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */
-/* { dg-final { scan-assembler-times "xscvdpspn" 2 } } */
-/* { dg-final { scan-assembler-times "xscvspdpn" 2 } } */
+/* { dg-final { scan-assembler "mtvsrd" } } */
+/* { dg-final { scan-assembler "mfvsrd" } } */
+/* { dg-final { scan-assembler "xscvdpspn" } } */
+/* { dg-final { scan-assembler "xscvspdpn" } } */
-/* Check code generation for direct move for long types. */
+/* Check code generation for direct move for float types. */
#define TYPE float
#define IS_FLOAT 1
#define NO_ALTIVEC 1
+#define VSX_REG_ATTR "ww"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
index ace728ff6d4..352e76166d0 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
@@ -10,5 +10,6 @@
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
+#define VSX_REG_ATTR "ww"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c
index 907e802c72b..0a78f9cb258 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c
@@ -3,13 +3,14 @@
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
-/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */
-/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */
+/* { dg-final { scan-assembler "mtvsrd" } } */
+/* { dg-final { scan-assembler "mfvsrd" } } */
/* Check code generation for direct move for long types. */
#define TYPE long
#define IS_INT 1
#define NO_ALTIVEC 1
+#define VSX_REG_ATTR "d"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c
index fba613e4548..cee9e0e0f1d 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c
@@ -10,5 +10,6 @@
#define IS_INT 1
#define NO_ALTIVEC 1
#define DO_MAIN
+#define VSX_REG_ATTR "d"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
index cdfa18857f1..3067b9a8e62 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
@@ -3,11 +3,12 @@
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O2" } */
-/* { dg-final { scan-assembler-times "mtvsrd" 4 } } */
-/* { dg-final { scan-assembler-times "mfvsrd" 4 } } */
+/* { dg-final { scan-assembler "mtvsrd" } } */
+/* { dg-final { scan-assembler "mfvsrd" } } */
-/* Check code generation for direct move for long types. */
+/* Check code generation for direct move for vector types. */
#define TYPE vector int
+#define VSX_REG_ATTR "wa"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
index 5c0c9abdac5..0d8264faf71 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
@@ -8,5 +8,6 @@
#define TYPE vector int
#define DO_MAIN
+#define VSX_REG_ATTR "wa"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move.h b/gcc/testsuite/gcc.target/powerpc/direct-move.h
index 4e84fd678bb..6a5b7ba1806 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move.h
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move.h
@@ -1,5 +1,11 @@
/* Test functions for direct move support. */
+#include <math.h>
+extern void abort (void);
+
+#ifndef VSX_REG_ATTR
+#define VSX_REG_ATTR "wa"
+#endif
void __attribute__((__noinline__))
copy (TYPE *a, TYPE *b)
@@ -42,7 +48,7 @@ void __attribute__((__noinline__))
load_vsx (TYPE *a, TYPE *b)
{
TYPE c = *a;
- __asm__ ("# vsx, reg = %x0" : "+wa" (c));
+ __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (c));
*b = c;
}
#endif
@@ -55,7 +61,7 @@ load_gpr_to_vsx (TYPE *a, TYPE *b)
TYPE d;
__asm__ ("# gpr, reg = %0" : "+b" (c));
d = c;
- __asm__ ("# vsx, reg = %x0" : "+wa" (d));
+ __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (d));
*b = d;
}
#endif
@@ -66,7 +72,7 @@ load_vsx_to_gpr (TYPE *a, TYPE *b)
{
TYPE c = *a;
TYPE d;
- __asm__ ("# vsx, reg = %x0" : "+wa" (c));
+ __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (c));
d = c;
__asm__ ("# gpr, reg = %0" : "+b" (d));
*b = d;
@@ -107,7 +113,7 @@ const struct test_struct test_functions[] = {
void __attribute__((__noinline__))
test_value (TYPE a)
{
- size_t i;
+ long i;
for (i = 0; i < sizeof (test_functions) / sizeof (test_functions[0]); i++)
{
@@ -123,8 +129,7 @@ test_value (TYPE a)
int
main (void)
{
- size_t i;
- long j;
+ long i,j;
union {
TYPE value;
unsigned char bytes[sizeof (TYPE)];
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion.c b/gcc/testsuite/gcc.target/powerpc/fusion.c
index 3bea1c9f5a8..60e635972c4 100644
--- a/gcc/testsuite/gcc.target/powerpc/fusion.c
+++ b/gcc/testsuite/gcc.target/powerpc/fusion.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power7 -mtune=power8 -O3" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/no-r11-1.c b/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
index 57c01a3e259..94b7988ec76 100644
--- a/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
/* { dg-options "-O2 -mno-pointers-to-nested-functions" } */
int
diff --git a/gcc/testsuite/gcc.target/powerpc/no-r11-2.c b/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
index 3e4a6ca0ff4..214a9dfb49a 100644
--- a/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
/* { dg-options "-O2 -mpointers-to-nested-functions" } */
int
diff --git a/gcc/testsuite/gcc.target/powerpc/no-r11-3.c b/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
index c98797e7f69..9cc83090921 100644
--- a/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
/* { dg-options "-O2 -mno-pointers-to-nested-functions" } */
extern void ext_call (int (func) (void));
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
new file mode 100644
index 00000000000..3cfd8161dd6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
@@ -0,0 +1,139 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf -fno-math-errno" } */
+
+float abs_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return __builtin_fabsf (f);
+}
+
+float nabs_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return - __builtin_fabsf (f);
+}
+
+float neg_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return - f;
+}
+
+float add_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 + f2;
+}
+
+float sub_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 - f2;
+}
+
+float mul_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 * f2;
+}
+
+float div_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 / f2;
+}
+
+float sqrt_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return __builtin_sqrtf (f);
+}
+
+
+double abs_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return __builtin_fabs (d);
+}
+
+double nabs_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return - __builtin_fabs (d);
+}
+
+double neg_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return - d;
+}
+
+double add_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 + d2;
+}
+
+double sub_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 - d2;
+}
+
+double mul_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 * d2;
+}
+
+double div_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 / d2;
+}
+
+double sqrt_df (float *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return __builtin_sqrt (d);
+}
+
+/* { dg-final { scan-assembler "xsabsdp" } } */
+/* { dg-final { scan-assembler "xsadddp" } } */
+/* { dg-final { scan-assembler "xsaddsp" } } */
+/* { dg-final { scan-assembler "xsdivdp" } } */
+/* { dg-final { scan-assembler "xsdivsp" } } */
+/* { dg-final { scan-assembler "xsmuldp" } } */
+/* { dg-final { scan-assembler "xsmulsp" } } */
+/* { dg-final { scan-assembler "xsnabsdp" } } */
+/* { dg-final { scan-assembler "xsnegdp" } } */
+/* { dg-final { scan-assembler "xssqrtdp" } } */
+/* { dg-final { scan-assembler "xssqrtsp" } } */
+/* { dg-final { scan-assembler "xssubdp" } } */
+/* { dg-final { scan-assembler "xssubsp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
new file mode 100644
index 00000000000..33f19991f76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
@@ -0,0 +1,42 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf" } */
+
+float load_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return f;
+}
+
+double load_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return d;
+}
+
+double load_dfsf (float *p)
+{
+ double d = (double) *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return d;
+}
+
+void store_sf (float *p, float f)
+{
+ __asm__ ("# reg %x0" : "+v" (f));
+ *p = f;
+}
+
+void store_df (double *p, double d)
+{
+ __asm__ ("# reg %x0" : "+v" (d));
+ *p = d;
+}
+
+/* { dg-final { scan-assembler "lxsspx" } } */
+/* { dg-final { scan-assembler "lxsdx" } } */
+/* { dg-final { scan-assembler "stxsspx" } } */
+/* { dg-final { scan-assembler "stxsdx" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
index c98666c47a0..b39fe4115bc 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
@@ -5,8 +5,7 @@
/* { dg-final { scan-assembler-times "fabs" 3 } } */
/* { dg-final { scan-assembler-times "fnabs" 3 } } */
/* { dg-final { scan-assembler-times "fsel" 3 } } */
-/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
-/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+/* { dg-final { scan-assembler-times "fcpsgn\|xscpsgndp" 4 } } */
double normal1 (double, double);
double power5 (double, double) __attribute__((__target__("cpu=power5")));
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
index 8ef95b7a15b..e8a2de3636a 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
@@ -5,8 +5,7 @@
/* { dg-final { scan-assembler-times "fabs" 3 } } */
/* { dg-final { scan-assembler-times "fnabs" 3 } } */
/* { dg-final { scan-assembler-times "fsel" 3 } } */
-/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
-/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+/* { dg-final { scan-assembler-times "fcpsgn\|xscpsgndp" 4 } } */
/* fabs/fnabs/fsel */
double normal1 (double a, double b) { return __builtin_copysign (a, b); }
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
index 8fcb7fd7fae..9dc730e0dbd 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
@@ -89,8 +89,10 @@ typedef struct sf
long a1;
long a2;
long a3;
+#if _CALL_ELF != 2
long a4;
long a5;
+#endif
parm_t slot[100];
} stack_frame_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
index a9883d9e335..e4825973b11 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
@@ -107,8 +107,10 @@ typedef struct sf
long a1;
long a2;
long a3;
+#if _CALL_ELF != 2
long a4;
long a5;
+#endif
parm_t slot[100];
} stack_frame_t;
@@ -119,6 +121,12 @@ typedef union
vector int v;
} vector_int_t;
+#ifdef __LITTLE_ENDIAN__
+#define MAKE_SLOT(x, y) ((long)x | ((long)y << 32))
+#else
+#define MAKE_SLOT(x, y) ((long)y | ((long)x << 32))
+#endif
+
/* Paramter passing.
s : gpr 3
v : vpr 2
@@ -226,8 +234,8 @@ fcevv (char *s, ...)
sp = __builtin_frame_address(0);
sp = sp->backchain;
- if (sp->slot[2].l != 0x100000002ULL
- || sp->slot[4].l != 0x500000006ULL)
+ if (sp->slot[2].l != MAKE_SLOT (1, 2)
+ || sp->slot[4].l != MAKE_SLOT (5, 6))
abort();
}
@@ -268,8 +276,8 @@ fciievv (char *s, int i, int j, ...)
sp = __builtin_frame_address(0);
sp = sp->backchain;
- if (sp->slot[4].l != 0x100000002ULL
- || sp->slot[6].l != 0x500000006ULL)
+ if (sp->slot[4].l != MAKE_SLOT (1, 2)
+ || sp->slot[6].l != MAKE_SLOT (5, 6))
abort();
}
@@ -296,8 +304,8 @@ fcvevv (char *s, vector int x, ...)
sp = __builtin_frame_address(0);
sp = sp->backchain;
- if (sp->slot[4].l != 0x100000002ULL
- || sp->slot[6].l != 0x500000006ULL)
+ if (sp->slot[4].l != MAKE_SLOT (1, 2)
+ || sp->slot[6].l != MAKE_SLOT (5, 6))
abort();
}
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
index eb54a653bf7..4e91b1bba26 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
@@ -33,15 +33,27 @@ reg_parms_t gparms;
/* Wrapper to save the GPRs and FPRs and then jump to the real function. */
+#if _CALL_ELF != 2
+#define FUNC_START(NAME) \
+ "\t.globl\t" NAME "\n\t" \
+ ".section \".opd\",\"aw\"\n\t" \
+ ".align 3\n" \
+ NAME ":\n\t" \
+ ".quad .L." NAME ",.TOC.@tocbase,0\n\t" \
+ ".text\n\t" \
+ ".type " NAME ", @function\n" \
+ ".L." NAME ":\n\t"
+#else
+#define FUNC_START(NAME) \
+ "\t.globl\t" NAME "\n\t" \
+ ".text\n\t" \
+ NAME ":\n" \
+ "0:\taddis 2,12,(.TOC.-0b)@ha\n\t" \
+ "addi 2,2,(.TOC.-0b)@l\n\t" \
+ ".localentry " NAME ",.-" NAME "\n\t"
+#endif
#define WRAPPER(NAME) \
-__asm__ ("\t.globl\t" #NAME "_asm\n\t" \
- ".section \".opd\",\"aw\"\n\t" \
- ".align 3\n" \
- #NAME "_asm:\n\t" \
- ".quad .L." #NAME "_asm,.TOC.@tocbase,0\n\t" \
- ".text\n\t" \
- ".type " #NAME "_asm, @function\n" \
- ".L." #NAME "_asm:\n\t" \
+__asm__ (FUNC_START (#NAME "_asm") \
"ld 11,gparms@got(2)\n\t" \
"std 3,0(11)\n\t" \
"std 4,8(11)\n\t" \
@@ -75,8 +87,10 @@ typedef struct sf
long a1;
long a2;
long a3;
+#if _CALL_ELF != 2
long a4;
long a5;
+#endif
unsigned long slot[100];
} stack_frame_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr42747.c b/gcc/testsuite/gcc.target/powerpc/pr42747.c
index 9e7310e1767..41362db1774 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr42747.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr42747.c
@@ -5,4 +5,4 @@
double foo (double x) { return __builtin_sqrt (x); }
-/* { dg-final { scan-assembler "xssqrtdp" } } */
+/* { dg-final { scan-assembler "xssqrtdp\|fsqrt" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr43154.c b/gcc/testsuite/gcc.target/powerpc/pr43154.c
index d083e977b2f..eb1919743b5 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr43154.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr43154.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O2 -mcpu=power7" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr48258-1.c b/gcc/testsuite/gcc.target/powerpc/pr48258-1.c
index 4f37815d384..3ccbf7693d9 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr48258-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr48258-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O3 -mcpu=power7 -mabi=altivec -ffast-math -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvaddsp" 3 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr57744.c b/gcc/testsuite/gcc.target/powerpc/pr57744.c
index d1522f7bb13..222fd6abd4f 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr57744.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr57744.c
@@ -3,6 +3,8 @@
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8 -O3" } */
+void abort (void);
+
typedef unsigned U_16 __attribute__((mode(TI)));
extern int libat_compare_exchange_16 (U_16 *, U_16 *, U_16, int, int)
@@ -31,7 +33,7 @@ volatile int do_test = 0;
int main (void)
{
if (do_test && !libat_compare_exchange_16 (&a, &b, c, 0, 0))
- aborrt ();
+ abort ();
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr57949-1.c b/gcc/testsuite/gcc.target/powerpc/pr57949-1.c
new file mode 100644
index 00000000000..dac305a01f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr57949-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
+/* { dg-options "-O2 -mcpu=power7 -mno-compat-align-parm" } */
+
+/* Verify that vs is 16-byte aligned with -mcompat-align-parm. */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+struct s { long m; v4sf v; };
+long n;
+v4sf ve;
+
+void pr57949 (long d1, long d2, long d3, long d4, long d5, long d6,
+ long d7, long d8, long d9, struct s vs) {
+ n = vs.m;
+ ve = vs.v;
+}
+
+/* { dg-final { scan-assembler "li \.\*,144" } } */
+/* { dg-final { scan-assembler "ld \.\*,128\\(1\\)" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr57949-2.c b/gcc/testsuite/gcc.target/powerpc/pr57949-2.c
new file mode 100644
index 00000000000..39a24d9e497
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr57949-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
+/* { dg-options "-O2 -mcpu=power7" } */
+
+/* Verify that vs is not 16-byte aligned in the absence of -mno-compat-align-parm. */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+struct s { long m; v4sf v; };
+long n;
+v4sf ve;
+
+void pr57949 (long d1, long d2, long d3, long d4, long d5, long d6,
+ long d7, long d8, long d9, struct s vs) {
+ n = vs.m;
+ ve = vs.v;
+}
+
+/* { dg-final { scan-assembler "ld .\*,136\\(1\\)" } } */
+/* { dg-final { scan-assembler "ld .\*,120\\(1\\)" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr58330.c b/gcc/testsuite/gcc.target/powerpc/pr58330.c
new file mode 100644
index 00000000000..76983dd55ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr58330.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O -mno-popcntb" } */
+/* { dg-final { scan-assembler-not "stwbrx" } } */
+
+void
+write_reverse (unsigned long *addr, unsigned long val)
+{
+ unsigned long reverse = __builtin_bswap64 (val);
+ __atomic_store_n (addr, reverse, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr58673-1.c b/gcc/testsuite/gcc.target/powerpc/pr58673-1.c
new file mode 100644
index 00000000000..6f7838f8dde
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr58673-1.c
@@ -0,0 +1,78 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -m64 -O1" } */
+
+enum typecode
+{
+ QIcode, QUcode, HIcode, HUcode, SIcode, SUcode, DIcode, DUcode, SFcode,
+ DFcode, XFcode, Pcode, Tcode, LAST_AND_UNUSED_TYPECODE
+};
+enum bytecode_opcode
+{
+ neverneverland, drop, duplicate, over, setstackSI, adjstackSI, constQI,
+ constHI, constSI, constDI, constSF, constDF, constXF, constP, loadQI,
+ loadHI, loadSI, loadDI, loadSF, loadDF, loadXF, loadP, storeQI, storeHI,
+ storeSI, storeDI, storeSF, storeDF, storeXF, storeP, storeBLK, clearBLK,
+ addconstPSI, newlocalSI, localP, argP, convertQIHI, convertHISI,
+ convertSIDI, convertQISI, convertQUHU, convertHUSU, convertSUDU,
+ convertQUSU, convertSFDF, convertDFXF, convertHIQI, convertSIHI,
+ convertDISI, convertSIQI, convertSUQU, convertDFSF, convertXFDF,
+ convertSISF, convertSIDF, convertSIXF, convertSUSF, convertSUDF,
+ convertSUXF, convertDISF, convertDIDF, convertDIXF, convertDUSF,
+ convertDUDF, convertDUXF, convertSFSI, convertDFSI, convertXFSI,
+ convertSFSU, convertDFSU, convertXFSU, convertSFDI, convertDFDI,
+ convertXFDI, convertSFDU, convertDFDU, convertXFDU, convertPSI,
+ convertSIP, convertSIT, convertDIT, convertSFT, convertDFT, convertXFT,
+ convertPT, zxloadBI, sxloadBI, sstoreBI, addSI, addDI, addSF, addDF,
+ addXF, addPSI, subSI, subDI, subSF, subDF, subXF, subPP, mulSI, mulDI,
+ mulSU, mulDU, mulSF, mulDF, mulXF, divSI, divDI, divSU, divDU, divSF,
+ divDF, divXF, modSI, modDI, modSU, modDU, andSI, andDI, iorSI, iorDI,
+ xorSI, xorDI, lshiftSI, lshiftSU, lshiftDI, lshiftDU, rshiftSI, rshiftSU,
+ rshiftDI, rshiftDU, ltSI, ltSU, ltDI, ltDU, ltSF, ltDF, ltXF, ltP, leSI,
+ leSU, leDI, leDU, leSF, leDF, leXF, leP, geSI, geSU, geDI, geDU, geSF,
+ geDF, geXF, geP, gtSI, gtSU, gtDI, gtDU, gtSF, gtDF, gtXF, gtP, eqSI,
+ eqDI, eqSF, eqDF, eqXF, eqP, neSI, neDI, neSF, neDF, neXF, neP, negSI,
+ negDI, negSF, negDF, negXF, notSI, notDI, notT, predecQI, predecHI,
+ predecSI, predecDI, predecP, predecSF, predecDF, predecXF, predecBI,
+ preincQI, preincHI, preincSI, preincDI, preincP, preincSF, preincDF,
+ preincXF, preincBI, postdecQI, postdecHI, postdecSI, postdecDI, postdecP,
+ postdecSF, postdecDF, postdecXF, postdecBI, postincQI, postincHI,
+ postincSI, postincDI, postincP, postincSF, postincDF, postincXF,
+ postincBI, xjumpif, xjumpifnot, jump, jumpP, caseSI, caseSU, caseDI,
+ caseDU, call, returnP, ret, linenote, LAST_AND_UNUSED_OPCODE
+};
+struct binary_operator
+{
+ enum bytecode_opcode opcode;
+ enum typecode arg0;
+};
+static struct conversion_recipe
+{
+ unsigned char *opcodes;
+ int cost;
+}
+conversion_recipe[((int) LAST_AND_UNUSED_TYPECODE)][((int)
+ LAST_AND_UNUSED_TYPECODE)];
+static struct conversion_recipe
+deduce_conversion (from, to)
+ enum typecode from, to;
+{
+ (conversion_recipe[(int) from][(int) to].
+ opcodes ? 0 : (conversion_recipe[(int) from][(int) to] =
+ deduce_conversion (from, to), 0));
+}
+
+void
+bc_expand_binary_operation (optab, resulttype, arg0, arg1)
+ struct binary_operator optab[];
+{
+ int i, besti, cost, bestcost;
+ enum typecode resultcode, arg0code;
+ for (i = 0; optab[i].opcode != -1; ++i)
+ {
+ (conversion_recipe[(int) arg0code][(int) optab[i].arg0].
+ opcodes ? 0 : (conversion_recipe[(int) arg0code][(int) optab[i].arg0] =
+ deduce_conversion (arg0code, optab[i].arg0), 0));
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr58673-2.c b/gcc/testsuite/gcc.target/powerpc/pr58673-2.c
new file mode 100644
index 00000000000..b70d2eed88c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr58673-2.c
@@ -0,0 +1,217 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O3 -m64 -funroll-loops" } */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+typedef long unsigned int size_t;
+typedef struct _IO_FILE FILE;
+typedef float real;
+typedef real rvec[3];
+typedef real matrix[3][3];
+typedef real tensor[3][3];
+enum
+{
+ F_BONDS, F_G96BONDS, F_MORSE, F_CUBICBONDS, F_CONNBONDS, F_HARMONIC,
+ F_ANGLES, F_G96ANGLES, F_PDIHS, F_RBDIHS, F_IDIHS, F_LJ14, F_COUL14, F_LJ,
+ F_BHAM, F_LJLR, F_DISPCORR, F_SR, F_LR, F_WPOL, F_POSRES, F_DISRES,
+ F_DISRESVIOL, F_ORIRES, F_ORIRESDEV, F_ANGRES, F_ANGRESZ, F_SHAKE,
+ F_SHAKENC, F_SETTLE, F_DUMMY2, F_DUMMY3, F_DUMMY3FD, F_DUMMY3FAD,
+ F_DUMMY3OUT, F_DUMMY4FD, F_EQM, F_EPOT, F_EKIN, F_ETOT, F_TEMP, F_PRES,
+ F_DVDL, F_DVDLKIN, F_NRE
+};
+typedef union
+{
+ struct
+ {
+ }
+ bham;
+ struct
+ {
+ real rA, krA, rB, krB;
+ }
+ harmonic;
+}
+t_iparams;
+typedef struct
+{
+ t_iparams *iparams;
+}
+t_idef;
+typedef struct
+{
+}
+t_inputrec;
+typedef struct
+{
+}
+t_commrec;
+typedef struct
+{
+}
+t_forcerec;
+typedef struct
+{
+}
+t_mdatoms;
+typedef struct
+{
+}
+t_filenm;
+enum
+{
+ eoPres, eoEpot, eoVir, eoDist, eoMu, eoForce, eoFx, eoFy, eoFz, eoPx, eoPy,
+ eoPz, eoPolarizability, eoDipole, eoObsNR, eoMemory =
+ eoObsNR, eoInter, eoUseVirial, eoNR
+};
+extern char *eoNames[eoNR];
+typedef struct
+{
+ int bPrint;
+}
+t_coupl_LJ;
+typedef struct
+{
+ int eObs;
+ t_iparams xi;
+}
+t_coupl_iparams;
+typedef struct
+{
+ real act_value[eoObsNR];
+ real av_value[eoObsNR];
+ real ref_value[eoObsNR];
+ int bObsUsed[eoObsNR];
+ int nLJ, nBU, nQ, nIP;
+ t_coupl_LJ *tcLJ;
+}
+t_coupl_rec;
+static void
+pr_ff (t_coupl_rec * tcr, real time, t_idef * idef, t_commrec * cr, int nfile,
+ t_filenm fnm[])
+{
+ static FILE *prop;
+ static FILE **out = ((void *) 0);
+ static FILE **qq = ((void *) 0);
+ static FILE **ip = ((void *) 0);
+ char buf[256];
+ char *leg[] = {
+ "C12", "C6"
+ };
+ char **raleg;
+ int i, j, index;
+ if ((prop == ((void *) 0)) && (out == ((void *) 0)) && (qq == ((void *) 0))
+ && (ip == ((void *) 0)))
+ {
+ for (i = j = 0; (i < eoObsNR); i++)
+ {
+ if (tcr->bObsUsed[i])
+ {
+ raleg[j++] =
+ (__extension__
+ (__builtin_constant_p (eoNames[i])
+ && ((size_t) (const void *) ((eoNames[i]) + 1) -
+ (size_t) (const void *) (eoNames[i]) ==
+ 1) ? (((const char *) (eoNames[i]))[0] ==
+ '\0' ? (char *) calloc ((size_t) 1,
+ (size_t) 1) : (
+ {
+ size_t
+ __len
+ =
+ strlen
+ (eoNames
+ [i])
+ +
+ 1;
+ char
+ *__retval
+ =
+ (char
+ *)
+ malloc
+ (__len);
+ __retval;}
+ )): __strdup (eoNames[i])));
+ raleg[j++] =
+ (__extension__
+ (__builtin_constant_p (buf)
+ && ((size_t) (const void *) ((buf) + 1) -
+ (size_t) (const void *) (buf) ==
+ 1) ? (((const char *) (buf))[0] ==
+ '\0' ? (char *) calloc ((size_t) 1,
+ (size_t) 1) : (
+ {
+ size_t
+ __len
+ =
+ strlen
+ (buf)
+ +
+ 1;
+ char
+ *__retval
+ =
+ (char
+ *)
+ malloc
+ (__len);
+ __retval;}
+ )): __strdup (buf)));
+ }
+ }
+ if (tcr->nLJ)
+ {
+ for (i = 0; (i < tcr->nLJ); i++)
+ {
+ if (tcr->tcLJ[i].bPrint)
+ {
+ xvgr_legend (out[i], (sizeof (leg) / sizeof ((leg)[0])),
+ leg);
+ }
+ }
+ }
+ }
+}
+
+void
+do_coupling (FILE * log, int nfile, t_filenm fnm[], t_coupl_rec * tcr, real t,
+ int step, real ener[], t_forcerec * fr, t_inputrec * ir,
+ int bMaster, t_mdatoms * md, t_idef * idef, real mu_aver,
+ int nmols, t_commrec * cr, matrix box, tensor virial,
+ tensor pres, rvec mu_tot, rvec x[], rvec f[], int bDoIt)
+{
+ int i, j, ati, atj, atnr2, type, ftype;
+ real deviation[eoObsNR], prdev[eoObsNR], epot0, dist, rmsf;
+ real ff6, ff12, ffa, ffb, ffc, ffq, factor, dt, mu_ind;
+ int bTest, bPrint;
+ t_coupl_iparams *tip;
+ if (bPrint)
+ {
+ pr_ff (tcr, t, idef, cr, nfile, fnm);
+ }
+ for (i = 0; (i < eoObsNR); i++)
+ {
+ deviation[i] =
+ calc_deviation (tcr->av_value[i], tcr->act_value[i],
+ tcr->ref_value[i]);
+ prdev[i] = tcr->ref_value[i] - tcr->act_value[i];
+ }
+ if (bPrint)
+ pr_dev (tcr, t, prdev, cr, nfile, fnm);
+ for (i = 0; (i < atnr2); i++)
+ {
+ factor = dt * deviation[tip->eObs];
+ switch (ftype)
+ {
+ case F_BONDS:
+ if (fabs (tip->xi.harmonic.krA) > 1.2e-38)
+ idef->iparams[type].harmonic.krA *=
+ (1 + factor / tip->xi.harmonic.krA);
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr59054.c b/gcc/testsuite/gcc.target/powerpc/pr59054.c
new file mode 100644
index 00000000000..ab2ff6dea29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr59054.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O0 -m64" } */
+
+long foo (void) { return 0; }
+
+/* { dg-final { scan-assembler-not "xxlor" } } */
+/* { dg-final { scan-assembler-not "stfd" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr60137.c b/gcc/testsuite/gcc.target/powerpc/pr60137.c
new file mode 100644
index 00000000000..4777a53829d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr60137.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O3 -mno-vsx" } */
+
+/* target/60137, compiler got a 'could not split insn error'. */
+
+extern int target_flags;
+extern char fixed_regs[53];
+extern char call_used_regs[53];
+
+void init_reg_sets_1(void)
+{
+ int i;
+ for (i = 0; i < 53; i++)
+ fixed_regs[i] = call_used_regs[i] = (call_used_regs[i] &((target_flags & 0x02000000) ? 2 : 1)) != 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr60203.c b/gcc/testsuite/gcc.target/powerpc/pr60203.c
new file mode 100644
index 00000000000..6a4b4fa1ddb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr60203.c
@@ -0,0 +1,40 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O3" } */
+
+union u_ld { long double ld; double d[2]; };
+
+long double
+pack (double a, double aa)
+{
+ union u_ld u;
+ u.d[0] = a;
+ u.d[1] = aa;
+ return u.ld;
+}
+
+double
+unpack_0 (long double x)
+{
+ union u_ld u;
+ u.ld = x;
+ return u.d[0];
+}
+
+double
+unpack_1 (long double x)
+{
+ union u_ld u;
+ u.ld = x;
+ return u.d[1];
+}
+
+/* { dg-final { scan-assembler-not "stfd" } } */
+/* { dg-final { scan-assembler-not "lfd" } } */
+/* { dg-final { scan-assembler-not "lxsdx" } } */
+/* { dg-final { scan-assembler-not "stxsdx" } } */
+/* { dg-final { scan-assembler-not "mfvsrd" } } */
+/* { dg-final { scan-assembler-not "mtvsrd" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/powerpc/quad-atomic.c b/gcc/testsuite/gcc.target/powerpc/quad-atomic.c
new file mode 100644
index 00000000000..6cf278852d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/quad-atomic.c
@@ -0,0 +1,67 @@
+/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-mcpu=power8 -O2" } */
+
+/* Test whether we get the right bits for quad word atomic instructions. */
+#include <stdlib.h>
+
+static __int128_t quad_fetch_and (__int128_t *, __int128_t value) __attribute__((__noinline__));
+static __int128_t quad_fetch_or (__int128_t *, __int128_t value) __attribute__((__noinline__));
+static __int128_t quad_fetch_add (__int128_t *, __int128_t value) __attribute__((__noinline__));
+
+static __int128_t
+quad_fetch_and (__int128_t *ptr, __int128_t value)
+{
+ return __atomic_fetch_and (ptr, value, __ATOMIC_ACQUIRE);
+}
+
+static __int128_t
+quad_fetch_or (__int128_t *ptr, __int128_t value)
+{
+ return __atomic_fetch_or (ptr, value, __ATOMIC_ACQUIRE);
+}
+
+static __int128_t
+quad_fetch_add (__int128_t *ptr, __int128_t value)
+{
+ return __atomic_fetch_add (ptr, value, __ATOMIC_ACQUIRE);
+}
+
+int
+main (void)
+{
+ __int128_t result;
+ __int128_t value;
+ __int128_t and_input = ((((__int128_t) 0x1234567890abcdefULL) << 64) | ((__int128_t) 0xfedcba0987654321ULL));
+ __int128_t and_value = ((((__int128_t) 0xfffffffffffffff0ULL) << 64) | ((__int128_t) 0xfffffffffffffff0ULL));
+ __int128_t and_exp = ((((__int128_t) 0x1234567890abcde0ULL) << 64) | ((__int128_t) 0xfedcba0987654320ULL));
+
+ __int128_t or_input = ((((__int128_t) 0x1234567890abcdefULL) << 64) | ((__int128_t) 0xfedcba0987654321ULL));
+ __int128_t or_value = ((((__int128_t) 0x0000000000000010ULL) << 64) | ((__int128_t) 0x000000000000000eULL));
+ __int128_t or_exp = ((((__int128_t) 0x1234567890abcdffULL) << 64) | ((__int128_t) 0xfedcba098765432fULL));
+
+ __int128_t add_input = ((((__int128_t) 0x1234567890abcdefULL) << 64) | ((__int128_t) 0xfedcba0987654321ULL));
+ __int128_t add_value = ((((__int128_t) 0x0000000001000000ULL) << 64) | ((__int128_t) 0x0000001000000000ULL));
+ __int128_t add_exp = ((((__int128_t) 0x1234567891abcdefULL) << 64) | ((__int128_t) 0xfedcba1987654321ULL));
+
+
+ value = and_input;
+ result = quad_fetch_and (&value, and_value);
+ if (result != and_input || value != and_exp)
+ abort ();
+
+ value = or_input;
+ result = quad_fetch_or (&value, or_value);
+ if (result != or_input || value != or_exp)
+ abort ();
+
+ value = add_input;
+ result = quad_fetch_add (&value, add_value);
+ if (result != add_input || value != add_exp)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-1.c b/gcc/testsuite/gcc.target/powerpc/recip-1.c
index 4ae0c4f119f..59660e35bd5 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-1.c
@@ -3,8 +3,8 @@
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power6" } */
/* { dg-final { scan-assembler-times "frsqrte" 2 } } */
/* { dg-final { scan-assembler-times "fmsub" 2 } } */
-/* { dg-final { scan-assembler-times "fmul" 8 } } */
-/* { dg-final { scan-assembler-times "fnmsub" 4 } } */
+/* { dg-final { scan-assembler-times "fmul" 6 } } */
+/* { dg-final { scan-assembler-times "fnmsub" 3 } } */
double
rsqrt_d (double a)
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-3.c b/gcc/testsuite/gcc.target/powerpc/recip-3.c
index 905e793952e..1f8e30572b2 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-3.c
@@ -1,14 +1,14 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power7" } */
-/* { dg-final { scan-assembler-times "xsrsqrtedp" 1 } } */
+/* { dg-final { scan-assembler-times "xsrsqrtedp\|frsqrte\ " 1 } } */
/* { dg-final { scan-assembler-times "xsmsub.dp\|fmsub\ " 1 } } */
-/* { dg-final { scan-assembler-times "xsmuldp" 4 } } */
+/* { dg-final { scan-assembler-times "xsmuldp\|fmul\ " 4 } } */
/* { dg-final { scan-assembler-times "xsnmsub.dp\|fnmsub\ " 2 } } */
-/* { dg-final { scan-assembler-times "frsqrtes" 1 } } */
-/* { dg-final { scan-assembler-times "fmsubs" 1 } } */
-/* { dg-final { scan-assembler-times "fmuls" 4 } } */
-/* { dg-final { scan-assembler-times "fnmsubs" 2 } } */
+/* { dg-final { scan-assembler-times "xsrsqrtesp\|frsqrtes" 1 } } */
+/* { dg-final { scan-assembler-times "xsmsub.sp\|fmsubs" 1 } } */
+/* { dg-final { scan-assembler-times "xsmulsp\|fmuls" 2 } } */
+/* { dg-final { scan-assembler-times "xsnmsub.sp\|fnmsubs" 1 } } */
double
rsqrt_d (double a)
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-4.c b/gcc/testsuite/gcc.target/powerpc/recip-4.c
index 35eef6f0f0f..a62b60db201 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-4.c
@@ -7,8 +7,8 @@
/* { dg-final { scan-assembler-times "xvnmsub.dp" 2 } } */
/* { dg-final { scan-assembler-times "xvrsqrtesp" 1 } } */
/* { dg-final { scan-assembler-times "xvmsub.sp" 1 } } */
-/* { dg-final { scan-assembler-times "xvmulsp" 4 } } */
-/* { dg-final { scan-assembler-times "xvnmsub.sp" 2 } } */
+/* { dg-final { scan-assembler-times "xvmulsp" 2 } } */
+/* { dg-final { scan-assembler-times "xvnmsub.sp" 1 } } */
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-5.c b/gcc/testsuite/gcc.target/powerpc/recip-5.c
index 3d7d691d5ac..53b74fa8c24 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-5.c
@@ -4,8 +4,16 @@
/* { dg-options "-O3 -ftree-vectorize -mrecip=all -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvredp" 4 } } */
/* { dg-final { scan-assembler-times "xvresp" 5 } } */
-/* { dg-final { scan-assembler-times "xsredp" 2 } } */
-/* { dg-final { scan-assembler-times "fres" 2 } } */
+/* { dg-final { scan-assembler-times "xsredp\|fre\ " 2 } } */
+/* { dg-final { scan-assembler-times "xsresp\|fres" 2 } } */
+/* { dg-final { scan-assembler-times "xsmulsp\|fmuls" 2 } } */
+/* { dg-final { scan-assembler-times "xsnmsub.sp\|fnmsubs" 2 } } */
+/* { dg-final { scan-assembler-times "xsmuldp\|fmul\ " 2 } } */
+/* { dg-final { scan-assembler-times "xsnmsub.dp\|fnmsub\ " 4 } } */
+/* { dg-final { scan-assembler-times "xvmulsp" 7 } } */
+/* { dg-final { scan-assembler-times "xvnmsub.sp" 5 } } */
+/* { dg-final { scan-assembler-times "xvmuldp" 6 } } */
+/* { dg-final { scan-assembler-times "xvnmsub.dp" 8 } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/rs6000-ldouble-3.c b/gcc/testsuite/gcc.target/powerpc/rs6000-ldouble-3.c
new file mode 100644
index 00000000000..1c78052e6d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/rs6000-ldouble-3.c
@@ -0,0 +1,21 @@
+/* Test accuracy of long double division (glibc bug 15396). */
+/* { dg-do run { target powerpc*-*-linux* powerpc*-*-darwin* powerpc*-*-aix* rs6000-*-* } } */
+/* { dg-options "-mlong-double-128" } */
+
+extern void exit (int);
+extern void abort (void);
+
+volatile long double a = 0x1p-1024L;
+volatile long double b = 0x3p-53L;
+volatile long double r;
+volatile long double expected = 0x1.55555555555555555555555555p-973L;
+
+int
+main (void)
+{
+ r = a / b;
+ /* Allow error up to 2ulp. */
+ if (__builtin_fabsl (r - expected) > 0x1p-1073L)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
index 8450920ec0c..7aeba6cb563 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
@@ -16,9 +16,9 @@
/* { dg-final { scan-assembler "xvrspiz" } } */
/* { dg-final { scan-assembler "xsrdpi" } } */
/* { dg-final { scan-assembler "xsrdpic" } } */
-/* { dg-final { scan-assembler "xsrdpim" } } */
-/* { dg-final { scan-assembler "xsrdpip" } } */
-/* { dg-final { scan-assembler "xsrdpiz" } } */
+/* { dg-final { scan-assembler "xsrdpim\|frim" } } */
+/* { dg-final { scan-assembler "xsrdpip\|frip" } } */
+/* { dg-final { scan-assembler "xsrdpiz\|friz" } } */
/* { dg-final { scan-assembler "xsmaxdp" } } */
/* { dg-final { scan-assembler "xsmindp" } } */
/* { dg-final { scan-assembler "xxland" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
new file mode 100644
index 00000000000..b9d6139b080
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 12 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-10.c b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
new file mode 100644
index 00000000000..b91b3478ee3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(2)))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 2 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-11.c b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
new file mode 100644
index 00000000000..49167734253
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch -mno-hotpatch --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-12.c b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
new file mode 100644
index 00000000000..b3e9427d4e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
new file mode 100644
index 00000000000..6cc29447de4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
new file mode 100644
index 00000000000..9f0b2b756a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=0 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
new file mode 100644
index 00000000000..c1dba20a379
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
@@ -0,0 +1,26 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+inline void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp2(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp2' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
new file mode 100644
index 00000000000..ec267d65aae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 12 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
new file mode 100644
index 00000000000..5af090d03a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(1)))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
new file mode 100644
index 00000000000..e73a510b4d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(0)))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
new file mode 100644
index 00000000000..399aa7260b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
@@ -0,0 +1,28 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+inline void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+__attribute__ ((always_inline))
+void hp2(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp2' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
new file mode 100644
index 00000000000..5da675866b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(2)))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
+
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 2 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c
new file mode 100644
index 00000000000..45a2cc5dc20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c
new file mode 100644
index 00000000000..5947f564f53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=0" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c
new file mode 100644
index 00000000000..e0c7f6f52c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c
new file mode 100644
index 00000000000..d9f13425adc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c
@@ -0,0 +1,11 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=-1" } */
+
+int main (void)
+{
+ return 0;
+}
+
+/* { dg-excess-errors "argument to '-mhotpatch=' should be a non-negative integer" } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c
new file mode 100644
index 00000000000..53f7eac9e54
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c
@@ -0,0 +1,28 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1000000" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1000000)))
+void hp2(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1000001)))
+void hp3(void)
+{ /* { dg-error "requested 'hotpatch' attribute is not a non-negative integer constant or too large .max. 1000000." } */
+ printf("hello, world!\n");
+}
+
+int main (void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c
new file mode 100644
index 00000000000..cb10b66f0d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c
@@ -0,0 +1,11 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1000001" } */
+
+int main (void)
+{
+ return 0;
+}
+
+/* { dg-excess-errors "argument to '-mhotpatch=' is too large .max. 1000000." } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c
new file mode 100644
index 00000000000..98ccb42c003
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c
@@ -0,0 +1,68 @@
+/* Functional tests for the function hotpatching feature. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+void hp1(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+inline void hp2(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+__attribute__ ((hotpatch(0)))
+void hp4(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(0)))
+inline void hp5(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(0)))
+__attribute__ ((always_inline))
+void hp6(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp6' with the 'always_inline' attribute is not hotpatchable" } */
+
+__attribute__ ((hotpatch(1)))
+void hp7(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1)))
+inline void hp8(void)
+{
+ printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1)))
+__attribute__ ((always_inline))
+void hp9(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+ printf("hello, world!\n");
+} /* { dg-warning "function 'hp9' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/htm-builtins-1.c b/gcc/testsuite/gcc.target/s390/htm-builtins-1.c
new file mode 100644
index 00000000000..c90490faa59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-builtins-1.c
@@ -0,0 +1,1073 @@
+/* Functional tests of the htm __builtin_... macros. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target htm } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+/* ---------------------------- included header files ---------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <htmintrin.h>
+
+/* ---------------------------- local definitions -------------------------- */
+
+#define DEFAULT_MAX_REPETITIONS 5
+#define DEFAULT_REQUIRED_QUORUM ((DEFAULT_MAX_REPETITIONS) - 1)
+#define NUM_WARMUP_RUNS 10
+
+/* ---------------------------- local macros ------------------------------- */
+
+#define TEST_DF_REP(name) \
+ { #name, name, DEFAULT_MAX_REPETITIONS, DEFAULT_REQUIRED_QUORUM }
+#define TEST_NO_REP(name) { #name, name, 1, 1 }
+
+/* ---------------------------- local types -------------------------------- */
+
+typedef int (*test_func_t)(void);
+
+typedef struct
+{
+ const char *name;
+ test_func_t test_func;
+ int max_repetitions;
+ int required_quorum;
+} test_table_entry_t;
+
+/* ---------------------------- local variables ---------------------------- */
+
+__attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256;
+static struct __htm_tdb local_tdb;
+static int do_dump_tdb = 0;
+
+/* ---------------------------- exported variables (globals) --------------- */
+
+__attribute__ ((aligned(256))) struct
+{
+ float float_1;
+ float float_2;
+ float float_3;
+} global = { 1.0, 2.5, 0.0 };
+
+__attribute__ ((aligned(256))) struct
+{
+ volatile uint64_t c1;
+ volatile uint64_t c2;
+ volatile uint64_t c3;
+} counters = { 0, 0, 0 };
+
+/* ---------------------------- local helper functions --------------------- */
+
+static void dump_tdb (struct __htm_tdb *tdb)
+{
+ unsigned char *p;
+ int i;
+ int j;
+
+ if (do_dump_tdb == 0)
+ {
+ return;
+ }
+ p = (unsigned char *)tdb;
+ for (i = 0; i < 16; i++)
+ {
+ fprintf (stderr, "0x%02x ", i * 16);
+ for (j = 0; j < 16; j++)
+ {
+ fprintf (stderr, "%02x", (int)p[i * 16 + j]);
+ if (j < 15)
+ {
+ fprintf (stderr, " ");
+ }
+ if (j == 7)
+ {
+ fprintf (stderr, " ");
+ }
+ }
+ fprintf (stderr, "\n");
+ }
+
+ return;
+}
+
+/* ---------------------------- local test functions ----------------------- */
+
+/* Check values of the constants defined in htmintrin.h. */
+static int test_constants (void)
+{
+ if (_HTM_TBEGIN_STARTED != 0)
+ {
+ return 100 * _HTM_TBEGIN_STARTED + 1;
+ }
+ if (_HTM_TBEGIN_INDETERMINATE != 1)
+ {
+ return 100 * _HTM_TBEGIN_INDETERMINATE + 2;
+ }
+ if (_HTM_TBEGIN_TRANSIENT != 2)
+ {
+ return 100 * _HTM_TBEGIN_TRANSIENT + 3;
+ }
+ if (_HTM_TBEGIN_PERSISTENT != 3)
+ {
+ return 100 * _HTM_TBEGIN_PERSISTENT + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_ntstg_tend (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
+ counters.c2 = 2;
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 5;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 2)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ }
+ else
+ {
+ return 100 * rc + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_ntstg_tabort (void)
+{
+ float f;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ f = 0;
+ if (__builtin_tbegin ((void *)0) == 0)
+ {
+ __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
+ counters.c2 = 2;
+ f = 1;
+ __builtin_tabort (256);
+ return 1;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 0)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (f != 0)
+ {
+ return 100 * f + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_nofloat (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
+ {
+ __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
+ counters.c2 = 2;
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 5;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 2)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ }
+ else
+ {
+ return 100 * rc + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ counters.c3 = 0;
+ if ((rc = __builtin_tbegin_retry ((void *)0, 5)) == 0)
+ {
+ int do_abort;
+
+ do_abort = (counters.c1 == 0) ? 1 : 0;
+ __builtin_non_tx_store (
+ (uint64_t *)&counters.c1, counters.c1 + 1);
+ if (do_abort == 1)
+ {
+ __builtin_tabort (256);
+ }
+ counters.c2 = counters.c2 + 10;
+ __builtin_non_tx_store ((uint64_t *)&counters.c3, 3);
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 5;
+ }
+ if (counters.c1 != 2)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 10)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (counters.c3 != 3)
+ {
+ return 100 * counters.c3 + 6;
+ }
+ }
+ else
+ {
+ return 100 * rc + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry_nofloat (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ counters.c3 = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat ((void *)0, 5)) == 0)
+ {
+ int do_abort;
+
+ do_abort = (counters.c1 == 0) ? 1 : 0;
+ __builtin_non_tx_store (
+ (uint64_t *)&counters.c1, counters.c1 + 1);
+ if (do_abort == 1)
+ {
+ __builtin_tabort (256);
+ }
+ counters.c2 = counters.c2 + 10;
+ __builtin_non_tx_store ((uint64_t *)&counters.c3, 3);
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 5;
+ }
+ if (counters.c1 != 2)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 10)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (counters.c3 != 3)
+ {
+ return 100 * counters.c3 + 6;
+ }
+ }
+ else
+ {
+ return 100 * rc + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_aborts (void)
+{
+ float f;
+ int rc;
+
+ f = 77;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ f = 88;
+ __builtin_tabort (256);
+ return 2;
+ }
+ else if (rc != 2)
+ {
+ return 3;
+ }
+ if (f != 77)
+ {
+ return 4;
+ }
+ f = 66;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ f = 99;
+ __builtin_tabort (257);
+ return 5;
+ }
+ else if (rc != 3)
+ {
+ return 100 * rc + 6;
+ }
+ if (f != 66)
+ {
+ return 100 * f + 7;
+ }
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ global.float_3 = global.float_1 + global.float_2;
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 8;
+ }
+ }
+ else
+ {
+ return 100 * rc + 9;
+ }
+ if (global.float_3 != global.float_1 + global.float_2)
+ {
+ return 100 * rc + 10;
+ }
+
+ return 0;
+}
+
+static __attribute__((noinline)) void indirect_abort(int abort_code)
+{
+ __builtin_tabort (abort_code);
+
+ return;
+}
+
+static int test_tbegin_indirect_aborts (void)
+{
+ float f;
+ int rc;
+
+ f = 77;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ f = 88;
+ indirect_abort(256);
+ return 2;
+ }
+ else if (rc != 2)
+ {
+ return 100 * rc + 3;
+ }
+ if (f != 77)
+ {
+ return 100 * rc + 4;
+ }
+ f = 66;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ f = 99;
+ indirect_abort(257);
+ return 5;
+ }
+ else if (rc != 3)
+ {
+ return 100 * rc + 6;
+ }
+ if (f != 66)
+ {
+ return 100 * f + 7;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_nofloat_aborts (void)
+{
+ int rc;
+
+ if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
+ {
+ __builtin_tabort (256);
+ return 2;
+ }
+ if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
+ {
+ __builtin_tabort (257);
+ return 1005;
+ }
+ else if (rc != 3)
+ {
+ return 1000 * rc + 6;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_nofloat_indirect_aborts (void)
+{
+ int rc;
+
+ if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
+ {
+ indirect_abort (256);
+ return 2;
+ }
+ if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
+ {
+ indirect_abort (257);
+ return 1005;
+ }
+ else if (rc != 3)
+ {
+ return 1000 * rc + 6;
+ }
+
+ return 0;
+}
+
+static
+int _test_tbegin_retry_aborts (int retries, uint64_t abort_code)
+{
+ int rc;
+
+ counters.c1 = 0;
+ if ((rc = __builtin_tbegin_retry ((void *)0, retries)) == 0)
+ {
+ __builtin_non_tx_store ((uint64_t *)&counters.c1, counters.c1 + 1);
+ __builtin_tabort (abort_code);
+ return 2;
+ }
+ else
+ {
+ if ((abort_code & 1) == 0)
+ {
+ if (rc != 2)
+ {
+ return 100 * rc + 2003;
+ }
+ else if (counters.c1 != (uint64_t)retries + 1)
+ {
+ return 1000 * counters.c1 + 100 * retries + 4;
+ }
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 3005;
+ }
+ else if (counters.c1 != 1)
+ {
+ return 1000 * counters.c1 + 100 * retries + 6;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry_aborts (void)
+{
+ int rc;
+ int retries;
+
+ for (retries = 1; retries <= 3; retries++)
+ {
+ rc = _test_tbegin_retry_aborts (retries, 256);
+ if (rc != 0)
+ {
+ return 10000 + rc;
+ }
+ }
+ for (retries = 1; retries <= 3; retries++)
+ {
+ rc = _test_tbegin_retry_aborts (retries, 257);
+ if (rc != 0)
+ {
+ return 20000 + rc;
+ }
+ }
+ if ((rc = __builtin_tbegin_retry ((void *)0, 5)) == 0)
+ {
+ global.float_3 = global.float_1 + global.float_2;
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 30000 + 100 * rc + 6;
+ }
+ }
+ else
+ {
+ return 30000 + 100 * rc + 7;
+ }
+
+ return 0;
+}
+
+static int _test_tbegin_retry_nofloat_aborts (int retries, uint64_t abort_code)
+{
+ int rc;
+
+ counters.c1 = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat ((void *)0, retries)) == 0)
+ {
+ __builtin_non_tx_store ((uint64_t *)&counters.c1, counters.c1 + 1);
+ __builtin_tabort (abort_code);
+ return 2;
+ }
+ else
+ {
+ if ((abort_code & 1) == 0)
+ {
+ if (rc != 2)
+ {
+ return 100 * rc + 2003;
+ }
+ else if (counters.c1 != (uint64_t)retries + 1)
+ {
+ return 1000 * counters.c1 + 100 * retries + 4;
+ }
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 3005;
+ }
+ else if (counters.c1 != 1)
+ {
+ return 1000 * counters.c1 + 100 * retries + 6;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry_nofloat_aborts (void)
+{
+ int rc;
+ int retries;
+
+ for (retries = 1; retries <= 3; retries++)
+ {
+ rc = _test_tbegin_retry_nofloat_aborts (retries, 256);
+ if (rc != 0)
+ {
+ return 10 * retries + rc;
+ }
+ }
+ for (retries = 1; retries <= 3; retries++)
+ {
+ rc = _test_tbegin_retry_nofloat_aborts (retries, 257);
+ if (rc != 0)
+ {
+ return 10000 + 10 * retries + rc;
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_tdb (void)
+{
+ int rc;
+
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin (&local_tdb)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 1;
+ }
+ if (local_tdb.format != 0)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 2;
+ }
+ }
+ else
+ {
+ return 100 * rc + 3;
+ }
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin (&local_tdb)) == 0)
+ {
+ __builtin_tabort (257);
+ return 4;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 5;
+ }
+ if (local_tdb.format != 1)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 6;
+ }
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin (&local_tdb256)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 1100 * rc + 1;
+ }
+ if (local_tdb256.format != 0)
+ {
+ dump_tdb (&local_tdb256);
+ return 1100 * local_tdb256.format + 2;
+ }
+ }
+ else
+ {
+ return 1100 * rc + 3;
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin (&local_tdb256)) == 0)
+ {
+ __builtin_tabort (257);
+ return 2004;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 2100 * rc + 5;
+ }
+ if (local_tdb256.format != 1)
+ {
+ dump_tdb (&local_tdb256);
+ return 2100 * local_tdb256.format + 6;
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_nofloat_tdb (void)
+{
+ int rc;
+
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin_nofloat (&local_tdb)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 1;
+ }
+ if (local_tdb.format != 0)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 2;
+ }
+ }
+ else
+ {
+ return 3;
+ }
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin_nofloat (&local_tdb)) == 0)
+ {
+ __builtin_tabort (257);
+ return 4;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 5;
+ }
+ if (local_tdb.format != 1)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 6;
+ }
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_nofloat (&local_tdb256)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 1100 * rc + 1;
+ }
+ if (local_tdb256.format != 0)
+ {
+ dump_tdb (&local_tdb256);
+ return 1100 * local_tdb256.format + 2;
+ }
+ }
+ else
+ {
+ return 1003;
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_nofloat (&local_tdb256)) == 0)
+ {
+ __builtin_tabort (257);
+ return 2004;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 2100 * rc + 5;
+ }
+ if (local_tdb256.format != 1)
+ {
+ dump_tdb (&local_tdb256);
+ return 2100 * local_tdb256.format + 6;
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry_tdb (void)
+{
+ int rc;
+
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_retry (&local_tdb256, 2)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 1100 * rc + 1;
+ }
+ if (local_tdb256.format != 0)
+ {
+ dump_tdb (&local_tdb256);
+ return 1100 * local_tdb256.format + 2;
+ }
+ }
+ else
+ {
+ return 1003;
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_retry (&local_tdb256, 2)) == 0)
+ {
+ __builtin_tabort (257);
+ return 2004;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 2100 * rc + 5;
+ }
+ if (local_tdb256.format != 1)
+ {
+ dump_tdb (&local_tdb256);
+ return 2100 * local_tdb256.format + 6;
+ }
+ }
+
+ return 0;
+}
+
+static int test_tbegin_retry_nofloat_tdb (void)
+{
+ int rc;
+
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb, 2)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 100 * rc + 1;
+ }
+ if (local_tdb.format != 0)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 2;
+ }
+ }
+ else
+ {
+ return 100 * rc + 3;
+ }
+ local_tdb.format = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb, 2)) == 0)
+ {
+ __builtin_tabort (257);
+ return 4;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 5;
+ }
+ if (local_tdb.format != 1)
+ {
+ dump_tdb (&local_tdb);
+ return 100 * local_tdb.format + 6;
+ }
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb256, 2)) == 0)
+ {
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 1100 * rc + 1;
+ }
+ if (local_tdb256.format != 0)
+ {
+ dump_tdb (&local_tdb256);
+ return 1100 * local_tdb256.format + 2;
+ }
+ }
+ else
+ {
+ return 1100 * rc + 3;
+ }
+ local_tdb256.format = 0;
+ if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb256, 2)) == 0)
+ {
+ __builtin_tabort (257);
+ return 2004;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 2100 * rc + 5;
+ }
+ if (local_tdb256.format != 1)
+ {
+ dump_tdb (&local_tdb256);
+ return 2100 * local_tdb256.format + 6;
+ }
+ }
+
+ return 0;
+}
+
+static int test_etnd (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ counters.c3 = 0;
+ if ((rc = __builtin_tbegin ((void *)0)) == 0)
+ {
+ counters.c1 = __builtin_tx_nesting_depth ();
+ if (__builtin_tbegin ((void *)0) == 0)
+ {
+ counters.c2 = __builtin_tx_nesting_depth ();
+ if (__builtin_tbegin ((void *)0) == 0)
+ {
+ counters.c3 = __builtin_tx_nesting_depth ();
+ __builtin_tend ();
+ }
+ __builtin_tend ();
+ }
+ __builtin_tend ();
+ }
+ else
+ {
+ return 100 * rc + 1;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 2)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (counters.c3 != 3)
+ {
+ return 100 * counters.c3 + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbeginc (void)
+{
+ int rc;
+
+ counters.c1 = 0;
+ __builtin_tbeginc ();
+ counters.c1 = 1;
+ rc = __builtin_tend ();
+ if (rc != 0)
+ {
+ return 10000 * rc + 1;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100000 * counters.c1 + 3;
+ }
+
+ return 0;
+}
+
+/* ---------------------------- local testing framework functions ---------- */
+
+static int run_one_test (const test_table_entry_t *test_entry)
+{
+ int do_print_passes;
+ int succeeded;
+ int rc;
+ int i;
+
+ /* Warmup run to get all necessary data and instruction pages into the page
+ * tables. */
+ {
+ int run;
+
+ do_dump_tdb = 0;
+ for (run = 0; run < NUM_WARMUP_RUNS; run++)
+ {
+ test_entry->test_func ();
+ }
+ do_dump_tdb = 1;
+ }
+ do_print_passes = (
+ test_entry->required_quorum != 1 ||
+ test_entry->max_repetitions != 1);
+ printf ("RRR RUN %s\n", test_entry->name);
+ if (do_print_passes == 1)
+ {
+ printf (
+ " (requires %d successful out of %d runs)\n",
+ test_entry->required_quorum,
+ test_entry->max_repetitions);
+ }
+ succeeded = 0;
+ rc = 0;
+ for (rc = 0, i = 0; i < test_entry->max_repetitions; i++)
+ {
+ if (do_print_passes == 1)
+ {
+ if (i == 0)
+ {
+ printf (" ");
+ }
+ else
+ {
+ printf (",");
+ }
+ }
+ rc = test_entry->test_func ();
+ if (rc == 0)
+ {
+ if (do_print_passes == 1)
+ {
+ printf (" success");
+ }
+ succeeded++;
+ if (succeeded >= test_entry->required_quorum)
+ {
+ break;
+ }
+ }
+ else
+ {
+ printf (" failed (rc = %d)", rc);
+ }
+ }
+ if (do_print_passes == 1 || rc != 0)
+ {
+ printf ("\n");
+ }
+ if (succeeded >= test_entry->required_quorum)
+ {
+ printf ("+++ OK %s\n", test_entry->name);
+
+ return 0;
+ }
+ else
+ {
+ printf ("--- FAIL %s\n", test_entry->name);
+
+ return (rc != 0) ? rc : -1;
+ }
+}
+
+static int run_all_tests (const test_table_entry_t *test_table)
+{
+ const test_table_entry_t *test;
+ int rc;
+
+ for (
+ rc = 0, test = &test_table[0];
+ test->test_func != NULL && rc == 0; test++)
+ {
+ rc = run_one_test (test);
+ }
+
+ return rc;
+}
+
+/* ---------------------------- interface functions ------------------------ */
+
+int main (void)
+{
+ const test_table_entry_t test_table[] = {
+ TEST_NO_REP (test_constants),
+ TEST_DF_REP (test_tbegin_ntstg_tend),
+ TEST_DF_REP (test_tbegin_ntstg_tabort),
+ TEST_DF_REP (test_tbegin_nofloat),
+ TEST_NO_REP (test_tbegin_retry),
+ TEST_NO_REP (test_tbegin_retry_nofloat),
+ TEST_DF_REP (test_tbegin_aborts),
+ TEST_DF_REP (test_tbegin_indirect_aborts),
+ TEST_DF_REP (test_tbegin_nofloat_aborts),
+ TEST_DF_REP (test_tbegin_nofloat_indirect_aborts),
+ TEST_NO_REP (test_tbegin_retry_aborts),
+ TEST_NO_REP (test_tbegin_retry_nofloat_aborts),
+ TEST_DF_REP (test_tbegin_tdb),
+ TEST_DF_REP (test_tbegin_nofloat_tdb),
+ TEST_NO_REP (test_tbegin_retry_tdb),
+ TEST_NO_REP (test_tbegin_retry_nofloat_tdb),
+ TEST_DF_REP (test_etnd),
+ TEST_DF_REP (test_tbeginc),
+ { (void *)0, 0, 0 }
+ };
+
+ {
+ int rc;
+
+ rc = run_all_tests (test_table);
+
+ return rc;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/s390/htm-builtins-2.c b/gcc/testsuite/gcc.target/s390/htm-builtins-2.c
new file mode 100644
index 00000000000..15b0d12ae92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-builtins-2.c
@@ -0,0 +1,682 @@
+/* Functional tests of the htm __TM_... macros. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target htm } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+/* ---------------------------- included header files ---------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <htmxlintrin.h>
+
+/* ---------------------------- local definitions -------------------------- */
+
+#define DEFAULT_MAX_REPETITIONS 5
+#define DEFAULT_REQUIRED_QUORUM ((DEFAULT_MAX_REPETITIONS) - 1)
+#define DEFAULT_ABORT_ADDRESS (0x12345678u)
+
+/* ---------------------------- local macros ------------------------------- */
+
+#define TEST_DF_REP(name) \
+ { #name, name, DEFAULT_MAX_REPETITIONS, DEFAULT_REQUIRED_QUORUM }
+#define TEST_NO_REP(name) { #name, name, 1, 1 }
+
+/* ---------------------------- local types -------------------------------- */
+
+typedef int (*test_func_t)(void);
+
+typedef struct
+{
+ const char *name;
+ test_func_t test_func;
+ int max_repetitions;
+ int required_quorum;
+} test_table_entry_t;
+
+typedef enum
+{
+ ABORT_T_SYSTEM = 0,
+ ABORT_T_USER = 1,
+} abort_user_t;
+
+typedef enum
+{
+ ABORT_T_NONE = 0,
+ ABORT_T_ILLEGAL,
+ ABORT_T_FOOTPRINT_EXCEEDED,
+ ABORT_T_NESTED_TOO_DEEP,
+ ABORT_T_CONFLICT,
+
+ ABORT_T_INVALID_ABORT_CODE
+} abort_t;
+
+/* ---------------------------- local variables ---------------------------- */
+
+__attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256;
+static struct __htm_tdb local_tdb;
+
+static abort_t const abort_classes[] =
+{
+ ABORT_T_INVALID_ABORT_CODE,
+ ABORT_T_NONE,
+ ABORT_T_NONE,
+ ABORT_T_NONE,
+
+ ABORT_T_ILLEGAL,
+ ABORT_T_NONE,
+ ABORT_T_NONE,
+ ABORT_T_FOOTPRINT_EXCEEDED,
+
+ ABORT_T_FOOTPRINT_EXCEEDED,
+ ABORT_T_CONFLICT,
+ ABORT_T_CONFLICT,
+ ABORT_T_ILLEGAL,
+
+ ABORT_T_NONE,
+ ABORT_T_NESTED_TOO_DEEP,
+ ABORT_T_NONE,
+ ABORT_T_NONE,
+
+ ABORT_T_NONE
+};
+
+static size_t num_abort_classes = sizeof(abort_classes) / sizeof(abort_t);
+
+/* ---------------------------- exported variables (globals) --------------- */
+
+int global_int = 0;
+uint64_t global_u64 = 0;
+float global_float_1 = 1.0;
+float global_float_2 = 2.5;
+float global_float_3 = 0.0;
+__attribute__ ((aligned(256))) struct
+{
+ volatile uint64_t c1;
+ volatile uint64_t c2;
+ volatile uint64_t c3;
+} counters = { 0, 0, 0 };
+
+/* ---------------------------- local helper functions --------------------- */
+
+static void dump_tdb(struct __htm_tdb *tdb)
+{
+ unsigned char *p;
+ int i;
+ int j;
+
+ p = (unsigned char *)tdb;
+ for (i = 0; i < 16; i++)
+ {
+ fprintf(stderr, "0x%02x ", i * 16);
+ for (j = 0; j < 16; j++)
+ {
+ fprintf(stderr, "%02x", (int)p[i * 16 + j]);
+ if (j < 15)
+ {
+ fprintf(stderr, " ");
+ }
+ if (j == 7)
+ {
+ fprintf(stderr, " ");
+ }
+ }
+ fprintf(stderr, "\n");
+ }
+
+ return;
+}
+
+static void make_fake_tdb(struct __htm_tdb *tdb)
+{
+ memset(tdb, 0, sizeof(*tdb));
+ tdb->format = 1;
+ tdb->nesting_depth = 1;
+ tdb->atia = DEFAULT_ABORT_ADDRESS;
+ tdb->abort_code = 11;
+
+ return;
+}
+
+static int check_abort_code_in_tdb(struct __htm_tdb *tdb, uint64_t abort_code)
+{
+ long expect_rc;
+ long rc;
+
+ if (abort_code != 0)
+ {
+ long addr;
+
+ addr = __TM_failure_address(&local_tdb);
+ if (addr != DEFAULT_ABORT_ADDRESS)
+ {
+ return 11;
+ }
+ }
+ {
+ long long tdb_abort_code;
+
+ tdb_abort_code = __TM_failure_code(tdb);
+ if ((uint64_t)tdb_abort_code != abort_code)
+ {
+ fprintf(
+ stderr, "tm_ac %" PRIu64 ", ac %" PRIu64
+ ", tdb_ac %" PRIu64 "\n",
+ (uint64_t)tdb_abort_code, abort_code,
+ (uint64_t)tdb->abort_code);
+ return 10;
+ }
+ }
+ expect_rc = (abort_code >= 256) ? 1 : 0;
+ rc = __TM_is_user_abort(tdb);
+ if (rc != expect_rc)
+ {
+ fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
+ return 1;
+ }
+ {
+ unsigned char code;
+
+ code = 0xffu;
+ rc = __TM_is_named_user_abort(tdb, &code);
+ if (rc != expect_rc)
+ {
+ fprintf(
+ stderr, "rc %ld, expect_rc %ld\n", rc,
+ expect_rc);
+ return 2;
+ }
+ if (expect_rc == 1 && code != abort_code - 256)
+ {
+ return 3;
+ }
+ }
+ if (abort_code > (uint64_t)num_abort_classes)
+ {
+ abort_code = (uint64_t)num_abort_classes;
+ }
+ expect_rc = (abort_classes[abort_code] == ABORT_T_ILLEGAL) ? 1 : 0;
+ rc = __TM_is_illegal(tdb);
+ if (rc != expect_rc)
+ {
+ dump_tdb(tdb);
+ fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
+ return 4;
+ }
+ expect_rc =
+ (abort_classes[abort_code] == ABORT_T_FOOTPRINT_EXCEEDED) ?
+ 1 : 0;
+ rc = __TM_is_footprint_exceeded(tdb);
+ if (rc != expect_rc)
+ {
+ dump_tdb(tdb);
+ fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
+ return 5;
+ }
+ expect_rc =
+ (abort_classes[abort_code] == ABORT_T_NESTED_TOO_DEEP) ? 1 : 0;
+ rc = __TM_is_nested_too_deep(tdb);
+ if (rc != expect_rc)
+ {
+ dump_tdb(tdb);
+ fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
+ return 6;
+ }
+ expect_rc = (abort_classes[abort_code] == ABORT_T_CONFLICT) ? 1 : 0;
+ rc = __TM_is_conflict(tdb);
+ if (rc != expect_rc)
+ {
+ dump_tdb(tdb);
+ fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
+ return 7;
+ }
+
+ return 0;
+}
+
+/* ---------------------------- local test functions ----------------------- */
+
+/* Not a test; make sure that the involved global cachelines are reserved for
+ * writing. */
+static int init_cache(void)
+{
+ make_fake_tdb(&local_tdb);
+ make_fake_tdb(&local_tdb256);
+ global_int = 0;
+ global_u64 = 0;
+ global_float_1 = 1.0;
+ global_float_2 = 2.5;
+ global_float_3 = 0.0;
+ counters.c1 = 0;
+ counters.c2 = 0;
+ counters.c3 = 0;
+
+ return 0;
+}
+
+static int test_abort_classification(void)
+{
+ int i;
+
+ make_fake_tdb(&local_tdb);
+ for (i = 0; i <= 256; i++)
+ {
+ int rc;
+
+ local_tdb.abort_code = (uint64_t)i;
+ rc = check_abort_code_in_tdb(&local_tdb, (uint64_t)i);
+ if (rc != 0)
+ {
+ return 100 * i + rc;
+ }
+ }
+
+ return 0;
+}
+
+static int test_cc_classification(void)
+{
+ long rc;
+
+ rc = __TM_is_failure_persistent(0);
+ if (rc != 0)
+ {
+ return 1;
+ }
+ rc = __TM_is_failure_persistent(1);
+ if (rc != 0)
+ {
+ return 2;
+ }
+ rc = __TM_is_failure_persistent(2);
+ if (rc != 0)
+ {
+ return 3;
+ }
+ rc = __TM_is_failure_persistent(3);
+ if (rc != 1)
+ {
+ return 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_ntstg_tend(void)
+{
+ long rc;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ if ((rc = __TM_simple_begin()) == 0)
+ {
+ __TM_non_transactional_store((uint64_t *)&counters.c1, 1);
+ counters.c2 = 2;
+ rc = __TM_end();
+ if (rc != 0)
+ {
+ return 100 * rc + 5;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 2)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ }
+ else
+ {
+ return 100 * rc + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_ntstg_tabort(void)
+{
+ register float f;
+
+ counters.c1 = 0;
+ counters.c2 = 0;
+ f = 0;
+ if (__TM_simple_begin() == 0)
+ {
+ __TM_non_transactional_store((uint64_t *)&counters.c1, 1);
+ counters.c2 = 2;
+ f = 1;
+ __TM_named_abort(0);
+ return 1;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 0)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (f != 0)
+ {
+ return 100 * f + 4;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_aborts(void)
+{
+ float f;
+ long rc;
+
+ f = 77;
+ if ((rc = __TM_simple_begin()) == 0)
+ {
+ f = 88;
+ __TM_abort();
+ return 2;
+ }
+ else if (rc != 2)
+ {
+ return 3;
+ }
+ if (f != 77)
+ {
+ return 4;
+ }
+ f = 66;
+ if ((rc = __TM_simple_begin()) == 0)
+ {
+ f = 99;
+ __TM_named_abort(3);
+ return 5;
+ }
+ else if (rc != 3)
+ {
+ return 100 * rc + 6;
+ }
+ if (f != 66)
+ {
+ return 100 * f + 7;
+ }
+ if ((rc = __TM_simple_begin()) == 0)
+ {
+ global_float_3 = global_float_1 + global_float_2;
+ rc = __TM_end();
+ if (rc != 0)
+ {
+ return 100 * rc + 8;
+ }
+ }
+ else
+ {
+ return 100 * rc + 9;
+ }
+ if (global_float_3 != global_float_1 + global_float_2)
+ {
+ return 100 * rc + 10;
+ }
+
+ return 0;
+}
+
+static int test_tbegin_tdb(void)
+{
+ long rc;
+
+ local_tdb.format = 0;
+ if ((rc = __TM_begin(&local_tdb)) == 0)
+ {
+ rc = __TM_end();
+ if (rc != 0)
+ {
+ return 100 * rc + 1;
+ }
+ if (local_tdb.format != 0)
+ {
+ dump_tdb(&local_tdb);
+ return 100 * local_tdb.format + 2;
+ }
+ }
+ else
+ {
+ return 100 * rc + 3;
+ }
+ local_tdb.format = 0;
+ if ((rc = __TM_begin(&local_tdb)) == 0)
+ {
+ __TM_named_abort(1);
+ return 4;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 100 * rc + 5;
+ }
+ if (local_tdb.format != 1)
+ {
+ dump_tdb(&local_tdb);
+ return 100 * local_tdb.format + 6;
+ }
+ }
+ local_tdb256.format = 0;
+ if ((rc = __TM_begin(&local_tdb256)) == 0)
+ {
+ rc = __TM_end();
+ if (rc != 0)
+ {
+ return 1100 * rc + 1;
+ }
+ if (local_tdb256.format != 0)
+ {
+ dump_tdb(&local_tdb256);
+ return 1100 * local_tdb256.format + 2;
+ }
+ }
+ else
+ {
+ return 1100 * rc + 3;
+ }
+#if 1 /*!!!does not work*/
+ local_tdb256.format = 0;
+ if ((rc = __TM_begin(&local_tdb256)) == 0)
+ {
+ __TM_named_abort(1);
+ return 2004;
+ }
+ else
+ {
+ if (rc != 3)
+ {
+ return 2100 * rc + 5;
+ }
+ if (local_tdb256.format != 1)
+ {
+ dump_tdb(&local_tdb256);
+ return 2100 * local_tdb256.format + 6;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int test_etnd(void)
+{
+ long rc;
+
+ {
+ long nd;
+
+ make_fake_tdb(&local_tdb);
+ local_tdb.nesting_depth = 0;
+ nd = __TM_nesting_depth(&local_tdb);
+ if (nd != 0)
+ {
+ return 1;
+ }
+ local_tdb.nesting_depth = 7;
+ nd = __TM_nesting_depth(&local_tdb);
+ if (nd != 7)
+ {
+ return 7;
+ }
+ local_tdb.format = 0;
+ nd = __TM_nesting_depth(&local_tdb);
+ if (nd != 0)
+ {
+ return 2;
+ }
+ }
+ counters.c1 = 0;
+ counters.c1 = 0;
+ counters.c2 = 0;
+ counters.c3 = 0;
+ if ((rc = __TM_simple_begin()) == 0)
+ {
+ counters.c1 = __TM_nesting_depth(0);
+ if (__TM_simple_begin() == 0)
+ {
+ counters.c2 = __TM_nesting_depth(0);
+ if (__TM_simple_begin() == 0)
+ {
+ counters.c3 = __TM_nesting_depth(0);
+ __TM_end();
+ }
+ __TM_end();
+ }
+ __TM_end();
+ }
+ else
+ {
+ return 100 * rc + 1;
+ }
+ if (counters.c1 != 1)
+ {
+ return 100 * counters.c1 + 2;
+ }
+ if (counters.c2 != 2)
+ {
+ return 100 * counters.c2 + 3;
+ }
+ if (counters.c3 != 3)
+ {
+ return 100 * counters.c3 + 4;
+ }
+
+ return 0;
+}
+
+/* ---------------------------- local testing framework functions ---------- */
+
+static int run_one_test(const test_table_entry_t *test_entry)
+{
+ int do_print_passes;
+ int succeeded;
+ int rc;
+ int i;
+
+ do_print_passes = (
+ test_entry->required_quorum != 1 ||
+ test_entry->max_repetitions != 1);
+ printf("RRR RUN %s\n", test_entry->name);
+ if (do_print_passes == 1)
+ {
+ printf(
+ " (requires %d successful out of %d runs)\n",
+ test_entry->required_quorum,
+ test_entry->max_repetitions);
+ }
+ succeeded = 0;
+ rc = 0;
+ for (rc = 0, i = 0; i < test_entry->max_repetitions; i++)
+ {
+ if (do_print_passes == 1)
+ {
+ if (i == 0)
+ {
+ printf(" ");
+ }
+ else
+ {
+ printf(",");
+ }
+ }
+ rc = test_entry->test_func();
+ if (rc == 0)
+ {
+ if (do_print_passes == 1)
+ {
+ printf(" success");
+ }
+ succeeded++;
+ if (succeeded >= test_entry->required_quorum)
+ {
+ break;
+ }
+ }
+ else
+ {
+ printf(" failed (rc = %d)", rc);
+ }
+ }
+ if (do_print_passes == 1 || rc != 0)
+ {
+ printf("\n");
+ }
+ if (succeeded >= test_entry->required_quorum)
+ {
+ printf("+++ OK %s\n", test_entry->name);
+
+ return 0;
+ }
+ else
+ {
+ printf("--- FAIL %s\n", test_entry->name);
+
+ return (rc != 0) ? rc : -1;
+ }
+}
+
+static int run_all_tests(const test_table_entry_t *test_table)
+{
+ const test_table_entry_t *test;
+ int rc;
+
+ for (
+ rc = 0, test = &test_table[0];
+ test->test_func != NULL && rc == 0; test++)
+ {
+ rc = run_one_test(test);
+ }
+
+ return rc;
+}
+
+/* ---------------------------- interface functions ------------------------ */
+
+int main(void)
+{
+ const test_table_entry_t test_table[] = {
+ TEST_NO_REP(init_cache),
+ TEST_NO_REP(test_abort_classification),
+ TEST_NO_REP(test_cc_classification),
+ TEST_DF_REP(test_tbegin_ntstg_tend),
+ TEST_DF_REP(test_tbegin_ntstg_tabort),
+ TEST_DF_REP(test_tbegin_aborts),
+ TEST_DF_REP(test_tbegin_tdb),
+ TEST_DF_REP(test_etnd),
+ { (void *)0, 0, 0 }
+ };
+
+ {
+ int rc;
+
+ rc = run_all_tests(test_table);
+
+ return rc;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/s390/htm-builtins-compile-1.c b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-1.c
new file mode 100644
index 00000000000..c1faa6bb3b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-1.c
@@ -0,0 +1,165 @@
+/* This checks the availability of the low-level builtins introduced
+ for transactional execution. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target htm } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+#include <stdint.h>
+#include <htmintrin.h>
+
+int global = 0;
+uint64_t g;
+struct __htm_tdb global_tdb;
+
+int
+foo (struct __htm_tdb* tdb, int reg, int *mem, uint64_t *mem64)
+{
+
+ int cc;
+ int n;
+
+ __builtin_tbegin ((void *)0);
+ __builtin_tbegin ((void *)-99999);
+ __builtin_tbegin ((void *)99999);
+ while (__builtin_tbegin ((void *)0) != 0)
+ {
+ }
+ cc = __builtin_tbegin ((void *)0x12345678);
+ cc = __builtin_tbegin (tdb);
+ cc = __builtin_tbegin (&global_tdb);
+ cc = __builtin_tbegin ((void *)(long long)(reg + 0x12345678));
+ cc = __builtin_tbegin ((void *)(long long)(reg));
+
+ __builtin_tbegin_nofloat ((void *)0);
+ __builtin_tbegin_nofloat ((void *)-99999);
+ __builtin_tbegin_nofloat ((void *)99999);
+ cc = __builtin_tbegin_nofloat ((void *)0x12345678);
+ cc = __builtin_tbegin_nofloat (tdb);
+ cc = __builtin_tbegin_nofloat (&global_tdb);
+ cc = __builtin_tbegin_nofloat ((void *)(long long)(reg + 0x12345678));
+ cc = __builtin_tbegin_nofloat ((void *)(long long)(reg));
+
+ __builtin_tbegin_retry ((void *)0, 0);
+ cc = __builtin_tbegin_retry ((void *)0, 1);
+ cc = __builtin_tbegin_retry ((void *)0, -1);
+ cc = __builtin_tbegin_retry ((void *)0, 42);
+ cc = __builtin_tbegin_retry ((void *)0, reg);
+ cc = __builtin_tbegin_retry ((void *)0, *mem);
+ cc = __builtin_tbegin_retry ((void *)0, global);
+ cc = __builtin_tbegin_retry (tdb, 42);
+ cc = __builtin_tbegin_retry (&global_tdb, 42);
+ cc = __builtin_tbegin_retry ((void *)0x12345678, global);
+ cc = __builtin_tbegin_retry (
+ (void *)(long long) (reg + 0x12345678), global + 1);
+ cc = __builtin_tbegin_retry (
+ (void *)(long long)(reg), global - 1);
+
+ __builtin_tbegin_retry_nofloat ((void *)0, 0);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, 1);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, -1);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, 42);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, reg);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, *mem);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0, global);
+ cc = __builtin_tbegin_retry_nofloat (tdb, 42);
+ cc = __builtin_tbegin_retry_nofloat (&global_tdb, 42);
+ cc = __builtin_tbegin_retry_nofloat ((void *)0x12345678, global);
+ cc = __builtin_tbegin_retry_nofloat (
+ (void *)(long long) (reg + 0x12345678), global + 1);
+ cc = __builtin_tbegin_retry_nofloat (
+ (void *)(long long)(reg), global - 1);
+
+ __builtin_tbeginc ();
+
+ __builtin_tx_nesting_depth ();
+ n = __builtin_tx_nesting_depth ();
+
+ __builtin_non_tx_store (mem64, 0);
+ {
+ const uint64_t val_var = 0x1122334455667788;
+
+ __builtin_non_tx_store (mem64, val_var);
+ }
+ __builtin_non_tx_store (mem64, (uint64_t)reg);
+ __builtin_non_tx_store (mem64, g);
+ __builtin_non_tx_store ((uint64_t *)0, 0);
+ __builtin_non_tx_store ((uint64_t *)0x12345678, 0);
+ __builtin_non_tx_store (&g, 23);
+ __builtin_non_tx_store (&g, reg);
+ __builtin_non_tx_store (&g, *mem);
+ __builtin_non_tx_store (&g, global);
+
+ __builtin_tend();
+
+ __builtin_tx_assist (0);
+ __builtin_tx_assist (1);
+ __builtin_tx_assist (reg);
+ __builtin_tx_assist (*mem);
+ __builtin_tx_assist (global);
+}
+
+/* The taborts must go into separate function since they are
+ "noreturn". */
+
+void
+tabort1 ()
+{
+ __builtin_tabort (256);
+}
+
+void
+tabort2 (int reg)
+{
+ __builtin_tabort (reg);
+}
+
+void
+tabort3 (int reg)
+{
+ /* { dg-final { scan-assembler-times "tabort\t255" 1 } } */
+ __builtin_tabort (reg + 255);
+}
+
+void
+tabort4 (int *mem)
+{
+ __builtin_tabort (*mem);
+}
+
+void
+tabort5 ()
+{
+ __builtin_tabort (global);
+}
+
+void
+tabort6 (int *mem)
+{
+ /* Here global + 255 gets reloaded into a reg. Better would be to
+ just reload global or *mem and get the +255 for free as address
+ arithmetic. */
+ __builtin_tabort (*mem + 255);
+}
+
+void
+tabort7 ()
+{
+ __builtin_tabort (global + 255);
+}
+
+void
+tabort8 ()
+{
+ __builtin_tabort (-1);
+}
+
+
+/* Make sure the tdb NULL argument ends up as immediate value in the
+ instruction. */
+/* { dg-final { scan-assembler-times "tbegin\t0," 17 } } */
+/* { dg-final { scan-assembler-times "tbegin\t" 41 } } */
+/* Check number of occurences of certain instructions. */
+/* { dg-final { scan-assembler-times "tbeginc\t" 1 } } */
+/* { dg-final { scan-assembler-times "tabort\t" 8 } } */
+/* { dg-final { scan-assembler "ppa\t" } } */
diff --git a/gcc/testsuite/gcc.target/s390/htm-builtins-compile-2.c b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-2.c
new file mode 100644
index 00000000000..6d82864d62a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target htm } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+void must_not_compile1 (void)
+{
+ __builtin_tabort (0); /* { dg-error "Invalid transaction abort code:" } */
+}
+
+void must_not_compile2 (void)
+{
+ __builtin_tabort (255); /* { dg-error "Invalid transaction abort code:" } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/htm-builtins-compile-3.c b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-3.c
new file mode 100644
index 00000000000..77ceeb7706f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-builtins-compile-3.c
@@ -0,0 +1,37 @@
+/* This checks the availability of the XL compiler intrinsics for
+ transactional execution with the expected prototypes. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+#include <htmxlintrin.h>
+
+int a = 0;
+unsigned long g;
+
+int
+foo ()
+{
+ struct __htm_tdb *tdb_struct;
+ void * const tdb = tdb_struct;
+ long result;
+ unsigned char code;
+
+ result = __TM_simple_begin ();
+ result = __TM_begin (tdb);
+ result = __TM_end ();
+ __TM_abort ();
+ __TM_named_abort (42);
+ __TM_non_transactional_store (&g, 42);
+ result = __TM_nesting_depth (tdb);
+
+ result = __TM_is_user_abort (tdb);
+ result = __TM_is_named_user_abort (tdb, &code);
+ result = __TM_is_illegal (tdb);
+ result = __TM_is_footprint_exceeded (tdb);
+ result = __TM_is_nested_too_deep (tdb);
+ result = __TM_is_conflict (tdb);
+ result = __TM_is_failure_persistent (result);
+ result = __TM_failure_address (tdb);
+ result = __TM_failure_code (tdb);
+}
diff --git a/gcc/testsuite/gcc.target/s390/htm-nofloat-1.c b/gcc/testsuite/gcc.target/s390/htm-nofloat-1.c
new file mode 100644
index 00000000000..df7e2bac874
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-nofloat-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+int
+foo ()
+{
+ __builtin_tbegin_nofloat (0);
+ __builtin_tbegin_retry_nofloat (0, 42);
+}
+/* Make sure no FPR saves/restores are emitted. */
+/* { dg-final { scan-assembler-not "std" } } */
+/* { dg-final { scan-assembler-not "ld" } } */
diff --git a/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c b/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c
new file mode 100644
index 00000000000..59621a4c19b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mhtm -Wa,-march=zEC12,-mzarch --save-temps" } */
+
+/* __builtin_tbegin has to emit clobbers for all FPRs since the tbegin
+ instruction does not automatically preserves them. If the
+ transaction body is fully contained in a function the backend tries
+ after reload to get rid of the FPR save/restore operations
+ triggered by the clobbers. This testcase failed since the backend
+ was able to get rid of all FPR saves/restores and since these were
+ the only stack operations also of the entire stack space. So even
+ the save/restore of the stack pointer was omitted in the end.
+ However, since the frame layout has been fixed before, the prologue
+ still generated the stack pointer decrement making foo return with
+ a modified stack pointer. */
+
+void abort(void);
+
+void __attribute__((noinline))
+foo (int a)
+{
+ /* This is just to prevent the tbegin code from actually being
+ executed. That way the test may even run on machines prior to
+ zEC12. */
+ if (a == 42)
+ return;
+
+ if (__builtin_tbegin (0) == 0)
+ __builtin_tend ();
+}
+
+#ifdef __s390x__
+#define GET_STACK_POINTER(SP) \
+ asm volatile ("stg %%r15, %0" : "=QRST" (SP));
+#else
+#define GET_STACK_POINTER(SP) \
+ asm volatile ("st %%r15, %0" : "=QR" (SP));
+#endif
+
+int main(void)
+{
+ unsigned long new_sp, old_sp;
+
+ GET_STACK_POINTER (old_sp);
+ foo(42);
+ GET_STACK_POINTER (new_sp);
+
+ if (old_sp != new_sp)
+ abort ();
+
+ return 0;
+}
+
+/* Make sure no FPR saves/restores are emitted. */
+/* { dg-final { scan-assembler-not "\tstd\t" } } */
+/* { dg-final { scan-assembler-not "\tld\t" } } */
diff --git a/gcc/testsuite/gcc.target/s390/s390.exp b/gcc/testsuite/gcc.target/s390/s390.exp
index a4a6609cb01..f7f9ad25607 100644
--- a/gcc/testsuite/gcc.target/s390/s390.exp
+++ b/gcc/testsuite/gcc.target/s390/s390.exp
@@ -24,6 +24,19 @@ if ![istarget s390*-*-*] then {
# Load support procs.
load_lib gcc-dg.exp
+# Return 1 if htm (etnd - extract nesting depth) instructions can be
+# compiled.
+proc check_effective_target_htm { } {
+ if { ![check_runtime s390_check_htm [subst {
+ int main (void)
+ {
+ unsigned int nd = 77;
+ asm (".insn rre,0xb2ec0000,%0,0" : "=d" (nd));
+ return nd;
+ }
+ }]] } { return 0 } else { return 1 }
+}
+
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-19.c b/gcc/testsuite/gcc.target/sh/pr51244-19.c
index 4d4f781ed5c..3eb0a927ca3 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-19.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-19.c
@@ -22,11 +22,16 @@
unwanted sequences. Thus, if we see any movt insns, something is not
working as expected. This test requires -O2 because the T bit stores
in question will be eliminated in additional insn split passes after
- reload. */
+ reload.
+
+ Notice: When this test case was initially added, the T bit optimization
+ was buggy and this test case resulted in wrong code. The movt
+ instructions actually have to be present in this case to get
+ correct code. */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
-/* { dg-final { scan-assembler-not "movt" } } */
+/* { dg-final { scan-assembler "movt" } } */
struct request
{
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-3.c b/gcc/testsuite/gcc.target/sh/pr54089-3.c
index ffb976ba11b..3fb0f7a9aea 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-3.c
@@ -5,7 +5,7 @@
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m1*" "-m2" "-m2e*" } } */
/* { dg-final { scan-assembler-not "and" } } */
-/* { dg-final { scan-assembler-not "31" } } */
+/* { dg-final { scan-assembler-not "#31" } } */
int
test00 (unsigned int a, int* b, int c, int* d, unsigned int e)
diff --git a/gcc/testsuite/gcc.target/sh/torture/pr58314.c b/gcc/testsuite/gcc.target/sh/torture/pr58314.c
new file mode 100644
index 00000000000..61447d84ff9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/torture/pr58314.c
@@ -0,0 +1,102 @@
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-Os" } */
+
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+typedef signed short s16;
+
+
+static inline __attribute__((always_inline)) __attribute__((__const__)) __u16 __arch_swab16(__u16 x)
+{
+ __asm__(
+ "swap.b %1, %0"
+ : "=r" (x)
+ : "r" (x));
+ return x;
+}
+
+void u16_add_cpu(__u16 *var)
+{
+ *var = __arch_swab16(*var);
+}
+
+typedef struct xfs_mount {
+ int m_attr_magicpct;
+} xfs_mount_t;
+
+typedef struct xfs_da_args {
+ struct xfs_mount *t_mountp;
+ int index;
+} xfs_da_args_t;
+
+typedef struct xfs_dabuf {
+ void *data;
+} xfs_dabuf_t;
+
+typedef struct xfs_attr_leaf_map {
+ __u16 base;
+ __u16 size;
+} xfs_attr_leaf_map_t;
+typedef struct xfs_attr_leaf_hdr {
+ __u16 count;
+ xfs_attr_leaf_map_t freemap[3];
+} xfs_attr_leaf_hdr_t;
+
+typedef struct xfs_attr_leaf_entry {
+ __u16 nameidx;
+} xfs_attr_leaf_entry_t;
+
+typedef struct xfs_attr_leafblock {
+ xfs_attr_leaf_hdr_t hdr;
+ xfs_attr_leaf_entry_t entries[1];
+} xfs_attr_leafblock_t;
+
+int
+xfs_attr_leaf_remove(xfs_attr_leafblock_t *leaf, xfs_da_args_t *args)
+{
+ xfs_attr_leaf_hdr_t *hdr;
+ xfs_attr_leaf_map_t *map;
+ xfs_attr_leaf_entry_t *entry;
+ int before, after, smallest, entsize;
+ int tablesize, tmp, i;
+ xfs_mount_t *mp;
+ hdr = &leaf->hdr;
+ mp = args->t_mountp;
+
+ entry = &leaf->entries[args->index];
+
+ tablesize = __arch_swab16(hdr->count);
+
+ map = &hdr->freemap[0];
+ tmp = map->size;
+ before = after = -1;
+ smallest = 3 - 1;
+ entsize = xfs_attr_leaf_entsize(leaf, args->index);
+
+ for (i = 0; i < 2; map++, i++) {
+
+ if (map->base == tablesize)
+ u16_add_cpu(&map->base);
+
+ if (__arch_swab16(map->base) + __arch_swab16(map->size) == __arch_swab16(entry->nameidx))
+ before = i;
+ else if (map->base == entsize)
+ after = i;
+ else if (__arch_swab16(map->size) < tmp)
+ smallest = i;
+ }
+
+ if (before >= 0)
+ {
+ map = &hdr->freemap[after];
+ map->base = entry->nameidx;
+
+ }
+
+ map = &hdr->freemap[smallest];
+
+ map->base = __arch_swab16(entry->nameidx);
+
+ return(tmp < mp->m_attr_magicpct);
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-1.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-1.c
index 7d0b5063637..36645bdc331 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-1.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-1.c
@@ -2,7 +2,7 @@
*/
/* Origin: Kai Tietz <kai.tietz@onevision.com> */
/* { dg-do run } */
-/* { dg-options "-std=gnu99 -ffast-math" } */
+/* { dg-options "-std=gnu99 -ffast-math -maccumulate-outgoing-args" } */
#include "callabi.h"
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
index 048da6e56ac..3b26da6312c 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
@@ -1,6 +1,6 @@
/* Test for cross x86_64<->w64 abi standard calls. */
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin -maccumulate-outgoing-args" } */
/* { dg-additional-sources "func-2b.c" } */
extern void __attribute__ ((sysv_abi)) abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
index fe85dd1860d..0665665e44a 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
@@ -1,5 +1,5 @@
/* Test for cross x86_64<->w64 abi standard calls. */
-/* { dg-options "-mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-options "-mabi=ms -std=gnu99 -ffast-math -fno-builtin -maccumulate-outgoing-args" } */
long double func_cross (long double a, double b, float c, long d, int e,
char f)
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
index 730b8db9c1f..ab124660518 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
@@ -1,6 +1,6 @@
/* Test for cross x86_64<->w64 abi standard calls via variable. */
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin -maccumulate-outgoing-args" } */
/* { dg-additional-sources "func-indirect-2b.c" } */
extern void __attribute__ ((sysv_abi)) abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
index 1a9fccd97f6..6d154364a77 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
@@ -1,5 +1,5 @@
/* Test for cross x86_64<->w64 abi standard calls via variable. */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin -maccumulate-outgoing-args" } */
typedef int (*func)(void *, char *, char *, short, long long);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect.c
index 0c0cbb271ca..1b77a00db67 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect.c
@@ -2,7 +2,7 @@
*/
/* Origin: Kai Tietz <kai.tietz@onevision.com> */
/* { dg-do run } */
-/* { dg-options "-std=gnu99 -ffast-math" } */
+/* { dg-options "-std=gnu99 -ffast-math -maccumulate-outgoing-args" } */
#include "callabi.h"
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-1.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-1.c
index 35f8b53cac1..027134f6c5b 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-1.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mabi=sysv" } */
+/* { dg-options "-O2 -mabi=sysv -maccumulate-outgoing-args" } */
__attribute__ ((ms_abi))
int foo (void)
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-2.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-2.c
index 2a54bc89cfc..93b1f64d65a 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-2.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/leaf-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mabi=sysv" } */
+/* { dg-options "-O2 -mabi=sysv -maccumulate-outgoing-args" } */
extern int glb1, gbl2, gbl3;
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/pr38891.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/pr38891.c
index d31b8c3774c..e3503d3582a 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/pr38891.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/pr38891.c
@@ -1,7 +1,7 @@
/* Test for cross x86_64<->w64 abi standard calls.
*/
/* { dg-do compile } */
-/* { dg-options "-mno-sse" } */
+/* { dg-options "-mno-sse -maccumulate-outgoing-args" } */
#include "callabi.h"
long double
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-1.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-1.c
index a6d8463ed5c..2be8a990090 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-1.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-1.c
@@ -2,7 +2,7 @@
*/
/* Origin: Kai Tietz <kai.tietz@onevision.com> */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -maccumulate-outgoing-args" } */
#include "callabi.h"
extern __SIZE_TYPE__ strlen (const char *);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-2.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-2.c
index e281e860f78..c6399457918 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-2.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-2.c
@@ -2,7 +2,7 @@
*/
/* Origin: Kai Tietz <kai.tietz@onevision.com> */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -maccumulate-outgoing-args" } */
#include "callabi.h"
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-3.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-3.c
index 7cca7ac8718..366d696cf32 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-3.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-3.c
@@ -2,7 +2,7 @@
*/
/* Origin: Kai Tietz <kai.tietz@onevision.com> */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -maccumulate-outgoing-args" } */
#include "callabi.h"
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
index a44470431ff..ec63d5acfe3 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
@@ -1,6 +1,6 @@
/* Test for cross x86_64<->w64 abi va_list calls. */
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin -maccumulate-outgoing-args" } */
/* { dg-additional-sources "vaarg-4b.c" } */
extern __SIZE_TYPE__ __attribute__ ((sysv_abi)) strlen (const char *);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
index f33906bd293..444d19039cc 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
@@ -1,5 +1,5 @@
/* Test for cross x86_64<->w64 abi va_list calls. */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin -maccumulate-outgoing-args" } */
#include <stdarg.h>
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
index e9912957e7c..7e56e5d6bab 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
@@ -1,6 +1,6 @@
/* Test for cross x86_64<->w64 abi va_list calls. */
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin -maccumulate-outgoing-args" } */
/* { dg-additional-sources "vaarg-5b.c" } */
extern void __attribute__ ((sysv_abi)) abort (void);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
index e5dd4727bdd..c3de7143d44 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
+++ b/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
@@ -1,5 +1,5 @@
/* Test for cross x86_64<->w64 abi va_list calls. */
-/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin -maccumulate-outgoing-args" } */
#include <stdarg.h>
diff --git a/gcc/testsuite/gfortran.dg/constructor_9.f90 b/gcc/testsuite/gfortran.dg/constructor_9.f90
new file mode 100644
index 00000000000..5196703031a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_9.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-options "-Wall" }
+!
+! PR 58471: [4.8/4.9 Regression] ICE on invalid with missing type constructor and -Wall
+!
+! Contributed by Andrew Benson <abensonca@gmail.com>
+
+module cf
+ implicit none
+ type :: cfmde
+ end type
+ interface cfmde
+ module procedure mdedc ! { dg-error "is neither function nor subroutine" }
+ end interface
+contains
+ subroutine cfi()
+ type(cfmde), pointer :: cfd
+ cfd=cfmde() ! { dg-error "Can't convert" }
+ end subroutine
+end module
+
+! { dg-final { cleanup-modules "cf" } }
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_10.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_10.f90
new file mode 100644
index 00000000000..1ccc49f2957
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_10.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+!
+! PR fortran/57697
+!
+! Further test of typebound defined assignment
+!
+module m0
+ implicit none
+ type component
+ integer :: i = 42
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type parent
+ type(component) :: foo
+ end type
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+block
+ type(parent), allocatable :: left
+ type(parent) :: right
+! print *, right%foo
+ left = right
+! print *, left%foo
+! if (left%foo%i /= 20) call abort()
+end block
+end
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_11.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_11.f90
new file mode 100644
index 00000000000..ec297d5492a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_11.f90
@@ -0,0 +1,43 @@
+! { dg-do run }
+!
+! PR fortran/57697
+!
+! Further test of typebound defined assignment
+!
+module m0
+ implicit none
+ type :: component
+ integer :: i = 42
+ integer, allocatable :: b
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type, extends(component) :: comp2
+ real :: aa
+ end type comp2
+ type parent
+ type(component) :: foo
+ real :: cc
+ end type
+ type p2
+ type(parent) :: x
+ end type p2
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+ type(p2), allocatable :: left
+ type(p2) :: right
+! print *, right%x%foo%i
+ left = right
+! print *, left%x%foo%i
+ if (left%x%foo%i /= 20) call abort()
+end
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_8.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_8.f90
new file mode 100644
index 00000000000..aab808583ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_8.f90
@@ -0,0 +1,40 @@
+! { dg-do compile }
+!
+! PR fortran/58469
+!
+! Related: PR fortran/57697
+!
+! Was ICEing before
+!
+module m0
+ implicit none
+ type :: component
+ integer :: i = 42
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type, extends(component) :: comp2
+ real :: aa
+ end type comp2
+ type parent
+ type(comp2) :: foo
+ end type
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+ type(parent), allocatable :: left
+ type(parent) :: right
+ print *, right%foo
+ left = right
+ print *, left%foo
+ if (left%foo%i /= 42) call abort()
+end
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_9.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_9.f90
new file mode 100644
index 00000000000..50fa0070f18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_9.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! PR fortran/57697
+!
+! Further test of typebound defined assignment
+!
+module m0
+ implicit none
+ type component
+ integer :: i = 42
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type parent
+ type(component) :: foo
+ end type
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+ block
+ type(parent), allocatable :: left
+ type(parent) :: right
+! print *, right%foo
+ left = right
+! print *, left%foo
+ if (left%foo%i /= 20) call abort()
+ end block
+ block
+ type(parent), allocatable :: left(:)
+ type(parent) :: right(5)
+! print *, right%foo
+ left = right
+! print *, left%foo
+ if (any (left%foo%i /= 20)) call abort()
+ end block
+end
diff --git a/gcc/testsuite/gfortran.dg/derived_external_function_1.f90 b/gcc/testsuite/gfortran.dg/derived_external_function_1.f90
new file mode 100644
index 00000000000..7421c4c0f22
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/derived_external_function_1.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+!
+! PR fortran/58771
+!
+! Contributed by Vittorio Secca <zeccav@gmail.com>
+!
+! ICEd on the write statement with f() because the derived type backend
+! declaration not built.
+!
+module m
+ type t
+ integer(4) g
+ end type
+end
+
+type(t) function f() result(ff)
+ use m
+ ff%g = 42
+end
+
+ use m
+ character (20) :: line1, line2
+ type(t) f
+ write (line1, *) f()
+ write (line2, *) 42_4
+ if (line1 .ne. line2) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/dynamic_dispatch_12.f90 b/gcc/testsuite/gfortran.dg/dynamic_dispatch_12.f90
new file mode 100644
index 00000000000..d37e1f6a9b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dynamic_dispatch_12.f90
@@ -0,0 +1,74 @@
+! { dg-do run }
+!
+! PR 59654: [4.8/4.9 Regression] [OOP] Broken function table with complex OO use case
+!
+! Contributed by Thomas Clune <Thomas.L.Clune@nasa.gov>
+
+module TestResult_mod
+ implicit none
+
+ type TestResult
+ integer :: numRun = 0
+ contains
+ procedure :: run
+ procedure, nopass :: getNumRun
+ end type
+
+contains
+
+ subroutine run (this)
+ class (TestResult) :: this
+ this%numRun = this%numRun + 1
+ end subroutine
+
+ subroutine getNumRun()
+ end subroutine
+
+end module
+
+
+module BaseTestRunner_mod
+ implicit none
+
+ type :: BaseTestRunner
+ contains
+ procedure, nopass :: norun
+ end type
+
+contains
+
+ function norun () result(result)
+ use TestResult_mod, only: TestResult
+ type (TestResult) :: result
+ end function
+
+end module
+
+
+module TestRunner_mod
+ use BaseTestRunner_mod, only: BaseTestRunner
+ implicit none
+end module
+
+
+program main
+ use TestRunner_mod, only: BaseTestRunner
+ use TestResult_mod, only: TestResult
+ implicit none
+
+ type (TestResult) :: result
+
+ call runtest (result)
+
+contains
+
+ subroutine runtest (result)
+ use TestResult_mod, only: TestResult
+ class (TestResult) :: result
+ call result%run()
+ if (result%numRun /= 1) call abort()
+ end subroutine
+
+end
+
+! { dg-final { cleanup-modules "TestResult_mod BaseTestRunner_mod TestRunner_mod" } }
diff --git a/gcc/testsuite/gfortran.dg/extends_15.f90 b/gcc/testsuite/gfortran.dg/extends_15.f90
new file mode 100644
index 00000000000..06c31799a00
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/extends_15.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+!
+! PR 58355: [4.7/4.8/4.9 Regression] [F03] ICE with TYPE, EXTENDS before parent TYPE defined
+!
+! Contributed by Andrew Benson <abensonca@gmail.com>
+
+module ct
+ public :: t1
+
+ type, extends(t1) :: t2 ! { dg-error "has not been previously defined" }
+
+ type :: t1
+ end type
+end
+
+! { dg-final { cleanup-modules "ct" } }
diff --git a/gcc/testsuite/gfortran.dg/generic_28.f90 b/gcc/testsuite/gfortran.dg/generic_28.f90
new file mode 100644
index 00000000000..5ddc9798f98
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/generic_28.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+!
+! PR 58998: [4.8/4.9 Regression] Generic interface problem with gfortran
+!
+! Contributed by Paul van Delst
+
+ interface iargc
+ procedure iargc_8
+ end interface
+
+contains
+
+ integer(8) function iargc_8()
+ integer(4) iargc
+ iargc_8 = iargc()
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr59467.f90 b/gcc/testsuite/gfortran.dg/gomp/pr59467.f90
new file mode 100644
index 00000000000..e69c9eb49a0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr59467.f90
@@ -0,0 +1,24 @@
+! PR libgomp/59467
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+ FUNCTION t()
+ INTEGER :: a, b, t
+ a = 0
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE ! { dg-error "is not threadprivate or private in outer context" }
+ !$OMP ATOMIC WRITE
+ a = 6
+ !$OMP END SINGLE COPYPRIVATE (a)
+ b = a
+ !$OMP END PARALLEL
+ t = b
+ b = 0
+ !$OMP PARALLEL REDUCTION(+:b)
+ !$OMP SINGLE
+ !$OMP ATOMIC WRITE
+ b = 6
+ !$OMP END SINGLE COPYPRIVATE (b)
+ !$OMP END PARALLEL
+ t = t + b
+ END FUNCTION
diff --git a/gcc/testsuite/gfortran.dg/inline_sum_5.f90 b/gcc/testsuite/gfortran.dg/inline_sum_5.f90
new file mode 100644
index 00000000000..bda73fd99a3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/inline_sum_5.f90
@@ -0,0 +1,33 @@
+! { dg-do run }
+!
+! PR fortran/57798
+! The call to sum used to be inlined into a loop with an uninitialized bound
+!
+! Original testcase by Stephan Kramer <stephan.kramer@imperial.ac.uk>
+
+program test
+ implicit none
+
+ call sub(2, 11)
+
+ contains
+
+ function func(m, n)
+ integer, intent(in):: m,n
+ real, dimension(m, n):: func
+
+ func = 1.0
+
+ end function func
+
+ subroutine sub(m, n)
+ integer, intent(in):: m, n
+ real, dimension(m,n):: y
+
+ y = 1.0
+ if (any(sum(y*func(m,n), dim=1) /= m)) call abort
+
+ end subroutine sub
+
+end program test
+
diff --git a/gcc/testsuite/gfortran.dg/nan_7.f90 b/gcc/testsuite/gfortran.dg/nan_7.f90
index 12c7b3ce40f..4c2f62eeaed 100644
--- a/gcc/testsuite/gfortran.dg/nan_7.f90
+++ b/gcc/testsuite/gfortran.dg/nan_7.f90
@@ -2,6 +2,7 @@
! { dg-options "-fno-range-check" }
! { dg-require-effective-target fortran_real_16 }
! { dg-require-effective-target fortran_integer_16 }
+! { dg-skip-if "" { "powerpc*le-*-*" } { "*" } { "" } }
! PR47293 NAN not correctly read
character(len=200) :: str
real(16) :: r
diff --git a/gcc/testsuite/gfortran.dg/optional_class_1.f90 b/gcc/testsuite/gfortran.dg/optional_class_1.f90
new file mode 100644
index 00000000000..589fc6023e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_class_1.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! PR fortran/57445
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+! Spurious assert was added at revision 192495
+!
+module m
+ implicit none
+ type t
+ integer :: i
+ end type t
+contains
+ subroutine opt(xa, xc, xaa, xca)
+ type(t), allocatable, intent(out), optional :: xa
+ class(t), allocatable, intent(out), optional :: xc
+ type(t), allocatable, intent(out), optional :: xaa(:)
+ class(t), allocatable, intent(out), optional :: xca(:)
+ if (present (xca)) call foo_opt(xca=xca)
+ end subroutine opt
+ subroutine foo_opt(xa, xc, xaa, xca)
+ type(t), allocatable, intent(out), optional :: xa
+ class(t), allocatable, intent(out), optional :: xc
+ type(t), allocatable, intent(out), optional :: xaa(:)
+ class(t), allocatable, intent(out), optional :: xca(:)
+ if (present (xca)) then
+ if (allocated (xca)) deallocate (xca)
+ allocate (xca(3), source = [t(9),t(99),t(999)])
+ end if
+ end subroutine foo_opt
+end module m
+ use m
+ class(t), allocatable :: xca(:)
+ allocate (xca(1), source = t(42))
+ select type (xca)
+ type is (t)
+ if (any (xca%i .ne. [42])) call abort
+ end select
+ call opt (xca = xca)
+ select type (xca)
+ type is (t)
+ if (any (xca%i .ne. [9,99,999])) call abort
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_43.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_43.f90
new file mode 100644
index 00000000000..b1f77a06ec6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_43.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+! PR 58099: [4.8/4.9 Regression] [F03] over-zealous procedure-pointer error checking
+!
+! Contributed by Daniel Price <daniel.price@monash.edu>
+
+ implicit none
+ procedure(real), pointer :: wfunc
+
+ wfunc => w_cubic
+
+contains
+
+ pure real function w_cubic(q2)
+ real, intent(in) :: q2
+ w_cubic = 0.
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/reshape_6.f90 b/gcc/testsuite/gfortran.dg/reshape_6.f90
new file mode 100644
index 00000000000..149f31efe7a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/reshape_6.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! PR fortran/58989
+!
+program test
+
+ real(8), dimension(4,4) :: fluxes
+ real(8), dimension(2,2,2,2) :: f
+ integer, dimension(3) :: dmmy
+ integer, parameter :: indx(4)=(/2,2,2,2/)
+
+ fluxes = 1
+
+ dmmy = (/2,2,2/)
+
+ f = reshape(fluxes,(/dmmy,2/)) ! Caused an ICE
+ f = reshape(fluxes,(/2,2,2,2/)) ! Works as expected
+ f = reshape(fluxes,indx) ! Works as expected
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/select_type_34.f90 b/gcc/testsuite/gfortran.dg/select_type_34.f90
new file mode 100644
index 00000000000..e75a7abd56e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_type_34.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! PR 58185: [4.8/4.9 Regression] [OOP] ICE when selector in SELECT TYPE is non-polymorphic
+!
+! Contributed by John <jwmwalrus@gmail.com>
+
+ integer :: array
+ select type (a => array) ! { dg-error "Selector shall be polymorphic" }
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/transfer_intrinsic_6.f90 b/gcc/testsuite/gfortran.dg/transfer_intrinsic_6.f90
new file mode 100644
index 00000000000..e76bc49aeda
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/transfer_intrinsic_6.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! PR 58058: [4.7/4.8/4.9 Regression] Memory leak with transfer function
+!
+! Contributed by Thomas Jourdan <thomas.jourdan@orange.fr>
+
+ implicit none
+
+ integer, dimension(3) :: t1
+ character(len=64) :: str
+
+ t1 = (/1,2,3/)
+
+ str = transfer(t1,str)
+
+end
+
+! { dg-final { scan-tree-dump-times "__builtin_free" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_15.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_15.f90
new file mode 100644
index 00000000000..1dfebdce3d5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_15.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+!
+! PR 59493: [OOP] ICE: Segfault on Class(*) pointer association
+!
+! Contributed by Hossein Talebi <talebi.hossein@gmail.com>
+
+ implicit none
+
+ type ty_mytype1
+ end type
+
+ class(ty_mytype1), allocatable, target:: cla1
+ class(*), pointer :: ptr
+
+ ptr => cla1
+
+end
diff --git a/gcc/testsuite/gfortran.dg/use_29.f90 b/gcc/testsuite/gfortran.dg/use_29.f90
new file mode 100644
index 00000000000..89dfe509314
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/use_29.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+!
+! PR fortran/57435
+!
+! Contributed by Lorenz Hüdepohl
+!
+module precision
+end module precision
+ contains
+ use precision ! { dg-error "Unexpected USE statement in CONTAINS section" }
+module stressten_rt ! { dg-error "Unexpected MODULE statement in CONTAINS section" }
+ use precision ! { dg-error "Unexpected USE statement in CONTAINS section" }
+ implicit none ! { dg-error "Unexpected IMPLICIT NONE statement in CONTAINS section" }
+
+! { dg-error "Unexpected end of file" "" { target "*-*-*" } 0 }
diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/pr57517.f90 b/gcc/testsuite/gfortran.fortran-torture/compile/pr57517.f90
new file mode 100644
index 00000000000..f32698aa3a6
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/compile/pr57517.f90
@@ -0,0 +1,13 @@
+SUBROUTINE cal_helicity (uh, ph, phb, wavg, ims, ime, its, ite)
+ INTEGER, INTENT( IN ) :: ims, ime, its, ite
+ REAL, DIMENSION( ims:ime), INTENT( IN ) :: ph, phb, wavg
+ REAL, DIMENSION( ims:ime), INTENT( INOUT ) :: uh
+ INTEGER :: i
+ REAL :: zu
+ DO i = its, ite
+ zu = (ph(i ) + phb(i)) + (ph(i-1) + phb(i-1))
+ IF (wavg(i) .GT. 0) THEN
+ uh(i) = uh(i) + zu
+ ENDIF
+ END DO
+END SUBROUTINE cal_helicity
diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90 b/gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90
new file mode 100644
index 00000000000..8ea92924ad8
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90
@@ -0,0 +1,33 @@
+module testmod
+ implicit none
+
+ contains
+
+ subroutine foo(n)
+ integer, intent(in) :: n
+ real :: r(0:n,-n:n), a(0:n,-n:n), dj
+ integer :: k, j
+
+ ! initialize with some dummy values
+ do j = -n, n
+ a(:, j) = j
+ r(:,j) = j + 1
+ end do
+
+ ! here be dragons
+ do k = 0, n
+ dj = r(k, k - 2) * a(k, k - 2)
+ r(k,k) = a(k, k - 1) * dj
+ enddo
+
+ if (r(0,0) .ne. -2.) call abort
+
+ end subroutine
+
+end module
+
+program test
+ use testmod
+ implicit none
+ call foo(5)
+end program
diff --git a/gcc/testsuite/gnat.dg/array_bounds_test2.adb b/gcc/testsuite/gnat.dg/array_bounds_test2.adb
new file mode 100644
index 00000000000..43e1ed3ced0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/array_bounds_test2.adb
@@ -0,0 +1,25 @@
+-- { dg-do run }
+
+with Ada.Unchecked_Deallocation;
+
+procedure Array_Bounds_Test2 is
+
+ type String_Ptr_T is access String;
+ procedure Free is new Ada.Unchecked_Deallocation (String, String_Ptr_T);
+ String_Data : String_Ptr_T := new String'("Hello World");
+
+ function Peek return String_Ptr_T is
+ begin
+ return String_Data;
+ end Peek;
+
+begin
+ declare
+ Corrupted_String : String := Peek.all;
+ begin
+ Free(String_Data);
+ if Corrupted_String'First /= 1 then
+ raise Program_Error;
+ end if;
+ end;
+end;
diff --git a/gcc/testsuite/gnat.dg/in_out_parameter4.adb b/gcc/testsuite/gnat.dg/in_out_parameter4.adb
new file mode 100644
index 00000000000..4f5cc218198
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/in_out_parameter4.adb
@@ -0,0 +1,30 @@
+-- { dg-do run }
+-- { dg-options "-gnat12 -gnatVa" }
+
+procedure In_Out_Parameter4 is
+
+ type Enum is (E_Undetermined, E_Down, E_Up);
+ subtype Status_T is Enum range E_Down .. E_Up;
+
+ function Recurse (Val : in out Integer) return Status_T is
+
+ Result : Status_T;
+
+ procedure Dummy (I : in out Integer) is begin null; end;
+
+ begin
+ if Val > 500 then
+ Val := Val - 1;
+ Result := Recurse (Val);
+ return Result;
+ else
+ return E_UP;
+ end if;
+ end;
+
+ Val : Integer := 501;
+ S : Status_T;
+
+begin
+ S := Recurse (Val);
+end;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization16.adb b/gcc/testsuite/gnat.dg/loop_optimization16.adb
new file mode 100644
index 00000000000..b9f2b70bb45
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization16.adb
@@ -0,0 +1,24 @@
+-- { dg-do run }
+
+with Loop_Optimization16_Pkg; use Loop_Optimization16_Pkg;
+
+procedure Loop_Optimization16 is
+
+ Counter : Natural := 0;
+
+ C : constant Natural := F;
+
+ subtype Index_T is Index_Base range 1 .. Index_Base (C);
+
+begin
+
+ for I in Index_T'First .. Index_T'Last loop
+ Counter := Counter + 1;
+ exit when Counter > 200;
+ end loop;
+
+ if Counter > 200 then
+ raise Program_Error;
+ end if;
+
+end Loop_Optimization16;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization16_pkg.adb b/gcc/testsuite/gnat.dg/loop_optimization16_pkg.adb
new file mode 100644
index 00000000000..e4142f6e6a1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization16_pkg.adb
@@ -0,0 +1,8 @@
+package body Loop_Optimization16_Pkg is
+
+ function F return Natural is
+ begin
+ return Natural (Index_Base'Last);
+ end;
+
+end Loop_Optimization16_Pkg;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization16_pkg.ads b/gcc/testsuite/gnat.dg/loop_optimization16_pkg.ads
new file mode 100644
index 00000000000..abeecfb646f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization16_pkg.ads
@@ -0,0 +1,7 @@
+package Loop_Optimization16_Pkg is
+
+ type Index_Base is range 0 .. 127;
+
+ function F return Natural;
+
+end Loop_Optimization16_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt28.adb b/gcc/testsuite/gnat.dg/opt28.adb
new file mode 100644
index 00000000000..74a4c5c3be9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28.adb
@@ -0,0 +1,31 @@
+with Opt28_Pkg; use Opt28_Pkg;
+
+package body Opt28 is
+
+ function Full_Filename (Filename : String) return String is
+ Path : constant String := "PATH";
+ Posix_Path : constant Posix_String := To_Posix (Path);
+ begin
+
+ declare
+ M : constant Posix_String := Value_Of (Posix_Path);
+ N : constant Posix_String (1 .. M'Length) := M;
+ Var : constant String := To_String (Str => N);
+ Start_Pos : Natural := 1;
+ End_Pos : Natural := 1;
+ begin
+ while Start_Pos <= Var'Length loop
+ End_Pos := Position (Var (Start_Pos .. Var'Length));
+
+ if Is_File (To_Posix (Var (Start_Pos .. End_Pos - 1) & Filename)) then
+ return Var (Start_Pos .. End_Pos - 1) & Filename;
+ else
+ Start_Pos := End_Pos + 1;
+ end if;
+ end loop;
+ end;
+
+ return "";
+ end;
+
+end Opt28;
diff --git a/gcc/testsuite/gnat.dg/opt28.ads b/gcc/testsuite/gnat.dg/opt28.ads
new file mode 100644
index 00000000000..4887c214845
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28.ads
@@ -0,0 +1,8 @@
+-- { dg-do compile }
+-- { dg-options "-O2" }
+
+package Opt28 is
+
+ function Full_Filename (Filename : String) return String;
+
+end Opt28;
diff --git a/gcc/testsuite/gnat.dg/opt28_pkg.ads b/gcc/testsuite/gnat.dg/opt28_pkg.ads
new file mode 100644
index 00000000000..c3c32fe1c34
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28_pkg.ads
@@ -0,0 +1,11 @@
+package Opt28_Pkg is
+
+ type Posix_String is array (Positive range <>) of aliased Character;
+
+ function To_Posix (Str : String) return Posix_String;
+ function To_String (Str : Posix_String) return String;
+ function Is_File (Str : Posix_String) return Boolean;
+ function Value_Of (Name : Posix_String) return Posix_String;
+ function Position (In_Line : String) return Natural;
+
+end Opt28_Pkg;
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug086.go b/gcc/testsuite/go.test/test/fixedbugs/bug086.go
index fc69e0e3fc7..40d23620669 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug086.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug086.go
@@ -6,12 +6,12 @@
package main
-func f() int { // ERROR "return|control"
+func f() int {
if false {
return 0;
}
// we should not be able to return successfully w/o a return statement
-}
+} // ERROR "return"
func main() {
print(f(), "\n");
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index d0a9a9e04b7..815d5e129fd 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2868,6 +2868,22 @@ proc check_effective_target_powerpc_405_nocache { } {
}
}
+# Return 1 if this is a PowerPC target using the ELFv2 ABI.
+
+proc check_effective_target_powerpc_elfv2 { } {
+ if { [istarget powerpc*-*-*] } {
+ return [check_no_compiler_messages powerpc_elfv2 object {
+ #if _CALL_ELF != 2
+ #error not ELF v2 ABI
+ #else
+ int dummy;
+ #endif
+ }]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is a SPU target with a toolchain that
# supports automatic overlay generation.
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 0ee5eaa9db6..46a183a07b4 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -736,11 +736,10 @@ free_affine_expand_cache (struct pointer_map_t **cache)
}
/* If VAL != CST * DIV for any constant CST, returns false.
- Otherwise, if VAL != 0 (and hence CST != 0), and *MULT_SET is true,
- additionally compares CST and MULT, and if they are different,
- returns false. Finally, if neither of these two cases occur,
- true is returned, and if CST != 0, CST is stored to MULT and
- MULT_SET is set to true. */
+ Otherwise, if *MULT_SET is true, additionally compares CST and MULT,
+ and if they are different, returns false. Finally, if neither of these
+ two cases occur, true is returned, and CST is stored to MULT and MULT_SET
+ is set to true. */
static bool
double_int_constant_multiple_p (double_int val, double_int div,
@@ -749,7 +748,13 @@ double_int_constant_multiple_p (double_int val, double_int div,
double_int rem, cst;
if (val.is_zero ())
- return true;
+ {
+ if (*mult_set && !mult->is_zero ())
+ return false;
+ *mult_set = true;
+ *mult = double_int_zero;
+ return true;
+ }
if (div.is_zero ())
return false;
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 9b6186e3393..f145f1752c9 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -726,15 +726,28 @@ shrink_wrap_one_built_in_call (gimple bi_call)
return false and do not do any transformation for
the call. */
if (nconds == 0)
- return false;
+ {
+ conds.release ();
+ return false;
+ }
bi_call_bb = gimple_bb (bi_call);
- /* Now find the join target bb -- split
- bi_call_bb if needed. */
- bi_call_bsi = gsi_for_stmt (bi_call);
+ /* Now find the join target bb -- split bi_call_bb if needed. */
+ if (stmt_ends_bb_p (bi_call))
+ {
+ /* If the call must be the last in the bb, don't split the block,
+ it could e.g. have EH edges. */
+ join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
+ if (join_tgt_in_edge_from_call == NULL)
+ {
+ conds.release ();
+ return false;
+ }
+ }
+ else
+ join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
- join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
bi_call_bsi = gsi_for_stmt (bi_call);
join_tgt_bb = join_tgt_in_edge_from_call->dest;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 28f05a589c6..f65d8734aaa 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -104,7 +104,6 @@ static int locus_map_eq (const void *, const void *);
static void assign_discriminator (location_t, basic_block);
static edge gimple_redirect_edge_and_branch (edge, basic_block);
static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
-static unsigned int split_critical_edges (void);
/* Various helpers. */
static inline bool stmt_starts_bb_p (gimple, gimple);
@@ -3513,11 +3512,10 @@ verify_gimple_assign_binary (gimple stmt)
case PLUS_EXPR:
case MINUS_EXPR:
{
- /* We use regular PLUS_EXPR and MINUS_EXPR for vectors.
- ??? This just makes the checker happy and may not be what is
- intended. */
- if (TREE_CODE (lhs_type) == VECTOR_TYPE
- && POINTER_TYPE_P (TREE_TYPE (lhs_type)))
+ tree lhs_etype = lhs_type;
+ tree rhs1_etype = rhs1_type;
+ tree rhs2_etype = rhs2_type;
+ if (TREE_CODE (lhs_type) == VECTOR_TYPE)
{
if (TREE_CODE (rhs1_type) != VECTOR_TYPE
|| TREE_CODE (rhs2_type) != VECTOR_TYPE)
@@ -3525,22 +3523,13 @@ verify_gimple_assign_binary (gimple stmt)
error ("invalid non-vector operands to vector valued plus");
return true;
}
- lhs_type = TREE_TYPE (lhs_type);
- rhs1_type = TREE_TYPE (rhs1_type);
- rhs2_type = TREE_TYPE (rhs2_type);
- /* PLUS_EXPR is commutative, so we might end up canonicalizing
- the pointer to 2nd place. */
- if (POINTER_TYPE_P (rhs2_type))
- {
- tree tem = rhs1_type;
- rhs1_type = rhs2_type;
- rhs2_type = tem;
- }
- goto do_pointer_plus_expr_check;
+ lhs_etype = TREE_TYPE (lhs_type);
+ rhs1_etype = TREE_TYPE (rhs1_type);
+ rhs2_etype = TREE_TYPE (rhs2_type);
}
- if (POINTER_TYPE_P (lhs_type)
- || POINTER_TYPE_P (rhs1_type)
- || POINTER_TYPE_P (rhs2_type))
+ if (POINTER_TYPE_P (lhs_etype)
+ || POINTER_TYPE_P (rhs1_etype)
+ || POINTER_TYPE_P (rhs2_etype))
{
error ("invalid (pointer) operands to plus/minus");
return true;
@@ -3552,7 +3541,6 @@ verify_gimple_assign_binary (gimple stmt)
case POINTER_PLUS_EXPR:
{
-do_pointer_plus_expr_check:
if (!POINTER_TYPE_P (rhs1_type)
|| !useless_type_conversion_p (lhs_type, rhs1_type)
|| !ptrofftype_p (rhs2_type))
@@ -7658,7 +7646,7 @@ struct cfg_hooks gimple_cfg_hooks = {
/* Split all critical edges. */
-static unsigned int
+unsigned int
split_critical_edges (void)
{
basic_block bb;
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 23fae4f2df9..5efe74f54b8 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -386,7 +386,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
double_int bit_offset = double_int_zero;
HOST_WIDE_INT hbit_offset;
bool seen_variable_array_ref = false;
- tree base_type;
/* First get the final access size from just the outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
@@ -417,8 +416,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
and find the ultimate containing object. */
while (1)
{
- base_type = TREE_TYPE (exp);
-
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
@@ -543,7 +540,38 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
case VIEW_CONVERT_EXPR:
break;
+ case TARGET_MEM_REF:
+ /* Via the variable index or index2 we can reach the
+ whole object. Still hand back the decl here. */
+ if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR
+ && (TMR_INDEX (exp) || TMR_INDEX2 (exp)))
+ {
+ exp = TREE_OPERAND (TMR_BASE (exp), 0);
+ bit_offset = double_int_zero;
+ maxsize = -1;
+ goto done;
+ }
+ /* Fallthru. */
case MEM_REF:
+ /* We need to deal with variable arrays ending structures such as
+ struct { int length; int a[1]; } x; x.a[d]
+ struct { struct { int a; int b; } a[1]; } x; x.a[d].a
+ struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
+ struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
+ where we do not know maxsize for variable index accesses to
+ the array. The simplest way to conservatively deal with this
+ is to punt in the case that offset + maxsize reaches the
+ base type boundary. This needs to include possible trailing
+ padding that is there for alignment purposes. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (HOST_WIDE_INT) TREE_INT_CST_LOW
+ (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
/* Hand back the decl for MEM[&decl, off]. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
{
@@ -565,45 +593,24 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
}
goto done;
- case TARGET_MEM_REF:
- /* Hand back the decl for MEM[&decl, off]. */
- if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
- {
- /* Via the variable index or index2 we can reach the
- whole object. */
- if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
- {
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- bit_offset = double_int_zero;
- maxsize = -1;
- goto done;
- }
- if (integer_zerop (TMR_OFFSET (exp)))
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- else
- {
- double_int off = mem_ref_offset (exp);
- off = off.alshift (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT),
- HOST_BITS_PER_DOUBLE_INT);
- off += bit_offset;
- if (off.fits_shwi ())
- {
- bit_offset = off;
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- }
- }
- }
- goto done;
-
default:
goto done;
}
exp = TREE_OPERAND (exp, 0);
}
- done:
+ /* We need to deal with variable arrays ending structures. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (HOST_WIDE_INT)
+ TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
+ done:
if (!bit_offset.fits_shwi ())
{
*poffset = 0;
@@ -615,24 +622,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
hbit_offset = bit_offset.to_shwi ();
- /* We need to deal with variable arrays ending structures such as
- struct { int length; int a[1]; } x; x.a[d]
- struct { struct { int a; int b; } a[1]; } x; x.a[d].a
- struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
- struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
- where we do not know maxsize for variable index accesses to
- the array. The simplest way to conservatively deal with this
- is to punt in the case that offset + maxsize reaches the
- base type boundary. This needs to include possible trailing padding
- that is there for alignment purposes. */
-
- if (seen_variable_array_ref
- && maxsize != -1
- && (!host_integerp (TYPE_SIZE (base_type), 1)
- || (hbit_offset + maxsize
- == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
- maxsize = -1;
-
/* In case of a decl or constant base object we can do better. */
if (DECL_P (exp))
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 20584b8c60f..e0aef5b9249 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -425,6 +425,7 @@ extern basic_block move_sese_region_to_fn (struct function *, basic_block,
basic_block, tree);
void remove_edge_and_dominated_blocks (edge);
bool tree_node_can_be_shared (tree);
+extern unsigned int split_critical_edges (void);
/* In tree-cfgcleanup.c */
extern bitmap cfgcleanup_altered_bbs;
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 95d0394fc51..a2cb82d3920 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -797,20 +797,6 @@ if_convertible_stmt_p (gimple stmt, vec<data_reference_p> refs)
return true;
}
-/* Return true when BB post-dominates all its predecessors. */
-
-static bool
-bb_postdominates_preds (basic_block bb)
-{
- unsigned i;
-
- for (i = 0; i < EDGE_COUNT (bb->preds); i++)
- if (!dominated_by_p (CDI_POST_DOMINATORS, EDGE_PRED (bb, i)->src, bb))
- return false;
-
- return true;
-}
-
/* Return true when BB is if-convertible. This routine does not check
basic block's statements and phis.
@@ -868,10 +854,23 @@ if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
return false;
}
- if (EDGE_COUNT (bb->preds) == 2
- && bb != loop->header
- && !bb_postdominates_preds (bb))
- return false;
+ /* At least one incoming edge has to be non-critical as otherwise edge
+ predicates are not equal to basic-block predicates of the edge
+ source. */
+ if (EDGE_COUNT (bb->preds) > 1
+ && bb != loop->header)
+ {
+ bool found = false;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (EDGE_COUNT (e->src->succs) == 1)
+ found = true;
+ if (!found)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "only critical predecessors\n");
+ return false;
+ }
+ }
return true;
}
@@ -1084,7 +1083,6 @@ if_convertible_loop_p_1 (struct loop *loop,
return false;
calculate_dominance_info (CDI_DOMINATORS);
- calculate_dominance_info (CDI_POST_DOMINATORS);
/* Allow statements that can be handled during if-conversion. */
ifc_bbs = get_loop_body_in_if_conv_order (loop);
@@ -1220,8 +1218,7 @@ if_convertible_loop_p (struct loop *loop)
if-conversion. */
static basic_block
-find_phi_replacement_condition (struct loop *loop,
- basic_block bb, tree *cond,
+find_phi_replacement_condition (basic_block bb, tree *cond,
gimple_stmt_iterator *gsi)
{
edge first_edge, second_edge;
@@ -1231,34 +1228,10 @@ find_phi_replacement_condition (struct loop *loop,
first_edge = EDGE_PRED (bb, 0);
second_edge = EDGE_PRED (bb, 1);
- /* Use condition based on following criteria:
- 1)
- S1: x = !c ? a : b;
-
- S2: x = c ? b : a;
-
- S2 is preferred over S1. Make 'b' first_bb and use its condition.
-
- 2) Do not make loop header first_bb.
-
- 3)
- S1: x = !(c == d)? a : b;
-
- S21: t1 = c == d;
- S22: x = t1 ? b : a;
-
- S3: x = (c == d) ? b : a;
-
- S3 is preferred over S1 and S2*, Make 'b' first_bb and use
- its condition.
-
- 4) If pred B is dominated by pred A then use pred B's condition.
- See PR23115. */
-
- /* Select condition that is not TRUTH_NOT_EXPR. */
+ /* Prefer an edge with a not negated predicate.
+ ??? That's a very weak cost model. */
tmp_cond = bb_predicate (first_edge->src);
gcc_assert (tmp_cond);
-
if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
{
edge tmp_edge;
@@ -1268,11 +1241,9 @@ find_phi_replacement_condition (struct loop *loop,
second_edge = tmp_edge;
}
- /* Check if FIRST_BB is loop header or not and make sure that
- FIRST_BB does not dominate SECOND_BB. */
- if (first_edge->src == loop->header
- || dominated_by_p (CDI_DOMINATORS,
- second_edge->src, first_edge->src))
+ /* Check if the edge we take the condition from is not critical.
+ We know that at least one non-critical edge exists. */
+ if (EDGE_COUNT (first_edge->src->succs) > 1)
{
*cond = bb_predicate (second_edge->src);
@@ -1347,9 +1318,6 @@ predicate_scalar_phi (gimple phi, tree cond,
arg_1 = gimple_phi_arg_def (phi, 1);
}
- gcc_checking_assert (bb == bb->loop_father->header
- || bb_postdominates_preds (bb));
-
/* Build new RHS using selected condition and arguments. */
rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
arg_0, arg_1);
@@ -1395,7 +1363,7 @@ predicate_all_scalar_phis (struct loop *loop)
/* BB has two predecessors. Using predecessor's aux field, set
appropriate condition for the PHI node replacement. */
gsi = gsi_after_labels (bb);
- true_bb = find_phi_replacement_condition (loop, bb, &cond, &gsi);
+ true_bb = find_phi_replacement_condition (bb, &cond, &gsi);
while (!gsi_end_p (phi_gsi))
{
@@ -1765,9 +1733,6 @@ combine_blocks (struct loop *loop)
free (ifc_bbs);
ifc_bbs = NULL;
-
- /* Post-dominators are corrupt now. */
- free_dominance_info (CDI_POST_DOMINATORS);
}
/* If-convert LOOP when it is legal. For the moment this pass has no
@@ -1830,8 +1795,6 @@ main_tree_if_conversion (void)
if (changed && flag_tree_loop_if_convert_stores)
todo |= TODO_update_ssa_only_virtuals;
- free_dominance_info (CDI_POST_DOMINATORS);
-
#ifdef ENABLE_CHECKING
{
basic_block bb;
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 101efbed0a5..619d93cb891 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -518,17 +518,19 @@ already_processed_vertex_p (bitmap processed, int v)
|| !bitmap_bit_p (remaining_stmts, v));
}
-/* Returns NULL when there is no anti-dependence among the successors
- of vertex V, otherwise returns the edge with the anti-dep. */
+/* Returns NULL when there is no anti-dependence or output-dependence
+ among the successors of vertex V, otherwise returns the edge with the
+ dependency. */
static struct graph_edge *
-has_anti_dependence (struct vertex *v)
+has_anti_or_output_dependence (struct vertex *v)
{
struct graph_edge *e;
if (v->succ)
for (e = v->succ; e; e = e->succ_next)
- if (RDGE_TYPE (e) == anti_dd)
+ if (RDGE_TYPE (e) == anti_dd
+ || RDGE_TYPE (e) == output_dd)
return e;
return NULL;
@@ -580,11 +582,10 @@ mark_nodes_having_upstream_mem_writes (struct graph *rdg)
|| predecessor_has_mem_write (rdg, &(rdg->vertices[x]))
/* In anti dependences the read should occur before
the write, this is why both the read and the write
- should be placed in the same partition. */
- || has_anti_dependence (&(rdg->vertices[x])))
- {
- bitmap_set_bit (upstream_mem_writes, x);
- }
+ should be placed in the same partition. In output
+ dependences the writes order need to be preserved. */
+ || has_anti_or_output_dependence (&(rdg->vertices[x])))
+ bitmap_set_bit (upstream_mem_writes, x);
}
nodes.release ();
@@ -613,7 +614,7 @@ rdg_flag_uses (struct graph *rdg, int u, partition_t partition, bitmap loops,
use_operand_p use_p;
struct vertex *x = &(rdg->vertices[u]);
gimple stmt = RDGV_STMT (x);
- struct graph_edge *anti_dep = has_anti_dependence (x);
+ struct graph_edge *anti_dep = has_anti_or_output_dependence (x);
/* Keep in the same partition the destination of an antidependence,
because this is a store to the exact same location. Putting this
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 2b8311a6c05..6dc971a8581 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -64,7 +64,7 @@ static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
the subobject (innermost array or field with address taken).
object_sizes[2] is lower bound for number of bytes till the end of
the object and object_sizes[3] lower bound for subobject. */
-static unsigned HOST_WIDE_INT *object_sizes[4];
+static vec<unsigned HOST_WIDE_INT> object_sizes[4];
/* Bitmaps what object sizes have been computed already. */
static bitmap computed[4];
@@ -493,7 +493,7 @@ compute_builtin_object_size (tree ptr, int object_size_type)
if (TREE_CODE (ptr) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (ptr))
- && object_sizes[object_size_type] != NULL)
+ && computed[object_size_type] != NULL)
{
if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
{
@@ -501,6 +501,8 @@ compute_builtin_object_size (tree ptr, int object_size_type)
bitmap_iterator bi;
unsigned int i;
+ if (num_ssa_names > object_sizes[object_size_type].length ())
+ object_sizes[object_size_type].safe_grow (num_ssa_names);
if (dump_file)
{
fprintf (dump_file, "Computing %s %sobject size for ",
@@ -1162,12 +1164,12 @@ init_object_sizes (void)
{
int object_size_type;
- if (object_sizes[0])
+ if (computed[0])
return;
for (object_size_type = 0; object_size_type <= 3; object_size_type++)
{
- object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
+ object_sizes[object_size_type].safe_grow (num_ssa_names);
computed[object_size_type] = BITMAP_ALLOC (NULL);
}
@@ -1184,9 +1186,8 @@ fini_object_sizes (void)
for (object_size_type = 0; object_size_type <= 3; object_size_type++)
{
- free (object_sizes[object_size_type]);
+ object_sizes[object_size_type].release ();
BITMAP_FREE (computed[object_size_type]);
- object_sizes[object_size_type] = NULL;
}
}
@@ -1202,16 +1203,9 @@ compute_object_sizes (void)
gimple_stmt_iterator i;
for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
{
- tree callee, result;
+ tree result;
gimple call = gsi_stmt (i);
-
- if (gimple_code (call) != GIMPLE_CALL)
- continue;
-
- callee = gimple_call_fndecl (call);
- if (!callee
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
- || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
+ if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
continue;
init_object_sizes ();
@@ -1240,20 +1234,32 @@ compute_object_sizes (void)
continue;
}
+ gcc_assert (TREE_CODE (result) == INTEGER_CST);
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Simplified\n ");
print_gimple_stmt (dump_file, call, 0, dump_flags);
+ fprintf (dump_file, " to ");
+ print_generic_expr (dump_file, result, 0);
+ fprintf (dump_file, "\n");
}
- if (!update_call_from_tree (&i, result))
- gcc_unreachable ();
+ tree lhs = gimple_call_lhs (call);
+ if (!lhs)
+ continue;
- if (dump_file && (dump_flags & TDF_DETAILS))
+ /* Propagate into all uses and fold those stmts. */
+ gimple use_stmt;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
- fprintf (dump_file, "to\n ");
- print_gimple_stmt (dump_file, gsi_stmt (i), 0, dump_flags);
- fprintf (dump_file, "\n");
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, result);
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ fold_stmt (&gsi);
+ update_stmt (gsi_stmt (gsi));
}
}
}
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index d7b846ae79b..9d2c3ca3b41 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -478,9 +478,12 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
if (gsi == NULL)
return NULL;
addr = TREE_OPERAND (*var_p, 0);
- name = make_temp_ssa_name (TREE_TYPE (addr), NULL,
- get_name (TREE_OPERAND
- (TREE_OPERAND (*var_p, 0), 0)));
+ const char *obj_name
+ = get_name (TREE_OPERAND (TREE_OPERAND (*var_p, 0), 0));
+ if (obj_name)
+ name = make_temp_ssa_name (TREE_TYPE (addr), NULL, obj_name);
+ else
+ name = make_ssa_name (TREE_TYPE (addr), NULL);
stmt = gimple_build_assign (name, addr);
gsi_insert_on_edge_immediate (entry, stmt);
@@ -679,6 +682,12 @@ eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
dta.changed = true;
}
}
+ else if (gimple_clobber_p (stmt))
+ {
+ stmt = gimple_build_nop ();
+ gsi_replace (gsi, stmt, false);
+ dta.changed = true;
+ }
else
{
dta.gsi = gsi;
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index dceea8cc89a..73a7a26c9dd 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -1323,90 +1323,43 @@ replace_ref_with (gimple stmt, tree new_tree, bool set, bool in_lhs)
gsi_insert_after (&bsi, new_stmt, GSI_NEW_STMT);
}
-/* Returns the reference to the address of REF in the ITER-th iteration of
- LOOP, or NULL if we fail to determine it (ITER may be negative). We
- try to preserve the original shape of the reference (not rewrite it
- as an indirect ref to the address), to make tree_could_trap_p in
- prepare_initializers_chain return false more often. */
-
-static tree
-ref_at_iteration (struct loop *loop, tree ref, int iter)
-{
- tree idx, *idx_p, type, val, op0 = NULL_TREE, ret;
- affine_iv iv;
- bool ok;
-
- if (handled_component_p (ref))
- {
- op0 = ref_at_iteration (loop, TREE_OPERAND (ref, 0), iter);
- if (!op0)
- return NULL_TREE;
- }
- else if (!INDIRECT_REF_P (ref)
- && TREE_CODE (ref) != MEM_REF)
- return unshare_expr (ref);
-
- if (TREE_CODE (ref) == MEM_REF)
- {
- ret = unshare_expr (ref);
- idx = TREE_OPERAND (ref, 0);
- idx_p = &TREE_OPERAND (ret, 0);
- }
- else if (TREE_CODE (ref) == COMPONENT_REF)
- {
- /* Check that the offset is loop invariant. */
- if (TREE_OPERAND (ref, 2)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
- return NULL_TREE;
-
- return build3 (COMPONENT_REF, TREE_TYPE (ref), op0,
- unshare_expr (TREE_OPERAND (ref, 1)),
- unshare_expr (TREE_OPERAND (ref, 2)));
- }
- else if (TREE_CODE (ref) == ARRAY_REF)
- {
- /* Check that the lower bound and the step are loop invariant. */
- if (TREE_OPERAND (ref, 2)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
- return NULL_TREE;
- if (TREE_OPERAND (ref, 3)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 3)))
- return NULL_TREE;
-
- ret = build4 (ARRAY_REF, TREE_TYPE (ref), op0, NULL_TREE,
- unshare_expr (TREE_OPERAND (ref, 2)),
- unshare_expr (TREE_OPERAND (ref, 3)));
- idx = TREE_OPERAND (ref, 1);
- idx_p = &TREE_OPERAND (ret, 1);
- }
- else
- return NULL_TREE;
-
- ok = simple_iv (loop, loop, idx, &iv, true);
- if (!ok)
- return NULL_TREE;
- iv.base = expand_simple_operations (iv.base);
- if (integer_zerop (iv.step))
- *idx_p = unshare_expr (iv.base);
+/* Returns a memory reference to DR in the 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)
+{
+ tree off = DR_OFFSET (dr);
+ tree coff = DR_INIT (dr);
+ 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
- {
- type = TREE_TYPE (iv.base);
- if (POINTER_TYPE_P (type))
- {
- val = fold_build2 (MULT_EXPR, sizetype, iv.step,
- size_int (iter));
- val = fold_build_pointer_plus (iv.base, val);
- }
- else
- {
- val = fold_build2 (MULT_EXPR, type, iv.step,
- build_int_cst_type (type, iter));
- val = fold_build2 (PLUS_EXPR, type, iv.base, val);
- }
- *idx_p = unshare_expr (val);
+ off = size_binop (PLUS_EXPR, off,
+ size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
+ tree addr = fold_build_pointer_plus (DR_BASE_ADDRESS (dr), off);
+ addr = force_gimple_operand_1 (addr, stmts, is_gimple_mem_ref_addr,
+ NULL_TREE);
+ tree alias_ptr = fold_convert (reference_alias_ptr_type (DR_REF (dr)), coff);
+ /* While data-ref analysis punts on bit offsets it still handles
+ bitfield accesses at byte boundaries. Cope with that. Note that
+ we cannot simply re-apply the outer COMPONENT_REF because the
+ byte-granular portion of it is already applied via DR_INIT and
+ DR_OFFSET, so simply build a BIT_FIELD_REF knowing that the bits
+ start at offset zero. */
+ if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
+ {
+ tree field = TREE_OPERAND (DR_REF (dr), 1);
+ return build3 (BIT_FIELD_REF, TREE_TYPE (DR_REF (dr)),
+ build2 (MEM_REF, DECL_BIT_FIELD_TYPE (field),
+ addr, alias_ptr),
+ DECL_SIZE (field), bitsize_zero_node);
}
-
- return ret;
+ else
+ return fold_build2 (MEM_REF, TREE_TYPE (DR_REF (dr)), addr, alias_ptr);
}
/* Get the initialization expression for the INDEX-th temporary variable
@@ -2068,7 +2021,11 @@ combinable_refs_p (dref r1, dref r2,
stmt = find_common_use_stmt (&name1, &name2);
- if (!stmt)
+ if (!stmt
+ /* A simple post-dominance check - make sure the combination
+ is executed under the same condition as the references. */
+ || (gimple_bb (stmt) != gimple_bb (r1->stmt)
+ && gimple_bb (stmt) != gimple_bb (r2->stmt)))
return false;
acode = gimple_assign_rhs_code (stmt);
@@ -2365,14 +2322,10 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
if (chain->inits[i] != NULL_TREE)
continue;
- init = ref_at_iteration (loop, DR_REF (dr), (int) i - n);
- if (!init)
- return false;
-
+ init = ref_at_iteration (dr, (int) i - n, &stmts);
if (!chain->all_always_accessed && tree_could_trap_p (init))
return false;
- init = force_gimple_operand (init, &stmts, false, NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (entry, stmts);
@@ -2449,6 +2402,7 @@ tree_predictive_commoning_loop (struct loop *loop)
if (!components)
{
free_data_refs (datarefs);
+ free_affine_expand_cache (&name_expansions);
return false;
}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index bb04fd74446..5142d4b11c0 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1161,8 +1161,7 @@ build_accesses_from_assign (gimple stmt)
GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
static bool
-asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
- void *data ATTRIBUTE_UNUSED)
+asm_visit_addr (gimple, tree op, tree, void *)
{
op = get_base_address (op);
if (op
@@ -1440,6 +1439,7 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
{
tree prev_base = base;
tree off;
+ tree mem_ref;
HOST_WIDE_INT base_offset;
unsigned HOST_WIDE_INT misalign;
unsigned int align;
@@ -1490,7 +1490,12 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
if (align < TYPE_ALIGN (exp_type))
exp_type = build_aligned_type (exp_type, align);
- return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
+ mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
+ if (TREE_THIS_VOLATILE (prev_base))
+ TREE_THIS_VOLATILE (mem_ref) = 1;
+ if (TREE_SIDE_EFFECTS (prev_base))
+ TREE_SIDE_EFFECTS (mem_ref) = 1;
+ return mem_ref;
}
/* Construct a memory reference to a part of an aggregate BASE at the given
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a64bffcaec7..0ad91a9b745 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1707,6 +1707,9 @@ insert_clobber_before_stack_restore (tree saved_val, tree var,
insert_clobber_before_stack_restore (gimple_phi_result (stmt), var,
visited);
}
+ else if (gimple_assign_ssa_name_copy_p (stmt))
+ insert_clobber_before_stack_restore (gimple_assign_lhs (stmt), var,
+ visited);
else
gcc_assert (is_gimple_debug (stmt));
}
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 05c58feca5d..7a3434b173c 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -574,6 +574,11 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
in the references (gcc.c-torture/execute/pr42142.c).
The simplest way is to check if the kill dominates
the use. */
+ /* But when both are in the same block we cannot
+ easily tell whether we came from a backedge
+ unless we decide to compute stmt UIDs
+ (see PR58246). */
+ && (basic_block) data != gimple_bb (def_stmt)
&& dominated_by_p (CDI_DOMINATORS, (basic_block) data,
gimple_bb (def_stmt))
&& operand_equal_p (ref->ref, lhs, 0))
@@ -1302,26 +1307,19 @@ eliminate_unnecessary_stmts (void)
stats.total++;
/* We can mark a call to free as not necessary if the
- defining statement of its argument is an allocation
- function and that is not necessary itself. */
- if (gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+ defining statement of its argument is not necessary
+ (and thus is getting removed). */
+ if (gimple_plf (stmt, STMT_NECESSARY)
+ && gimple_call_builtin_p (stmt, BUILT_IN_FREE))
{
tree ptr = gimple_call_arg (stmt, 0);
- tree callee2;
- gimple def_stmt;
- if (TREE_CODE (ptr) != SSA_NAME)
- continue;
- def_stmt = SSA_NAME_DEF_STMT (ptr);
- if (!is_gimple_call (def_stmt)
- || gimple_plf (def_stmt, STMT_NECESSARY))
- continue;
- callee2 = gimple_call_fndecl (def_stmt);
- if (callee2 == NULL_TREE
- || DECL_BUILT_IN_CLASS (callee2) != BUILT_IN_NORMAL
- || (DECL_FUNCTION_CODE (callee2) != BUILT_IN_MALLOC
- && DECL_FUNCTION_CODE (callee2) != BUILT_IN_CALLOC))
- continue;
- gimple_set_plf (stmt, STMT_NECESSARY, false);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (ptr);
+ if (!gimple_nop_p (def_stmt)
+ && !gimple_plf (def_stmt, STMT_NECESSARY))
+ gimple_set_plf (stmt, STMT_NECESSARY, false);
+ }
}
/* If GSI is not necessary then remove it. */
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 78ad0733016..72ed570dc55 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1190,6 +1190,67 @@ determine_invariantness (void)
fini_walk_dominator_tree (&walk_data);
}
+/* Return true if CODE is an operation that when operating on signed
+ integer types involves undefined behavior on overflow and the
+ operation can be expressed with unsigned arithmetic. */
+
+static bool
+arith_code_with_undefined_signed_overflow (tree_code code)
+{
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case NEGATE_EXPR:
+ case POINTER_PLUS_EXPR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
+ operation that can be transformed to unsigned arithmetic by converting
+ its operand, carrying out the operation in the corresponding unsigned
+ type and converting the result back to the original type.
+
+ Returns a sequence of statements that replace STMT and also contain
+ a modified form of STMT itself. */
+
+static gimple_seq
+rewrite_to_defined_overflow (gimple stmt)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "rewriting stmt with undefined signed "
+ "overflow ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ }
+
+ tree lhs = gimple_assign_lhs (stmt);
+ tree type = unsigned_type_for (TREE_TYPE (lhs));
+ gimple_seq stmts = NULL;
+ for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
+ {
+ gimple_seq stmts2 = NULL;
+ gimple_set_op (stmt, i,
+ force_gimple_operand (fold_convert (type,
+ gimple_op (stmt, i)),
+ &stmts2, true, NULL_TREE));
+ gimple_seq_add_seq (&stmts, stmts2);
+ }
+ gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt));
+ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+ gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
+ gimple_seq_add_stmt (&stmts, stmt);
+ gimple cvt = gimple_build_assign_with_ops
+ (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE);
+ gimple_seq_add_stmt (&stmts, cvt);
+
+ return stmts;
+}
+
/* Hoist the statements in basic block BB out of the loops prescribed by
data stored in LIM_DATA structures associated with each statement. Callback
for walk_dominator_tree. */
@@ -1321,7 +1382,21 @@ move_computations_stmt (struct dom_walk_data *dw_data,
}
}
gsi_remove (&bsi, false);
- gsi_insert_on_edge (e, stmt);
+ /* In case this is a stmt that is not unconditionally executed
+ when the target loop header is executed and the stmt may
+ invoke undefined integer or pointer overflow rewrite it to
+ unsigned arithmetic. */
+ if (is_gimple_assign (stmt)
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
+ && arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt))
+ && (!ALWAYS_EXECUTED_IN (bb)
+ || !(ALWAYS_EXECUTED_IN (bb) == level
+ || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
+ gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt));
+ else
+ gsi_insert_on_edge (e, stmt);
}
}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 090e114c36d..76a64e578f9 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -552,10 +552,18 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
{
double_int max;
mpz_t d;
+ tree type = TREE_TYPE (c);
bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
|| mpz_sgn (bnds->below) >= 0);
- if (multiple_of_p (TREE_TYPE (c), c, s))
+ if (integer_onep (s)
+ || (TREE_CODE (c) == INTEGER_CST
+ && TREE_CODE (s) == INTEGER_CST
+ && tree_to_double_int (c).mod (tree_to_double_int (s),
+ TYPE_UNSIGNED (type),
+ EXACT_DIV_EXPR).is_zero ())
+ || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (c))
+ && multiple_of_p (type, c, s)))
{
/* If C is an exact multiple of S, then its value will be reached before
the induction variable overflows (unless the loop is exited in some
@@ -572,16 +580,15 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
the whole # of iterations analysis will fail). */
if (!no_overflow)
{
- max = double_int::mask (TYPE_PRECISION (TREE_TYPE (c))
- - tree_low_cst (num_ending_zeros (s), 1));
+ max = double_int::mask (TYPE_PRECISION (type)
+ - tree_low_cst (num_ending_zeros (s), 1));
mpz_set_double_int (bnd, max, true);
return;
}
/* Now we know that the induction variable does not overflow, so the loop
iterates at most (range of type / S) times. */
- mpz_set_double_int (bnd, double_int::mask (TYPE_PRECISION (TREE_TYPE (c))),
- true);
+ mpz_set_double_int (bnd, double_int::mask (TYPE_PRECISION (type)), true);
/* If the induction variable is guaranteed to reach the value of C before
overflow, ... */
@@ -1311,7 +1318,8 @@ number_of_iterations_cond (struct loop *loop,
}
/* If the loop exits immediately, there is nothing to do. */
- if (integer_zerop (fold_build2 (code, boolean_type_node, iv0->base, iv1->base)))
+ tree tem = fold_binary (code, boolean_type_node, iv0->base, iv1->base);
+ if (tem && integer_zerop (tem))
{
niter->niter = build_int_cst (unsigned_type_for (type), 0);
niter->max = double_int_zero;
@@ -2067,7 +2075,8 @@ chain_of_csts_start (struct loop *loop, tree x)
return NULL;
}
- if (gimple_code (stmt) != GIMPLE_ASSIGN)
+ if (gimple_code (stmt) != GIMPLE_ASSIGN
+ || gimple_assign_rhs_class (stmt) == GIMPLE_TERNARY_RHS)
return NULL;
code = gimple_assign_rhs_code (stmt);
@@ -2135,7 +2144,7 @@ get_val_for (tree x, tree base)
{
gimple stmt;
- gcc_assert (is_gimple_min_invariant (base));
+ gcc_checking_assert (is_gimple_min_invariant (base));
if (!x)
return base;
@@ -2144,7 +2153,7 @@ get_val_for (tree x, tree base)
if (gimple_code (stmt) == GIMPLE_PHI)
return base;
- gcc_assert (is_gimple_assign (stmt));
+ gcc_checking_assert (is_gimple_assign (stmt));
/* STMT must be either an assignment of a single SSA name or an
expression involving an SSA name and a constant. Try to fold that
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 10c8091758e..3e6a82e24ab 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3664,6 +3664,12 @@ insert (void)
if (dump_file && dump_flags & TDF_DETAILS)
fprintf (dump_file, "Starting insert iteration %d\n", num_iterations);
new_stuff = insert_aux (ENTRY_BLOCK_PTR);
+
+ /* Clear the NEW sets before the next iteration. We have already
+ fully propagated its contents. */
+ if (new_stuff)
+ FOR_ALL_BB (bb)
+ bitmap_set_free (NEW_SETS (bb));
}
statistics_histogram_event (cfun, "insert iterations", num_iterations);
}
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 46994389e16..14eae6b3f7b 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1774,7 +1774,14 @@ init_range_entry (struct range_entry *r, tree exp, gimple stmt)
switch (code)
{
case BIT_NOT_EXPR:
- if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE)
+ if (TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE
+ /* Ensure the range is either +[-,0], +[0,0],
+ -[-,0], -[0,0] or +[1,-], +[1,1], -[1,-] or
+ -[1,1]. If it is e.g. +[-,-] or -[-,-]
+ or similar expression of unconditional true or
+ false, it should not be negated. */
+ && ((high && integer_zerop (high))
+ || (low && integer_onep (low))))
{
in_p = !in_p;
exp = arg0;
@@ -1973,8 +1980,15 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange,
tem = fold_convert_loc (loc, optype, tem);
gsi = gsi_for_stmt (stmt);
- tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
- GSI_SAME_STMT);
+ /* In rare cases range->exp can be equal to lhs of stmt.
+ In that case we have to insert after the stmt rather then before
+ it. */
+ if (op == range->exp)
+ tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, false,
+ GSI_SAME_STMT);
+ else
+ tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
+ GSI_SAME_STMT);
/* If doing inter-bb range test optimization, update the
stmts immediately. Start with changing the first range test
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 58fe903e74f..5dce65afe85 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -660,7 +660,7 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
}
/* For non-calls, store the information that makes up the address. */
-
+ tree orig = ref;
while (ref)
{
vn_reference_op_s temp;
@@ -711,7 +711,15 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
.arshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
- if (off.fits_shwi ())
+ if (off.fits_shwi ()
+ /* Probibit value-numbering zero offset components
+ of addresses the same before the pass folding
+ __builtin_object_size had a chance to run
+ (checking cfun->after_inlining does the
+ trick here). */
+ && (TREE_CODE (orig) != ADDR_EXPR
+ || !off.is_zero ()
+ || cfun->after_inlining))
temp.off = off.low;
}
}
@@ -1062,7 +1070,7 @@ vn_reference_fold_indirect (vec<vn_reference_op_s> *ops,
addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
&addr_offset);
gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
- if (addr_base != op->op0)
+ if (addr_base != TREE_OPERAND (op->op0, 0))
{
double_int off = tree_to_double_int (mem_op->op0);
off = off.sext (TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
@@ -2555,6 +2563,7 @@ static inline bool
set_ssa_val_to (tree from, tree to)
{
tree currval = SSA_VAL (from);
+ HOST_WIDE_INT toff, coff;
if (from != to)
{
@@ -2590,7 +2599,17 @@ set_ssa_val_to (tree from, tree to)
print_generic_expr (dump_file, to, 0);
}
- if (currval != to && !operand_equal_p (currval, to, OEP_PURE_SAME))
+ if (currval != to
+ && !operand_equal_p (currval, to, 0)
+ /* ??? For addresses involving volatile objects or types operand_equal_p
+ does not reliably detect ADDR_EXPRs as equal. We know we are only
+ getting invariant gimple addresses here, so can use
+ get_addr_base_and_unit_offset to do this comparison. */
+ && !(TREE_CODE (currval) == ADDR_EXPR
+ && TREE_CODE (to) == ADDR_EXPR
+ && (get_addr_base_and_unit_offset (TREE_OPERAND (currval, 0), &coff)
+ == get_addr_base_and_unit_offset (TREE_OPERAND (to, 0), &toff))
+ && coff == toff))
{
VN_INFO (from)->valnum = to;
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 9f091748e63..3df200ea3f5 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -559,7 +559,7 @@ static void
execute_sink_code (void)
{
loop_optimizer_init (LOOPS_NORMAL);
-
+ split_critical_edges ();
connect_infinite_loops_to_exit ();
memset (&sink_stats, 0, sizeof (sink_stats));
calculate_dominance_info (CDI_DOMINATORS);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index fcb4ab890f6..dbad4a80d86 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1890,6 +1890,28 @@ strlen_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
int count_vdef = 100;
do_invalidate (dombb, phi, visited, &count_vdef);
BITMAP_FREE (visited);
+ if (count_vdef == 0)
+ {
+ /* If there were too many vdefs in between immediate
+ dominator and current bb, invalidate everything.
+ If stridx_to_strinfo has been unshared, we need
+ to free it, otherwise just set it to NULL. */
+ if (!strinfo_shared ())
+ {
+ unsigned int i;
+ strinfo si;
+
+ for (i = 1;
+ vec_safe_iterate (stridx_to_strinfo, i, &si);
+ ++i)
+ {
+ free_strinfo (si);
+ (*stridx_to_strinfo)[i] = NULL;
+ }
+ }
+ else
+ stridx_to_strinfo = NULL;
+ }
break;
}
}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 31a4c49c66c..d4b14001179 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -2237,18 +2237,37 @@ perform_var_substitution (constraint_graph_t graph)
{
unsigned j = si->node_mapping[i];
if (j != i)
- fprintf (dump_file, "%s node id %d (%s) mapped to SCC leader "
- "node id %d (%s)\n",
- bitmap_bit_p (graph->direct_nodes, i)
- ? "Direct" : "Indirect", i, get_varinfo (i)->name,
- j, get_varinfo (j)->name);
+ {
+ fprintf (dump_file, "%s node id %d ",
+ bitmap_bit_p (graph->direct_nodes, i)
+ ? "Direct" : "Indirect", i);
+ if (i < FIRST_REF_NODE)
+ fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
+ else
+ fprintf (dump_file, "\"*%s\"",
+ get_varinfo (i - FIRST_REF_NODE)->name);
+ fprintf (dump_file, " mapped to SCC leader node id %d ", j);
+ if (j < FIRST_REF_NODE)
+ fprintf (dump_file, "\"%s\"\n", get_varinfo (j)->name);
+ else
+ fprintf (dump_file, "\"*%s\"\n",
+ get_varinfo (j - FIRST_REF_NODE)->name);
+ }
else
- fprintf (dump_file,
- "Equivalence classes for %s node id %d (%s): pointer %d"
- ", location %d\n",
- bitmap_bit_p (graph->direct_nodes, i)
- ? "direct" : "indirect", i, get_varinfo (i)->name,
- graph->pointer_label[i], graph->loc_label[i]);
+ {
+ fprintf (dump_file,
+ "Equivalence classes for %s node id %d ",
+ bitmap_bit_p (graph->direct_nodes, i)
+ ? "direct" : "indirect", i);
+ if (i < FIRST_REF_NODE)
+ fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
+ else
+ fprintf (dump_file, "\"*%s\"",
+ get_varinfo (i - FIRST_REF_NODE)->name);
+ fprintf (dump_file,
+ ": pointer %d, location %d\n",
+ graph->pointer_label[i], graph->loc_label[i]);
+ }
}
/* Quickly eliminate our non-pointer variables. */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index b20d3067d66..419b4ec024e 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -297,7 +297,8 @@ stmt_local_def (gimple stmt)
tree val;
def_operand_p def_p;
- if (gimple_has_side_effects (stmt))
+ if (gimple_has_side_effects (stmt)
+ || gimple_vdef (stmt) != NULL_TREE)
return false;
def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c
index 2a2e143de38..d3efd312ff1 100644
--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -590,6 +590,30 @@ mark_replaceable (temp_expr_table_p tab, tree var, bool more_replacing)
}
+/* Helper function for find_ssaname_in_stores. Called via walk_tree to
+ find a SSA_NAME DATA somewhere in *TP. */
+
+static tree
+find_ssaname (tree *tp, int *walk_subtrees, void *data)
+{
+ tree var = (tree) data;
+ if (*tp == var)
+ return var;
+ else if (IS_TYPE_OR_DECL_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
+/* Helper function for find_replaceable_in_bb. Return true if SSA_NAME DATA
+ is used somewhere in T, which is a store in the statement. Called via
+ walk_stmt_load_store_addr_ops. */
+
+static bool
+find_ssaname_in_store (gimple, tree, tree t, void *data)
+{
+ return walk_tree (&t, find_ssaname, data, NULL) != NULL_TREE;
+}
+
/* This function processes basic block BB, and looks for variables which can
be replaced by their expressions. Results are stored in the table TAB. */
@@ -643,8 +667,7 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
/* If the stmt does a memory store and the replacement
is a load aliasing it avoid creating overlapping
assignments which we cannot expand correctly. */
- if (gimple_vdef (stmt)
- && gimple_assign_single_p (stmt))
+ if (gimple_vdef (stmt))
{
gimple def_stmt = SSA_NAME_DEF_STMT (use);
while (is_gimple_assign (def_stmt)
@@ -653,9 +676,29 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
= SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
if (gimple_vuse (def_stmt)
&& gimple_assign_single_p (def_stmt)
- && refs_may_alias_p (gimple_assign_lhs (stmt),
- gimple_assign_rhs1 (def_stmt)))
- same_root_var = true;
+ && stmt_may_clobber_ref_p (stmt,
+ gimple_assign_rhs1 (def_stmt)))
+ {
+ /* For calls, it is not a problem if USE is among
+ call's arguments or say OBJ_TYPE_REF argument,
+ all those necessarily need to be evaluated before
+ the call that may clobber the memory. But if
+ LHS of the call refers to USE, expansion might
+ evaluate it after the call, prevent TER in that
+ case.
+ For inline asm, allow TER of loads into input
+ arguments, but disallow TER for USEs that occur
+ somewhere in outputs. */
+ if (is_gimple_call (stmt)
+ || gimple_code (stmt) == GIMPLE_ASM)
+ {
+ if (walk_stmt_load_store_ops (stmt, use, NULL,
+ find_ssaname_in_store))
+ same_root_var = true;
+ }
+ else
+ same_root_var = true;
+ }
}
/* Mark expression as replaceable unless stmt is volatile, or the
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index c6581dcedcd..b1b5f967325 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -328,8 +328,10 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
case NEGATE_EXPR:
if (FLOAT_TYPE_P (TREE_TYPE (op0)))
*m = build_real (TREE_TYPE (op0), dconstm1);
- else
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (op0)))
*m = build_int_cst (TREE_TYPE (op0), -1);
+ else
+ return false;
*ass_var = dest;
return true;
@@ -341,8 +343,10 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
{
if (FLOAT_TYPE_P (TREE_TYPE (non_ass_var)))
*m = build_real (TREE_TYPE (non_ass_var), dconstm1);
- else
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (non_ass_var)))
*m = build_int_cst (TREE_TYPE (non_ass_var), -1);
+ else
+ return false;
*a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
}
@@ -570,6 +574,11 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
if (!tail_recursion && (m || a))
return;
+ /* For pointers don't allow additions or multiplications. */
+ if ((m || a)
+ && POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
+ return;
+
nw = XNEW (struct tailcall);
nw->call_gsi = gsi;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index fdb73c3212b..1d5d0227545 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2498,10 +2498,17 @@ vect_analyze_data_ref_access (struct data_reference *dr)
return false;
}
- /* Allow invariant loads in loops. */
+ /* Allow invariant loads in not nested loops. */
if (loop_vinfo && integer_zerop (step))
{
GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = NULL;
+ if (nested_in_vect_loop_p (loop, stmt))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "zero step in inner loop of nest");
+ return false;
+ }
return DR_IS_READ (dr);
}
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 1252c5a04fc..5fcf5b0efd2 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1537,7 +1537,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp)
if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
|| LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0
- || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
+ || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "epilog loop required.");
@@ -3115,14 +3115,12 @@ get_initial_def_for_induction (gimple iv_phi)
stmt_vec_info stmt_vinfo = vinfo_for_stmt (iv_phi);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- tree scalar_type;
tree vectype;
int nunits;
edge pe = loop_preheader_edge (loop);
struct loop *iv_loop;
basic_block new_bb;
tree new_vec, vec_init, vec_step, t;
- tree access_fn;
tree new_var;
tree new_name;
gimple init_stmt, induction_phi, new_stmt;
@@ -3130,7 +3128,6 @@ get_initial_def_for_induction (gimple iv_phi)
tree init_expr, step_expr;
int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
int i;
- bool ok;
int ncopies;
tree expr;
stmt_vec_info phi_info = vinfo_for_stmt (iv_phi);
@@ -3159,16 +3156,14 @@ get_initial_def_for_induction (gimple iv_phi)
latch_e = loop_latch_edge (iv_loop);
loop_arg = PHI_ARG_DEF_FROM_EDGE (iv_phi, latch_e);
- access_fn = analyze_scalar_evolution (iv_loop, PHI_RESULT (iv_phi));
- gcc_assert (access_fn);
- STRIP_NOPS (access_fn);
- ok = vect_is_simple_iv_evolution (iv_loop->num, access_fn,
- &init_expr, &step_expr);
- gcc_assert (ok);
+ step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info);
+ gcc_assert (step_expr != NULL_TREE);
+
pe = loop_preheader_edge (iv_loop);
+ init_expr = PHI_ARG_DEF_FROM_EDGE (iv_phi,
+ loop_preheader_edge (iv_loop));
- scalar_type = TREE_TYPE (init_expr);
- vectype = get_vectype_for_scalar_type (scalar_type);
+ vectype = get_vectype_for_scalar_type (TREE_TYPE (init_expr));
resvectype = get_vectype_for_scalar_type (TREE_TYPE (PHI_RESULT (iv_phi)));
gcc_assert (vectype);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
@@ -3177,6 +3172,16 @@ get_initial_def_for_induction (gimple iv_phi)
gcc_assert (phi_info);
gcc_assert (ncopies >= 1);
+ /* Convert the step to the desired type. */
+ step_expr = force_gimple_operand (fold_convert (TREE_TYPE (vectype),
+ step_expr),
+ &stmts, true, NULL_TREE);
+ if (stmts)
+ {
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+ gcc_assert (!new_bb);
+ }
+
/* Find the first insertion point in the BB. */
si = gsi_after_labels (bb);
@@ -3186,9 +3191,7 @@ get_initial_def_for_induction (gimple iv_phi)
/* iv_loop is nested in the loop to be vectorized. init_expr had already
been created during vectorization of previous stmts. We obtain it
from the STMT_VINFO_VEC_STMT of the defining stmt. */
- tree iv_def = PHI_ARG_DEF_FROM_EDGE (iv_phi,
- loop_preheader_edge (iv_loop));
- vec_init = vect_get_vec_def_for_operand (iv_def, iv_phi, NULL);
+ vec_init = vect_get_vec_def_for_operand (init_expr, iv_phi, NULL);
/* If the initial value is not of proper type, convert it. */
if (!useless_type_conversion_p (vectype, TREE_TYPE (vec_init)))
{
@@ -3211,8 +3214,11 @@ get_initial_def_for_induction (gimple iv_phi)
/* iv_loop is the loop to be vectorized. Create:
vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */
- new_var = vect_get_new_vect_var (scalar_type, vect_scalar_var, "var_");
- new_name = force_gimple_operand (init_expr, &stmts, false, new_var);
+ new_var = vect_get_new_vect_var (TREE_TYPE (vectype),
+ vect_scalar_var, "var_");
+ new_name = force_gimple_operand (fold_convert (TREE_TYPE (vectype),
+ init_expr),
+ &stmts, false, new_var);
if (stmts)
{
new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
@@ -3224,9 +3230,7 @@ get_initial_def_for_induction (gimple iv_phi)
for (i = 1; i < nunits; i++)
{
/* Create: new_name_i = new_name + step_expr */
- enum tree_code code = POINTER_TYPE_P (scalar_type)
- ? POINTER_PLUS_EXPR : PLUS_EXPR;
- init_stmt = gimple_build_assign_with_ops (code, new_var,
+ init_stmt = gimple_build_assign_with_ops (PLUS_EXPR, new_var,
new_name, step_expr);
new_name = make_ssa_name (new_var, init_stmt);
gimple_assign_set_lhs (init_stmt, new_name);
@@ -4326,12 +4330,12 @@ vect_finalize_reduction:
result. (The reduction result is expected to have two immediate uses -
one at the latch block, and one at the loop exit). */
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
- if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
+ if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p)))
+ && !is_gimple_debug (USE_STMT (use_p)))
phis.safe_push (USE_STMT (use_p));
- /* We expect to have found an exit_phi because of loop-closed-ssa
- form. */
- gcc_assert (!phis.is_empty ());
+ /* While we expect to have found an exit_phi because of loop-closed-ssa
+ form we can end up without one if the scalar cycle is dead. */
FOR_EACH_VEC_ELT (phis, i, exit_phi)
{
@@ -4456,7 +4460,10 @@ vect_finalize_reduction:
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
{
if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
- phis.safe_push (USE_STMT (use_p));
+ {
+ if (!is_gimple_debug (USE_STMT (use_p)))
+ phis.safe_push (USE_STMT (use_p));
+ }
else
{
if (double_reduc && gimple_code (USE_STMT (use_p)) == GIMPLE_PHI)
@@ -4466,7 +4473,8 @@ vect_finalize_reduction:
FOR_EACH_IMM_USE_FAST (phi_use_p, phi_imm_iter, phi_res)
{
if (!flow_bb_inside_loop_p (loop,
- gimple_bb (USE_STMT (phi_use_p))))
+ gimple_bb (USE_STMT (phi_use_p)))
+ && !is_gimple_debug (USE_STMT (phi_use_p)))
phis.safe_push (USE_STMT (phi_use_p));
}
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 6f3de12c182..96dd191691b 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6054,8 +6054,7 @@ get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
corresponding to that mode. The theory is that any use that
would cause problems with this will disable vectorization anyway. */
else if (!SCALAR_FLOAT_TYPE_P (scalar_type)
- && !INTEGRAL_TYPE_P (scalar_type)
- && !POINTER_TYPE_P (scalar_type))
+ && !INTEGRAL_TYPE_P (scalar_type))
scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1);
/* We can't build a vector type of elements with alignment bigger than
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 0b8fdf9889c..96a439a9b8a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5246,10 +5246,14 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
&& gimple_assign_rhs_code (op_def) == BIT_IOR_EXPR))
{
/* Recurse on each operand. */
- retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
- code, e, bsi);
- retval |= register_edge_assert_for_1 (gimple_assign_rhs2 (op_def),
- code, e, bsi);
+ tree op0 = gimple_assign_rhs1 (op_def);
+ tree op1 = gimple_assign_rhs2 (op_def);
+ if (TREE_CODE (op0) == SSA_NAME
+ && has_single_use (op0))
+ retval |= register_edge_assert_for_1 (op0, code, e, bsi);
+ if (TREE_CODE (op1) == SSA_NAME
+ && has_single_use (op1))
+ retval |= register_edge_assert_for_1 (op1, code, e, bsi);
}
else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR
&& TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1)
@@ -5267,9 +5271,13 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
}
else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
{
- /* Recurse through the type conversion. */
- retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def),
- code, e, bsi);
+ /* Recurse through the type conversion, unless it is a narrowing
+ conversion or conversion from non-integral type. */
+ tree rhs = gimple_assign_rhs1 (op_def);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
+ && (TYPE_PRECISION (TREE_TYPE (rhs))
+ <= TYPE_PRECISION (TREE_TYPE (op))))
+ retval |= register_edge_assert_for_1 (rhs, code, e, bsi);
}
return retval;
@@ -7449,7 +7457,8 @@ union_ranges (enum value_range_type *vr0type,
}
else if ((operand_less_p (vr1min, *vr0max) == 1
|| operand_equal_p (vr1min, *vr0max, 0))
- && operand_less_p (*vr0min, vr1min) == 1)
+ && operand_less_p (*vr0min, vr1min) == 1
+ && operand_less_p (*vr0max, vr1max) == 1)
{
/* [ ( ] ) or [ ]( ) */
if (*vr0type == VR_RANGE
@@ -7483,7 +7492,8 @@ union_ranges (enum value_range_type *vr0type,
}
else if ((operand_less_p (*vr0min, vr1max) == 1
|| operand_equal_p (*vr0min, vr1max, 0))
- && operand_less_p (vr1min, *vr0min) == 1)
+ && operand_less_p (vr1min, *vr0min) == 1
+ && operand_less_p (vr1max, *vr0max) == 1)
{
/* ( [ ) ] or ( )[ ] */
if (*vr0type == VR_RANGE
diff --git a/gcc/tree.h b/gcc/tree.h
index d6414faf145..c90e4a64ecc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3589,7 +3589,7 @@ struct GTY(()) tree_optimization_option {
/* Target optabs for this set of optimization options. This is of
type `struct target_optabs *'. */
- unsigned char *GTY ((atomic)) optabs;
+ void *GTY ((atomic)) optabs;
/* The value of this_target_optabs against which the optabs above were
generated. */
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index c120c82ad05..c319d346441 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1270,8 +1270,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
/* Build an EH edge for the direct call if necessary. */
lp_nr = lookup_stmt_eh_lp (icall_stmt);
- if (lp_nr != 0
- && stmt_could_throw_p (dcall_stmt))
+ if (lp_nr > 0 && stmt_could_throw_p (dcall_stmt))
{
edge e_eh, e;
edge_iterator ei;