summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-15 12:31:11 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-15 12:31:11 +0000
commitdadc3e9aaef6a13b31d6633dffe7a958dfdd97fa (patch)
tree4d5cfbd66d8378127df093c279459122738db994
parentc50985730df65ebf60ae38b5edcf652ae64f8191 (diff)
downloadgcc-dadc3e9aaef6a13b31d6633dffe7a958dfdd97fa.tar.gz
2016-04-15 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9 svn merge -r230011:230100 ^/trunk }} git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@235022 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.MELT5
-rw-r--r--gcc/ChangeLog655
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/acinclude.m495
-rw-r--r--gcc/c-family/ChangeLog9
-rw-r--r--gcc/c-family/c-pragma.c1
-rw-r--r--gcc/c-family/c-pragma.h1
-rw-r--r--gcc/c/ChangeLog27
-rw-r--r--gcc/c/c-parser.c154
-rw-r--r--gcc/c/c-typeck.c10
-rw-r--r--gcc/common.opt2
-rw-r--r--gcc/config.in15
-rw-r--r--gcc/config/aarch64/aarch64-protos.h2
-rw-r--r--gcc/config/aarch64/aarch64.c81
-rw-r--r--gcc/config/aarch64/aarch64.h7
-rw-r--r--gcc/config/aarch64/aarch64.md18
-rw-r--r--gcc/config/aarch64/iterators.md6
-rw-r--r--gcc/config/aarch64/predicates.md2
-rw-r--r--gcc/config/alpha/alpha.c2
-rw-r--r--gcc/config/arc/arc.c26
-rw-r--r--gcc/config/arm/arm.c18
-rw-r--r--gcc/config/avr/avr.c15
-rw-r--r--gcc/config/bfin/bfin.c10
-rw-r--r--gcc/config/c6x/c6x.c20
-rw-r--r--gcc/config/cr16/cr16.c8
-rw-r--r--gcc/config/cris/cris.c10
-rw-r--r--gcc/config/epiphany/epiphany.c10
-rw-r--r--gcc/config/fr30/fr30.c2
-rw-r--r--gcc/config/frv/frv.c8
-rw-r--r--gcc/config/h8300/h8300.c18
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c390
-rw-r--r--gcc/config/i386/i386.md4
-rw-r--r--gcc/config/i386/sse.md189
-rw-r--r--gcc/config/ia64/ia64.c3
-rw-r--r--gcc/config/initfini-array.h2
-rw-r--r--gcc/config/iq2000/iq2000.c12
-rw-r--r--gcc/config/lm32/lm32.c4
-rw-r--r--gcc/config/m32c/m32c.c2
-rw-r--r--gcc/config/m32r/m32r.c13
-rw-r--r--gcc/config/m68k/m68k.c2
-rw-r--r--gcc/config/mcore/mcore.c8
-rw-r--r--gcc/config/microblaze/microblaze.c4
-rw-r--r--gcc/config/mips/mips.c7
-rw-r--r--gcc/config/mmix/mmix.c6
-rw-r--r--gcc/config/mn10300/mn10300.c15
-rw-r--r--gcc/config/msp430/msp430.c4
-rw-r--r--gcc/config/nds32/nds32.c4
-rw-r--r--gcc/config/nios2/nios2.c6
-rw-r--r--gcc/config/nvptx/nvptx.c14
-rw-r--r--gcc/config/pa/pa.c4
-rw-r--r--gcc/config/pdp11/pdp11.c2
-rw-r--r--gcc/config/rs6000/aix53.h1
-rw-r--r--gcc/config/rs6000/aix61.h1
-rw-r--r--gcc/config/rs6000/constraints.md10
-rw-r--r--gcc/config/rs6000/predicates.md203
-rw-r--r--gcc/config/rs6000/rs6000-c.c2
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def16
-rw-r--r--gcc/config/rs6000/rs6000-opts.h1
-rw-r--r--gcc/config/rs6000/rs6000-protos.h8
-rw-r--r--gcc/config/rs6000/rs6000-tables.opt11
-rw-r--r--gcc/config/rs6000/rs6000.c1083
-rw-r--r--gcc/config/rs6000/rs6000.h34
-rw-r--r--gcc/config/rs6000/rs6000.md441
-rw-r--r--gcc/config/rs6000/rs6000.opt28
-rw-r--r--gcc/config/rx/rx.c12
-rw-r--r--gcc/config/s390/s390.c2
-rw-r--r--gcc/config/sh/sh.c21
-rw-r--r--gcc/config/sol2.h6
-rw-r--r--gcc/config/sparc/sparc.c33
-rw-r--r--gcc/config/spu/spu.c4
-rw-r--r--gcc/config/stormy16/stormy16.c7
-rw-r--r--gcc/config/tilegx/tilegx.c24
-rw-r--r--gcc/config/tilepro/tilepro.c24
-rw-r--r--gcc/config/v850/v850.c22
-rw-r--r--gcc/config/vax/vax.c4
-rw-r--r--gcc/config/visium/visium.c50
-rw-r--r--gcc/config/visium/visium.h43
-rw-r--r--gcc/config/xtensa/xtensa.c4
-rwxr-xr-xgcc/configure169
-rw-r--r--gcc/configure.ac20
-rw-r--r--gcc/cp/ChangeLog50
-rw-r--r--gcc/cp/call.c11
-rw-r--r--gcc/cp/init.c73
-rw-r--r--gcc/cp/parser.c207
-rw-r--r--gcc/cp/parser.h3
-rw-r--r--gcc/doc/invoke.texi55
-rw-r--r--gcc/doc/md.texi15
-rw-r--r--gcc/expr.c49
-rw-r--r--gcc/final.c6
-rw-r--r--gcc/gcc.c5
-rw-r--r--gcc/haifa-sched.c26
-rw-r--r--gcc/ifcvt.c190
-rw-r--r--gcc/internal-fn.c8
-rw-r--r--gcc/ipa-inline-analysis.c2
-rw-r--r--gcc/ipa-prop.c20
-rw-r--r--gcc/ipa-prop.h2
-rw-r--r--gcc/lra-lives.c14
-rw-r--r--gcc/omp-builtins.def4
-rw-r--r--gcc/omp-low.c65
-rw-r--r--gcc/omp-low.h2
-rw-r--r--gcc/optabs-query.c17
-rw-r--r--gcc/optabs-query.h12
-rw-r--r--gcc/optabs-tree.c13
-rw-r--r--gcc/optabs-tree.h1
-rw-r--r--gcc/optabs.c127
-rw-r--r--gcc/optabs.def8
-rw-r--r--gcc/optabs.h7
-rw-r--r--gcc/output.h4
-rw-r--r--gcc/print-rtl.h2
-rw-r--r--gcc/regrename.c46
-rw-r--r--gcc/regrename.h4
-rw-r--r--gcc/sched-int.h3
-rw-r--r--gcc/sched-rgn.c104
-rw-r--r--gcc/target.def2
-rw-r--r--gcc/targhooks.c1
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog140
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-1.c34
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-2.c21
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-3.c53
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-4.c41
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-5.c47
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc5
-rw-r--r--gcc/testsuite/g++.dg/init/new43.C164
-rw-r--r--gcc/testsuite/g++.dg/init/new44.C532
-rw-r--r--gcc/testsuite/g++.dg/init/new45.C106
-rw-r--r--gcc/testsuite/g++.dg/other/new-size-type.C3
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr68259.C54
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr67192.c79
-rw-r--r--gcc/testsuite/gcc.dg/pr68129_1.c10
-rw-r--r--gcc/testsuite/gcc.dg/sso/p1.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p13.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p2.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p3.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p4.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p5.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p6.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p7.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p8.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/p9.c16
-rw-r--r--gcc/testsuite/gcc.dg/sso/q1.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q13.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q2.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q3.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q4.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q5.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q6.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q7.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q8.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/q9.c8
-rw-r--r--gcc/testsuite/gcc.dg/sso/r3.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso/r5.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso/r6.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso/r7.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso/r8.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso/s3.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso/s5.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso/s6.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso/s7.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso/s8.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso/t1.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t13.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t2.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t3.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t4.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t5.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t6.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t7.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t8.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/t9.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/u5.c12
-rw-r--r--gcc/testsuite/gcc.dg/sso/u6.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr68240.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr68248.c20
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-cond-5.c81
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cond_op_imm_1.c99
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vec-mask-bit-not.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr56118.c17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ctz-1.c13
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ctz-2.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extswsli-1.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extswsli-2.c37
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extswsli-3.c22
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-call.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-mix.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion2.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion3.c18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mod-1.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mod-2.c13
-rw-r--r--gcc/testsuite/gcc.target/sparc/sparc-ret-1.c (renamed from gcc/testsuite/gcc.target/sparc/sparc-ret.c)0
-rw-r--r--gcc/testsuite/gcc.target/sparc/sparc-ret-2.c13
-rw-r--r--gcc/testsuite/gfortran.dg/pr68251.f901048
-rw-r--r--gcc/testsuite/lib/target-supports.exp228
-rw-r--r--gcc/tree-core.h10
-rw-r--r--gcc/tree-eh.c2
-rw-r--r--gcc/tree-if-conv.c36
-rw-r--r--gcc/tree-sra.c6
-rw-r--r--gcc/tree-ssa-dom.c8
-rw-r--r--gcc/tree-ssa-sccvn.c28
-rw-r--r--gcc/tree-ssa-threadupdate.c6
-rw-r--r--gcc/tree-ssa-threadupdate.h1
-rw-r--r--gcc/tree-ssanames.c15
-rw-r--r--gcc/tree-streamer-in.c5
-rw-r--r--gcc/tree-streamer-out.c5
-rw-r--r--gcc/tree-vect-data-refs.c104
-rw-r--r--gcc/tree-vect-generic.c5
-rw-r--r--gcc/tree-vect-loop.c135
-rw-r--r--gcc/tree-vect-patterns.c184
-rw-r--r--gcc/tree-vect-slp.c38
-rw-r--r--gcc/tree-vect-stmts.c261
-rw-r--r--gcc/tree-vectorizer.h10
-rw-r--r--gcc/tree.c4
-rw-r--r--gcc/tree.h7
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config/ia64/crtbegin.S2
-rw-r--r--libgcc/config/ia64/crtend.S2
-rw-r--r--libgomp/ChangeLog9
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-1.c41
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/routine-g-1.c64
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/routine-gwv-1.c66
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/routine-v-1.c64
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/routine-w-1.c64
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/routine-wv-1.c64
-rw-r--r--libitm/ChangeLog14
-rw-r--r--libitm/alloc.cc83
-rw-r--r--libitm/alloc_cpp.cc57
-rw-r--r--libitm/libitm.map5
-rw-r--r--libitm/libitm_i.h17
-rw-r--r--libitm/testsuite/libitm.c++/newdelete.C12
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/bits/functional_hash.h4
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h113
-rw-r--r--libstdc++-v3/include/bits/stl_heap.h6
237 files changed, 9115 insertions, 1349 deletions
diff --git a/ChangeLog.MELT b/ChangeLog.MELT
index bb7e26e7f9b..ab5f0aad39e 100644
--- a/ChangeLog.MELT
+++ b/ChangeLog.MELT
@@ -1,5 +1,10 @@
2016-04-15 Basile Starynkevitch <basile@starynkevitch.net>
+ {{merging with even more of GCC 6, using subversion 1.9
+ svn merge -r230011:230100 ^/trunk
+ }}
+
+2016-04-15 Basile Starynkevitch <basile@starynkevitch.net>
{{trouble merging with GCC 6 svn rev 230333, should investigate}}
2016-04-15 Basile Starynkevitch <basile@starynkevitch.net>
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 514306f723e..2100306a011 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,622 @@
+2015-11-10 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * config/i386/sse.md (maskload<mode>): Rename to ...
+ (maskload<mode><sseintvecmodelower>): ... this.
+ (maskstore<mode>): Rename to ...
+ (maskstore<mode><sseintvecmodelower>): ... this.
+ (maskload<mode><avx512fmaskmodelower>): New.
+ (maskstore<mode><avx512fmaskmodelower>): New.
+
+2015-11-10 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * internal-fn.c (expand_MASK_LOAD): Adjust to maskload optab changes.
+ (expand_MASK_STORE): Adjust to maskstore optab changes.
+ * optabs-query.c (can_vec_mask_load_store_p): Add MASK_MODE arg.
+ Adjust to maskload, maskstore optab changes.
+ * optabs-query.h (can_vec_mask_load_store_p): Add MASK_MODE arg.
+ * optabs.def (maskload_optab): Transform into convert optab.
+ (maskstore_optab): Likewise.
+ * tree-if-conv.c (ifcvt_can_use_mask_load_store): Adjust to
+ can_vec_mask_load_store_p signature change.
+ (predicate_mem_writes): Use boolean mask.
+ * tree-vect-stmts.c (vectorizable_mask_load_store): Adjust to
+ can_vec_mask_load_store_p signature change. Allow invariant masks.
+ (vectorizable_operation): Ignore type precision for boolean vectors.
+
+2015-11-10 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * expr.c (do_store_flag): Use expand_vec_cmp_expr for mask results.
+ (const_vector_mask_from_tree): New.
+ (const_vector_from_tree): Use const_vector_mask_from_tree
+ for boolean vectors.
+ * optabs-query.h (get_vec_cmp_icode): New.
+ * optabs-tree.c (expand_vec_cmp_expr_p): New.
+ * optabs-tree.h (expand_vec_cmp_expr_p): New.
+ * optabs.c (vector_compare_rtx): Add OPNO arg.
+ (expand_vec_cond_expr): Adjust to vector_compare_rtx change.
+ (expand_vec_cmp_expr): New.
+ * optabs.def (vec_cmp_optab): New.
+ (vec_cmpu_optab): New.
+ * optabs.h (expand_vec_cmp_expr): New.
+ * tree-vect-generic.c (expand_vector_comparison): Add vector
+ comparison optabs check.
+ * tree-vect-loop.c (vect_determine_vectorization_factor): Ignore mask
+ operations for VF. Add mask type computation.
+ * tree-vect-stmts.c (get_mask_type_for_scalar_type): New.
+ (vectorizable_comparison): New.
+ (vect_analyze_stmt): Add vectorizable_comparison.
+ (vect_transform_stmt): Likewise.
+ (vect_init_vector): Support boolean vector invariants.
+ (vect_get_vec_def_for_operand): Add VECTYPE arg.
+ (vectorizable_condition): Directly provide vectype for invariants
+ used in comparison.
+ * tree-vectorizer.h (get_mask_type_for_scalar_type): New.
+ (enum vect_var_kind): Add vect_mask_var.
+ (enum stmt_vec_info_type): Add comparison_vec_info_type.
+ (vectorizable_comparison): New.
+ (vect_get_vec_def_for_operand): Add VECTYPE arg.
+ * tree-vect-data-refs.c (vect_get_new_vect_var): Support vect_mask_var.
+ (vect_create_destination_var): Likewise.
+ * tree-vect-patterns.c (check_bool_pattern): Check fails
+ if we can vectorize comparison directly.
+ (search_type_for_mask): New.
+ (vect_recog_bool_pattern): Support cases when bool pattern
+ check fails.
+ * tree-vect-slp.c (vect_build_slp_tree_1): Allow
+ comparison statements.
+ (vect_get_constant_vectors): Support boolean vector
+ constants.
+ * config/i386/i386-protos.h (ix86_expand_mask_vec_cmp): New.
+ (ix86_expand_int_vec_cmp): New.
+ (ix86_expand_fp_vec_cmp): New.
+ * config/i386/i386.c (ix86_expand_sse_cmp): Allow NULL for
+ op_true and op_false.
+ (ix86_int_cmp_code_to_pcmp_immediate): New.
+ (ix86_fp_cmp_code_to_pcmp_immediate): New.
+ (ix86_cmp_code_to_pcmp_immediate): New.
+ (ix86_expand_mask_vec_cmp): New.
+ (ix86_expand_fp_vec_cmp): New.
+ (ix86_expand_int_sse_cmp): New.
+ (ix86_expand_int_vcond): Use ix86_expand_int_sse_cmp.
+ (ix86_expand_int_vec_cmp): New.
+ (ix86_get_mask_mode): New.
+ (TARGET_VECTORIZE_GET_MASK_MODE): New.
+ * config/i386/sse.md (avx512fmaskmodelower): New.
+ (vec_cmp<mode><avx512fmaskmodelower>): New.
+ (vec_cmp<mode><sseintvecmodelower>): New.
+ (vec_cmpv2div2di): New.
+ (vec_cmpu<mode><avx512fmaskmodelower>): New.
+ (vec_cmpu<mode><sseintvecmodelower>): New.
+ (vec_cmpuv2div2di): New.
+
+2015-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/68240
+ * tree-ssa-sccvn.c (cond_stmts_equal_p): Handle commutative compares
+ properly.
+ (visit_phi): For PHIs with just a single executable edge
+ take its value directly.
+ (expressions_equal_p): Handle VN_TOP properly.
+
+2015-11-10 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences):
+ Handle memory using/clobbering stmts without a STMT_VINFO_DATA_REF
+ conservatively.
+
+2015-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56118
+ * tree-vect-slp.c (vect_bb_vectorization_profitable_p): Make equal
+ cost favor vectorized version.
+
+2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.md (<neg_not_op><mode>cc): New define_expand.
+ * config/aarch64/iterators.md (NEG_NOT): New code iterator.
+ (neg_not_op): New code attribute.
+
+2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * ifcvt.c (noce_try_inverse_constants): New function.
+ (noce_process_if_block): Call it.
+ * optabs.h (emit_conditional_neg_or_complement): Declare prototype.
+ * optabs.def (negcc_optab, notcc_optab): Declare.
+ * optabs.c (emit_conditional_neg_or_complement): New function.
+ * doc/tm.texi (Standard Names): Document negcc, notcc names.
+
+2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR rtl-optimization/68236
+ * haifa-sched.c (autopref_multipass_dfa_lookahead_guard): Return 0
+ if insn_queue doesn't exist.
+ (haifa_sched_finish): Reset insn_queue to NULL.
+
+2015-11-10 Robert Suchanek <robert.suchanek@imgtec.com>
+
+ * regrename.c (create_new_chain): Initialize renamed and tied_chain.
+ (build_def_use): Initialize terminated_this_insn.
+ (find_best_rename_reg): Pick and check register from the tied chain.
+ (regrename_do_replace): Mark head as renamed.
+ (struct du_head *terminated_this_insn). New static variable.
+ (scan_rtx_reg): Tie chains in move insns. Set terminated_this_insn.
+ * regrename.h (struct du_head): Add tied_chain, renamed members.
+
+2015-11-10 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ PR bootstrap/68256
+ * config/aarch64/aarch64.c (aarch64_use_constant_blocks_p):
+ Return false.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/57845
+ * config/sparc/sparc.c (sparc_function_value_1): In 32-bit mode, do
+ not promote the mode for aggregate types.
+
+2015-11-09 Nathan Sidwell <nathan@codesourcery.com>
+
+ * omp-low.h (replace_oacc_fn_attrib, build_oacc_routine_dims): Declare.
+ * omp-low.c (build_oacc_routine_dims): New.
+
+2015-11-09 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/constraints.md (wF constraint): New constraints
+ for power9/toc fusion.
+ (wG constraint): Likewise.
+
+ * config/rs6000/predicates.md (u6bit_cint_operand): New
+ predicate, recognize 0..63.
+ (upper16_cint_operand): New predicate for power9 and toc fusion.
+ (fpr_reg_operand): Likewise.
+ (toc_fusion_or_p9_reg_operand): Likewise.
+ (toc_fusion_mem_raw): Likewise.
+ (toc_fusion_mem_wrapped): Likewise.
+ (fusion_gpr_addis): If power9 fusion, allow fusion for a larger
+ address range.
+ (fusion_gpr_mem_combo): Delete, use fusion_addis_mem_combo_load
+ instead.
+ (fusion_addis_mem_combo_load): Add support for power9 fusion of
+ floating point loads, floating point stores, and gpr stores.
+ (fusion_addis_mem_combo_store): Likewise.
+ (fusion_offsettable_mem_operand): Likewise.
+
+ * config/rs6000/rs6000-protos.h (emit_fusion_addis): Add
+ declarations.
+ (emit_fusion_load_store): Likewise.
+ (fusion_p9_p): Likewise.
+ (expand_fusion_p9_load): Likewise.
+ (expand_fusion_p9_store): Likewise.
+ (emit_fusion_p9_load): Likewise.
+ (emit_fusion_p9_store): Likewise.
+ (fusion_wrap_memory_address): Likewise.
+
+ * config/rs6000/rs6000.c (struct rs6000_reg_addr): Add new
+ elements for power9 fusion.
+ (rs6000_debug_print_mode): Rework debug information to print more
+ information about fusion.
+ (rs6000_init_hard_regno_mode_ok): Setup for power9 fusion
+ support.
+ (rs6000_legitimate_address_p): Recognize toc fusion as a valid
+ offsettable memory address.
+ (rs6000_rtx_costs): Update costs for new ISA 3.0 instructions.
+ (emit_fusion_gpr_load): Move most of the code from
+ emit_fusion_gpr_load into emit_fusion-addis that handles both
+ power8 and power9 fusion.
+ (emit_fusion_addis): Likewise.
+ (emit_fusion_load_store): Likewise.
+ (fusion_wrap_memory_address): Add support for TOC fusion.
+ (fusion_split_address): Likewise.
+ (fusion_p9_p): Add support for power9 fusion.
+ (expand_fusion_p9_load): Likewise.
+ (expand_fusion_p9_store): Likewise.
+ (emit_fusion_p9_load): Likewise.
+ (emit_fusion_p9_store): Likewise.
+
+ * config/rs6000/rs6000.h (TARGET_EXTSWSLI): Macros for support for
+ new instructions in ISA 3.0.
+ (TARGET_CTZ): Likewise.
+ (TARGET_TOC_FUSION_INT): Macros for power9 fusion support.
+ (TARGET_TOC_FUSION_FP): Likewise.
+
+ * config/rs6000/rs6000.md (UNSPEC_FUSION_P9): New power9/toc
+ fusion unspecs.
+ (UNSPEC_FUSION_ADDIS): Likewise.
+ (QHSI mode iterator): New iterator for power9 fusion.
+ (GPR_FUSION): Likewise.
+ (FPR_FUSION): Likewise.
+ (mod<mode>3): Add support for ISA 3.0
+ modulus instructions.
+ (umod<mode>3): Likewise.
+ (divmod peephole): Likewise.
+ (udivmod peephole): Likewise.
+ (ctz<mode>2): Add support for ISA 3.0 count trailing zeros scalar
+ instructions.
+ (ctz<mode>2_h): Likewise.
+ (ashdi3_extswsli): Add support for ISA 3.0 EXTSWSLI instruction.
+ (ashdi3_extswsli_dot): Likewise.
+ (ashdi3_extswsli_dot2): Likewise.
+ (power9 fusion splitter): New power9/toc fusion support.
+ (toc_fusionload_<mode>): Likewise.
+ (toc_fusionload_di): Likewise.
+ (fusion_gpr_load_<mode>): Update predicate function.
+ (power9 fusion peephole2s): New power9/toc fusion support.
+ (fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load): Likewise.
+ (fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store): Likewise.
+ (fusion_fpr_<P:mode>_<FPR_FUSION:mode>_load): Likewise.
+ (fusion_fpr_<P:mode>_<FPR_FUSION:mode>_store): Likewise.
+ (fusion_p9_<mode>_constant): Likewise.
+
+2015-11-09 Steve Ellcey <sellcey@imgtec.com>
+
+ * optabs.c (prepare_libcall_arg): New function.
+ (expand_fixed_convert): Add call to prepare_libcall_arg.
+
+2015-11-09 Nikolai Bozhenov <n.bozhenov@samsung.com>
+
+ * sched-int.h (dump_rgn_dependencies_dot): Declare
+ * sched-rgn.c (dump_rgn_dependencies_dot): New function
+ * print-rtl.h (print_insn): Add prototype
+
+ * haifa-sched.c (setup_sched_dump): Don't redirect output to stderr.
+ * common.opt (-fsched-verbose): Set default value to 1.
+ * invoke.texi (-fsched-verbose): Update the option's description.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/visium/visium.h (PRINT_OPERAND): Delete.
+ (PRINT_OPERAND_PUNCT_VALID_P): Likewise.
+ (PRINT_OPERAND_ADDRESS): Likewise.
+ * config/visium/visium.c (TARGET_PRINT_OPERAND_PUNCT_VALID_P): Define
+ to...
+ (visium_print_operand_punct_valid_p): ...this. New function.
+ (TARGET_PRINT_OPERAND): Define to...
+ (print_operand): Rename to...
+ (visium_print_operand): ...this.
+ (TARGET_PRINT_OPERAND_ADDRESS): Define to...
+ (visium_output_address): Rename to...
+ (visium_print_operand_address): ...this.
+ (print_operand_address): Delete.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/68259
+ * tree.h (reverse_storage_order_for_component_p) <COMPONENT_REF>:
+ Check that the type of the first operand is an aggregate type.
+
+2015-11-09 Nathan Sidwell <nathan@codesourcery.com>
+
+ * omp-low.c: Fix some OpenACC comment typos.
+ (lower_reduction_clauses): Remove BUILT_IN_GOACC_GET_THREAD_NUM call.
+ * omp-builtins.def (BUILT_IN_GOACC_GET_THREAD_NUM,
+ BUILT_IN_GOACC_GET_NUM_THREADS): Delete.
+
+2015-11-09 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (*strmovqi_1): Fix insn enable condition.
+
+2015-11-09 Jeff Law <law@redhat.com>
+
+ * tree-ssanames.c (verify_ssaname_freelists): Simplify check for
+ being in gimple/ssa form. Remove redundant check for SSA_NAME.
+ Fix comment typo.
+
+2015-11-09 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.opt (-mpower9-fusion): Add new switches for
+ ISA 3.0 (power9).
+ (-mpower9-vector): Likewise.
+ (-mpower9-dform): Likewise.
+ (-mpower9-minmax): Likewise.
+ (-mtoc-fusion): Likewise.
+ (-mmodulo): Likewise.
+ (-mfloat128-hardware): Likewise.
+
+ * config/rs6000/rs6000-cpus.def (ISA_3_0_MASKS_SERVER): Add option
+ mask for ISA 3.0 (power9).
+ (POWERPC_MASKS): Add new ISA 3.0 switches.
+ (power9 cpu): Add power9 cpu.
+
+ * config/rs6000/rs6000.h (ASM_CPU_POWER9_SPEC): Add support for
+ power9.
+ (ASM_CPU_SPEC): Likewise.
+ (EXTRA_SPECS): Likewise.
+
+ * config/rs6000/rs6000-opts.h (enum processor_type): Add
+ PROCESSOR_POWER9.
+
+ * config/rs6000/rs6000.c (power9_cost): Initial cost setup for
+ power9.
+ (rs6000_debug_reg_global): Add support for power9 fusion.
+ (rs6000_setup_reg_addr_masks): Cache mode size.
+ (rs6000_option_override_internal): Until real power9 tuning is
+ added, use -mtune=power8 for -mcpu=power9.
+ (rs6000_setup_reg_addr_masks): Do not allow pre-increment,
+ pre-decrement, or pre-modify on SFmode/DFmode if we allow the use
+ of Altivec registers.
+ (rs6000_option_override_internal): Add support for ISA 3.0
+ switches.
+ (rs6000_loop_align): Add support for power9 cpu.
+ (rs6000_file_start): Likewise.
+ (rs6000_adjust_cost): Likewise.
+ (rs6000_issue_rate): Likewise.
+ (insn_must_be_first_in_group): Likewise.
+ (insn_must_be_last_in_group): Likewise.
+ (force_new_group): Likewise.
+ (rs6000_register_move_cost): Likewise.
+ (rs6000_opt_masks): Likewise.
+
+ * config/rs6000/rs6000.md (cpu attribute): Add power9.
+ * config/rs6000/rs6000-tables.opt: Regenerate.
+
+ * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
+ _ARCH_PWR9 if power9 support is available.
+
+ * config/rs6000/aix61.h (ASM_CPU_SPEC): Add power9.
+ * config/rs6000/aix53.h (ASM_CPU_SPEC): Likewise.
+
+ * configure.ac: Determine if the assembler supports the ISA 3.0
+ instructions.
+ * config.in (HAVE_AS_POWER9): Likewise.
+ * configure: Regenerate.
+
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Document ISA 3.0
+ switches.
+
+2015-11-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_simd_valid_immediate):
+ Remove integer CONST_DOUBLE handling. It should never occur.
+
+2015-11-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/68129
+ * config/aarch64/aarch64.h (TARGET_SUPPORTS_WIDE_INT): Define to 1.
+ * config/aarch64/aarch64.c (aarch64_print_operand, CONST_DOUBLE):
+ Delete VOIDmode case. Assert that mode is not VOIDmode.
+ * config/aarch64/predicates.md (const0_operand): Remove const_double
+ match.
+
+2015-11-09 Martin Liska <mliska@suse.cz>
+
+ * ipa-inline-analysis.c (estimate_function_body_sizes): Call
+ body_info release function.
+ * ipa-prop.c (ipa_release_body_info): New function.
+ (ipa_analyze_node): Call the function.
+ (ipa_node_params::~ipa_node_params): Release known_csts.
+ * ipa-prop.h (ipa_release_body_info): Declare.
+
+2015-11-09 Martin Liska <mliska@suse.cz>
+
+ * gcc.c (record_temp_file): Release name string.
+ * ifcvt.c (noce_convert_multiple_sets): Use auto_vec instead
+ of vec.
+ * lra-lives.c (free_live_range_list): Utilize
+ lra_live_range_pool for allocation and deallocation.
+ (create_live_range): Likewise.
+ (copy_live_range): Likewise.
+ (lra_merge_live_ranges): Likewise.
+ (remove_some_program_points_and_update_live_ranges): Likewise.
+ (lra_create_live_ranges_1): Release point_freq_vec that can
+ be not freed from previous iteration of the function.
+ * tree-eh.c (lower_try_finally_switch): Use auto_vec instead of
+ vec.
+ * tree-sra.c (sra_deinitialize): Release all vectors in
+ base_access_vec.
+ * tree-ssa-dom.c (free_dom_edge_info): Make the function extern.
+ * tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges):
+ Release edge_info for a removed edge.
+ (thread_through_all_blocks): Free region vector.
+ * tree-ssa.h (free_dom_edge_info): Declare function extern.
+
+2015-11-09 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * optabs.c (expand_vec_cond_expr): Always get sign from type.
+ * tree.c (wide_int_to_tree): Support negative values for boolean.
+ (build_nonstandard_boolean_type): Use signed type for booleans.
+
+2015-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/68248
+ * tree-vect-generic.c (expand_vector_operations_1): Handle
+ scalar rhs2.
+
+2015-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56118
+ * tree-vectorizer.h (vect_find_last_scalar_stmt_in_slp): Declare.
+ * tree-vect-slp.c (vect_find_last_scalar_stmt_in_slp): Export.
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences): New
+ function.
+ (vect_slp_analyze_data_ref_dependences): Instead of computing
+ all dependences of the region DRs just analyze the code motions
+ SLP vectorization will perform. Remove SLP instances that
+ cannot have their store/load motions applied.
+ (vect_analyze_data_refs): Allow DRs without a vectype
+ in BB vectorization.
+
+2015-11-09 Julian Brown <julian@codesourcery.com>
+
+ * final.c (output_asm_insn): Pass VOIDmode to output_address.
+ (output_address): Add MODE argument. Pass to print_operand_address
+ hook.
+ * targhooks.c (default_print_operand_address): Add MODE argument.
+ * targhooks.h (default_print_operand_address): Update prototype.
+ * output.h (output_address): Update prototype.
+ * target.def (print_operand_address): Add MODE argument.
+ * config/vax/vax.c (print_operand_address): Pass VOIDmode to
+ output_address.
+ (print_operand): Pass access mode to output_address.
+ * config/mcore/mcore.c (mcore_print_operand_address): Add MODE
+ argument.
+ (mcore_print_operand): Update calls to mcore_print_operand_address.
+ * config/fr30/fr30.c (fr30_print_operand): Pass VOIDmode to
+ output_address.
+ * config/lm32/lm32.c (lm32_print_operand): Pass mode in calls to
+ output_address.
+ * config/tilegx/tilegx.c (output_memory_reference_mode): Remove
+ global.
+ (tilegx_print_operand): Don't set above global. Update calls to
+ output_address.
+ (tilegx_print_operand_address): Add MODE argument. Use instead of
+ output_memory_reference_mode global.
+ * config/frv/frv.c (frv_print_operand_address): Add MODE argument.
+ (frv_print_operand): Pass mode to frv_print_operand_address calls.
+ * config/mn10300/mn10300.c (mn10300_print_operand): Pass mode to
+ output_address.
+ * config/cris/cris.c (cris_print_operand_address): Add MODE
+ argument.
+ (cris_print_operand): Pass mode to output_address calls.
+ * config/spu/spu.c (print_operand): Pass mode to output_address
+ calls.
+ * config/aarch64/aarch64.h (aarch64_print_operand)
+ (aarch64_print_operand_address): Remove prototypes.
+ * config/aarch64/aarch64.c (aarch64_memory_reference_mode): Delete
+ global.
+ (aarch64_print_operand): Make static. Update calls to
+ output_address.
+ (aarch64_print_operand_address): Add MODE argument. Use instead of
+ aarch64_memory_reference_mode global.
+ (TARGET_PRINT_OPERAND, TARGET_PRINT_OPERAND_ADDRESS): Define target
+ hooks.
+ * config/aarch64/aarch64.h (PRINT_OPERAND, PRINT_OPERAND_ADDRESS):
+ Delete macro definitions.
+ * config/pa/pa.c (pa_print_operand): Pass mode in output_address
+ calls.
+ * config/xtensa/xtensa.c (print_operand): Pass mode in
+ output_address calls.
+ * config/h8300/h8300.c (h8300_print_operand_address): Add MODE
+ argument.
+ (h83000_print_operand): Update calls to h8300_print_operand_address
+ and output_address.
+ * config/ia64/ia64.c (ia64_print_operand_address): Add MODE
+ argument.
+ * config/tilepro/tilepro.c (output_memory_reference_mode): Delete
+ global.
+ (tilepro_print_operand): Pass mode to output_address.
+ (tilepro_print_operand_address): Add MODE argument. Use instead of
+ output_memory_reference_mode.
+ * config/nvptx/nvptx.c (output_decl_chunk, nvptx_assemble_integer)
+ (nvptx_output_call_insn, nvptx_print_address_operand): Pass VOIDmode
+ to output_address calls.
+ (nvptx_print_operand_address): Add MODE argument.
+ * config/alpha/alpha.c (print_operand): Pass mode argument in
+ output_address calls.
+ * config/m68k/m68k.c (print_operand): Pass mode argument in
+ output_address call.
+ * config/avr/avr.c (avr_print_operand_address): Add MODE argument.
+ (avr_print_operand): Update calls to avr_print_operand_address.
+ * config/sparc/sparc.c (sparc_print_operand_address): Add MODE
+ argument. Update calls to output_address.
+ (sparc_print_operand): Pass mode to output_address.
+ * config/iq2000/iq2000.c (iq2000_print_operand_address): Add MODE
+ argument.
+ (iq2000_print_operand): Pass mode in output_address calls.
+ * config/stormy16/stormy16.c (xstormy16_print_operand_address): Add
+ MODE argument.
+ (xstormy16_print_operand): Pass mode to
+ xstormy16_print_operand_address calls.
+ * config/mips/mips.c (mips_print_operand): Update calls to
+ output_address.
+ (mips_print_operand_address): Add MODE argument.
+ * config/epiphany/epiphany.c (epiphany_print_operand): Update calls
+ to output_address.
+ (epiphany_print_operand_address): Add MODE argument. Add FIXME note.
+ * config/pdp11/pdp11.c (pdp11_asm_print_operand): Update call to
+ output_address.
+ * config/rx/rx.c (rx_print_operand_address): Add MODE argument.
+ (rx_print_operand): Update calls to output_address,
+ rx_print_operand_address.
+ * config/nds32/nds32.c (nds32_print_operand): Update calls to
+ output_address.
+ (nds32_print_operand_address): Add MODE argument.
+ * config/rs6000/rs6000.c (print_operand): Pass mem mode to
+ output_address calls.
+ * config/c6x/c6x.c (print_address_offset): Pass mem mode to
+ output_address call.
+ (c6x_print_address_operand): Update calls to output_address.
+ (c6x_print_operand_address): Pass mode to above.
+ * config/v850/v850.c (v850_print_operand_address): Add MODE
+ argument.
+ (v850_print_operand): Pass mode to v850_print_operand_address,
+ output_address.
+ * config/mmix/mmix.c (mmix_print_operand_address): Add MODE
+ argument.
+ (mmix_print_operand): Pass mode in output_address calls.
+ * config/sh/sh.c (sh_print_operand_address): Add MODE argument.
+ (sh_print_operand): Pass mem mode to output_address,
+ sh_print_operand_address.
+ * config/cr16/cr16.c (cr16_print_operand_address): Add MODE
+ argument.
+ (cr16_print_operand): Pass mode to output_address,
+ cr16_print_operand_address.
+ * config/bfin/bfin.c (print_address_operand): Pass VOIDmode to
+ output_address.
+ * config/microblaze/microblaze.c (print_operand): Pass mode to
+ output_address.
+ * config/nios2/nios2.c (nios2_print_operand): Pass VOIDmode to
+ output_address.
+ (nios2_print_operand_address): Add MODE argument. Update call to
+ nios2_print_operand_address.
+ * config/s390/s390.c (print_operand): Pass mode to output_address.
+ * config/m32c/m32c.c (m32c_print_operand_address): Add MODE
+ argument.
+ * config/arc/arc.c (arc_print_operand): Pass VOIDmode to
+ output_address.
+ * config/arm/arm.c (arm_print_operand_address): Add MODE argument.
+ Use instead of output_memory_reference_mode.
+ (output_memory_reference_mode): Delete global.
+ (arm_print_operand): Pass mem mode to output_address.
+ * config/m32r/m32r.c (m32r_print_operand_address): Add MODE
+ argument.
+ (m32r_print_operand): Pass mode to output_address.
+ * config/msp430/msp430.c (msp430_print_operand_addr): Add MODE
+ argument.
+ (msp430_print_operand): Pass mode to msp430_print_operand_addr.
+ * config/i386/i386.c (ix86_print_operand): Pass mode to
+ output_address calls.
+ (ix86_print_operand_address): Add MODE argument.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/68251
+ * tree-core.h (REF_REVERSE_STORAGE_ORDER): Move around.
+ * tree.h (REF_REVERSE_STORAGE_ORDER): Change to default_def_flag.
+ * tree-streamer-in.c (unpack_ts_base_value_fields): Adjust.
+ * tree-streamer-out.c (pack_ts_base_value_fields): Likewise.
+
+2015-11-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR rtl-optimization/67749
+ * ifcvt.c (noce_try_cmove_arith): Do not emit move in IF-ELSE
+ case before emitting the two blocks. Instead modify the register
+ in the corresponding final insn of the basic block.
+
+2015-11-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * acinclude.m4 (gcc_AC_INITFINI_ARRAY): Allow for differences in
+ assembler syntax.
+ Support Solaris ld.
+ Define HAVE_INITFINI_ARRAY_SUPPORT as 0/1.
+
+ * config/sol2.h (SUPPORTS_INIT_PRIORITY): Define to
+ HAVE_INITFINI_ARRAY_SUPPORT.
+ * config/initfini-array.h: Check HAVE_INITFINI_ARRAY_SUPPORT
+ value.
+
+ * configure.ac (gcc_cv_as_sparc_nobits): Remove.
+ * config/sparc/sparc.c (sparc_solaris_elf_asm_named_section):
+ Don't check HAVE_AS_SPARC_NOBITS.
+ Heed SECTION_NOTYPE.
+
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/68253
+ * fold-const.c (fold_truth_andor_1): Initialize new variables to 0.
+
2015-11-09 Richard Henderson <rth@redhat.com>
* config/i386/i386-c.c (ix86_target_macros): Define __SEG_FS,
@@ -242,7 +861,7 @@
(TYPE_SATURATING): Adjust.
(REF_REVERSE_STORAGE_ORDER): New flag.
(reverse_storage_order_for_component_p): New inline predicate.
- (storage_order_barrier_p): Likewise.
+ (storage_order_barrier_p): Likewise.
(get_inner_reference): Adjust prototype.
* varasm.c: Include expmed.h.
(assemble_variable_contents): Adjust call to output_constant.
@@ -353,7 +972,7 @@
* tree-ssa-sccvn.c (vn_reference_eq): Return false on storage order
barriers.
(copy_reference_ops_from_ref) <MEM_REF>: Set REVERSE field according
- to the REF_REVERSE_STORAGE_ORDER flag.
+ to the REF_REVERSE_STORAGE_ORDER flag.
<BIT_FIELD_REF>: Likewise.
<VIEW_CONVERT_EXPR>: Set it for storage order barriers.
(contains_storage_order_barrier_p): New predicate.
@@ -673,11 +1292,11 @@
Properly apply.
2015-11-05 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
- * config/aarch64/aarch64.c
- (aarch64_can_use_per_function_literal_pools_p): New.
- (aarch64_use_blocks_for_constant_p): Adjust declaration
- and use aarch64_can_use_function_literal_pools_p.
- (aarch64_select_rtx_section): Update.
+ * config/aarch64/aarch64.c
+ (aarch64_can_use_per_function_literal_pools_p): New.
+ (aarch64_use_blocks_for_constant_p): Adjust declaration
+ and use aarch64_can_use_function_literal_pools_p.
+ (aarch64_select_rtx_section): Update.
2015-11-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
@@ -722,16 +1341,16 @@
* config/aarch64/aarch64-simd.md: Matching expressions for frsqrte and
frsqrts.
* config/aarch64/aarch64-tuning-flags.def: Added recip_sqrt.
- * config/aarch64/aarch64.c: New functions. Emit rsqrt estimation code when
- applicable.
+ * config/aarch64/aarch64.c: New functions. Emit rsqrt estimation
+ code when applicable.
* config/aarch64/aarch64.md: Added enum entries.
* config/aarch64/aarch64.opt: Added option -mlow-precision-recip-sqrt.
- * testsuite/gcc.target/aarch64/rsqrt_asm_check_common.h: Common macros for
- assembly checks.
+ * testsuite/gcc.target/aarch64/rsqrt_asm_check_common.h: Common
+ macros for assembly checks.
* testsuite/gcc.target/aarch64/rsqrt_asm_check_negative_1.c: Make sure
frsqrts and frsqrte are not emitted.
- * testsuite/gcc.target/aarch64/rsqrt_asm_check_1.c: Make sure frsqrts and
- frsqrte are emitted.
+ * testsuite/gcc.target/aarch64/rsqrt_asm_check_1.c: Make sure
+ frsqrts and frsqrte are emitted.
* testsuite/gcc.target/aarch64/rsqrt_1.c: Functional tests for rsqrt.
2015-11-07 Jan Hubicka <hubicka@ucw.cz>
@@ -1021,11 +1640,11 @@
2015-11-05 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
- * config/aarch64/aarch64.c
- (aarch64_can_use_per_function_literal_pools_p): New.
- (aarch64_use_blocks_for_constant_p): Adjust declaration
- and use aarch64_can_use_function_literal_pools_p.
- (aarch64_select_rtx_section): Update.
+ * config/aarch64/aarch64.c
+ (aarch64_can_use_per_function_literal_pools_p): New.
+ (aarch64_use_blocks_for_constant_p): Adjust declaration
+ and use aarch64_can_use_function_literal_pools_p.
+ (aarch64_select_rtx_section): Update.
2015-11-05 Ilya Enkovich <enkovich.gnu@gmail.com>
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 563100ef632..7ed3ab068e1 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20151109
+20151110
diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
index 0bcd844fac6..b8a4c28424d 100644
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -309,43 +309,96 @@ int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
gcc_cv_initfini_array=yes
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
- cat > conftest.s <<\EOF
-.section .dtors,"a",%progbits
+ case $target:$gas in
+ *:yes)
+ sh_flags='"a"'
+ sh_type='%progbits'
+ ;;
+ i?86-*-solaris2*:no | x86_64-*-solaris2*:no)
+ sh_flags='"a"'
+ sh_type='@progbits'
+ ;;
+ sparc*-*-solaris2*:no)
+ sh_flags='#alloc'
+ sh_type='#progbits'
+ sh_quote='"'
+ ;;
+ esac
+ case "$target:$gnu_ld" in
+ *:yes)
+ cat > conftest.s <<EOF
+.section .dtors,$sh_flags,$sh_type
.balign 4
.byte 'A', 'A', 'A', 'A'
-.section .ctors,"a",%progbits
+.section .ctors,$sh_flags,$sh_type
.balign 4
.byte 'B', 'B', 'B', 'B'
-.section .fini_array.65530,"a",%progbits
+.section .fini_array.65530,$sh_flags,$sh_type
.balign 4
.byte 'C', 'C', 'C', 'C'
-.section .init_array.65530,"a",%progbits
+.section .init_array.65530,$sh_flags,$sh_type
.balign 4
.byte 'D', 'D', 'D', 'D'
-.section .dtors.64528,"a",%progbits
+.section .dtors.64528,$sh_flags,$sh_type
.balign 4
.byte 'E', 'E', 'E', 'E'
-.section .ctors.64528,"a",%progbits
+.section .ctors.64528,$sh_flags,$sh_type
.balign 4
.byte 'F', 'F', 'F', 'F'
-.section .fini_array.01005,"a",%progbits
+.section .fini_array.01005,$sh_flags,$sh_type
.balign 4
.byte 'G', 'G', 'G', 'G'
-.section .init_array.01005,"a",%progbits
+.section .init_array.01005,$sh_flags,$sh_type
.balign 4
.byte 'H', 'H', 'H', 'H'
.text
.globl _start
_start:
EOF
- if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
- && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
- && $gcc_cv_objdump -s -j .init_array conftest \
- | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
- && $gcc_cv_objdump -s -j .fini_array conftest \
- | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
- gcc_cv_initfini_array=yes
- fi
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ *-*-solaris2*:no)
+ # When Solaris ld added constructor priority support, it was
+ # decided to only handle .init_array.N/.fini_array.N since
+ # there was no need for backwards compatibility with
+ # .ctors.N/.dtors.N. .ctors/.dtors remain as separate
+ # sections with correct execution order resp. to
+ # .init_array/.fini_array, while gld merges them into
+ # .init_array/.fini_array.
+ cat > conftest.s <<EOF
+.section $sh_quote.fini_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'C', 'C', 'C', 'C'
+.section $sh_quote.init_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'D', 'D', 'D', 'D'
+.section $sh_quote.fini_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'G', 'G', 'G', 'G'
+.section $sh_quote.init_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHDDDD > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGCCCC > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ esac
changequote(,)dnl
rm -f conftest conftest.*
changequote([,])dnl
@@ -375,10 +428,10 @@ changequote([,])dnl
fi])
enable_initfini_array=$gcc_cv_initfini_array
])
-if test $enable_initfini_array = yes; then
- AC_DEFINE(HAVE_INITFINI_ARRAY_SUPPORT, 1,
- [Define .init_array/.fini_array sections are available and working.])
-fi])
+AC_DEFINE_UNQUOTED(HAVE_INITFINI_ARRAY_SUPPORT,
+ [`if test $enable_initfini_array = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if .init_array/.fini_array sections are available and working.])
+])
dnl # _gcc_COMPUTE_GAS_VERSION
dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index f52b3e354c5..4188535df78 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,12 @@
+2015-11-09 Thomas Schwinge <thomas@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+ James Norris <jnorris@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+ Nathan Sidwell <nathan@codesourcery.com>
+
+ * c-pragma.c (oacc_pragmas): Add "routine".
+ * c-pragma.h (pragma_kind): Add PRAGMA_OACC_ROUTINE.
+
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* c-common.c (c_common_attributes): Add scalar_storage_order.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 50551fbf924..875d45ed545 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1257,6 +1257,7 @@ static const struct omp_pragma_def oacc_pragmas[] = {
{ "kernels", PRAGMA_OACC_KERNELS },
{ "loop", PRAGMA_OACC_LOOP },
{ "parallel", PRAGMA_OACC_PARALLEL },
+ { "routine", PRAGMA_OACC_ROUTINE },
{ "update", PRAGMA_OACC_UPDATE },
{ "wait", PRAGMA_OACC_WAIT }
};
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 4175e832bab..a36e49abeae 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -35,6 +35,7 @@ typedef enum pragma_kind {
PRAGMA_OACC_KERNELS,
PRAGMA_OACC_LOOP,
PRAGMA_OACC_PARALLEL,
+ PRAGMA_OACC_ROUTINE,
PRAGMA_OACC_UPDATE,
PRAGMA_OACC_WAIT,
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 6fea3a996e9..0124dcc578d 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,30 @@
+2015-11-09 Thomas Schwinge <thomas@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+ James Norris <jnorris@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+ Nathan Sidwell <nathan@codesourcery.com>
+
+ c/
+ * c-parser.c (c_parser_declaration_or_fndef): Add OpenACC
+ routine arg.
+ (c_parser_declaration_or_fndef): Call c_finish_oacc_routine.
+ (c_parser_pragma): Parse 'acc routine'.
+ (OACC_ROUTINE_CLAUSE_MARK): Define.
+ (c_parser_oacc_routine, (c_finish_oacc_routine): New.
+
+2015-11-09 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ PR debug/67192
+ * c-typeck.c (c_finish_loop): For unconditional loops, set the
+ location of the backward-goto to the start of the loop body.
+
+2015-11-09 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ PR debug/67192
+ * c-parser.c (c_parser_while_statement): Finish the loop before
+ parsing ahead for misleading indentation.
+ (c_parser_for_statement): Likewise.
+
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* c-decl.c (finish_struct): If the structure has reverse storage
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 4109d6d44b3..15cbde5e72d 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1162,7 +1162,8 @@ enum c_parser_prec {
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
- bool, bool, tree *, vec<c_token>);
+ bool, bool, tree *, vec<c_token>,
+ tree = NULL_TREE);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
@@ -1251,6 +1252,7 @@ static bool c_parser_omp_target (c_parser *, enum pragma_context);
static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context);
+static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
/* These Objective-C parser functions are only ever called when
compiling Objective-C. */
@@ -1436,6 +1438,7 @@ c_parser_external_declaration (c_parser *parser)
}
static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
6.7, 6.9.1). If FNDEF_OK is true, a function definition is
@@ -1513,7 +1516,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok,
tree *objc_foreach_object_declaration,
- vec<c_token> omp_declare_simd_clauses)
+ vec<c_token> omp_declare_simd_clauses,
+ tree oacc_routine_clauses)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -1583,6 +1587,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
pedwarn (here, 0, "empty declaration");
}
c_parser_consume_token (parser);
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, NULL_TREE,
+ oacc_routine_clauses, false, true, false);
return;
}
@@ -1680,7 +1687,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
prefix_attrs = specs->attrs;
all_prefix_attrs = prefix_attrs;
specs->attrs = NULL_TREE;
- while (true)
+ for (bool first = true;; first = false)
{
struct c_declarator *declarator;
bool dummy = false;
@@ -1699,6 +1706,10 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, NULL_TREE,
+ oacc_routine_clauses,
+ false, first, false);
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
@@ -1813,6 +1824,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
init = c_parser_initializer (parser);
finish_init ();
}
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+ false, first, false);
if (d != error_mark_node)
{
maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
@@ -1856,6 +1870,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
if (parms)
temp_pop_parm_decls ();
}
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+ false, first, false);
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
@@ -1966,6 +1983,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, current_function_decl,
+ oacc_routine_clauses, false, first, true);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
fnbody = c_parser_compound_statement (parser);
@@ -5437,13 +5457,13 @@ c_parser_while_statement (c_parser *parser, bool ivdep)
= get_token_indent_info (c_parser_peek_token (parser));
body = c_parser_c99_block_statement (parser);
+ c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
- c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
- add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
}
@@ -5727,15 +5747,16 @@ c_parser_for_statement (c_parser *parser, bool ivdep)
body = c_parser_c99_block_statement (parser);
- token_indent_info next_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
-
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
else
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
+
+ token_indent_info next_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+ warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
+
c_break_label = save_break;
c_cont_label = save_cont;
}
@@ -9705,6 +9726,10 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_oacc_enter_exit_data (parser, false);
return false;
+ case PRAGMA_OACC_ROUTINE:
+ c_parser_oacc_routine (parser, context);
+ return false;
+
case PRAGMA_OACC_UPDATE:
if (context != pragma_compound)
{
@@ -13399,6 +13424,117 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
}
/* OpenACC 2.0:
+ # pragma acc routine oacc-routine-clause[optseq] new-line
+ function-definition
+
+ # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
+*/
+
+#define OACC_ROUTINE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) )
+
+/* Parse an OpenACC routine directive. For named directives, we apply
+ immediately to the named function. For unnamed ones we then parse
+ a declaration or definition, which must be for a function. */
+
+static void
+c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
+{
+ tree decl = NULL_TREE;
+ /* Create a dummy claue, to record location. */
+ tree c_head = build_omp_clause (c_parser_peek_token (parser)->location,
+ OMP_CLAUSE_SEQ);
+
+ if (context != pragma_external)
+ c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
+
+ c_parser_consume_pragma (parser);
+
+ /* Scan for optional '( name )'. */
+ if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ c_parser_consume_token (parser);
+
+ c_token *token = c_parser_peek_token (parser);
+
+ if (token->type == CPP_NAME && (token->id_kind == C_ID_ID
+ || token->id_kind == C_ID_TYPENAME))
+ {
+ decl = lookup_name (token->value);
+ if (!decl)
+ {
+ error_at (token->location, "%qE has not been declared",
+ token->value);
+ decl = error_mark_node;
+ }
+ }
+ else
+ c_parser_error (parser, "expected function name");
+
+ if (token->type != CPP_CLOSE_PAREN)
+ c_parser_consume_token (parser);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+ }
+
+ /* Build a chain of clauses. */
+ parser->in_pragma = true;
+ tree clauses = c_parser_oacc_all_clauses
+ (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine");
+
+ /* Force clauses to be non-null, by attaching context to it. */
+ clauses = tree_cons (c_head, clauses, NULL_TREE);
+
+ if (decl)
+ c_finish_oacc_routine (parser, decl, clauses, true, true, false);
+ else if (c_parser_peek_token (parser)->type == CPP_PRAGMA)
+ /* This will emit an error. */
+ c_finish_oacc_routine (parser, NULL_TREE, clauses, false, true, false);
+ else
+ c_parser_declaration_or_fndef (parser, true, false, false, false,
+ true, NULL, vNULL, clauses);
+}
+
+/* Finalize an OpenACC routine pragma, applying it to FNDECL. CLAUSES
+ are the parsed clauses. IS_DEFN is true if we're applying it to
+ the definition (so expect FNDEF to look somewhat defined. */
+
+static void
+c_finish_oacc_routine (c_parser *ARG_UNUSED (parser), tree fndecl,
+ tree clauses, bool named, bool first, bool is_defn)
+{
+ location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
+
+ if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first)
+ {
+ if (fndecl != error_mark_node)
+ error_at (loc, "%<#pragma acc routine%> %s",
+ named ? "does not refer to a function"
+ : "not followed by single function");
+ return;
+ }
+
+ if (get_oacc_fn_attrib (fndecl))
+ error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+
+ if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ error_at (loc, "%<#pragma acc routine%> must be applied before %s",
+ TREE_USED (fndecl) ? "use" : "definition");
+
+ /* Process for function attrib */
+ tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
+ replace_oacc_fn_attrib (fndecl, dims);
+
+ /* Also attach as a declare. */
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("omp declare target"),
+ clauses, DECL_ATTRIBUTES (fndecl));
+}
+
+/* OpenACC 2.0:
# pragma acc update oacc-update-clause[optseq] new-line
*/
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 2080db95ebc..9ee26814245 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9898,6 +9898,16 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
exit = fold_build3_loc (input_location,
COND_EXPR, void_type_node, cond, exit, t);
}
+ else
+ {
+ /* For the backward-goto's location of an unconditional loop
+ use the beginning of the body, or, if there is none, the
+ top of the loop. */
+ location_t loc = EXPR_LOCATION (expr_first (body));
+ if (loc == UNKNOWN_LOCATION)
+ loc = start_locus;
+ SET_EXPR_LOCATION (exit, loc);
+ }
add_stmt (top);
}
diff --git a/gcc/common.opt b/gcc/common.opt
index 961a1b63c47..757ce858735 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1972,7 +1972,7 @@ Common Report Var(flag_schedule_speculative_load_dangerous) Optimization
Allow speculative motion of more loads.
fsched-verbose=
-Common RejectNegative Joined UInteger Var(sched_verbose_param)
+Common RejectNegative Joined UInteger Var(sched_verbose_param) Init(1)
-fsched-verbose=<number> Set the verbosity level of the scheduler.
fsched2-use-superblocks
diff --git a/gcc/config.in b/gcc/config.in
index 6f46f7039bd..bb0d22053e9 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -556,6 +556,12 @@
#endif
+/* Define if your assembler supports POWER9 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_POWER9
+#endif
+
+
/* Define if your assembler supports .ref */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_REF
@@ -598,12 +604,6 @@
#endif
-/* Define to 1 if your assembler supports #nobits, 0 otherwise. */
-#ifndef USED_FOR_TARGET
-#undef HAVE_AS_SPARC_NOBITS
-#endif
-
-
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
#ifndef USED_FOR_TARGET
@@ -1329,7 +1329,8 @@
#endif
-/* Define .init_array/.fini_array sections are available and working. */
+/* Define 0/1 if .init_array/.fini_array sections are available and working.
+ */
#ifndef USED_FOR_TARGET
#undef HAVE_INITFINI_ARRAY_SUPPORT
#endif
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 0f20f604481..7c74f585fb8 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -345,8 +345,6 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
const_tree, unsigned);
void aarch64_init_expanders (void);
void aarch64_init_simd_builtins (void);
-void aarch64_print_operand (FILE *, rtx, char);
-void aarch64_print_operand_address (FILE *, rtx);
void aarch64_emit_call_insn (rtx);
void aarch64_register_pragmas (void);
void aarch64_relayout_simd_types (void);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 1b7be838c73..7d6dfc342b8 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -558,10 +558,6 @@ static const struct aarch64_option_extension all_extensions[] =
{NULL, 0, 0}
};
-/* Used to track the size of an address when generating a pre/post
- increment address. */
-static machine_mode aarch64_memory_reference_mode;
-
typedef enum aarch64_cond_code
{
AARCH64_EQ = 0, AARCH64_NE, AARCH64_CS, AARCH64_CC, AARCH64_MI, AARCH64_PL,
@@ -4133,8 +4129,8 @@ aarch64_ccmp_mode_to_code (enum machine_mode mode)
}
-void
-aarch64_print_operand (FILE *f, rtx x, char code)
+static void
+aarch64_print_operand (FILE *f, rtx x, int code)
{
switch (code)
{
@@ -4364,8 +4360,7 @@ aarch64_print_operand (FILE *f, rtx x, char code)
break;
case MEM:
- aarch64_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
case CONST:
@@ -4396,11 +4391,10 @@ aarch64_print_operand (FILE *f, rtx x, char code)
break;
case CONST_DOUBLE:
- /* CONST_DOUBLE can represent a double-width integer.
- In this case, the mode of x is VOIDmode. */
- if (GET_MODE (x) == VOIDmode)
- ; /* Do Nothing. */
- else if (aarch64_float_const_zero_rtx_p (x))
+ /* Since we define TARGET_SUPPORTS_WIDE_INT we shouldn't ever
+ be getting CONST_DOUBLEs holding integers. */
+ gcc_assert (GET_MODE (x) != VOIDmode);
+ if (aarch64_float_const_zero_rtx_p (x))
{
fputc ('0', f);
break;
@@ -4555,13 +4549,12 @@ aarch64_print_operand (FILE *f, rtx x, char code)
}
}
-void
-aarch64_print_operand_address (FILE *f, rtx x)
+static void
+aarch64_print_operand_address (FILE *f, machine_mode mode, rtx x)
{
struct aarch64_address_info addr;
- if (aarch64_classify_address (&addr, x, aarch64_memory_reference_mode,
- MEM, true))
+ if (aarch64_classify_address (&addr, x, mode, MEM, true))
switch (addr.type)
{
case ADDRESS_REG_IMM:
@@ -4604,19 +4597,19 @@ aarch64_print_operand_address (FILE *f, rtx x)
{
case PRE_INC:
asm_fprintf (f, "[%s, %d]!", reg_names [REGNO (addr.base)],
- GET_MODE_SIZE (aarch64_memory_reference_mode));
+ GET_MODE_SIZE (mode));
return;
case POST_INC:
asm_fprintf (f, "[%s], %d", reg_names [REGNO (addr.base)],
- GET_MODE_SIZE (aarch64_memory_reference_mode));
+ GET_MODE_SIZE (mode));
return;
case PRE_DEC:
asm_fprintf (f, "[%s, -%d]!", reg_names [REGNO (addr.base)],
- GET_MODE_SIZE (aarch64_memory_reference_mode));
+ GET_MODE_SIZE (mode));
return;
case POST_DEC:
asm_fprintf (f, "[%s], -%d", reg_names [REGNO (addr.base)],
- GET_MODE_SIZE (aarch64_memory_reference_mode));
+ GET_MODE_SIZE (mode));
return;
case PRE_MODIFY:
asm_fprintf (f, "[%s, %wd]!", reg_names [REGNO (addr.base)],
@@ -5251,9 +5244,11 @@ aarch64_can_use_per_function_literal_pools_p (void)
static bool
aarch64_use_blocks_for_constant_p (machine_mode, const_rtx)
{
- /* We can't use blocks for constants when we're using a per-function
- constant pool. */
- return !aarch64_can_use_per_function_literal_pools_p ();
+ /* Fixme:: In an ideal world this would work similar
+ to the logic in aarch64_select_rtx_section but this
+ breaks bootstrap in gcc go. For now we workaround
+ this by returning false here. */
+ return false;
}
/* Select appropriate section for constants depending
@@ -10165,32 +10160,16 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
it must be laid out in the vector register in reverse order. */
rtx el = CONST_VECTOR_ELT (op, BYTES_BIG_ENDIAN ? (n_elts - 1 - i) : i);
unsigned HOST_WIDE_INT elpart;
- unsigned int part, parts;
- if (CONST_INT_P (el))
- {
- elpart = INTVAL (el);
- parts = 1;
- }
- else if (GET_CODE (el) == CONST_DOUBLE)
- {
- elpart = CONST_DOUBLE_LOW (el);
- parts = 2;
- }
- else
- gcc_unreachable ();
+ gcc_assert (CONST_INT_P (el));
+ elpart = INTVAL (el);
+
+ for (unsigned int byte = 0; byte < innersize; byte++)
+ {
+ bytes[idx++] = (elpart & 0xff) ^ invmask;
+ elpart >>= BITS_PER_UNIT;
+ }
- for (part = 0; part < parts; part++)
- {
- unsigned int byte;
- for (byte = 0; byte < innersize; byte++)
- {
- bytes[idx++] = (elpart & 0xff) ^ invmask;
- elpart >>= BITS_PER_UNIT;
- }
- if (GET_CODE (el) == CONST_DOUBLE)
- elpart = CONST_DOUBLE_HIGH (el);
- }
}
/* Sanity check. */
@@ -13811,6 +13790,12 @@ aarch64_promoted_type (const_tree t)
#undef TARGET_USE_PSEUDO_PIC_REG
#define TARGET_USE_PSEUDO_PIC_REG aarch64_use_pseudo_pic_reg
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND aarch64_print_operand
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS aarch64_print_operand_address
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index b041a1e38d0..8834c9b4dd0 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -792,11 +792,6 @@ do { \
/* Jump table alignment is explicit in ASM_OUTPUT_CASE_LABEL. */
#define ADDR_VEC_ALIGN(JUMPTABLE) 0
-#define PRINT_OPERAND(STREAM, X, CODE) aarch64_print_operand (STREAM, X, CODE)
-
-#define PRINT_OPERAND_ADDRESS(STREAM, X) \
- aarch64_print_operand_address (STREAM, X)
-
#define MCOUNT_NAME "_mcount"
#define NO_PROFILE_COUNTERS 1
@@ -863,6 +858,8 @@ extern enum aarch64_code_model aarch64_cmodel;
(aarch64_cmodel == AARCH64_CMODEL_TINY \
|| aarch64_cmodel == AARCH64_CMODEL_TINY_PIC)
+#define TARGET_SUPPORTS_WIDE_INT 1
+
/* Modes valid for AdvSIMD D registers, i.e. that fit in half a Q register. */
#define AARCH64_VALID_SIMD_DREG_MODE(MODE) \
((MODE) == V2SImode || (MODE) == V4HImode || (MODE) == V8QImode \
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 641314a649c..731c8f29464 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3102,6 +3102,24 @@
}
)
+(define_expand "<neg_not_op><mode>cc"
+ [(set (match_operand:GPI 0 "register_operand" "")
+ (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
+ (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
+ (match_operand:GPI 3 "register_operand" "")))]
+ ""
+ {
+ rtx ccreg;
+ enum rtx_code code = GET_CODE (operands[1]);
+
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
+ ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
+ }
+)
;; CRC32 instructions.
(define_insn "aarch64_<crc_variant>"
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 6f35036b013..c4a1c9888ea 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -693,6 +693,9 @@
;; Code iterator for logical operations whose :nlogical works on SIMD registers.
(define_code_iterator NLOGICAL [and ior])
+;; Code iterator for unary negate and bitwise complement.
+(define_code_iterator NEG_NOT [neg not])
+
;; Code iterator for sign/zero extension
(define_code_iterator ANY_EXTEND [sign_extend zero_extend])
@@ -822,6 +825,9 @@
;; Logical operator instruction mnemonics
(define_code_attr logical [(and "and") (ior "orr") (xor "eor")])
+;; Operation names for negate and bitwise complement.
+(define_code_attr neg_not_op [(neg "neg") (not "not")])
+
;; Similar, but when not(op)
(define_code_attr nlogical [(and "bic") (ior "orn") (xor "eon")])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 046f852b1d3..e7f76e04854 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -32,7 +32,7 @@
;; Return true if OP a (const_int 0) operand.
(define_predicate "const0_operand"
- (and (match_code "const_int, const_double")
+ (and (match_code "const_int")
(match_test "op == CONST0_RTX (mode)")))
(define_predicate "aarch64_ccmp_immediate"
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 11da372fce7..f2ad9d07cb3 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -5327,7 +5327,7 @@ print_operand (FILE *file, rtx x, int code)
if (REG_P (x))
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (MEM_P (x))
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
{
switch (XINT (XEXP (x, 0), 1))
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 47341d54f90..01261bc702a 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -2929,19 +2929,22 @@ arc_print_operand (FILE *file, rtx x, int code)
|| GET_CODE (XEXP (x, 0)) == POST_INC
|| GET_CODE (XEXP (x, 0)) == POST_DEC
|| GET_CODE (XEXP (x, 0)) == POST_MODIFY)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
else if (output_scaled)
{
rtx addr = XEXP (x, 0);
int size = GET_MODE_SIZE (GET_MODE (x));
- output_address (plus_constant (Pmode, XEXP (addr, 0),
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (addr, 0),
((INTVAL (XEXP (addr, 1)) + 4)
>> (size == 2 ? 1 : 2))));
output_scaled = 0;
}
else
- output_address (plus_constant (Pmode, XEXP (x, 0), 4));
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (x, 0), 4));
fputc (']', file);
}
else
@@ -3132,28 +3135,31 @@ arc_print_operand (FILE *file, rtx x, int code)
switch (GET_CODE (addr))
{
case PRE_INC: case POST_INC:
- output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (addr, 0), size)); break;
case PRE_DEC: case POST_DEC:
- output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (addr, 0), -size));
break;
case PRE_MODIFY: case POST_MODIFY:
- output_address (XEXP (addr, 1)); break;
+ output_address (VOIDmode, XEXP (addr, 1)); break;
case PLUS:
if (output_scaled)
{
- output_address (plus_constant (Pmode, XEXP (addr, 0),
+ output_address (VOIDmode,
+ plus_constant (Pmode, XEXP (addr, 0),
(INTVAL (XEXP (addr, 1))
>> (size == 2 ? 1 : 2))));
output_scaled = 0;
}
else
- output_address (addr);
+ output_address (VOIDmode, addr);
break;
default:
if (flag_pic && CONSTANT_ADDRESS_P (addr))
arc_output_pic_addr_const (file, addr, code);
else
- output_address (addr);
+ output_address (VOIDmode, addr);
break;
}
fputc (']', file);
@@ -3239,7 +3245,7 @@ arc_print_operand_address (FILE *file , rtx addr)
gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
- output_address(XEXP(addr,0));
+ output_address (VOIDmode, XEXP (addr, 0));
break;
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 61e2aa23006..f4ebbc80f16 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -100,7 +100,7 @@ static bool thumb_force_lr_save (void);
static unsigned arm_size_return_regs (void);
static bool arm_assemble_integer (rtx, unsigned int, int);
static void arm_print_operand (FILE *, rtx, int);
-static void arm_print_operand_address (FILE *, rtx);
+static void arm_print_operand_address (FILE *, machine_mode, rtx);
static bool arm_print_operand_punct_valid_p (unsigned char code);
static const char *fp_const_from_val (REAL_VALUE_TYPE *);
static arm_cc get_arm_condition_code (rtx);
@@ -869,11 +869,6 @@ int prefer_neon_for_64bits = 0;
/* Nonzero if we shouldn't use literal pools. */
bool arm_disable_literal_pool = false;
-/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference,
- we must report the mode of the memory reference from
- TARGET_PRINT_OPERAND to TARGET_PRINT_OPERAND_ADDRESS. */
-machine_mode output_memory_reference_mode;
-
/* The register number to be used for the PIC offset register. */
unsigned arm_pic_register = INVALID_REGNUM;
@@ -22403,8 +22398,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
break;
case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
case CONST_DOUBLE:
@@ -22433,7 +22427,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
/* Target hook for printing a memory address. */
static void
-arm_print_operand_address (FILE *stream, rtx x)
+arm_print_operand_address (FILE *stream, machine_mode mode, rtx x)
{
if (TARGET_32BIT)
{
@@ -22491,20 +22485,18 @@ arm_print_operand_address (FILE *stream, rtx x)
else if (GET_CODE (x) == PRE_INC || GET_CODE (x) == POST_INC
|| GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_DEC)
{
- extern machine_mode output_memory_reference_mode;
-
gcc_assert (REG_P (XEXP (x, 0)));
if (GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC)
asm_fprintf (stream, "[%r, #%s%d]!",
REGNO (XEXP (x, 0)),
GET_CODE (x) == PRE_DEC ? "-" : "",
- GET_MODE_SIZE (output_memory_reference_mode));
+ GET_MODE_SIZE (mode));
else
asm_fprintf (stream, "[%r], #%s%d",
REGNO (XEXP (x, 0)),
GET_CODE (x) == POST_DEC ? "-" : "",
- GET_MODE_SIZE (output_memory_reference_mode));
+ GET_MODE_SIZE (mode));
}
else if (GET_CODE (x) == PRE_MODIFY)
{
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index f1c80eec298..609a42b00e4 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -2158,7 +2158,7 @@ cond_string (enum rtx_code code)
/* Output ADDR to FILE as address. */
static void
-avr_print_operand_address (FILE *file, rtx addr)
+avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
{
switch (GET_CODE (addr))
{
@@ -2358,7 +2358,7 @@ avr_print_operand (FILE *file, rtx x, int code)
if (GET_CODE (addr) != PLUS)
fatal_insn ("bad address, not (reg+disp):", addr);
- avr_print_operand_address (file, XEXP (addr, 0));
+ avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
}
else if (code == 'p' || code == 'r')
{
@@ -2366,13 +2366,14 @@ avr_print_operand (FILE *file, rtx x, int code)
fatal_insn ("bad address, not post_inc or pre_dec:", addr);
if (code == 'p')
- avr_print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
+ /* X, Y, Z */
+ avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
else
avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
}
else if (GET_CODE (addr) == PLUS)
{
- avr_print_operand_address (file, XEXP (addr,0));
+ avr_print_operand_address (file, VOIDmode, XEXP (addr,0));
if (REGNO (XEXP (addr, 0)) == REG_X)
fatal_insn ("internal compiler error. Bad address:"
,addr);
@@ -2380,13 +2381,13 @@ avr_print_operand (FILE *file, rtx x, int code)
avr_print_operand (file, XEXP (addr,1), code);
}
else
- avr_print_operand_address (file, addr);
+ avr_print_operand_address (file, VOIDmode, addr);
}
else if (code == 'i')
{
if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
avr_print_operand_address
- (file, plus_constant (HImode, x, -avr_arch->sfr_offset));
+ (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
else
fatal_insn ("bad address, not an I/O address:", x);
}
@@ -2426,7 +2427,7 @@ avr_print_operand (FILE *file, rtx x, int code)
else if (code == 'k')
fputs (cond_string (reverse_condition (GET_CODE (x))), file);
else
- avr_print_operand_address (file, x);
+ avr_print_operand_address (file, VOIDmode, x);
}
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 6a5f90a7f1e..d359fd4341b 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -1300,21 +1300,21 @@ print_address_operand (FILE *file, rtx x)
switch (GET_CODE (x))
{
case PLUS:
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
fprintf (file, "+");
- output_address (XEXP (x, 1));
+ output_address (VOIDmode, XEXP (x, 1));
break;
case PRE_DEC:
fprintf (file, "--");
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
break;
case POST_INC:
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
fprintf (file, "++");
break;
case POST_DEC:
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
fprintf (file, "--");
break;
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 41816ac8da3..f0d274e765c 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -1854,7 +1854,7 @@ print_address_offset (FILE *file, rtx off, machine_mode mem_mode)
}
}
fputs ("(", file);
- output_address (off);
+ output_address (mem_mode, off);
fputs (")", file);
}
@@ -1877,7 +1877,7 @@ c6x_print_address_operand (FILE *file, rtx x, machine_mode mem_mode)
case PRE_MODIFY:
case POST_MODIFY:
if (GET_CODE (x) == POST_MODIFY)
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
off = XEXP (XEXP (x, 1), 1);
if (XEXP (x, 0) == stack_pointer_rtx)
{
@@ -1894,7 +1894,7 @@ c6x_print_address_operand (FILE *file, rtx x, machine_mode mem_mode)
else
fprintf (file, "++");
if (GET_CODE (x) == PRE_MODIFY)
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
print_address_offset (file, off, mem_mode);
break;
@@ -1907,28 +1907,28 @@ c6x_print_address_operand (FILE *file, rtx x, machine_mode mem_mode)
}
else
fprintf (file, "+");
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
print_address_offset (file, off, mem_mode);
break;
case PRE_DEC:
gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
fprintf (file, "--");
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
fprintf (file, "[1]");
break;
case PRE_INC:
fprintf (file, "++");
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
fprintf (file, "[1]");
break;
case POST_INC:
gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
fprintf (file, "++[1]");
break;
case POST_DEC:
- output_address (XEXP (x, 0));
+ output_address (mem_mode, XEXP (x, 0));
fprintf (file, "--[1]");
break;
@@ -2042,9 +2042,9 @@ c6x_print_unit_specifier_field (FILE *file, rtx_insn *insn)
/* Output assembly language output for the address ADDR to FILE. */
static void
-c6x_print_operand_address (FILE *file, rtx addr)
+c6x_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
- c6x_print_address_operand (file, addr, VOIDmode);
+ c6x_print_address_operand (file, addr, mode);
}
/* Print an operand, X, to FILE, with an optional modifier in CODE.
diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c
index d77e07dc4bd..8fe836940bd 100644
--- a/gcc/config/cr16/cr16.c
+++ b/gcc/config/cr16/cr16.c
@@ -122,7 +122,7 @@ static enum data_model_type data_model = DM_DEFAULT;
/* TARGETM Function Prototypes and forward declarations */
static void cr16_print_operand (FILE *, rtx, int);
-static void cr16_print_operand_address (FILE *, rtx);
+static void cr16_print_operand_address (FILE *, machine_mode, rtx);
/* Stack layout and calling conventions. */
#undef TARGET_STRUCT_VALUE_RTX
@@ -1494,7 +1494,7 @@ cr16_print_operand (FILE * file, rtx x, int code)
return;
case MEM:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case CONST_DOUBLE:
@@ -1524,7 +1524,7 @@ cr16_print_operand (FILE * file, rtx x, int code)
{
putc ('$', file);
}
- cr16_print_operand_address (file, x);
+ cr16_print_operand_address (file, VOIDmode, x);
return;
}
default:
@@ -1537,7 +1537,7 @@ cr16_print_operand (FILE * file, rtx x, int code)
/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
static void
-cr16_print_operand_address (FILE * file, rtx addr)
+cr16_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
{
enum cr16_addrtype addrtype;
struct cr16_address address;
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 9d62721df2c..6e40ea14877 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -114,7 +114,7 @@ static int cris_reg_saved_in_regsave_area (unsigned int, bool);
static void cris_print_operand (FILE *, rtx, int);
-static void cris_print_operand_address (FILE *, rtx);
+static void cris_print_operand_address (FILE *, machine_mode, rtx);
static bool cris_print_operand_punct_valid_p (unsigned char code);
@@ -803,7 +803,7 @@ cris_print_operand (FILE *file, rtx x, int code)
return;
}
}
- output_address (addr);
+ output_address (VOIDmode, addr);
}
return;
@@ -942,7 +942,7 @@ cris_print_operand (FILE *file, rtx x, int code)
adj_mem
= adjust_address (adj_mem, GET_MODE (adj_mem), size / 2);
- output_address (XEXP (adj_mem, 0));
+ output_address (VOIDmode, XEXP (adj_mem, 0));
return;
}
@@ -1129,7 +1129,7 @@ cris_print_operand (FILE *file, rtx x, int code)
return;
case MEM:
- output_address (XEXP (operand, 0));
+ output_address (GET_MODE (operand), XEXP (operand, 0));
return;
case CONST_DOUBLE:
@@ -1200,7 +1200,7 @@ cris_print_operand_punct_valid_p (unsigned char code)
/* The PRINT_OPERAND_ADDRESS worker. */
static void
-cris_print_operand_address (FILE *file, rtx x)
+cris_print_operand_address (FILE *file, machine_mode /*mode*/, rtx x)
{
/* All these were inside MEM:s so output indirection characters. */
putc ('[', file);
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index c0578037329..1313fb44cbd 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -1317,7 +1317,7 @@ epiphany_print_operand (FILE *file, rtx x, int code)
offset = 0;
break;
}
- output_address (addr);
+ output_address (GET_MODE (x), addr);
fputc (']', file);
if (offset)
{
@@ -1338,7 +1338,7 @@ epiphany_print_operand (FILE *file, rtx x, int code)
case 1:
break;
}
- output_address (offset);
+ output_address (GET_MODE (x), offset);
}
break;
case CONST_DOUBLE :
@@ -1370,7 +1370,7 @@ epiphany_print_operand (FILE *file, rtx x, int code)
/* Print a memory address as an operand to reference that memory location. */
static void
-epiphany_print_operand_address (FILE *file, rtx addr)
+epiphany_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
{
register rtx base, index = 0;
int offset = 0;
@@ -1424,7 +1424,9 @@ epiphany_print_operand_address (FILE *file, rtx addr)
break;
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: case POST_MODIFY:
/* We shouldn't get here as we've lost the mode of the memory object
- (which says how much to inc/dec by. */
+ (which says how much to inc/dec by.
+ FIXME: We have the mode now, address printing can be moved into this
+ function. */
gcc_unreachable ();
break;
default:
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index b6b02494a92..c52a4e0c3c3 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -662,7 +662,7 @@ fr30_print_operand (FILE *file, rtx x, int code)
break;
case SYMBOL_REF:
- output_address (x0);
+ output_address (VOIDmode, x0);
break;
default:
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 3a3494316d6..275b597b2e8 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -262,7 +262,7 @@ static int frv_default_flags_for_cpu (void);
static int frv_string_begins_with (const char *, const char *);
static FRV_INLINE bool frv_small_data_reloc_p (rtx, int);
static void frv_print_operand (FILE *, rtx, int);
-static void frv_print_operand_address (FILE *, rtx);
+static void frv_print_operand_address (FILE *, machine_mode, rtx);
static bool frv_print_operand_punct_valid_p (unsigned char code);
static void frv_print_operand_memory_reference_reg
(FILE *, rtx);
@@ -2470,7 +2470,7 @@ frv_index_memory (rtx memref, machine_mode mode, int index)
/* Print a memory address as an operand to reference that memory location. */
static void
-frv_print_operand_address (FILE * stream, rtx x)
+frv_print_operand_address (FILE * stream, machine_mode /* mode */, rtx x)
{
if (GET_CODE (x) == MEM)
x = XEXP (x, 0);
@@ -3003,10 +3003,10 @@ frv_print_operand (FILE * file, rtx x, int code)
frv_output_const_unspec (file, &unspec);
else if (GET_CODE (x) == MEM)
- frv_print_operand_address (file, XEXP (x, 0));
+ frv_print_operand_address (file, GET_MODE (x), XEXP (x, 0));
else if (CONSTANT_ADDRESS_P (x))
- frv_print_operand_address (file, x);
+ frv_print_operand_address (file, VOIDmode, x);
else
fatal_insn ("bad insn in frv_print_operand, 0 case", x);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 4eb2ed8b527..d5a726e32f3 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -95,7 +95,7 @@ static unsigned int h8300_asm_insn_count (const char *);
static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree h8300_handle_eightbit_data_attribute (tree *, tree, tree, int, bool *);
static tree h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *);
-static void h8300_print_operand_address (FILE *, rtx);
+static void h8300_print_operand_address (FILE *, machine_mode, rtx);
static void h8300_print_operand (FILE *, rtx, int);
static bool h8300_print_operand_punct_valid_p (unsigned char code);
#ifndef OBJECT_FORMAT_ELF
@@ -1647,7 +1647,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
}
break;
case 'o':
- h8300_print_operand_address (file, x);
+ h8300_print_operand_address (file, VOIDmode, x);
break;
case 's':
if (GET_CODE (x) == CONST_INT)
@@ -1719,7 +1719,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
rtx addr = XEXP (x, 0);
fprintf (file, "@");
- output_address (addr);
+ output_address (GET_MODE (x), addr);
/* Add a length suffix to constant addresses. Although this
is often unnecessary, it helps to avoid ambiguity in the
@@ -1764,7 +1764,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
case CONST:
case LABEL_REF:
fprintf (file, "#");
- h8300_print_operand_address (file, x);
+ h8300_print_operand_address (file, VOIDmode, x);
break;
case CONST_DOUBLE:
{
@@ -1790,7 +1790,7 @@ h8300_print_operand_punct_valid_p (unsigned char code)
/* Output assembly language output for the address ADDR to FILE. */
static void
-h8300_print_operand_address (FILE *file, rtx addr)
+h8300_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
rtx index;
int size;
@@ -1824,12 +1824,12 @@ h8300_print_operand_address (FILE *file, rtx addr)
if (GET_CODE (index) == REG)
{
/* reg,foo */
- h8300_print_operand_address (file, XEXP (addr, 1));
+ h8300_print_operand_address (file, mode, XEXP (addr, 1));
fprintf (file, ",");
switch (size)
{
case 0:
- h8300_print_operand_address (file, index);
+ h8300_print_operand_address (file, mode, index);
break;
case 1:
@@ -1852,9 +1852,9 @@ h8300_print_operand_address (FILE *file, rtx addr)
else
{
/* foo+k */
- h8300_print_operand_address (file, XEXP (addr, 0));
+ h8300_print_operand_address (file, mode, XEXP (addr, 0));
fprintf (file, "+");
- h8300_print_operand_address (file, XEXP (addr, 1));
+ h8300_print_operand_address (file, mode, XEXP (addr, 1));
}
fprintf (file, ")");
break;
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 026b778f4e3..9e20714099d 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -129,6 +129,9 @@ extern bool ix86_expand_fp_vcond (rtx[]);
extern bool ix86_expand_int_vcond (rtx[]);
extern void ix86_expand_vec_perm (rtx[]);
extern bool ix86_expand_vec_perm_const (rtx[]);
+extern bool ix86_expand_mask_vec_cmp (rtx[]);
+extern bool ix86_expand_int_vec_cmp (rtx[]);
+extern bool ix86_expand_fp_vec_cmp (rtx[]);
extern void ix86_expand_sse_unpack (rtx, rtx, bool, bool);
extern bool ix86_expand_int_addcc (rtx[]);
extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0d84cde9cbe..f6c17dfd405 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -16612,7 +16612,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
if (TARGET_64BIT)
x = gen_rtx_UNSPEC (DImode, gen_rtvec (1, x), UNSPEC_LEA_ADDR);
- output_address (x);
+ output_address (VOIDmode, x);
return;
case 'L':
@@ -17503,7 +17503,7 @@ ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t as)
}
static void
-ix86_print_operand_address (FILE *file, rtx addr)
+ix86_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
{
ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC);
}
@@ -22582,8 +22582,8 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
if (optimize
- || reg_overlap_mentioned_p (dest, op_true)
- || reg_overlap_mentioned_p (dest, op_false))
+ || (op_true && reg_overlap_mentioned_p (dest, op_true))
+ || (op_false && reg_overlap_mentioned_p (dest, op_false)))
dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
/* Compare patterns for int modes are unspec in AVX512F only. */
@@ -22644,6 +22644,14 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
rtx t2, t3, x;
+ /* If we have an integer mask and FP value then we need
+ to cast mask to FP mode. */
+ if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
+ {
+ cmp = force_reg (cmpmode, cmp);
+ cmp = gen_rtx_SUBREG (mode, cmp, 0);
+ }
+
if (vector_all_ones_operand (op_true, mode)
&& rtx_equal_p (op_false, CONST0_RTX (mode))
&& !maskcmp)
@@ -22855,34 +22863,127 @@ ix86_expand_fp_movcc (rtx operands[])
return true;
}
-/* Expand a floating-point vector conditional move; a vcond operation
- rather than a movcc operation. */
+/* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
+
+static int
+ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return 0;
+ case LT:
+ case LTU:
+ return 1;
+ case LE:
+ case LEU:
+ return 2;
+ case NE:
+ return 4;
+ case GE:
+ case GEU:
+ return 5;
+ case GT:
+ case GTU:
+ return 6;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */
+
+static int
+ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return 0x08;
+ case NE:
+ return 0x04;
+ case GT:
+ return 0x16;
+ case LE:
+ return 0x1a;
+ case GE:
+ return 0x15;
+ case LT:
+ return 0x19;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return immediate value to be used in UNSPEC_PCMP
+ for comparison CODE in MODE. */
+
+static int
+ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
+{
+ if (FLOAT_MODE_P (mode))
+ return ix86_fp_cmp_code_to_pcmp_immediate (code);
+ return ix86_int_cmp_code_to_pcmp_immediate (code);
+}
+
+/* Expand AVX-512 vector comparison. */
bool
-ix86_expand_fp_vcond (rtx operands[])
+ix86_expand_mask_vec_cmp (rtx operands[])
{
- enum rtx_code code = GET_CODE (operands[3]);
+ machine_mode mask_mode = GET_MODE (operands[0]);
+ machine_mode cmp_mode = GET_MODE (operands[2]);
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
+ int unspec_code;
+ rtx unspec;
+
+ switch (code)
+ {
+ case LEU:
+ case GTU:
+ case GEU:
+ case LTU:
+ unspec_code = UNSPEC_UNSIGNED_PCMP;
+ default:
+ unspec_code = UNSPEC_PCMP;
+ }
+
+ unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, operands[2],
+ operands[3], imm),
+ unspec_code);
+ emit_insn (gen_rtx_SET (operands[0], unspec));
+
+ return true;
+}
+
+/* Expand fp vector comparison. */
+
+bool
+ix86_expand_fp_vec_cmp (rtx operands[])
+{
+ enum rtx_code code = GET_CODE (operands[1]);
rtx cmp;
code = ix86_prepare_sse_fp_compare_args (operands[0], code,
- &operands[4], &operands[5]);
+ &operands[2], &operands[3]);
if (code == UNKNOWN)
{
rtx temp;
- switch (GET_CODE (operands[3]))
+ switch (GET_CODE (operands[1]))
{
case LTGT:
- temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
- operands[5], operands[0], operands[0]);
- cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
- operands[5], operands[1], operands[2]);
+ temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
+ operands[3], NULL, NULL);
+ cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
+ operands[3], NULL, NULL);
code = AND;
break;
case UNEQ:
- temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
- operands[5], operands[0], operands[0]);
- cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
- operands[5], operands[1], operands[2]);
+ temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
+ operands[3], NULL, NULL);
+ cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
+ operands[3], NULL, NULL);
code = IOR;
break;
default:
@@ -22890,72 +22991,26 @@ ix86_expand_fp_vcond (rtx operands[])
}
cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
OPTAB_DIRECT);
- ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
- return true;
}
+ else
+ cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
+ operands[1], operands[2]);
- if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
- operands[5], operands[1], operands[2]))
- return true;
+ if (operands[0] != cmp)
+ emit_move_insn (operands[0], cmp);
- cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
- operands[1], operands[2]);
- ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
return true;
}
-/* Expand a signed/unsigned integral vector conditional move. */
-
-bool
-ix86_expand_int_vcond (rtx operands[])
+static rtx
+ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
+ rtx op_true, rtx op_false, bool *negate)
{
- machine_mode data_mode = GET_MODE (operands[0]);
- machine_mode mode = GET_MODE (operands[4]);
- enum rtx_code code = GET_CODE (operands[3]);
- bool negate = false;
- rtx x, cop0, cop1;
+ machine_mode data_mode = GET_MODE (dest);
+ machine_mode mode = GET_MODE (cop0);
+ rtx x;
- cop0 = operands[4];
- cop1 = operands[5];
-
- /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
- and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
- if ((code == LT || code == GE)
- && data_mode == mode
- && cop1 == CONST0_RTX (mode)
- && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
- && GET_MODE_UNIT_SIZE (data_mode) > 1
- && GET_MODE_UNIT_SIZE (data_mode) <= 8
- && (GET_MODE_SIZE (data_mode) == 16
- || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
- {
- rtx negop = operands[2 - (code == LT)];
- int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
- if (negop == CONST1_RTX (data_mode))
- {
- rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
- operands[0], 1, OPTAB_DIRECT);
- if (res != operands[0])
- emit_move_insn (operands[0], res);
- return true;
- }
- else if (GET_MODE_INNER (data_mode) != DImode
- && vector_all_ones_operand (negop, data_mode))
- {
- rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
- operands[0], 0, OPTAB_DIRECT);
- if (res != operands[0])
- emit_move_insn (operands[0], res);
- return true;
- }
- }
-
- if (!nonimmediate_operand (cop1, mode))
- cop1 = force_reg (mode, cop1);
- if (!general_operand (operands[1], data_mode))
- operands[1] = force_reg (data_mode, operands[1]);
- if (!general_operand (operands[2], data_mode))
- operands[2] = force_reg (data_mode, operands[2]);
+ *negate = false;
/* XOP supports all of the comparisons on all 128-bit vector int types. */
if (TARGET_XOP
@@ -22976,13 +23031,13 @@ ix86_expand_int_vcond (rtx operands[])
case LE:
case LEU:
code = reverse_condition (code);
- negate = true;
+ *negate = true;
break;
case GE:
case GEU:
code = reverse_condition (code);
- negate = true;
+ *negate = true;
/* FALLTHRU */
case LT:
@@ -23003,14 +23058,14 @@ ix86_expand_int_vcond (rtx operands[])
case EQ:
/* SSE4.1 supports EQ. */
if (!TARGET_SSE4_1)
- return false;
+ return NULL;
break;
case GT:
case GTU:
/* SSE4.2 supports GT/GTU. */
if (!TARGET_SSE4_2)
- return false;
+ return NULL;
break;
default:
@@ -23071,12 +23126,13 @@ ix86_expand_int_vcond (rtx operands[])
case V8HImode:
/* Perform a parallel unsigned saturating subtraction. */
x = gen_reg_rtx (mode);
- emit_insn (gen_rtx_SET (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
+ emit_insn (gen_rtx_SET (x, gen_rtx_US_MINUS (mode, cop0,
+ cop1)));
cop0 = x;
cop1 = CONST0_RTX (mode);
code = EQ;
- negate = !negate;
+ *negate = !*negate;
break;
default:
@@ -23085,22 +23141,162 @@ ix86_expand_int_vcond (rtx operands[])
}
}
+ if (*negate)
+ std::swap (op_true, op_false);
+
/* Allow the comparison to be done in one mode, but the movcc to
happen in another mode. */
if (data_mode == mode)
{
- x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
- operands[1+negate], operands[2-negate]);
+ x = ix86_expand_sse_cmp (dest, code, cop0, cop1,
+ op_true, op_false);
}
else
{
gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
- operands[1+negate], operands[2-negate]);
+ op_true, op_false);
if (GET_MODE (x) == mode)
x = gen_lowpart (data_mode, x);
}
+ return x;
+}
+
+/* Expand integer vector comparison. */
+
+bool
+ix86_expand_int_vec_cmp (rtx operands[])
+{
+ rtx_code code = GET_CODE (operands[1]);
+ bool negate = false;
+ rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
+ operands[3], NULL, NULL, &negate);
+
+ if (!cmp)
+ return false;
+
+ if (negate)
+ cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
+ CONST0_RTX (GET_MODE (cmp)),
+ NULL, NULL, &negate);
+
+ gcc_assert (!negate);
+
+ if (operands[0] != cmp)
+ emit_move_insn (operands[0], cmp);
+
+ return true;
+}
+
+/* Expand a floating-point vector conditional move; a vcond operation
+ rather than a movcc operation. */
+
+bool
+ix86_expand_fp_vcond (rtx operands[])
+{
+ enum rtx_code code = GET_CODE (operands[3]);
+ rtx cmp;
+
+ code = ix86_prepare_sse_fp_compare_args (operands[0], code,
+ &operands[4], &operands[5]);
+ if (code == UNKNOWN)
+ {
+ rtx temp;
+ switch (GET_CODE (operands[3]))
+ {
+ case LTGT:
+ temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
+ operands[5], operands[0], operands[0]);
+ cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
+ operands[5], operands[1], operands[2]);
+ code = AND;
+ break;
+ case UNEQ:
+ temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
+ operands[5], operands[0], operands[0]);
+ cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
+ operands[5], operands[1], operands[2]);
+ code = IOR;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
+ OPTAB_DIRECT);
+ ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
+ return true;
+ }
+
+ if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
+ operands[5], operands[1], operands[2]))
+ return true;
+
+ cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
+ operands[1], operands[2]);
+ ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
+ return true;
+}
+
+/* Expand a signed/unsigned integral vector conditional move. */
+
+bool
+ix86_expand_int_vcond (rtx operands[])
+{
+ machine_mode data_mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[4]);
+ enum rtx_code code = GET_CODE (operands[3]);
+ bool negate = false;
+ rtx x, cop0, cop1;
+
+ cop0 = operands[4];
+ cop1 = operands[5];
+
+ /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
+ and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
+ if ((code == LT || code == GE)
+ && data_mode == mode
+ && cop1 == CONST0_RTX (mode)
+ && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
+ && GET_MODE_UNIT_SIZE (data_mode) > 1
+ && GET_MODE_UNIT_SIZE (data_mode) <= 8
+ && (GET_MODE_SIZE (data_mode) == 16
+ || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
+ {
+ rtx negop = operands[2 - (code == LT)];
+ int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
+ if (negop == CONST1_RTX (data_mode))
+ {
+ rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
+ operands[0], 1, OPTAB_DIRECT);
+ if (res != operands[0])
+ emit_move_insn (operands[0], res);
+ return true;
+ }
+ else if (GET_MODE_INNER (data_mode) != DImode
+ && vector_all_ones_operand (negop, data_mode))
+ {
+ rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
+ operands[0], 0, OPTAB_DIRECT);
+ if (res != operands[0])
+ emit_move_insn (operands[0], res);
+ return true;
+ }
+ }
+
+ if (!nonimmediate_operand (cop1, mode))
+ cop1 = force_reg (mode, cop1);
+ if (!general_operand (operands[1], data_mode))
+ operands[1] = force_reg (data_mode, operands[1]);
+ if (!general_operand (operands[2], data_mode))
+ operands[2] = force_reg (data_mode, operands[2]);
+
+ x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
+ operands[1], operands[2], &negate);
+
+ if (!x)
+ return false;
+
ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
operands[2-negate]);
return true;
@@ -53085,6 +53281,28 @@ ix86_autovectorize_vector_sizes (void)
(TARGET_AVX && !TARGET_PREFER_AVX128) ? 32 | 16 : 0;
}
+/* Implemenation of targetm.vectorize.get_mask_mode. */
+
+static machine_mode
+ix86_get_mask_mode (unsigned nunits, unsigned vector_size)
+{
+ unsigned elem_size = vector_size / nunits;
+
+ /* Scalar mask case. */
+ if (TARGET_AVX512F && vector_size == 64)
+ {
+ if (elem_size == 4 || elem_size == 8 || TARGET_AVX512BW)
+ return smallest_mode_for_size (nunits, MODE_INT);
+ }
+
+ machine_mode elem_mode
+ = smallest_mode_for_size (elem_size * BITS_PER_UNIT, MODE_INT);
+
+ gcc_assert (elem_size * nunits == vector_size);
+
+ return mode_for_vector (elem_mode, nunits);
+}
+
/* Return class of registers which could be used for pseudo of MODE
@@ -54096,6 +54314,8 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \
ix86_autovectorize_vector_sizes
+#undef TARGET_VECTORIZE_GET_MASK_MODE
+#define TARGET_VECTORIZE_GET_MASK_MODE ix86_get_mask_mode
#undef TARGET_VECTORIZE_INIT_COST
#define TARGET_VECTORIZE_INIT_COST ix86_init_cost
#undef TARGET_VECTORIZE_ADD_STMT_COST
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2cb94fec34e..52dd03717b4 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -16251,9 +16251,9 @@
(set (match_operand:P 1 "register_operand" "=S")
(plus:P (match_dup 3)
(const_int 1)))]
- "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
- "%^movsb
+ "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
&& ix86_check_no_addr_space (insn)"
+ "%^movsb"
[(set_attr "type" "str")
(set_attr "memory" "both")
(set (attr "prefix_rex")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 43dcc6a17e2..f804255aedf 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -613,6 +613,15 @@
(V16SF "HI") (V8SF "QI") (V4SF "QI")
(V8DF "QI") (V4DF "QI") (V2DF "QI")])
+;; Mapping of vector modes to corresponding mask size
+(define_mode_attr avx512fmaskmodelower
+ [(V64QI "di") (V32QI "si") (V16QI "hi")
+ (V32HI "si") (V16HI "hi") (V8HI "qi") (V4HI "qi")
+ (V16SI "hi") (V8SI "qi") (V4SI "qi")
+ (V8DI "qi") (V4DI "qi") (V2DI "qi")
+ (V16SF "hi") (V8SF "qi") (V4SF "qi")
+ (V8DF "qi") (V4DF "qi") (V2DF "qi")])
+
;; Mapping of vector float modes to an integer mode of the same size
(define_mode_attr sseintvecmode
[(V16SF "V16SI") (V8DF "V8DI")
@@ -2811,6 +2820,150 @@
(const_string "0")))
(set_attr "mode" "<MODE>")])
+(define_expand "vec_cmp<mode><avx512fmaskmodelower>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (match_operator:<avx512fmaskmode> 1 ""
+ [(match_operand:V48_AVX512VL 2 "register_operand")
+ (match_operand:V48_AVX512VL 3 "nonimmediate_operand")]))]
+ "TARGET_AVX512F"
+{
+ bool ok = ix86_expand_mask_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmp<mode><avx512fmaskmodelower>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (match_operator:<avx512fmaskmode> 1 ""
+ [(match_operand:VI12_AVX512VL 2 "register_operand")
+ (match_operand:VI12_AVX512VL 3 "nonimmediate_operand")]))]
+ "TARGET_AVX512BW"
+{
+ bool ok = ix86_expand_mask_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmp<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VI_256 2 "register_operand")
+ (match_operand:VI_256 3 "nonimmediate_operand")]))]
+ "TARGET_AVX2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmp<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VI124_128 2 "register_operand")
+ (match_operand:VI124_128 3 "nonimmediate_operand")]))]
+ "TARGET_SSE2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpv2div2di"
+ [(set (match_operand:V2DI 0 "register_operand")
+ (match_operator:V2DI 1 ""
+ [(match_operand:V2DI 2 "register_operand")
+ (match_operand:V2DI 3 "nonimmediate_operand")]))]
+ "TARGET_SSE4_2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmp<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VF_256 2 "register_operand")
+ (match_operand:VF_256 3 "nonimmediate_operand")]))]
+ "TARGET_AVX"
+{
+ bool ok = ix86_expand_fp_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmp<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VF_128 2 "register_operand")
+ (match_operand:VF_128 3 "nonimmediate_operand")]))]
+ "TARGET_SSE"
+{
+ bool ok = ix86_expand_fp_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpu<mode><avx512fmaskmodelower>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (match_operator:<avx512fmaskmode> 1 ""
+ [(match_operand:VI48_AVX512VL 2 "register_operand")
+ (match_operand:VI48_AVX512VL 3 "nonimmediate_operand")]))]
+ "TARGET_AVX512F"
+{
+ bool ok = ix86_expand_mask_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpu<mode><avx512fmaskmodelower>"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (match_operator:<avx512fmaskmode> 1 ""
+ [(match_operand:VI12_AVX512VL 2 "register_operand")
+ (match_operand:VI12_AVX512VL 3 "nonimmediate_operand")]))]
+ "TARGET_AVX512BW"
+{
+ bool ok = ix86_expand_mask_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpu<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VI_256 2 "register_operand")
+ (match_operand:VI_256 3 "nonimmediate_operand")]))]
+ "TARGET_AVX2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpu<mode><sseintvecmodelower>"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (match_operator:<sseintvecmode> 1 ""
+ [(match_operand:VI124_128 2 "register_operand")
+ (match_operand:VI124_128 3 "nonimmediate_operand")]))]
+ "TARGET_SSE2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "vec_cmpuv2div2di"
+ [(set (match_operand:V2DI 0 "register_operand")
+ (match_operator:V2DI 1 ""
+ [(match_operand:V2DI 2 "register_operand")
+ (match_operand:V2DI 3 "nonimmediate_operand")]))]
+ "TARGET_SSE4_2"
+{
+ bool ok = ix86_expand_int_vec_cmp (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcond<V_512:mode><VF_512:mode>"
[(set (match_operand:V_512 0 "register_operand")
(if_then_else:V_512
@@ -17982,7 +18135,7 @@
(set_attr "btver2_decode" "vector")
(set_attr "mode" "<sseinsnmode>")])
-(define_expand "maskload<mode>"
+(define_expand "maskload<mode><sseintvecmodelower>"
[(set (match_operand:V48_AVX2 0 "register_operand")
(unspec:V48_AVX2
[(match_operand:<sseintvecmode> 2 "register_operand")
@@ -17990,7 +18143,23 @@
UNSPEC_MASKMOV))]
"TARGET_AVX")
-(define_expand "maskstore<mode>"
+(define_expand "maskload<mode><avx512fmaskmodelower>"
+ [(set (match_operand:V48_AVX512VL 0 "register_operand")
+ (vec_merge:V48_AVX512VL
+ (match_operand:V48_AVX512VL 1 "memory_operand")
+ (match_dup 0)
+ (match_operand:<avx512fmaskmode> 2 "register_operand")))]
+ "TARGET_AVX512F")
+
+(define_expand "maskload<mode><avx512fmaskmodelower>"
+ [(set (match_operand:VI12_AVX512VL 0 "register_operand")
+ (vec_merge:VI12_AVX512VL
+ (match_operand:VI12_AVX512VL 1 "memory_operand")
+ (match_dup 0)
+ (match_operand:<avx512fmaskmode> 2 "register_operand")))]
+ "TARGET_AVX512BW")
+
+(define_expand "maskstore<mode><sseintvecmodelower>"
[(set (match_operand:V48_AVX2 0 "memory_operand")
(unspec:V48_AVX2
[(match_operand:<sseintvecmode> 2 "register_operand")
@@ -17999,6 +18168,22 @@
UNSPEC_MASKMOV))]
"TARGET_AVX")
+(define_expand "maskstore<mode><avx512fmaskmodelower>"
+ [(set (match_operand:V48_AVX512VL 0 "memory_operand")
+ (vec_merge:V48_AVX512VL
+ (match_operand:V48_AVX512VL 1 "register_operand")
+ (match_dup 0)
+ (match_operand:<avx512fmaskmode> 2 "register_operand")))]
+ "TARGET_AVX512F")
+
+(define_expand "maskstore<mode><avx512fmaskmodelower>"
+ [(set (match_operand:VI12_AVX512VL 0 "memory_operand")
+ (vec_merge:VI12_AVX512VL
+ (match_operand:VI12_AVX512VL 1 "register_operand")
+ (match_dup 0)
+ (match_operand:<avx512fmaskmode> 2 "register_operand")))]
+ "TARGET_AVX512BW")
+
(define_insn_and_split "avx_<castmode><avxsizesuffix>_<castmode>"
[(set (match_operand:AVX256MODE2P 0 "nonimmediate_operand" "=x,m")
(unspec:AVX256MODE2P
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index d92af177082..08e9cb66cbf 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -236,7 +236,7 @@ static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void ia64_output_function_end_prologue (FILE *);
static void ia64_print_operand (FILE *, rtx, int);
-static void ia64_print_operand_address (FILE *, rtx);
+static void ia64_print_operand_address (FILE *, machine_mode, rtx);
static bool ia64_print_operand_punct_valid_p (unsigned char code);
static int ia64_issue_rate (void);
@@ -5239,6 +5239,7 @@ ia64_output_dwarf_dtprel (FILE *file, int size, rtx x)
static void
ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
+ machine_mode /*mode*/,
rtx address ATTRIBUTE_UNUSED)
{
}
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
index 06da397404a..59adedebf00 100644
--- a/gcc/config/initfini-array.h
+++ b/gcc/config/initfini-array.h
@@ -23,7 +23,7 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-#ifdef HAVE_INITFINI_ARRAY_SUPPORT
+#if HAVE_INITFINI_ARRAY_SUPPORT
#define USE_INITFINI_ARRAY
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 05167db03a7..26b9e6741ff 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -172,7 +172,7 @@ static void iq2000_trampoline_init (rtx, tree, rtx);
static rtx iq2000_function_value (const_tree, const_tree, bool);
static rtx iq2000_libcall_value (machine_mode, const_rtx);
static void iq2000_print_operand (FILE *, rtx, int);
-static void iq2000_print_operand_address (FILE *, rtx);
+static void iq2000_print_operand_address (FILE *, machine_mode, rtx);
static bool iq2000_print_operand_punct_valid_p (unsigned char code);
#undef TARGET_INIT_BUILTINS
@@ -2896,7 +2896,7 @@ iq2000_setup_incoming_varargs (cumulative_args_t cum_v,
reference whose address is ADDR. ADDR is an RTL expression. */
static void
-iq2000_print_operand_address (FILE * file, rtx addr)
+iq2000_print_operand_address (FILE * file, machine_mode mode, rtx addr)
{
if (!addr)
error ("PRINT_OPERAND_ADDRESS, null pointer");
@@ -2921,7 +2921,7 @@ iq2000_print_operand_address (FILE * file, rtx addr)
"PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
fprintf (file, "%%lo(");
- iq2000_print_operand_address (file, arg1);
+ iq2000_print_operand_address (file, mode, arg1);
fprintf (file, ")(%s)", reg_names [REGNO (arg0)]);
}
break;
@@ -3169,10 +3169,12 @@ iq2000_print_operand (FILE *file, rtx op, int letter)
else if (code == MEM)
{
+ machine_mode mode = GET_MODE (op);
+
if (letter == 'D')
- output_address (plus_constant (Pmode, XEXP (op, 0), 4));
+ output_address (mode, plus_constant (Pmode, XEXP (op, 0), 4));
else
- output_address (XEXP (op, 0));
+ output_address (mode, XEXP (op, 0));
}
else if (code == CONST_DOUBLE
diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c
index 1223d472b25..7a19a8204ca 100644
--- a/gcc/config/lm32/lm32.c
+++ b/gcc/config/lm32/lm32.c
@@ -498,7 +498,7 @@ lm32_print_operand (FILE * file, rtx op, int letter)
else if (code == HIGH)
output_addr_const (file, XEXP (op, 0));
else if (code == MEM)
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
fprintf (file, "%s", reg_names[0]);
else if (GET_CODE (op) == CONST_DOUBLE)
@@ -551,7 +551,7 @@ lm32_print_operand_address (FILE * file, rtx addr)
break;
case MEM:
- output_address (XEXP (addr, 0));
+ output_address (VOIDmode, XEXP (addr, 0));
break;
case PLUS:
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 4a6ca867567..baf978f2ddf 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -2795,7 +2795,7 @@ m32c_print_operand_punct_valid_p (unsigned char c)
#define TARGET_PRINT_OPERAND_ADDRESS m32c_print_operand_address
static void
-m32c_print_operand_address (FILE * stream, rtx address)
+m32c_print_operand_address (FILE * stream, machine_mode /*mode*/, rtx address)
{
if (GET_CODE (address) == MEM)
address = XEXP (address, 0);
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 4a47797dbd4..e4085daf6a5 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -66,7 +66,7 @@ static rtx m32r_legitimize_address (rtx, rtx, machine_mode);
static bool m32r_mode_dependent_address_p (const_rtx, addr_space_t);
static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
static void m32r_print_operand (FILE *, rtx, int);
-static void m32r_print_operand_address (FILE *, rtx);
+static void m32r_print_operand_address (FILE *, machine_mode, rtx);
static bool m32r_print_operand_punct_valid_p (unsigned char code);
static void m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
static void m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -2086,6 +2086,8 @@ m32r_print_operand (FILE * file, rtx x, int code)
fputs (reg_names[REGNO (x)+1], file);
else if (MEM_P (x))
{
+ machine_mode mode = GET_MODE (x);
+
fprintf (file, "@(");
/* Handle possible auto-increment. Since it is pre-increment and
we have already done it, we can just use an offset of four. */
@@ -2093,9 +2095,10 @@ m32r_print_operand (FILE * file, rtx x, int code)
currently necessary, but keep it around. */
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 4));
else
- output_address (plus_constant (Pmode, XEXP (x, 0), 4));
+ output_address (mode, plus_constant (Pmode, XEXP (x, 0), 4));
fputc (')', file);
}
else
@@ -2255,7 +2258,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
else
{
fputs ("@(", file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), addr);
fputc (')', file);
}
break;
@@ -2282,7 +2285,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
/* Print a memory address as an operand to reference that memory location. */
static void
-m32r_print_operand_address (FILE * file, rtx addr)
+m32r_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
{
rtx base;
rtx index = 0;
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 37b1af2db3a..7a768d45c30 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -4470,7 +4470,7 @@ print_operand (FILE *file, rtx op, int letter)
}
else if (GET_CODE (op) == MEM)
{
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
if (letter == 'd' && ! TARGET_68020
&& CONSTANT_ADDRESS_P (XEXP (op, 0))
&& !(GET_CODE (XEXP (op, 0)) == CONST_INT
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 9ca23269dc9..d28f2b71ffc 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -112,7 +112,7 @@ static void mcore_asm_named_section (const char *,
unsigned int, tree);
#endif
static void mcore_print_operand (FILE *, rtx, int);
-static void mcore_print_operand_address (FILE *, rtx);
+static void mcore_print_operand_address (FILE *, machine_mode, rtx);
static bool mcore_print_operand_punct_valid_p (unsigned char code);
static void mcore_unique_section (tree, int);
static void mcore_encode_section_info (tree, rtx, int);
@@ -309,7 +309,7 @@ calc_live_regs (int * count)
/* Print the operand address in x to the stream. */
static void
-mcore_print_operand_address (FILE * stream, rtx x)
+mcore_print_operand_address (FILE * stream, machine_mode /*mode*/, rtx x)
{
switch (GET_CODE (x))
{
@@ -401,7 +401,7 @@ mcore_print_operand (FILE * stream, rtx x, int code)
break;
case MEM:
mcore_print_operand_address
- (stream, XEXP (adjust_address (x, SImode, 4), 0));
+ (stream, GET_MODE (x), XEXP (adjust_address (x, SImode, 4), 0));
break;
default:
gcc_unreachable ();
@@ -425,7 +425,7 @@ mcore_print_operand (FILE * stream, rtx x, int code)
fputs (reg_names[REGNO (x)], (stream));
break;
case MEM:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
default:
output_addr_const (stream, x);
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index b418506fc79..aebbc3b0380 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2317,7 +2317,7 @@ print_operand (FILE * file, rtx op, int letter)
if (letter == 'o')
{
rtx op4 = adjust_address (op, GET_MODE (op), 4);
- output_address (XEXP (op4, 0));
+ output_address (GET_MODE (op), XEXP (op4, 0));
}
else if (letter == 'y')
{
@@ -2329,7 +2329,7 @@ print_operand (FILE * file, rtx op, int letter)
}
}
else
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
else if (letter == 'h' || letter == 'j')
{
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 9d6283fe116..9880b236d6d 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -8595,7 +8595,8 @@ mips_print_operand (FILE *file, rtx op, int letter)
case MEM:
if (letter == 'D')
- output_address (plus_constant (Pmode, XEXP (op, 0), 4));
+ output_address (GET_MODE (op), plus_constant (Pmode,
+ XEXP (op, 0), 4));
else if (letter == 'b')
{
gcc_assert (REG_P (XEXP (op, 0)));
@@ -8604,7 +8605,7 @@ mips_print_operand (FILE *file, rtx op, int letter)
else if (letter && letter != 'z')
output_operand_lossage ("invalid use of '%%%c'", letter);
else
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
break;
default:
@@ -8624,7 +8625,7 @@ mips_print_operand (FILE *file, rtx op, int letter)
/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
static void
-mips_print_operand_address (FILE *file, rtx x)
+mips_print_operand_address (FILE *file, machine_mode /*mode*/, rtx x)
{
struct mips_address_info addr;
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 2be7f582c2b..4cafc02d2f3 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -162,7 +162,7 @@ static bool mmix_frame_pointer_required (void);
static void mmix_asm_trampoline_template (FILE *);
static void mmix_trampoline_init (rtx, tree, rtx);
static void mmix_print_operand (FILE *, rtx, int);
-static void mmix_print_operand_address (FILE *, rtx);
+static void mmix_print_operand_address (FILE *, machine_mode, rtx);
static bool mmix_print_operand_punct_valid_p (unsigned char);
static void mmix_conditional_register_usage (void);
@@ -1697,7 +1697,7 @@ mmix_print_operand (FILE *stream, rtx x, int code)
return;
case MEM:
- output_address (XEXP (modified_x, 0));
+ output_address (GET_MODE (modified_x), XEXP (modified_x, 0));
return;
case CONST_INT:
@@ -1754,7 +1754,7 @@ mmix_print_operand_punct_valid_p (unsigned char code)
/* TARGET_PRINT_OPERAND_ADDRESS. */
static void
-mmix_print_operand_address (FILE *stream, rtx x)
+mmix_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
{
if (REG_P (x))
{
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index ff4742785eb..2f191e416fe 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -239,7 +239,7 @@ mn10300_print_operand (FILE *file, rtx x, int code)
{
case MEM:
fputc ('(', file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
fputc (')', file);
break;
@@ -258,7 +258,7 @@ mn10300_print_operand (FILE *file, rtx x, int code)
{
case MEM:
fputc ('(', file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
fputc (')', file);
break;
@@ -317,7 +317,7 @@ mn10300_print_operand (FILE *file, rtx x, int code)
case MEM:
fputc ('(', file);
x = adjust_address (x, SImode, 4);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
fputc (')', file);
break;
@@ -369,9 +369,10 @@ mn10300_print_operand (FILE *file, rtx x, int code)
case 'A':
fputc ('(', file);
if (REG_P (XEXP (x, 0)))
- output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), const0_rtx));
+ output_address (VOIDmode, gen_rtx_PLUS (SImode,
+ XEXP (x, 0), const0_rtx));
else
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
fputc (')', file);
break;
@@ -402,12 +403,12 @@ mn10300_print_operand (FILE *file, rtx x, int code)
{
case MEM:
fputc ('(', file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
fputc (')', file);
break;
case PLUS:
- output_address (x);
+ output_address (VOIDmode, x);
break;
case REG:
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 3fdaab5b041..8832582af8e 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -3287,7 +3287,7 @@ msp430_print_operand_raw (FILE * file, rtx op)
is ADDR. */
static void
-msp430_print_operand_addr (FILE * file, rtx addr)
+msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
{
switch (GET_CODE (addr))
{
@@ -3531,7 +3531,7 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case MEM:
addr = XEXP (op, 0);
- msp430_print_operand_addr (file, addr);
+ msp430_print_operand_addr (file, GET_MODE (op), addr);
break;
case CONST:
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index a014e9f75d9..1bdb518a02e 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -2311,7 +2311,7 @@ nds32_print_operand (FILE *stream, rtx x, int code)
break;
case MEM:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
case CODE_LABEL:
@@ -2331,7 +2331,7 @@ nds32_print_operand (FILE *stream, rtx x, int code)
}
static void
-nds32_print_operand_address (FILE *stream, rtx x)
+nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
{
rtx op0, op1;
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index c8c0cc08095..3fd2d0144a0 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -2622,7 +2622,7 @@ nios2_print_operand (FILE *file, rtx op, int letter)
}
if (letter == 0)
{
- output_address (op);
+ output_address (VOIDmode, op);
return;
}
break;
@@ -2705,7 +2705,7 @@ nios2_output_addr_const_extra (FILE *file, rtx op)
/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
static void
-nios2_print_operand_address (FILE *file, rtx op)
+nios2_print_operand_address (FILE *file, machine_mode mode, rtx op)
{
switch (GET_CODE (op))
{
@@ -2751,7 +2751,7 @@ nios2_print_operand_address (FILE *file, rtx op)
case MEM:
{
rtx base = XEXP (op, 0);
- nios2_print_operand_address (file, base);
+ nios2_print_operand_address (file, mode, base);
return;
}
default:
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 0204ad3383e..f1ac307b346 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1579,7 +1579,7 @@ static void
output_decl_chunk (void)
{
begin_decl_field ();
- output_address (gen_int_mode (init_part, decl_chunk_mode));
+ output_address (VOIDmode, gen_int_mode (init_part, decl_chunk_mode));
init_part = 0;
}
@@ -1636,7 +1636,7 @@ nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
{
nvptx_record_needed_fndecl (SYMBOL_REF_DECL (x));
fprintf (asm_out_file, "generic(");
- output_address (x);
+ output_address (VOIDmode, x);
fprintf (asm_out_file, ")");
}
if (off != 0)
@@ -1894,7 +1894,7 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee)
assemble_name (asm_out_file, name);
}
else
- output_address (callee);
+ output_address (VOIDmode, callee);
if (arg_end > 1 || (decl && DECL_STATIC_CHAIN (decl)))
{
@@ -1954,9 +1954,9 @@ nvptx_print_address_operand (FILE *file, rtx x, machine_mode)
{
case PLUS:
off = XEXP (x, 1);
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
fprintf (file, "+");
- output_address (off);
+ output_address (VOIDmode, off);
break;
case SYMBOL_REF:
@@ -1974,9 +1974,9 @@ nvptx_print_address_operand (FILE *file, rtx x, machine_mode)
/* Write assembly language output for the address ADDR to FILE. */
static void
-nvptx_print_operand_address (FILE *file, rtx addr)
+nvptx_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
- nvptx_print_address_operand (file, addr, VOIDmode);
+ nvptx_print_address_operand (file, addr, mode);
}
/* Print an operand, X, to FILE, with an optional modifier in CODE.
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 4ef20e1c8c1..b8caab52319 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -5413,10 +5413,10 @@ pa_print_operand (FILE *file, rtx x, int code)
reg_names [REGNO (index)], reg_names [REGNO (base)]);
}
else
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
default:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
}
}
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 548933efd94..9a1aaebb6b5 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -724,7 +724,7 @@ pdp11_asm_print_operand (FILE *file, rtx x, int code)
else if (GET_CODE (x) == REG)
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != SImode)
{
REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), sval);
diff --git a/gcc/config/rs6000/aix53.h b/gcc/config/rs6000/aix53.h
index b912e7b8589..d9aa3c20f75 100644
--- a/gcc/config/rs6000/aix53.h
+++ b/gcc/config/rs6000/aix53.h
@@ -63,6 +63,7 @@ do { \
%{mcpu=power6x: -mpwr6} \
%{mcpu=power7: -mpwr7} \
%{mcpu=power8: -mpwr8} \
+%{mcpu=power9: -mpwr9} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rs64a: -mppc} \
%{mcpu=603: -m603} \
diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h
index 0e27057027f..46bdcf50035 100644
--- a/gcc/config/rs6000/aix61.h
+++ b/gcc/config/rs6000/aix61.h
@@ -80,6 +80,7 @@ do { \
%{mcpu=power6x: -mpwr6} \
%{mcpu=power7: -mpwr7} \
%{mcpu=power8: -mpwr8} \
+%{mcpu=power9: -mpwr9} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rs64a: -mppc} \
%{mcpu=603: -m603} \
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 2b8f4bb6066..7c69b6c9e1d 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -137,6 +137,16 @@
(and (match_code "const_int")
(match_test "TARGET_VSX && (ival == VECTOR_ELEMENT_SCALAR_64BIT)")))
+;; Extended fusion store
+(define_memory_constraint "wF"
+ "Memory operand suitable for power9 fusion load/stores"
+ (match_operand 0 "fusion_addis_mem_combo_load"))
+
+;; Fusion gpr load.
+(define_memory_constraint "wG"
+ "Memory operand suitable for TOC fusion memory references"
+ (match_operand 0 "toc_fusion_mem_wrapped"))
+
;; 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/predicates.md b/gcc/config/rs6000/predicates.md
index 1c99f7712f5..3b1a4561fba 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -142,6 +142,11 @@
(and (match_code "const_int")
(match_test "INTVAL (op) >= 0 && INTVAL (op) <= 31")))
+;; Return 1 if op is a unsigned 6-bit constant integer.
+(define_predicate "u6bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 63")))
+
;; Return 1 if op is a signed 8-bit constant integer.
;; Integer multiplication complete more quickly
(define_predicate "s8bit_cint_operand"
@@ -163,6 +168,12 @@
(and (match_code "const_int")
(match_test "satisfies_constraint_K (op)")))
+;; Return 1 if op is a constant integer that is a signed 16-bit constant
+;; shifted left 16 bits
+(define_predicate "upper16_cint_operand"
+ (and (match_code "const_int")
+ (match_test "satisfies_constraint_L (op)")))
+
;; Return 1 if op is a constant integer that cannot fit in a signed D field.
(define_predicate "non_short_cint_operand"
(and (match_code "const_int")
@@ -271,6 +282,70 @@
return (REGNO (op) != FIRST_GPR_REGNO);
})
+
+;; Return true if this is a traditional floating point register
+(define_predicate "fpr_reg_operand"
+ (match_code "reg,subreg")
+{
+ HOST_WIDE_INT r;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ if (!REG_P (op))
+ return 0;
+
+ r = REGNO (op);
+ if (r >= FIRST_PSEUDO_REGISTER)
+ return 1;
+
+ return FP_REGNO_P (r);
+})
+
+;; Return true if this is a register that can has D-form addressing (GPR and
+;; traditional FPR registers for scalars). ISA 3.0 (power9) adds D-form
+;; addressing for scalars in Altivec registers.
+;;
+;; If this is a pseudo only allow for GPR fusion in power8. If we have the
+;; power9 fusion allow the floating point types.
+(define_predicate "toc_fusion_or_p9_reg_operand"
+ (match_code "reg,subreg")
+{
+ HOST_WIDE_INT r;
+ bool gpr_p = (mode == QImode || mode == HImode || mode == SImode
+ || mode == SFmode
+ || (TARGET_POWERPC64 && (mode == DImode || mode == DFmode)));
+ bool fpr_p = (TARGET_P9_FUSION
+ && (mode == DFmode || mode == SFmode
+ || (TARGET_POWERPC64 && mode == DImode)));
+ bool vmx_p = (TARGET_P9_FUSION && TARGET_P9_VECTOR
+ && (mode == DFmode || mode == SFmode));
+
+ if (!TARGET_P8_FUSION)
+ return 0;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ if (!REG_P (op))
+ return 0;
+
+ r = REGNO (op);
+ if (r >= FIRST_PSEUDO_REGISTER)
+ return (gpr_p || fpr_p || vmx_p);
+
+ if (INT_REGNO_P (r))
+ return gpr_p;
+
+ if (FP_REGNO_P (r))
+ return fpr_p;
+
+ if (ALTIVEC_REGNO_P (r))
+ return vmx_p;
+
+ return 0;
+})
+
;; Return 1 if op is a HTM specific SPR register.
(define_predicate "htm_spr_reg_operand"
(match_operand 0 "register_operand")
@@ -1598,6 +1673,35 @@
return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
})
+;; Match the TOC memory operand that can be fused with an addis instruction.
+;; This is used in matching a potential fused address before register
+;; allocation.
+(define_predicate "toc_fusion_mem_raw"
+ (match_code "mem")
+{
+ if (!TARGET_TOC_FUSION_INT || !can_create_pseudo_p ())
+ return false;
+
+ return small_toc_ref (XEXP (op, 0), Pmode);
+})
+
+;; Match the memory operand that has been fused with an addis instruction and
+;; wrapped inside of an (unspec [...] UNSPEC_FUSION_ADDIS) wrapper.
+(define_predicate "toc_fusion_mem_wrapped"
+ (match_code "mem")
+{
+ rtx addr;
+
+ if (!TARGET_TOC_FUSION_INT)
+ return false;
+
+ if (!MEM_P (op))
+ return false;
+
+ addr = XEXP (op, 0);
+ return (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_FUSION_ADDIS);
+})
+
;; Match the first insn (addis) in fusing the combination of addis and loads to
;; GPR registers on power8.
(define_predicate "fusion_gpr_addis"
@@ -1620,8 +1724,6 @@
else
return 0;
- /* Power8 currently will only do the fusion if the top 11 bits of the addis
- value are all 1's or 0's. */
value = INTVAL (int_const);
if ((value & (HOST_WIDE_INT)0xffff) != 0)
return 0;
@@ -1629,6 +1731,12 @@
if ((value & (HOST_WIDE_INT)0xffff0000) == 0)
return 0;
+ /* Power8 currently will only do the fusion if the top 11 bits of the addis
+ value are all 1's or 0's. Ignore this restriction if we are testing
+ advanced fusion. */
+ if (TARGET_P9_FUSION)
+ return 1;
+
return (IN_RANGE (value >> 16, -32, 31));
})
@@ -1694,13 +1802,14 @@
;; Match a GPR load (lbz, lhz, lwz, ld) that uses a combined address in the
;; memory field with both the addis and the memory offset. Sign extension
;; is not handled here, since lha and lwa are not fused.
-(define_predicate "fusion_gpr_mem_combo"
- (match_code "mem,zero_extend")
+;; With extended fusion, also match a FPR load (lfd, lfs) and float_extend
+(define_predicate "fusion_addis_mem_combo_load"
+ (match_code "mem,zero_extend,float_extend")
{
rtx addr, base, offset;
- /* Handle zero extend. */
- if (GET_CODE (op) == ZERO_EXTEND)
+ /* Handle zero/float extend. */
+ if (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == FLOAT_EXTEND)
{
op = XEXP (op, 0);
mode = GET_MODE (op);
@@ -1721,6 +1830,71 @@
return 0;
break;
+ case SFmode:
+ case DFmode:
+ if (!TARGET_P9_FUSION)
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+
+ addr = XEXP (op, 0);
+ if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM)
+ return 0;
+
+ base = XEXP (addr, 0);
+ if (!fusion_gpr_addis (base, GET_MODE (base)))
+ return 0;
+
+ offset = XEXP (addr, 1);
+ if (GET_CODE (addr) == PLUS)
+ return satisfies_constraint_I (offset);
+
+ else if (GET_CODE (addr) == LO_SUM)
+ {
+ if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64))
+ return small_toc_ref (offset, GET_MODE (offset));
+
+ else if (TARGET_ELF && !TARGET_POWERPC64)
+ return CONSTANT_P (offset);
+ }
+
+ return 0;
+})
+
+;; Like fusion_addis_mem_combo_load, but for stores
+(define_predicate "fusion_addis_mem_combo_store"
+ (match_code "mem")
+{
+ rtx addr, base, offset;
+
+ if (!MEM_P (op) || !TARGET_P9_FUSION)
+ return 0;
+
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ break;
+
+ case DImode:
+ if (!TARGET_POWERPC64)
+ return 0;
+ break;
+
+ case SFmode:
+ if (!TARGET_SF_FPR)
+ return 0;
+ break;
+
+ case DFmode:
+ if (!TARGET_DF_FPR)
+ return 0;
+ break;
+
default:
return 0;
}
@@ -1748,3 +1922,20 @@
return 0;
})
+
+;; Return true if the operand is a float_extend or zero extend of an
+;; offsettable memory operand suitable for use in fusion
+(define_predicate "fusion_offsettable_mem_operand"
+ (match_code "mem,zero_extend,float_extend")
+{
+ if (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == FLOAT_EXTEND)
+ {
+ op = XEXP (op, 0);
+ mode = GET_MODE (op);
+ }
+
+ if (!memory_operand (op, mode))
+ return 0;
+
+ return offsettable_nonstrict_memref_p (op);
+})
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 8f02edd1a63..a1b4fd4d17e 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -349,6 +349,8 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7");
if ((flags & OPTION_MASK_DIRECT_MOVE) != 0)
rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR8");
+ if ((flags & OPTION_MASK_MODULO) != 0)
+ rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR9");
if ((flags & OPTION_MASK_SOFT_FLOAT) != 0)
rs6000_define_or_undefine_macro (define_p, "_SOFT_FLOAT");
if ((flags & OPTION_MASK_RECIP_PRECISION) != 0)
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index c63506bdf82..fc2b0f11353 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -60,6 +60,15 @@
| OPTION_MASK_QUAD_MEMORY_ATOMIC \
| OPTION_MASK_UPPER_REGS_SF)
+/* Add ISEL back into ISA 3.0, since it is supposed to be a win. Do not add
+ P9_DFORM or P9_MINMAX until they are fully debugged. */
+#define ISA_3_0_MASKS_SERVER (ISA_2_7_MASKS_SERVER \
+ | OPTION_MASK_FLOAT128_HW \
+ | OPTION_MASK_ISEL \
+ | OPTION_MASK_MODULO \
+ | OPTION_MASK_P9_FUSION \
+ | OPTION_MASK_P9_VECTOR)
+
#define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
/* Deal with ports that do not have -mstrict-align. */
@@ -87,10 +96,15 @@
| OPTION_MASK_ISEL \
| OPTION_MASK_MFCRF \
| OPTION_MASK_MFPGPR \
+ | OPTION_MASK_MODULO \
| OPTION_MASK_MULHW \
| OPTION_MASK_NO_UPDATE \
| OPTION_MASK_P8_FUSION \
| OPTION_MASK_P8_VECTOR \
+ | OPTION_MASK_P9_DFORM \
+ | OPTION_MASK_P9_FUSION \
+ | OPTION_MASK_P9_MINMAX \
+ | OPTION_MASK_P9_VECTOR \
| OPTION_MASK_POPCNTB \
| OPTION_MASK_POPCNTD \
| OPTION_MASK_POWERPC64 \
@@ -101,6 +115,7 @@
| OPTION_MASK_RECIP_PRECISION \
| OPTION_MASK_SOFT_FLOAT \
| OPTION_MASK_STRICT_ALIGN_OPTIONAL \
+ | OPTION_MASK_TOC_FUSION \
| OPTION_MASK_UPPER_REGS_DF \
| OPTION_MASK_UPPER_REGS_SF \
| OPTION_MASK_VSX \
@@ -195,6 +210,7 @@ RS6000_CPU ("power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
| MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
| MASK_VSX | MASK_RECIP_PRECISION | OPTION_MASK_UPPER_REGS_DF)
RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
+RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER)
RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index 2a028eaae8f..012c0db42fc 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -60,6 +60,7 @@ enum processor_type
PROCESSOR_POWER6,
PROCESSOR_POWER7,
PROCESSOR_POWER8,
+ PROCESSOR_POWER9,
PROCESSOR_RS64A,
PROCESSOR_MPCCORE,
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 82a695c06b6..9a149b9e29a 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -87,7 +87,15 @@ extern bool direct_move_p (rtx, rtx);
extern bool quad_load_store_p (rtx, rtx);
extern bool fusion_gpr_load_p (rtx, rtx, rtx, rtx);
extern void expand_fusion_gpr_load (rtx *);
+extern void emit_fusion_addis (rtx, rtx, const char *, const char *);
+extern void emit_fusion_load_store (rtx, rtx, rtx, const char *);
extern const char *emit_fusion_gpr_load (rtx, rtx);
+extern bool fusion_p9_p (rtx, rtx, rtx, rtx);
+extern void expand_fusion_p9_load (rtx *);
+extern void expand_fusion_p9_store (rtx *);
+extern const char *emit_fusion_p9_load (rtx, rtx, rtx);
+extern const char *emit_fusion_p9_store (rtx, rtx, rtx);
+extern rtx fusion_wrap_memory_address (rtx);
extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
enum reg_class);
extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
diff --git a/gcc/config/rs6000/rs6000-tables.opt b/gcc/config/rs6000/rs6000-tables.opt
index e4b41e148bc..2529ff1ca91 100644
--- a/gcc/config/rs6000/rs6000-tables.opt
+++ b/gcc/config/rs6000/rs6000-tables.opt
@@ -180,14 +180,17 @@ EnumValue
Enum(rs6000_cpu_opt_value) String(power8) Value(50)
EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc) Value(51)
+Enum(rs6000_cpu_opt_value) String(power9) Value(51)
EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc64) Value(52)
+Enum(rs6000_cpu_opt_value) String(powerpc) Value(52)
EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(53)
+Enum(rs6000_cpu_opt_value) String(powerpc64) Value(53)
EnumValue
-Enum(rs6000_cpu_opt_value) String(rs64) Value(54)
+Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(54)
+
+EnumValue
+Enum(rs6000_cpu_opt_value) String(rs64) Value(55)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8bdd64674bf..ca93609bb6b 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -376,8 +376,18 @@ struct rs6000_reg_addr {
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. */
+ enum insn_code fusion_gpr_ld; /* INSN for fusing gpr ADDIS/loads. */
+ /* INSNs for fusing addi with loads
+ or stores for each reg. class. */
+ enum insn_code fusion_addi_ld[(int)N_RELOAD_REG];
+ enum insn_code fusion_addi_st[(int)N_RELOAD_REG];
+ /* INSNs for fusing addis with loads
+ or stores for each reg. class. */
+ enum insn_code fusion_addis_ld[(int)N_RELOAD_REG];
+ enum insn_code fusion_addis_st[(int)N_RELOAD_REG];
addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks. */
bool scalar_in_vmx_p; /* Scalar value can go in VMX. */
+ bool fused_toc; /* Mode supports TOC fusion. */
};
static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
@@ -985,6 +995,26 @@ struct processor_costs power8_cost = {
COSTS_N_INSNS (3), /* SF->DF convert */
};
+/* Instruction costs on POWER9 processors. */
+static const
+struct processor_costs power9_cost = {
+ COSTS_N_INSNS (3), /* mulsi */
+ COSTS_N_INSNS (3), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (3), /* muldi */
+ COSTS_N_INSNS (19), /* divsi */
+ COSTS_N_INSNS (35), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (14), /* sdiv */
+ COSTS_N_INSNS (17), /* ddiv */
+ 128, /* cache line size */
+ 32, /* l1 cache */
+ 256, /* l2 cache */
+ 12, /* prefetch streams */
+ COSTS_N_INSNS (3), /* SF->DF convert */
+};
+
/* Instruction costs on POWER A2 processors. */
static const
struct processor_costs ppca2_cost = {
@@ -2006,25 +2036,113 @@ DEBUG_FUNCTION void
rs6000_debug_print_mode (ssize_t m)
{
ssize_t rc;
+ int spaces = 0;
+ bool fuse_extra_p;
fprintf (stderr, "Mode: %-5s", GET_MODE_NAME (m));
for (rc = 0; rc < N_RELOAD_REG; rc++)
fprintf (stderr, " %s: %s", reload_reg_map[rc].name,
rs6000_debug_addr_mask (reg_addr[m].addr_mask[rc], true));
+ if ((reg_addr[m].reload_store != CODE_FOR_nothing)
+ || (reg_addr[m].reload_load != CODE_FOR_nothing))
+ fprintf (stderr, " Reload=%c%c",
+ (reg_addr[m].reload_store != CODE_FOR_nothing) ? 's' : '*',
+ (reg_addr[m].reload_load != CODE_FOR_nothing) ? 'l' : '*');
+ else
+ spaces += sizeof (" Reload=sl") - 1;
+
+ if (reg_addr[m].scalar_in_vmx_p)
+ {
+ fprintf (stderr, "%*s Upper=y", spaces, "");
+ spaces = 0;
+ }
+ else
+ spaces += sizeof (" Upper=y") - 1;
+
+ fuse_extra_p = ((reg_addr[m].fusion_gpr_ld != CODE_FOR_nothing)
+ || reg_addr[m].fused_toc);
+ if (!fuse_extra_p)
+ {
+ for (rc = 0; rc < N_RELOAD_REG; rc++)
+ {
+ if (rc != RELOAD_REG_ANY)
+ {
+ if (reg_addr[m].fusion_addi_ld[rc] != CODE_FOR_nothing
+ || reg_addr[m].fusion_addi_ld[rc] != CODE_FOR_nothing
+ || reg_addr[m].fusion_addi_st[rc] != CODE_FOR_nothing
+ || reg_addr[m].fusion_addis_ld[rc] != CODE_FOR_nothing
+ || reg_addr[m].fusion_addis_st[rc] != CODE_FOR_nothing)
+ {
+ fuse_extra_p = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (fuse_extra_p)
+ {
+ fprintf (stderr, "%*s Fuse:", spaces, "");
+ spaces = 0;
+
+ for (rc = 0; rc < N_RELOAD_REG; rc++)
+ {
+ if (rc != RELOAD_REG_ANY)
+ {
+ char load, store;
+
+ if (reg_addr[m].fusion_addis_ld[rc] != CODE_FOR_nothing)
+ load = 'l';
+ else if (reg_addr[m].fusion_addi_ld[rc] != CODE_FOR_nothing)
+ load = 'L';
+ else
+ load = '-';
+
+ if (reg_addr[m].fusion_addis_st[rc] != CODE_FOR_nothing)
+ store = 's';
+ else if (reg_addr[m].fusion_addi_st[rc] != CODE_FOR_nothing)
+ store = 'S';
+ else
+ store = '-';
+
+ if (load == '-' && store == '-')
+ spaces += 5;
+ else
+ {
+ fprintf (stderr, "%*s%c=%c%c", (spaces + 1), "",
+ reload_reg_map[rc].name[0], load, store);
+ spaces = 0;
+ }
+ }
+ }
+
+ if (reg_addr[m].fusion_gpr_ld != CODE_FOR_nothing)
+ {
+ fprintf (stderr, "%*sP8gpr", (spaces + 1), "");
+ spaces = 0;
+ }
+ else
+ spaces += sizeof (" P8gpr") - 1;
+
+ if (reg_addr[m].fused_toc)
+ {
+ fprintf (stderr, "%*sToc", (spaces + 1), "");
+ spaces = 0;
+ }
+ else
+ spaces += sizeof (" Toc") - 1;
+ }
+ else
+ spaces += sizeof (" Fuse: G=ls F=ls v=ls P8gpr Toc") - 1;
+
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)
- || reg_addr[m].scalar_in_vmx_p)
+ || rs6000_vector_mem[m] != VECTOR_NONE)
{
- fprintf (stderr,
- " Vector-arith=%-10s Vector-mem=%-10s Reload=%c%c Upper=%c",
+ fprintf (stderr, "%*s vector: arith=%-10s mem=%s",
+ spaces, "",
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' : '*',
- (reg_addr[m].scalar_in_vmx_p) ? 'y' : 'n');
+ rs6000_debug_vector_unit (rs6000_vector_mem[m]));
}
fputs ("\n", stderr);
@@ -2423,8 +2541,18 @@ rs6000_debug_reg_global (void)
fprintf (stderr, DEBUG_FMT_S, "lra", "true");
if (TARGET_P8_FUSION)
- fprintf (stderr, DEBUG_FMT_S, "p8 fusion",
- (TARGET_P8_FUSION_SIGN) ? "zero+sign" : "zero");
+ {
+ char options[80];
+
+ strcpy (options, (TARGET_P9_FUSION) ? "power9" : "power8");
+ if (TARGET_TOC_FUSION)
+ strcat (options, ", toc");
+
+ if (TARGET_P8_FUSION_SIGN)
+ strcat (options, ", sign");
+
+ fprintf (stderr, DEBUG_FMT_S, "fusion", options);
+ }
fprintf (stderr, DEBUG_FMT_S, "plt-format",
TARGET_SECURE_PLT ? "secure" : "bss");
@@ -2463,6 +2591,7 @@ rs6000_setup_reg_addr_masks (void)
for (m = 0; m < NUM_MACHINE_MODES; ++m)
{
machine_mode m2 = (machine_mode)m;
+ unsigned short msize = GET_MODE_SIZE (m2);
/* 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
@@ -2492,16 +2621,18 @@ rs6000_setup_reg_addr_masks (void)
/* 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. */
+ '32-bit' GPRs. If we allow scalars into Altivec registers,
+ don't allow PRE_INC, PRE_DEC, or PRE_MODIFY. */
if (TARGET_UPDATE
&& (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
- && GET_MODE_SIZE (m2) <= 8
+ && msize <= 8
&& !VECTOR_MODE_P (m2)
&& !FLOAT128_VECTOR_P (m2)
&& !COMPLEX_MODE_P (m2)
- && !indexed_only_p
- && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m2) == 8))
+ && (m2 != DFmode || !TARGET_UPPER_REGS_DF)
+ && (m2 != SFmode || !TARGET_UPPER_REGS_SF)
+ && !(TARGET_E500_DOUBLE && msize == 8))
{
addr_mask |= RELOAD_REG_PRE_INCDEC;
@@ -2536,7 +2667,7 @@ rs6000_setup_reg_addr_masks (void)
/* VMX registers can do (REG & -16) and ((REG+REG) & -16)
addressing on 128-bit types. */
- if (rc == RELOAD_REG_VMX && GET_MODE_SIZE (m2) == 16
+ if (rc == RELOAD_REG_VMX && msize == 16
&& (addr_mask & RELOAD_REG_VALID) != 0)
addr_mask |= RELOAD_REG_AND_M16;
@@ -2986,6 +3117,130 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[SFmode].scalar_in_vmx_p = true;
}
+ /* Setup the fusion operations. */
+ if (TARGET_P8_FUSION)
+ {
+ reg_addr[QImode].fusion_gpr_ld = CODE_FOR_fusion_gpr_load_qi;
+ reg_addr[HImode].fusion_gpr_ld = CODE_FOR_fusion_gpr_load_hi;
+ reg_addr[SImode].fusion_gpr_ld = CODE_FOR_fusion_gpr_load_si;
+ if (TARGET_64BIT)
+ reg_addr[DImode].fusion_gpr_ld = CODE_FOR_fusion_gpr_load_di;
+ }
+
+ if (TARGET_P9_FUSION)
+ {
+ struct fuse_insns {
+ enum machine_mode mode; /* mode of the fused type. */
+ enum machine_mode pmode; /* pointer mode. */
+ enum rs6000_reload_reg_type rtype; /* register type. */
+ enum insn_code load; /* load insn. */
+ enum insn_code store; /* store insn. */
+ };
+
+ static const struct fuse_insns addis_insns[] = {
+ { SFmode, DImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_di_sf_load,
+ CODE_FOR_fusion_fpr_di_sf_store },
+
+ { SFmode, SImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_si_sf_load,
+ CODE_FOR_fusion_fpr_si_sf_store },
+
+ { DFmode, DImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_di_df_load,
+ CODE_FOR_fusion_fpr_di_df_store },
+
+ { DFmode, SImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_si_df_load,
+ CODE_FOR_fusion_fpr_si_df_store },
+
+ { DImode, DImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_di_di_load,
+ CODE_FOR_fusion_fpr_di_di_store },
+
+ { DImode, SImode, RELOAD_REG_FPR,
+ CODE_FOR_fusion_fpr_si_di_load,
+ CODE_FOR_fusion_fpr_si_di_store },
+
+ { QImode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_qi_load,
+ CODE_FOR_fusion_gpr_di_qi_store },
+
+ { QImode, SImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_si_qi_load,
+ CODE_FOR_fusion_gpr_si_qi_store },
+
+ { HImode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_hi_load,
+ CODE_FOR_fusion_gpr_di_hi_store },
+
+ { HImode, SImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_si_hi_load,
+ CODE_FOR_fusion_gpr_si_hi_store },
+
+ { SImode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_si_load,
+ CODE_FOR_fusion_gpr_di_si_store },
+
+ { SImode, SImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_si_si_load,
+ CODE_FOR_fusion_gpr_si_si_store },
+
+ { SFmode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_sf_load,
+ CODE_FOR_fusion_gpr_di_sf_store },
+
+ { SFmode, SImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_si_sf_load,
+ CODE_FOR_fusion_gpr_si_sf_store },
+
+ { DImode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_di_load,
+ CODE_FOR_fusion_gpr_di_di_store },
+
+ { DFmode, DImode, RELOAD_REG_GPR,
+ CODE_FOR_fusion_gpr_di_df_load,
+ CODE_FOR_fusion_gpr_di_df_store },
+ };
+
+ enum machine_mode cur_pmode = Pmode;
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (addis_insns); i++)
+ {
+ enum machine_mode xmode = addis_insns[i].mode;
+ enum rs6000_reload_reg_type rtype = addis_insns[i].rtype;
+
+ if (addis_insns[i].pmode != cur_pmode)
+ continue;
+
+ if (rtype == RELOAD_REG_FPR
+ && (!TARGET_HARD_FLOAT || !TARGET_FPRS))
+ continue;
+
+ reg_addr[xmode].fusion_addis_ld[rtype] = addis_insns[i].load;
+ reg_addr[xmode].fusion_addis_st[rtype] = addis_insns[i].store;
+ }
+ }
+
+ /* Note which types we support fusing TOC setup plus memory insn. We only do
+ fused TOCs for medium/large code models. */
+ if (TARGET_P8_FUSION && TARGET_TOC_FUSION && TARGET_POWERPC64
+ && (TARGET_CMODEL != CMODEL_SMALL))
+ {
+ reg_addr[QImode].fused_toc = true;
+ reg_addr[HImode].fused_toc = true;
+ reg_addr[SImode].fused_toc = true;
+ reg_addr[DImode].fused_toc = true;
+ if (TARGET_HARD_FLOAT && TARGET_FPRS)
+ {
+ if (TARGET_SINGLE_FLOAT)
+ reg_addr[SFmode].fused_toc = true;
+ if (TARGET_DOUBLE_FLOAT)
+ reg_addr[DFmode].fused_toc = true;
+ }
+ }
+
/* Precalculate HARD_REGNO_NREGS. */
for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
for (m = 0; m < NUM_MACHINE_MODES; ++m)
@@ -3382,7 +3637,22 @@ rs6000_option_override_internal (bool global_init_p)
if (rs6000_tune_index >= 0)
tune_index = rs6000_tune_index;
else if (have_cpu)
- rs6000_tune_index = tune_index = cpu_index;
+ {
+ /* Until power9 tuning is available, use power8 tuning if -mcpu=power9. */
+ if (processor_target_table[cpu_index].processor != PROCESSOR_POWER9)
+ rs6000_tune_index = tune_index = cpu_index;
+ else
+ {
+ size_t i;
+ tune_index = -1;
+ for (i = 0; i < ARRAY_SIZE (processor_target_table); i++)
+ if (processor_target_table[i].processor == PROCESSOR_POWER8)
+ {
+ rs6000_tune_index = tune_index = i;
+ break;
+ }
+ }
+ }
else
{
size_t i;
@@ -3557,7 +3827,9 @@ rs6000_option_override_internal (bool global_init_p)
/* For the newer switches (vsx, dfp, etc.) set some of the older options,
unless the user explicitly used the -mno-<option> to disable the code. */
- if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO)
+ if (TARGET_P9_VECTOR || TARGET_MODULO || TARGET_P9_DFORM || TARGET_P9_MINMAX)
+ rs6000_isa_flags |= (ISA_3_0_MASKS_SERVER & ~rs6000_isa_flags_explicit);
+ else if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO)
rs6000_isa_flags |= (ISA_2_7_MASKS_SERVER & ~rs6000_isa_flags_explicit);
else if (TARGET_VSX)
rs6000_isa_flags |= (ISA_2_6_MASKS_SERVER & ~rs6000_isa_flags_explicit);
@@ -3703,6 +3975,41 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_isa_flags |= (processor_target_table[tune_index].target_enable
& OPTION_MASK_P8_FUSION);
+ /* Setting additional fusion flags turns on base fusion. */
+ if (!TARGET_P8_FUSION && (TARGET_P8_FUSION_SIGN || TARGET_TOC_FUSION))
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_P8_FUSION)
+ {
+ if (TARGET_P8_FUSION_SIGN)
+ error ("-mpower8-fusion-sign requires -mpower8-fusion");
+
+ if (TARGET_TOC_FUSION)
+ error ("-mtoc-fusion requires -mpower8-fusion");
+
+ rs6000_isa_flags &= ~OPTION_MASK_P8_FUSION;
+ }
+ else
+ rs6000_isa_flags |= OPTION_MASK_P8_FUSION;
+ }
+
+ /* Power9 fusion is a superset over power8 fusion. */
+ if (TARGET_P9_FUSION && !TARGET_P8_FUSION)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_P8_FUSION)
+ {
+ error ("-mpower9-fusion requires -mpower8-fusion");
+ rs6000_isa_flags &= ~OPTION_MASK_P9_FUSION;
+ }
+ else
+ rs6000_isa_flags |= OPTION_MASK_P8_FUSION;
+ }
+
+ /* Enable power9 fusion if we are tuning for power9, even if we aren't
+ generating power9 instructions. */
+ if (!(rs6000_isa_flags_explicit & OPTION_MASK_P9_FUSION))
+ rs6000_isa_flags |= (processor_target_table[tune_index].target_enable
+ & OPTION_MASK_P9_FUSION);
+
/* Power8 does not fuse sign extended loads with the addis. If we are
optimizing at high levels for speed, convert a sign extended load into a
zero extending load, and an explicit sign extension. */
@@ -3712,6 +4019,58 @@ rs6000_option_override_internal (bool global_init_p)
&& optimize >= 3)
rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
+ /* TOC fusion requires 64-bit and medium/large code model. */
+ if (TARGET_TOC_FUSION && !TARGET_POWERPC64)
+ {
+ rs6000_isa_flags &= ~OPTION_MASK_TOC_FUSION;
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_TOC_FUSION) != 0)
+ warning (0, N_("-mtoc-fusion requires 64-bit"));
+ }
+
+ if (TARGET_TOC_FUSION && (TARGET_CMODEL == CMODEL_SMALL))
+ {
+ rs6000_isa_flags &= ~OPTION_MASK_TOC_FUSION;
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_TOC_FUSION) != 0)
+ warning (0, N_("-mtoc-fusion requires medium/large code model"));
+ }
+
+ /* Turn on -mtoc-fusion by default if p8-fusion and 64-bit medium/large code
+ model. */
+ if (TARGET_P8_FUSION && !TARGET_TOC_FUSION && TARGET_POWERPC64
+ && (TARGET_CMODEL != CMODEL_SMALL)
+ && !(rs6000_isa_flags_explicit & OPTION_MASK_TOC_FUSION))
+ rs6000_isa_flags |= OPTION_MASK_TOC_FUSION;
+
+ /* ISA 3.0 D-form instructions require p9-vector and upper-regs. */
+ if (TARGET_P9_DFORM && !TARGET_P9_VECTOR)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR)
+ error ("-mpower9-dform requires -mpower9-vector");
+ rs6000_isa_flags &= ~OPTION_MASK_P9_DFORM;
+ }
+
+ if (TARGET_P9_DFORM && !TARGET_UPPER_REGS_DF)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_DF)
+ error ("-mpower9-dform requires -mupper-regs-df");
+ rs6000_isa_flags &= ~OPTION_MASK_P9_DFORM;
+ }
+
+ if (TARGET_P9_DFORM && !TARGET_UPPER_REGS_SF)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_UPPER_REGS_SF)
+ error ("-mpower9-dform requires -mupper-regs-sf");
+ rs6000_isa_flags &= ~OPTION_MASK_P9_DFORM;
+ }
+
+ /* ISA 3.0 vector instructions include ISA 2.07. */
+ if (TARGET_P9_VECTOR && !TARGET_P8_VECTOR)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR)
+ error ("-mpower9-vector requires -mpower8-vector");
+ rs6000_isa_flags &= ~OPTION_MASK_P9_VECTOR;
+ }
+
/* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07
support. If we only have ISA 2.06 support, and the user did not specify
the switch, leave it set to -1 so the movmisalign patterns are enabled,
@@ -3757,9 +4116,32 @@ rs6000_option_override_internal (bool global_init_p)
if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
error ("-mfloat128 requires VSX support");
- rs6000_isa_flags &= ~OPTION_MASK_FLOAT128;
+ rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128 | OPTION_MASK_FLOAT128_HW);
+ }
+
+ /* IEEE 128-bit floating point hardware instructions imply enabling
+ __float128. */
+ if (TARGET_FLOAT128_HW
+ && (rs6000_isa_flags & (OPTION_MASK_P9_VECTOR
+ | OPTION_MASK_DIRECT_MOVE
+ | OPTION_MASK_UPPER_REGS_DF
+ | OPTION_MASK_UPPER_REGS_SF)) == 0)
+ {
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) != 0)
+ error ("-mfloat128-hardware requires full ISA 3.0 support");
+
+ rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
}
+ else if (TARGET_P9_VECTOR && !TARGET_FLOAT128_HW
+ && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) == 0)
+ rs6000_isa_flags |= OPTION_MASK_FLOAT128_HW;
+
+ if (TARGET_FLOAT128_HW
+ && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) == 0)
+ rs6000_isa_flags |= OPTION_MASK_FLOAT128;
+
+ /* Print the options after updating the defaults. */
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -3957,18 +4339,21 @@ rs6000_option_override_internal (bool global_init_p)
&& rs6000_cpu != PROCESSOR_POWER6
&& rs6000_cpu != PROCESSOR_POWER7
&& rs6000_cpu != PROCESSOR_POWER8
+ && rs6000_cpu != PROCESSOR_POWER9
&& rs6000_cpu != PROCESSOR_PPCA2
&& rs6000_cpu != PROCESSOR_CELL
&& rs6000_cpu != PROCESSOR_PPC476);
rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER7
- || rs6000_cpu == PROCESSOR_POWER8);
+ || rs6000_cpu == PROCESSOR_POWER8
+ || rs6000_cpu == PROCESSOR_POWER9);
rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER6
|| rs6000_cpu == PROCESSOR_POWER7
|| rs6000_cpu == PROCESSOR_POWER8
+ || rs6000_cpu == PROCESSOR_POWER9
|| rs6000_cpu == PROCESSOR_PPCE500MC
|| rs6000_cpu == PROCESSOR_PPCE500MC64
|| rs6000_cpu == PROCESSOR_PPCE5500
@@ -4216,6 +4601,10 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_cost = &power8_cost;
break;
+ case PROCESSOR_POWER9:
+ rs6000_cost = &power9_cost;
+ break;
+
case PROCESSOR_PPCA2:
rs6000_cost = &ppca2_cost;
break;
@@ -4396,7 +4785,8 @@ rs6000_loop_align (rtx label)
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER6
|| rs6000_cpu == PROCESSOR_POWER7
- || rs6000_cpu == PROCESSOR_POWER8))
+ || rs6000_cpu == PROCESSOR_POWER8
+ || rs6000_cpu == PROCESSOR_POWER9))
return 5;
else
return align_loops_log;
@@ -5213,7 +5603,9 @@ rs6000_file_start (void)
|| !global_options_set.x_rs6000_cpu_index)
{
fputs ("\t.machine ", asm_out_file);
- if ((rs6000_isa_flags & OPTION_MASK_DIRECT_MOVE) != 0)
+ if ((rs6000_isa_flags & OPTION_MASK_MODULO) != 0)
+ fputs ("power9\n", asm_out_file);
+ else if ((rs6000_isa_flags & OPTION_MASK_DIRECT_MOVE) != 0)
fputs ("power8\n", asm_out_file);
else if ((rs6000_isa_flags & OPTION_MASK_POPCNTD) != 0)
fputs ("power7\n", asm_out_file);
@@ -7957,6 +8349,8 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
&& legitimate_constant_pool_address_p (x, mode,
reg_ok_strict || lra_in_progress))
return 1;
+ if (reg_offset_p && reg_addr[mode].fused_toc && toc_fusion_mem_wrapped (x, mode))
+ return 1;
/* 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
@@ -19259,18 +19653,19 @@ print_operand (FILE *file, rtx x, int code)
fputs (reg_names[REGNO (x) + 1], file);
else if (MEM_P (x))
{
+ machine_mode mode = GET_MODE (x);
/* Handle possible auto-increment. Since it is pre-increment and
we have already done it, we can just use an offset of word. */
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0),
- UNITS_PER_WORD));
+ output_address (mode, plus_constant (Pmode, XEXP (XEXP (x, 0), 0),
+ UNITS_PER_WORD));
else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0),
- UNITS_PER_WORD));
+ output_address (mode, plus_constant (Pmode, XEXP (XEXP (x, 0), 0),
+ UNITS_PER_WORD));
else
- output_address (XEXP (adjust_address_nv (x, SImode,
- UNITS_PER_WORD),
+ output_address (mode, XEXP (adjust_address_nv (x, SImode,
+ UNITS_PER_WORD),
0));
if (small_data_operand (x, GET_MODE (x)))
@@ -19506,13 +19901,16 @@ print_operand (FILE *file, rtx x, int code)
fputs (reg_names[REGNO (x) + 2], file);
else if (MEM_P (x))
{
+ machine_mode mode = GET_MODE (x);
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 8));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 8));
else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 8));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 8));
else
- output_address (XEXP (adjust_address_nv (x, SImode, 8), 0));
+ output_address (mode, XEXP (adjust_address_nv (x, SImode, 8), 0));
if (small_data_operand (x, GET_MODE (x)))
fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
reg_names[SMALL_DATA_REG]);
@@ -19551,13 +19949,16 @@ print_operand (FILE *file, rtx x, int code)
fputs (reg_names[REGNO (x) + 3], file);
else if (MEM_P (x))
{
+ machine_mode mode = GET_MODE (x);
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 12));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 12));
else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
- output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 12));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 12));
else
- output_address (XEXP (adjust_address_nv (x, SImode, 12), 0));
+ output_address (mode, XEXP (adjust_address_nv (x, SImode, 12), 0));
if (small_data_operand (x, GET_MODE (x)))
fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
reg_names[SMALL_DATA_REG]);
@@ -19645,9 +20046,9 @@ print_operand (FILE *file, rtx x, int code)
fprintf (file, "%d(%s)", - GET_MODE_SIZE (GET_MODE (x)),
reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
- output_address (XEXP (XEXP (x, 0), 1));
+ output_address (GET_MODE (x), XEXP (XEXP (x, 0), 1));
else
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
}
else
{
@@ -28006,6 +28407,7 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
|| rs6000_cpu_attr == CPU_POWER5
|| rs6000_cpu_attr == CPU_POWER7
|| rs6000_cpu_attr == CPU_POWER8
+ || rs6000_cpu_attr == CPU_POWER9
|| rs6000_cpu_attr == CPU_CELL)
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0))
@@ -28578,6 +28980,7 @@ rs6000_issue_rate (void)
case CPU_POWER7:
return 5;
case CPU_POWER8:
+ case CPU_POWER9:
return 7;
default:
return 1;
@@ -29211,6 +29614,7 @@ insn_must_be_first_in_group (rtx_insn *insn)
}
break;
case PROCESSOR_POWER8:
+ case PROCESSOR_POWER9:
type = get_attr_type (insn);
switch (type)
@@ -29341,6 +29745,7 @@ insn_must_be_last_in_group (rtx_insn *insn)
}
break;
case PROCESSOR_POWER8:
+ case PROCESSOR_POWER9:
type = get_attr_type (insn);
switch (type)
@@ -29459,7 +29864,7 @@ force_new_group (int sched_verbose, FILE *dump, rtx *group_insns,
/* Do we have a special group ending nop? */
if (rs6000_cpu_attr == CPU_POWER6 || rs6000_cpu_attr == CPU_POWER7
- || rs6000_cpu_attr == CPU_POWER8)
+ || rs6000_cpu_attr == CPU_POWER8 || rs6000_cpu_attr == CPU_POWER9)
{
nop = gen_group_ending_nop ();
emit_insn_before (nop, next_insn);
@@ -31670,12 +32075,15 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
else
*total = rs6000_cost->divsi;
}
- /* Add in shift and subtract for MOD. */
- if (code == MOD || code == UMOD)
+ /* Add in shift and subtract for MOD unless we have a mod instruction. */
+ if (!TARGET_MODULO && (code == MOD || code == UMOD))
*total += COSTS_N_INSNS (2);
return false;
case CTZ:
+ *total = COSTS_N_INSNS (TARGET_CTZ ? 1 : 4);
+ return false;
+
case FFS:
*total = COSTS_N_INSNS (4);
return false;
@@ -31750,6 +32158,17 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code,
return false;
case ASHIFT:
+ /* The EXTSWSLI instruction is a combined instruction. Don't count both
+ the sign extend and shift separately within the insn. */
+ if (TARGET_EXTSWSLI && mode == DImode
+ && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode)
+ {
+ *total = 0;
+ return false;
+ }
+ /* fall through */
+
case ASHIFTRT:
case LSHIFTRT:
case ROTATE:
@@ -31959,7 +32378,8 @@ rs6000_register_move_cost (machine_mode mode,
expensive than memory in order to bias spills to memory .*/
else if ((rs6000_cpu == PROCESSOR_POWER6
|| rs6000_cpu == PROCESSOR_POWER7
- || rs6000_cpu == PROCESSOR_POWER8)
+ || rs6000_cpu == PROCESSOR_POWER8
+ || rs6000_cpu == PROCESSOR_POWER9)
&& reg_classes_intersect_p (rclass, LINK_OR_CTR_REGS))
ret = 6 * hard_regno_nregs[0][mode];
@@ -33489,12 +33909,14 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "efficient-unaligned-vsx", OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
false, true },
{ "float128", OPTION_MASK_FLOAT128, false, true },
+ { "float128-hardware", OPTION_MASK_FLOAT128_HW, false, true },
{ "fprnd", OPTION_MASK_FPRND, false, true },
{ "hard-dfp", OPTION_MASK_DFP, false, true },
{ "htm", OPTION_MASK_HTM, false, true },
{ "isel", OPTION_MASK_ISEL, false, true },
{ "mfcrf", OPTION_MASK_MFCRF, false, true },
{ "mfpgpr", OPTION_MASK_MFPGPR, false, true },
+ { "modulo", OPTION_MASK_MODULO, false, true },
{ "mulhw", OPTION_MASK_MULHW, false, true },
{ "multiple", OPTION_MASK_MULTIPLE, false, true },
{ "popcntb", OPTION_MASK_POPCNTB, false, true },
@@ -33502,6 +33924,10 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "power8-fusion", OPTION_MASK_P8_FUSION, false, true },
{ "power8-fusion-sign", OPTION_MASK_P8_FUSION_SIGN, false, true },
{ "power8-vector", OPTION_MASK_P8_VECTOR, false, true },
+ { "power9-dform", OPTION_MASK_P9_DFORM, false, true },
+ { "power9-fusion", OPTION_MASK_P9_FUSION, false, true },
+ { "power9-minmax", OPTION_MASK_P9_MINMAX, false, true },
+ { "power9-vector", OPTION_MASK_P9_VECTOR, false, true },
{ "powerpc-gfxopt", OPTION_MASK_PPC_GFXOPT, false, true },
{ "powerpc-gpopt", OPTION_MASK_PPC_GPOPT, false, true },
{ "quad-memory", OPTION_MASK_QUAD_MEMORY, false, true },
@@ -33509,6 +33935,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "recip-precision", OPTION_MASK_RECIP_PRECISION, false, true },
{ "save-toc-indirect", OPTION_MASK_SAVE_TOC_INDIRECT, false, true },
{ "string", OPTION_MASK_STRING, false, true },
+ { "toc-fusion", OPTION_MASK_TOC_FUSION, false, true },
{ "update", OPTION_MASK_NO_UPDATE, true , true },
{ "upper-regs-df", OPTION_MASK_UPPER_REGS_DF, false, true },
{ "upper-regs-sf", OPTION_MASK_UPPER_REGS_SF, false, true },
@@ -35013,72 +35440,21 @@ expand_fusion_gpr_load (rtx *operands)
return;
}
-/* Return a string to fuse an addis instruction with a gpr load to the same
- register that we loaded up the addis instruction. The address that is used
- is the logical address that was formed during peephole2:
- (lo_sum (high) (low-part))
+/* Emit the addis instruction that will be part of a fused instruction
+ sequence. */
- The code is complicated, so we call output_asm_insn directly, and just
- return "". */
-
-const char *
-emit_fusion_gpr_load (rtx target, rtx mem)
+void
+emit_fusion_addis (rtx target, rtx addis_value, const char *comment,
+ const char *mode_name)
{
- rtx addis_value;
rtx fuse_ops[10];
- rtx addr;
- rtx load_offset;
- const char *addis_str = NULL;
- const char *load_str = NULL;
- const char *mode_name = NULL;
char insn_template[80];
- machine_mode mode;
+ const char *addis_str = NULL;
const char *comment_str = ASM_COMMENT_START;
- if (GET_CODE (mem) == ZERO_EXTEND)
- mem = XEXP (mem, 0);
-
- gcc_assert (REG_P (target) && MEM_P (mem));
-
if (*comment_str == ' ')
comment_str++;
- addr = XEXP (mem, 0);
- if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM)
- gcc_unreachable ();
-
- addis_value = XEXP (addr, 0);
- load_offset = XEXP (addr, 1);
-
- /* Now emit the load instruction to the same register. */
- mode = GET_MODE (mem);
- switch (mode)
- {
- case QImode:
- mode_name = "char";
- load_str = "lbz";
- break;
-
- case HImode:
- mode_name = "short";
- load_str = "lhz";
- break;
-
- case SImode:
- mode_name = "int";
- load_str = "lwz";
- break;
-
- case DImode:
- gcc_assert (TARGET_POWERPC64);
- mode_name = "long";
- load_str = "ld";
- break;
-
- default:
- gcc_unreachable ();
- }
-
/* Emit the addis instruction. */
fuse_ops[0] = target;
if (satisfies_constraint_L (addis_value))
@@ -35157,67 +35533,530 @@ emit_fusion_gpr_load (rtx target, rtx mem)
if (!addis_str)
fatal_insn ("Could not generate addis value for fusion", addis_value);
- sprintf (insn_template, "%s\t\t%s gpr load fusion, type %s", addis_str,
- comment_str, mode_name);
+ sprintf (insn_template, "%s\t\t%s %s, type %s", addis_str, comment_str,
+ comment, mode_name);
output_asm_insn (insn_template, fuse_ops);
+}
- /* Emit the D-form load instruction. */
- if (CONST_INT_P (load_offset) && satisfies_constraint_I (load_offset))
+/* Emit a D-form load or store instruction that is the second instruction
+ of a fusion sequence. */
+
+void
+emit_fusion_load_store (rtx load_store_reg, rtx addis_reg, rtx offset,
+ const char *insn_str)
+{
+ rtx fuse_ops[10];
+ char insn_template[80];
+
+ fuse_ops[0] = load_store_reg;
+ fuse_ops[1] = addis_reg;
+
+ if (CONST_INT_P (offset) && satisfies_constraint_I (offset))
{
- sprintf (insn_template, "%s %%0,%%1(%%0)", load_str);
- fuse_ops[1] = load_offset;
+ sprintf (insn_template, "%s %%0,%%2(%%1)", insn_str);
+ fuse_ops[2] = offset;
output_asm_insn (insn_template, fuse_ops);
}
- else if (GET_CODE (load_offset) == UNSPEC
- && XINT (load_offset, 1) == UNSPEC_TOCREL)
+ else if (GET_CODE (offset) == UNSPEC
+ && XINT (offset, 1) == UNSPEC_TOCREL)
{
if (TARGET_ELF)
- sprintf (insn_template, "%s %%0,%%1@toc@l(%%0)", load_str);
+ sprintf (insn_template, "%s %%0,%%2@toc@l(%%1)", insn_str);
else if (TARGET_XCOFF)
- sprintf (insn_template, "%s %%0,%%1@l(%%0)", load_str);
+ sprintf (insn_template, "%s %%0,%%2@l(%%1)", insn_str);
else
gcc_unreachable ();
- fuse_ops[1] = XVECEXP (load_offset, 0, 0);
+ fuse_ops[2] = XVECEXP (offset, 0, 0);
output_asm_insn (insn_template, fuse_ops);
}
- else if (GET_CODE (load_offset) == PLUS
- && GET_CODE (XEXP (load_offset, 0)) == UNSPEC
- && XINT (XEXP (load_offset, 0), 1) == UNSPEC_TOCREL
- && CONST_INT_P (XEXP (load_offset, 1)))
+ else if (GET_CODE (offset) == PLUS
+ && GET_CODE (XEXP (offset, 0)) == UNSPEC
+ && XINT (XEXP (offset, 0), 1) == UNSPEC_TOCREL
+ && CONST_INT_P (XEXP (offset, 1)))
{
- rtx tocrel_unspec = XEXP (load_offset, 0);
+ rtx tocrel_unspec = XEXP (offset, 0);
if (TARGET_ELF)
- sprintf (insn_template, "%s %%0,%%1+%%2@toc@l(%%0)", load_str);
+ sprintf (insn_template, "%s %%0,%%2+%%3@toc@l(%%1)", insn_str);
else if (TARGET_XCOFF)
- sprintf (insn_template, "%s %%0,%%1+%%2@l(%%0)", load_str);
+ sprintf (insn_template, "%s %%0,%%2+%%3@l(%%1)", insn_str);
else
gcc_unreachable ();
- fuse_ops[1] = XVECEXP (tocrel_unspec, 0, 0);
- fuse_ops[2] = XEXP (load_offset, 1);
+ fuse_ops[2] = XVECEXP (tocrel_unspec, 0, 0);
+ fuse_ops[3] = XEXP (offset, 1);
output_asm_insn (insn_template, fuse_ops);
}
- else if (TARGET_ELF && !TARGET_POWERPC64 && CONSTANT_P (load_offset))
+ else if (TARGET_ELF && !TARGET_POWERPC64 && CONSTANT_P (offset))
{
- sprintf (insn_template, "%s %%0,%%1@l(%%0)", load_str);
+ sprintf (insn_template, "%s %%0,%%2@l(%%1)", insn_str);
- fuse_ops[1] = load_offset;
+ fuse_ops[2] = offset;
output_asm_insn (insn_template, fuse_ops);
}
else
- fatal_insn ("Unable to generate load offset for fusion", load_offset);
+ fatal_insn ("Unable to generate load/store offset for fusion", offset);
+
+ return;
+}
+
+/* Wrap a TOC address that can be fused to indicate that special fusion
+ processing is needed. */
+
+rtx
+fusion_wrap_memory_address (rtx old_mem)
+{
+ rtx old_addr = XEXP (old_mem, 0);
+ rtvec v = gen_rtvec (1, old_addr);
+ rtx new_addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_FUSION_ADDIS);
+ return replace_equiv_address_nv (old_mem, new_addr, false);
+}
+
+/* Given an address, convert it into the addis and load offset parts. Addresses
+ created during the peephole2 process look like:
+ (lo_sum (high (unspec [(sym)] UNSPEC_TOCREL))
+ (unspec [(...)] UNSPEC_TOCREL))
+
+ Addresses created via toc fusion look like:
+ (unspec [(unspec [(...)] UNSPEC_TOCREL)] UNSPEC_FUSION_ADDIS)) */
+
+static void
+fusion_split_address (rtx addr, rtx *p_hi, rtx *p_lo)
+{
+ rtx hi, lo;
+
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_FUSION_ADDIS)
+ {
+ lo = XVECEXP (addr, 0, 0);
+ hi = gen_rtx_HIGH (Pmode, lo);
+ }
+ else if (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ {
+ hi = XEXP (addr, 0);
+ lo = XEXP (addr, 1);
+ }
+ else
+ gcc_unreachable ();
+
+ *p_hi = hi;
+ *p_lo = lo;
+}
+
+/* Return a string to fuse an addis instruction with a gpr load to the same
+ register that we loaded up the addis instruction. The address that is used
+ is the logical address that was formed during peephole2:
+ (lo_sum (high) (low-part))
+
+ Or the address is the TOC address that is wrapped before register allocation:
+ (unspec [(addr) (toc-reg)] UNSPEC_FUSION_ADDIS)
+
+ The code is complicated, so we call output_asm_insn directly, and just
+ return "". */
+
+const char *
+emit_fusion_gpr_load (rtx target, rtx mem)
+{
+ rtx addis_value;
+ rtx addr;
+ rtx load_offset;
+ const char *load_str = NULL;
+ const char *mode_name = NULL;
+ machine_mode mode;
+
+ if (GET_CODE (mem) == ZERO_EXTEND)
+ mem = XEXP (mem, 0);
+
+ gcc_assert (REG_P (target) && MEM_P (mem));
+
+ addr = XEXP (mem, 0);
+ fusion_split_address (addr, &addis_value, &load_offset);
+
+ /* Now emit the load instruction to the same register. */
+ mode = GET_MODE (mem);
+ switch (mode)
+ {
+ case QImode:
+ mode_name = "char";
+ load_str = "lbz";
+ break;
+
+ case HImode:
+ mode_name = "short";
+ load_str = "lhz";
+ break;
+
+ case SImode:
+ case SFmode:
+ mode_name = (mode == SFmode) ? "float" : "int";
+ load_str = "lwz";
+ break;
+
+ case DImode:
+ case DFmode:
+ gcc_assert (TARGET_POWERPC64);
+ mode_name = (mode == DFmode) ? "double" : "long";
+ load_str = "ld";
+ break;
+
+ default:
+ fatal_insn ("Bad GPR fusion", gen_rtx_SET (target, mem));
+ }
+
+ /* Emit the addis instruction. */
+ emit_fusion_addis (target, addis_value, "gpr load fusion", mode_name);
+
+ /* Emit the D-form load instruction. */
+ emit_fusion_load_store (target, target, load_offset, load_str);
+
+ return "";
+}
+
+
+/* Return true if the peephole2 can combine a load/store involving a
+ combination of an addis instruction and the memory operation. This was
+ added to the ISA 3.0 (power9) hardware. */
+
+bool
+fusion_p9_p (rtx addis_reg, /* register set via addis. */
+ rtx addis_value, /* addis value. */
+ rtx dest, /* destination (memory or register). */
+ rtx src) /* source (register or memory). */
+{
+ rtx addr, mem, offset;
+ enum machine_mode mode = GET_MODE (src);
+
+ /* Validate arguments. */
+ if (!base_reg_operand (addis_reg, GET_MODE (addis_reg)))
+ return false;
+
+ if (!fusion_gpr_addis (addis_value, GET_MODE (addis_value)))
+ return false;
+
+ /* Ignore extend operations that are part of the load. */
+ if (GET_CODE (src) == FLOAT_EXTEND || GET_CODE (src) == ZERO_EXTEND)
+ src = XEXP (src, 0);
+
+ /* Test for memory<-register or register<-memory. */
+ if (fpr_reg_operand (src, mode) || int_reg_operand (src, mode))
+ {
+ if (!MEM_P (dest))
+ return false;
+
+ mem = dest;
+ }
+
+ else if (MEM_P (src))
+ {
+ if (!fpr_reg_operand (dest, mode) && !int_reg_operand (dest, mode))
+ return false;
+
+ mem = src;
+ }
+
+ else
+ return false;
+
+ addr = XEXP (mem, 0); /* either PLUS or LO_SUM. */
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (!rtx_equal_p (addis_reg, XEXP (addr, 0)))
+ return false;
+
+ return satisfies_constraint_I (XEXP (addr, 1));
+ }
+
+ else if (GET_CODE (addr) == LO_SUM)
+ {
+ if (!rtx_equal_p (addis_reg, XEXP (addr, 0)))
+ return false;
+
+ offset = XEXP (addr, 1);
+ if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64))
+ return small_toc_ref (offset, GET_MODE (offset));
+
+ else if (TARGET_ELF && !TARGET_POWERPC64)
+ return CONSTANT_P (offset);
+ }
+
+ return false;
+}
+
+/* During the peephole2 pass, adjust and expand the insns for an extended fusion
+ load sequence.
+
+ The operands are:
+ operands[0] register set with addis
+ operands[1] value set via addis
+ operands[2] target register being loaded
+ operands[3] D-form memory reference using operands[0].
+
+ This is similar to the fusion introduced with power8, except it scales to
+ both loads/stores and does not require the result register to be the same as
+ the base register. At the moment, we only do this if register set with addis
+ is dead. */
+
+void
+expand_fusion_p9_load (rtx *operands)
+{
+ rtx tmp_reg = operands[0];
+ rtx addis_value = operands[1];
+ rtx target = operands[2];
+ rtx orig_mem = operands[3];
+ rtx new_addr, new_mem, orig_addr, offset, set, clobber, insn;
+ enum rtx_code plus_or_lo_sum;
+ machine_mode target_mode = GET_MODE (target);
+ machine_mode extend_mode = target_mode;
+ machine_mode ptr_mode = Pmode;
+ enum rtx_code extend = UNKNOWN;
+
+ if (GET_CODE (orig_mem) == FLOAT_EXTEND || GET_CODE (orig_mem) == ZERO_EXTEND)
+ {
+ extend = GET_CODE (orig_mem);
+ orig_mem = XEXP (orig_mem, 0);
+ target_mode = GET_MODE (orig_mem);
+ }
+
+ gcc_assert (MEM_P (orig_mem));
+
+ orig_addr = XEXP (orig_mem, 0);
+ plus_or_lo_sum = GET_CODE (orig_addr);
+ gcc_assert (plus_or_lo_sum == PLUS || plus_or_lo_sum == LO_SUM);
+
+ offset = XEXP (orig_addr, 1);
+ new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_value, offset);
+ new_mem = replace_equiv_address_nv (orig_mem, new_addr, false);
+
+ if (extend != UNKNOWN)
+ new_mem = gen_rtx_fmt_e (extend, extend_mode, new_mem);
+
+ new_mem = gen_rtx_UNSPEC (extend_mode, gen_rtvec (1, new_mem),
+ UNSPEC_FUSION_P9);
+
+ set = gen_rtx_SET (target, new_mem);
+ clobber = gen_rtx_CLOBBER (VOIDmode, tmp_reg);
+ insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber));
+ emit_insn (insn);
+
+ return;
+}
+
+/* During the peephole2 pass, adjust and expand the insns for an extended fusion
+ store sequence.
+
+ The operands are:
+ operands[0] register set with addis
+ operands[1] value set via addis
+ operands[2] target D-form memory being stored to
+ operands[3] register being stored
+
+ This is similar to the fusion introduced with power8, except it scales to
+ both loads/stores and does not require the result register to be the same as
+ the base register. At the moment, we only do this if register set with addis
+ is dead. */
+
+void
+expand_fusion_p9_store (rtx *operands)
+{
+ rtx tmp_reg = operands[0];
+ rtx addis_value = operands[1];
+ rtx orig_mem = operands[2];
+ rtx src = operands[3];
+ rtx new_addr, new_mem, orig_addr, offset, set, clobber, insn, new_src;
+ enum rtx_code plus_or_lo_sum;
+ machine_mode target_mode = GET_MODE (orig_mem);
+ machine_mode ptr_mode = Pmode;
+
+ gcc_assert (MEM_P (orig_mem));
+
+ orig_addr = XEXP (orig_mem, 0);
+ plus_or_lo_sum = GET_CODE (orig_addr);
+ gcc_assert (plus_or_lo_sum == PLUS || plus_or_lo_sum == LO_SUM);
+
+ offset = XEXP (orig_addr, 1);
+ new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_value, offset);
+ new_mem = replace_equiv_address_nv (orig_mem, new_addr, false);
+
+ new_src = gen_rtx_UNSPEC (target_mode, gen_rtvec (1, src),
+ UNSPEC_FUSION_P9);
+
+ set = gen_rtx_SET (new_mem, new_src);
+ clobber = gen_rtx_CLOBBER (VOIDmode, tmp_reg);
+ insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber));
+ emit_insn (insn);
+
+ return;
+}
+
+/* Return a string to fuse an addis instruction with a load using extended
+ fusion. The address that is used is the logical address that was formed
+ during peephole2: (lo_sum (high) (low-part))
+
+ The code is complicated, so we call output_asm_insn directly, and just
+ return "". */
+
+const char *
+emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
+{
+ enum machine_mode mode = GET_MODE (reg);
+ rtx hi;
+ rtx lo;
+ rtx addr;
+ const char *load_string;
+ int r;
+
+ if (GET_CODE (mem) == FLOAT_EXTEND || GET_CODE (mem) == ZERO_EXTEND)
+ {
+ mem = XEXP (mem, 0);
+ mode = GET_MODE (mem);
+ }
+
+ if (GET_CODE (reg) == SUBREG)
+ {
+ gcc_assert (SUBREG_BYTE (reg) == 0);
+ reg = SUBREG_REG (reg);
+ }
+
+ if (!REG_P (reg))
+ fatal_insn ("emit_fusion_p9_load, bad reg #1", reg);
+
+ r = REGNO (reg);
+ if (FP_REGNO_P (r))
+ {
+ if (mode == SFmode)
+ load_string = "lfs";
+ else if (mode == DFmode || mode == DImode)
+ load_string = "lfd";
+ else
+ gcc_unreachable ();
+ }
+ else if (INT_REGNO_P (r))
+ {
+ switch (mode)
+ {
+ case QImode:
+ load_string = "lbz";
+ break;
+ case HImode:
+ load_string = "lhz";
+ break;
+ case SImode:
+ case SFmode:
+ load_string = "lwz";
+ break;
+ case DImode:
+ case DFmode:
+ if (!TARGET_POWERPC64)
+ gcc_unreachable ();
+ load_string = "ld";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ fatal_insn ("emit_fusion_p9_load, bad reg #2", reg);
+
+ if (!MEM_P (mem))
+ fatal_insn ("emit_fusion_p9_load not MEM", mem);
+
+ addr = XEXP (mem, 0);
+ fusion_split_address (addr, &hi, &lo);
+
+ /* Emit the addis instruction. */
+ emit_fusion_addis (tmp_reg, hi, "power9 load fusion", GET_MODE_NAME (mode));
+
+ /* Emit the D-form load instruction. */
+ emit_fusion_load_store (reg, tmp_reg, lo, load_string);
return "";
}
+
+/* Return a string to fuse an addis instruction with a store using extended
+ fusion. The address that is used is the logical address that was formed
+ during peephole2: (lo_sum (high) (low-part))
+
+ The code is complicated, so we call output_asm_insn directly, and just
+ return "". */
+
+const char *
+emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
+{
+ enum machine_mode mode = GET_MODE (reg);
+ rtx hi;
+ rtx lo;
+ rtx addr;
+ const char *store_string;
+ int r;
+
+ if (GET_CODE (reg) == SUBREG)
+ {
+ gcc_assert (SUBREG_BYTE (reg) == 0);
+ reg = SUBREG_REG (reg);
+ }
+
+ if (!REG_P (reg))
+ fatal_insn ("emit_fusion_p9_store, bad reg #1", reg);
+
+ r = REGNO (reg);
+ if (FP_REGNO_P (r))
+ {
+ if (mode == SFmode)
+ store_string = "stfs";
+ else if (mode == DFmode)
+ store_string = "stfd";
+ else
+ gcc_unreachable ();
+ }
+ else if (INT_REGNO_P (r))
+ {
+ switch (mode)
+ {
+ case QImode:
+ store_string = "stb";
+ break;
+ case HImode:
+ store_string = "sth";
+ break;
+ case SImode:
+ case SFmode:
+ store_string = "stw";
+ break;
+ case DImode:
+ case DFmode:
+ if (!TARGET_POWERPC64)
+ gcc_unreachable ();
+ store_string = "std";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ fatal_insn ("emit_fusion_p9_store, bad reg #2", reg);
+
+ if (!MEM_P (mem))
+ fatal_insn ("emit_fusion_p9_store not MEM", mem);
+
+ addr = XEXP (mem, 0);
+ fusion_split_address (addr, &hi, &lo);
+
+ /* Emit the addis instruction. */
+ emit_fusion_addis (tmp_reg, hi, "power9 store fusion", GET_MODE_NAME (mode));
+
+ /* Emit the D-form load instruction. */
+ emit_fusion_load_store (reg, tmp_reg, lo, store_string);
+
+ return "";
+}
+
/* Analyze vector computations and remove unnecessary doubleword
swaps (xxswapdi instructions). This pass is performed only
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 02da097227b..4ac4f3134d5 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -95,6 +95,12 @@
#define ASM_CPU_POWER8_SPEC ASM_CPU_POWER7_SPEC
#endif
+#ifdef HAVE_AS_POWER9
+#define ASM_CPU_POWER9_SPEC "-mpower9"
+#else
+#define ASM_CPU_POWER9_SPEC ASM_CPU_POWER8_SPEC
+#endif
+
#ifdef HAVE_AS_DCI
#define ASM_CPU_476_SPEC "-m476"
#else
@@ -119,6 +125,7 @@
%{mcpu=power6x: %(asm_cpu_power6) -maltivec} \
%{mcpu=power7: %(asm_cpu_power7)} \
%{mcpu=power8: %(asm_cpu_power8)} \
+%{mcpu=power9: %(asm_cpu_power9)} \
%{mcpu=a2: -ma2} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rs64a: -mppc64} \
@@ -193,6 +200,7 @@
{ "asm_cpu_power6", ASM_CPU_POWER6_SPEC }, \
{ "asm_cpu_power7", ASM_CPU_POWER7_SPEC }, \
{ "asm_cpu_power8", ASM_CPU_POWER8_SPEC }, \
+ { "asm_cpu_power9", ASM_CPU_POWER9_SPEC }, \
{ "asm_cpu_476", ASM_CPU_476_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -557,6 +565,8 @@ extern int rs6000_vector_align[];
#define TARGET_FCFIDUS TARGET_POPCNTD
#define TARGET_FCTIDUZ TARGET_POPCNTD
#define TARGET_FCTIWUZ TARGET_POPCNTD
+#define TARGET_CTZ TARGET_MODULO
+#define TARGET_EXTSWSLI (TARGET_MODULO && TARGET_POWERPC64)
#define TARGET_XSCVDPSPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR)
#define TARGET_XSCVSPDPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR)
@@ -693,6 +703,22 @@ extern int rs6000_vector_align[];
&& TARGET_DOUBLE_FLOAT \
&& (TARGET_PPC_GFXOPT || VECTOR_UNIT_VSX_P (DFmode)))
+/* Conditions to allow TOC fusion for loading/storing integers. */
+#define TARGET_TOC_FUSION_INT (TARGET_P8_FUSION \
+ && TARGET_TOC_FUSION \
+ && (TARGET_CMODEL != CMODEL_SMALL) \
+ && TARGET_POWERPC64)
+
+/* Conditions to allow TOC fusion for loading/storing floating point. */
+#define TARGET_TOC_FUSION_FP (TARGET_P9_FUSION \
+ && TARGET_TOC_FUSION \
+ && (TARGET_CMODEL != CMODEL_SMALL) \
+ && TARGET_POWERPC64 \
+ && TARGET_HARD_FLOAT \
+ && TARGET_FPRS \
+ && TARGET_SINGLE_FLOAT \
+ && TARGET_DOUBLE_FLOAT)
+
/* Whether the various reciprocal divide/square root estimate instructions
exist, and whether we should automatically generate code for the instruction
by default. */
@@ -2087,8 +2113,12 @@ do { \
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
((VALUE) = ((MODE) == SImode ? 32 : 64), 1)
-/* The CTZ patterns return -1 for input of zero. */
-#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = -1, 1)
+/* The CTZ patterns that are implemented in terms of CLZ return -1 for input of
+ zero. The hardware instructions added in Power9 return 32 or 64. */
+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((!TARGET_CTZ) \
+ ? ((VALUE) = -1, 1) \
+ : ((VALUE) = ((MODE) == SImode ? 32 : 64), 1))
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index eeeef342228..49c5c98f7d5 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -141,6 +141,8 @@
UNSPEC_LSQ
UNSPEC_FUSION_GPR
UNSPEC_STACK_CHECK
+ UNSPEC_FUSION_P9
+ UNSPEC_FUSION_ADDIS
])
;;
@@ -252,7 +254,7 @@
ppc750,ppc7400,ppc7450,
ppc403,ppc405,ppc440,ppc476,
ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,
- power4,power5,power6,power7,power8,
+ power4,power5,power6,power7,power8,power9,
rs64a,mpccore,cell,ppca2,titan"
(const (symbol_ref "rs6000_cpu_attr")))
@@ -327,12 +329,28 @@
; QImode or HImode for small atomic ops
(define_mode_iterator QHI [QI HI])
+; QImode, HImode, SImode for fused ops only for GPR loads
+(define_mode_iterator QHSI [QI HI SI])
+
; HImode or SImode for sign extended fusion ops
(define_mode_iterator HSI [HI SI])
; SImode or DImode, even if DImode doesn't fit in GPRs.
(define_mode_iterator SDI [SI DI])
+; Types that can be fused with an ADDIS instruction to load or store a GPR
+; register that has reg+offset addressing.
+(define_mode_iterator GPR_FUSION [QI
+ HI
+ SI
+ (DI "TARGET_POWERPC64")
+ SF
+ (DF "TARGET_POWERPC64")])
+
+; Types that can be fused with an ADDIS instruction to load or store a FPR
+; register that has reg+offset addressing.
+(define_mode_iterator FPR_FUSION [DI SF DF])
+
; The size of a pointer. Also, the size of the value that a record-condition
; (one with a '.') will compare; and the size used for arithmetic carries.
(define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
@@ -2101,12 +2119,25 @@
(clobber (reg:GPR CA_REGNO))])]
""
{
+ if (TARGET_CTZ)
+ {
+ emit_insn (gen_ctz<mode>2_hw (operands[0], operands[1]));
+ DONE;
+ }
+
operands[2] = gen_reg_rtx (<MODE>mode);
operands[3] = gen_reg_rtx (<MODE>mode);
operands[4] = gen_reg_rtx (<MODE>mode);
operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1);
})
+(define_insn "ctz<mode>2_hw"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (ctz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
+ "TARGET_CTZ"
+ "cnttz<wd> %0,%1"
+ [(set_attr "type" "cntlz")])
+
(define_expand "ffs<mode>2"
[(set (match_dup 2)
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
@@ -2885,9 +2916,9 @@
(set_attr "cell_micro" "not")])
(define_expand "mod<mode>3"
- [(use (match_operand:GPR 0 "gpc_reg_operand" ""))
- (use (match_operand:GPR 1 "gpc_reg_operand" ""))
- (use (match_operand:GPR 2 "reg_or_cint_operand" ""))]
+ [(set (match_operand:GPR 0 "gpc_reg_operand")
+ (mod:GPR (match_operand:GPR 1 "gpc_reg_operand")
+ (match_operand:GPR 2 "reg_or_cint_operand")))]
""
{
int i;
@@ -2897,16 +2928,93 @@
if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) <= 0
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
- FAIL;
+ {
+ if (!TARGET_MODULO)
+ FAIL;
- temp1 = gen_reg_rtx (<MODE>mode);
- temp2 = gen_reg_rtx (<MODE>mode);
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ }
+ else
+ {
+ temp1 = gen_reg_rtx (<MODE>mode);
+ temp2 = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_div<mode>3 (temp1, operands[1], operands[2]));
- emit_insn (gen_ashl<mode>3 (temp2, temp1, GEN_INT (i)));
- emit_insn (gen_sub<mode>3 (operands[0], operands[1], temp2));
- DONE;
+ emit_insn (gen_div<mode>3 (temp1, operands[1], operands[2]));
+ emit_insn (gen_ashl<mode>3 (temp2, temp1, GEN_INT (i)));
+ emit_insn (gen_sub<mode>3 (operands[0], operands[1], temp2));
+ DONE;
+ }
})
+
+;; In order to enable using a peephole2 for combining div/mod to eliminate the
+;; mod, prefer putting the result of mod into a different register
+(define_insn "*mod<mode>3"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (mod:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "gpc_reg_operand" "r")))]
+ "TARGET_MODULO"
+ "mods<wd> %0,%1,%2"
+ [(set_attr "type" "div")
+ (set_attr "size" "<bits>")])
+
+
+(define_insn "umod<mode>3"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (umod:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "gpc_reg_operand" "r")))]
+ "TARGET_MODULO"
+ "modu<wd> %0,%1,%2"
+ [(set_attr "type" "div")
+ (set_attr "size" "<bits>")])
+
+;; On machines with modulo support, do a combined div/mod the old fashioned
+;; method, since the multiply/subtract is faster than doing the mod instruction
+;; after a divide.
+
+(define_peephole2
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "gpc_reg_operand" "")))
+ (set (match_operand:GPR 3 "gpc_reg_operand" "")
+ (mod:GPR (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_MODULO
+ && ! reg_mentioned_p (operands[0], operands[1])
+ && ! reg_mentioned_p (operands[0], operands[2])
+ && ! reg_mentioned_p (operands[3], operands[1])
+ && ! reg_mentioned_p (operands[3], operands[2])"
+ [(set (match_dup 0)
+ (div:GPR (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 3)
+ (mult:GPR (match_dup 0)
+ (match_dup 2)))
+ (set (match_dup 3)
+ (minus:GPR (match_dup 1)
+ (match_dup 3)))])
+
+(define_peephole2
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "gpc_reg_operand" "")))
+ (set (match_operand:GPR 3 "gpc_reg_operand" "")
+ (umod:GPR (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_MODULO
+ && ! reg_mentioned_p (operands[0], operands[1])
+ && ! reg_mentioned_p (operands[0], operands[2])
+ && ! reg_mentioned_p (operands[3], operands[1])
+ && ! reg_mentioned_p (operands[3], operands[2])"
+ [(set (match_dup 0)
+ (div:GPR (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 3)
+ (mult:GPR (match_dup 0)
+ (match_dup 2)))
+ (set (match_dup 3)
+ (minus:GPR (match_dup 1)
+ (match_dup 3)))])
+
;; Logical instructions
;; The logical instructions are mostly combined by using match_operator,
@@ -3843,6 +3951,127 @@
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
+;; Pretend we have a memory form of extswsli until register allocation is done
+;; so that we use LWZ to load the value from memory, instead of LWA.
+(define_insn_and_split "ashdi3_extswsli"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (ashift:DI
+ (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,m"))
+ (match_operand:DI 2 "u6bit_cint_operand" "n,n")))]
+ "TARGET_EXTSWSLI"
+ "@
+ extswsli %0,%1,%2
+ #"
+ "&& reload_completed && MEM_P (operands[1])"
+ [(set (match_dup 3)
+ (match_dup 1))
+ (set (match_dup 0)
+ (ashift:DI (sign_extend:DI (match_dup 3))
+ (match_dup 2)))]
+{
+ operands[3] = gen_lowpart (SImode, operands[0]);
+}
+ [(set_attr "type" "shift")
+ (set_attr "maybe_var_shift" "no")])
+
+
+(define_insn_and_split "ashdi3_extswsli_dot"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,?x,??y")
+ (compare:CC
+ (ashift:DI
+ (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,r,m,m"))
+ (match_operand:DI 2 "u6bit_cint_operand" "n,n,n,n"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r,r,r,r"))]
+ "TARGET_EXTSWSLI"
+ "@
+ extswsli. %0,%1,%2
+ #
+ #
+ #"
+ "&& reload_completed
+ && (cc_reg_not_cr0_operand (operands[3], CCmode)
+ || memory_operand (operands[1], SImode))"
+ [(pc)]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx shift = operands[2];
+ rtx cr = operands[3];
+ rtx src2;
+
+ if (!MEM_P (src))
+ src2 = src;
+ else
+ {
+ src2 = gen_lowpart (SImode, dest);
+ emit_move_insn (src2, src);
+ }
+
+ if (REGNO (cr) == CR0_REGNO)
+ {
+ emit_insn (gen_ashdi3_extswsli_dot (dest, src2, shift, cr));
+ DONE;
+ }
+
+ emit_insn (gen_ashdi3_extswsli (dest, src2, shift));
+ emit_insn (gen_rtx_SET (cr, gen_rtx_COMPARE (CCmode, dest, const0_rtx)));
+ DONE;
+}
+ [(set_attr "type" "shift")
+ (set_attr "maybe_var_shift" "no")
+ (set_attr "dot" "yes")
+ (set_attr "length" "4,8,8,12")])
+
+(define_insn_and_split "ashdi3_extswsli_dot2"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,?x,??y")
+ (compare:CC
+ (ashift:DI
+ (sign_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "r,r,m,m"))
+ (match_operand:DI 2 "u6bit_cint_operand" "n,n,n,n"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
+ (ashift:DI (sign_extend:DI (match_dup 1))
+ (match_dup 2)))]
+ "TARGET_EXTSWSLI"
+ "@
+ extswsli. %0,%1,%2
+ #
+ #
+ #"
+ "&& reload_completed
+ && (cc_reg_not_cr0_operand (operands[3], CCmode)
+ || memory_operand (operands[1], SImode))"
+ [(pc)]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx shift = operands[2];
+ rtx cr = operands[3];
+ rtx src2;
+
+ if (!MEM_P (src))
+ src2 = src;
+ else
+ {
+ src2 = gen_lowpart (SImode, dest);
+ emit_move_insn (src2, src);
+ }
+
+ if (REGNO (cr) == CR0_REGNO)
+ {
+ emit_insn (gen_ashdi3_extswsli_dot2 (dest, src2, shift, cr));
+ DONE;
+ }
+
+ emit_insn (gen_ashdi3_extswsli (dest, src2, shift));
+ emit_insn (gen_rtx_SET (cr, gen_rtx_COMPARE (CCmode, dest, const0_rtx)));
+ DONE;
+}
+ [(set_attr "type" "shift")
+ (set_attr "maybe_var_shift" "no")
+ (set_attr "dot" "yes")
+ (set_attr "length" "4,8,8,12")])
(define_insn "lshr<mode>3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
@@ -12381,6 +12610,66 @@
;; a GPR. The addis instruction must be adjacent to the load, and use the same
;; register that is being loaded. The fused ops must be physically adjacent.
+;; There are two parts to addis fusion. The support for fused TOCs occur
+;; before register allocation, and is meant to reduce the lifetime for the
+;; tempoary register that holds the ADDIS result. On Power8 GPR loads, we try
+;; to use the register that is being load. The peephole2 then gathers any
+;; other fused possibilities that it can find after register allocation. If
+;; power9 fusion is selected, we also fuse floating point loads/stores.
+
+;; Fused TOC support: Replace simple GPR loads with a fused form. This is done
+;; before register allocation, so that we can avoid allocating a temporary base
+;; register that won't be used, and that we try to load into base registers,
+;; and not register 0. If we can't get a fused GPR load, generate a P9 fusion
+;; (addis followed by load) even on power8.
+
+(define_split
+ [(set (match_operand:INT1 0 "toc_fusion_or_p9_reg_operand" "")
+ (match_operand:INT1 1 "toc_fusion_mem_raw" ""))]
+ "TARGET_TOC_FUSION_INT && can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0) (match_dup 2))
+ (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
+ (use (match_dup 3))
+ (clobber (scratch:DI))])]
+{
+ operands[2] = fusion_wrap_memory_address (operands[1]);
+ operands[3] = gen_rtx_REG (Pmode, TOC_REGISTER);
+})
+
+(define_insn "*toc_fusionload_<mode>"
+ [(set (match_operand:QHSI 0 "int_reg_operand" "=&b,??r")
+ (match_operand:QHSI 1 "toc_fusion_mem_wrapped" "wG,wG"))
+ (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
+ (use (match_operand:DI 2 "base_reg_operand" "r,r"))
+ (clobber (match_scratch:DI 3 "=X,&b"))]
+ "TARGET_TOC_FUSION_INT"
+{
+ if (base_reg_operand (operands[0], <MODE>mode))
+ return emit_fusion_gpr_load (operands[0], operands[1]);
+
+ return emit_fusion_p9_load (operands[0], operands[1], operands[3]);
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "8")])
+
+(define_insn "*toc_fusionload_di"
+ [(set (match_operand:DI 0 "int_reg_operand" "=&b,??r,?d")
+ (match_operand:DI 1 "toc_fusion_mem_wrapped" "wG,wG,wG"))
+ (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS)
+ (use (match_operand:DI 2 "base_reg_operand" "r,r,r"))
+ (clobber (match_scratch:DI 3 "=X,&b,&b"))]
+ "TARGET_TOC_FUSION_INT && TARGET_POWERPC64
+ && (MEM_P (operands[1]) || int_reg_operand (operands[0], DImode))"
+{
+ if (base_reg_operand (operands[0], DImode))
+ return emit_fusion_gpr_load (operands[0], operands[1]);
+
+ return emit_fusion_p9_load (operands[0], operands[1], operands[3]);
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "8")])
+
+
;; Find cases where the addis that feeds into a load instruction is either used
;; once or is the same as the target register, and replace it with the fusion
;; insn
@@ -12404,7 +12693,7 @@
(define_insn "fusion_gpr_load_<mode>"
[(set (match_operand:INT1 0 "base_reg_operand" "=&b")
- (unspec:INT1 [(match_operand:INT1 1 "fusion_gpr_mem_combo" "")]
+ (unspec:INT1 [(match_operand:INT1 1 "fusion_addis_mem_combo_load" "")]
UNSPEC_FUSION_GPR))]
"TARGET_P8_FUSION"
{
@@ -12414,6 +12703,133 @@
(set_attr "length" "8")])
+;; ISA 3.0 (power9) fusion support
+;; Merge addis with floating load/store to FPRs (or GPRs).
+(define_peephole2
+ [(set (match_operand:P 0 "base_reg_operand" "")
+ (match_operand:P 1 "fusion_gpr_addis" ""))
+ (set (match_operand:SFDF 2 "toc_fusion_or_p9_reg_operand" "")
+ (match_operand:SFDF 3 "fusion_offsettable_mem_operand" ""))]
+ "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
+ && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])"
+ [(const_int 0)]
+{
+ expand_fusion_p9_load (operands);
+ DONE;
+})
+
+(define_peephole2
+ [(set (match_operand:P 0 "base_reg_operand" "")
+ (match_operand:P 1 "fusion_gpr_addis" ""))
+ (set (match_operand:SFDF 2 "offsettable_mem_operand" "")
+ (match_operand:SFDF 3 "toc_fusion_or_p9_reg_operand" ""))]
+ "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
+ && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])"
+ [(const_int 0)]
+{
+ expand_fusion_p9_store (operands);
+ DONE;
+})
+
+(define_peephole2
+ [(set (match_operand:SDI 0 "int_reg_operand" "")
+ (match_operand:SDI 1 "upper16_cint_operand" ""))
+ (set (match_dup 0)
+ (ior:SDI (match_dup 0)
+ (match_operand:SDI 2 "u_short_cint_operand" "")))]
+ "TARGET_P9_FUSION"
+ [(set (match_dup 0)
+ (unspec:SDI [(match_dup 1)
+ (match_dup 2)] UNSPEC_FUSION_P9))])
+
+(define_peephole2
+ [(set (match_operand:SDI 0 "int_reg_operand" "")
+ (match_operand:SDI 1 "upper16_cint_operand" ""))
+ (set (match_operand:SDI 2 "int_reg_operand" "")
+ (ior:SDI (match_dup 0)
+ (match_operand:SDI 3 "u_short_cint_operand" "")))]
+ "TARGET_P9_FUSION
+ && !rtx_equal_p (operands[0], operands[2])
+ && peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 2)
+ (unspec:SDI [(match_dup 1)
+ (match_dup 3)] UNSPEC_FUSION_P9))])
+
+;; Fusion insns, created by the define_peephole2 above (and eventually by
+;; reload). Because we want to eventually have secondary_reload generate
+;; these, they have to have a single alternative that gives the register
+;; classes. This means we need to have separate gpr/fpr/altivec versions.
+(define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load"
+ [(set (match_operand:GPR_FUSION 0 "int_reg_operand" "=r")
+ (unspec:GPR_FUSION
+ [(match_operand:GPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
+ UNSPEC_FUSION_P9))
+ (clobber (match_operand:P 2 "base_reg_operand" "=&b"))]
+ "TARGET_P9_FUSION"
+{
+ /* This insn is a secondary reload insn, which cannot have alternatives.
+ If we are not loading up register 0, use the power8 fusion instead. */
+ if (base_reg_operand (operands[0], <GPR_FUSION:MODE>mode))
+ return emit_fusion_gpr_load (operands[0], operands[1]);
+
+ return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "8")])
+
+(define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store"
+ [(set (match_operand:GPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
+ (unspec:GPR_FUSION
+ [(match_operand:GPR_FUSION 1 "int_reg_operand" "r")]
+ UNSPEC_FUSION_P9))
+ (clobber (match_operand:P 2 "base_reg_operand" "=&b"))]
+ "TARGET_P9_FUSION"
+{
+ return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
+}
+ [(set_attr "type" "store")
+ (set_attr "length" "8")])
+
+(define_insn "fusion_fpr_<P:mode>_<FPR_FUSION:mode>_load"
+ [(set (match_operand:FPR_FUSION 0 "fpr_reg_operand" "=d")
+ (unspec:FPR_FUSION
+ [(match_operand:FPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
+ UNSPEC_FUSION_P9))
+ (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
+ "TARGET_P9_FUSION"
+{
+ return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
+}
+ [(set_attr "type" "fpload")
+ (set_attr "length" "8")])
+
+(define_insn "fusion_fpr_<P:mode>_<FPR_FUSION:mode>_store"
+ [(set (match_operand:FPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
+ (unspec:FPR_FUSION
+ [(match_operand:FPR_FUSION 1 "fpr_reg_operand" "d")]
+ UNSPEC_FUSION_P9))
+ (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
+ "TARGET_P9_FUSION"
+{
+ return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
+}
+ [(set_attr "type" "fpstore")
+ (set_attr "length" "8")])
+
+(define_insn "*fusion_p9_<mode>_constant"
+ [(set (match_operand:SDI 0 "int_reg_operand" "=r")
+ (unspec:SDI [(match_operand:SDI 1 "upper16_cint_operand" "L")
+ (match_operand:SDI 2 "u_short_cint_operand" "K")]
+ UNSPEC_FUSION_P9))]
+ "TARGET_P9_FUSION"
+{
+ emit_fusion_addis (operands[0], operands[1], "constant", "<MODE>");
+ return "ori %0,%0,%2";
+}
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
+
+
;; Miscellaneous ISA 2.06 (power7) instructions
(define_insn "addg6s"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -12580,6 +12996,7 @@
"xxpermdi %x0,%x1,%x2,0"
[(set_attr "type" "vecperm")])
+
(include "sync.md")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index b9e4b7dfdb6..61e3c8a323e 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -601,6 +601,34 @@ moptimize-swaps
Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
Analyze and remove doubleword swaps from VSX computations.
+mpower9-fusion
+Target Report Mask(P9_FUSION) Var(rs6000_isa_flags)
+Fuse certain operations together for better performance on power9.
+
+mpower9-vector
+Target Report Mask(P9_VECTOR) Var(rs6000_isa_flags)
+Use/do not use vector and scalar instructions added in ISA 3.0.
+
+mpower9-dform
+Target Undocumented Mask(P9_DFORM) Var(rs6000_isa_flags)
+Use/do not use vector and scalar instructions added in ISA 3.0.
+
+mpower9-minmax
+Target Undocumented Mask(P9_MINMAX) Var(rs6000_isa_flags)
+Use/do not use the new min/max instructions defined in ISA 3.0.
+
+mtoc-fusion
+Target Undocumented Mask(TOC_FUSION) Var(rs6000_isa_flags)
+Fuse medium/large code model toc references with the memory instruction.
+
+mmodulo
+Target Report Mask(MODULO) Var(rs6000_isa_flags)
+Generate the integer modulo instructions.
+
mfloat128
Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
Enable/disable IEEE 128-bit floating point via the __float128 keyword.
+
+mfloat128-hardware
+Target Report Mask(FLOAT128_HW) Var(rs6000_isa_flags)
+Enable/disable using IEEE 128-bit floating point instructions.
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 055bac1b4da..bd0c0f4ba29 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -379,7 +379,7 @@ rx_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
reference whose address is ADDR. */
static void
-rx_print_operand_address (FILE * file, rtx addr)
+rx_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
{
switch (GET_CODE (addr))
{
@@ -690,7 +690,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
case MEM:
if (! WORDS_BIG_ENDIAN)
op = adjust_address (op, SImode, 4);
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
break;
default:
gcc_unreachable ();
@@ -714,7 +714,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
case MEM:
if (WORDS_BIG_ENDIAN)
op = adjust_address (op, SImode, 4);
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
break;
default:
gcc_unreachable ();
@@ -846,11 +846,11 @@ rx_print_operand (FILE * file, rtx op, int letter)
}
case MEM:
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
break;
case PLUS:
- output_address (op);
+ output_address (VOIDmode, op);
break;
case REG:
@@ -915,7 +915,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
case SYMBOL_REF:
case LABEL_REF:
case CODE_LABEL:
- rx_print_operand_address (file, op);
+ rx_print_operand_address (file, VOIDmode, op);
break;
default:
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 5e3513a6b89..40ee2f77b31 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -7031,7 +7031,7 @@ print_operand (FILE *file, rtx x, int code)
break;
case MEM:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
case CONST:
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 530fe530785..919ea1c99c7 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -212,7 +212,7 @@ static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
static void sh_print_operand (FILE *, rtx, int);
-static void sh_print_operand_address (FILE *, rtx);
+static void sh_print_operand_address (FILE *, machine_mode, rtx);
static bool sh_print_operand_punct_valid_p (unsigned char code);
static bool sh_asm_output_addr_const_extra (FILE *file, rtx x);
static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -1144,7 +1144,7 @@ sh_override_options_after_change (void)
/* Print the operand address in x to the stream. */
static void
-sh_print_operand_address (FILE *stream, rtx x)
+sh_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
{
switch (GET_CODE (x))
{
@@ -1296,7 +1296,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
else if (MEM_P (x))
{
x = adjust_address (x, SImode, 4 * SH_REG_LSW_OFFSET);
- sh_print_operand_address (stream, XEXP (x, 0));
+ sh_print_operand_address (stream, GET_MODE (x), XEXP (x, 0));
}
else
{
@@ -1323,7 +1323,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
else if (MEM_P (x))
{
x = adjust_address (x, SImode, 4 * SH_REG_MSW_OFFSET);
- sh_print_operand_address (stream, XEXP (x, 0));
+ sh_print_operand_address (stream, GET_MODE (x), XEXP (x, 0));
}
else
{
@@ -1348,10 +1348,13 @@ sh_print_operand (FILE *stream, rtx x, int code)
fputs (reg_names[REGNO (x) + 1], (stream));
break;
case MEM:
- if (GET_CODE (XEXP (x, 0)) != PRE_DEC
- && GET_CODE (XEXP (x, 0)) != POST_INC)
- x = adjust_address (x, SImode, 4);
- sh_print_operand_address (stream, XEXP (x, 0));
+ {
+ machine_mode mode = GET_MODE (x);
+ if (GET_CODE (XEXP (x, 0)) != PRE_DEC
+ && GET_CODE (XEXP (x, 0)) != POST_INC)
+ x = adjust_address (x, SImode, 4);
+ sh_print_operand_address (stream, mode, XEXP (x, 0));
+ }
break;
default:
break;
@@ -1562,7 +1565,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
break;
case MEM:
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
default:
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index f444e48659d..6bf0599feaa 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -398,11 +398,9 @@ along with GCC; see the file COPYING3. If not see
#define NO_DBX_BNSYM_ENSYM 1
#endif
-#ifndef USE_GLD
-/* The Solaris linker doesn't understand constructor priorities. */
+/* Enable constructor priorities if the configured linker supports it. */
#undef SUPPORTS_INIT_PRIORITY
-#define SUPPORTS_INIT_PRIORITY 0
-#endif
+#define SUPPORTS_INIT_PRIORITY HAVE_INITFINI_ARRAY_SUPPORT
/* Solaris has an implementation of __enable_execute_stack. */
#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 6d877d6fb95..23f112583c2 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -617,7 +617,7 @@ static machine_mode sparc_preferred_simd_mode (machine_mode);
static reg_class_t sparc_preferred_reload_class (rtx x, reg_class_t rclass);
static bool sparc_print_operand_punct_valid_p (unsigned char);
static void sparc_print_operand (FILE *, rtx, int);
-static void sparc_print_operand_address (FILE *, rtx);
+static void sparc_print_operand_address (FILE *, machine_mode, rtx);
static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
machine_mode,
secondary_reload_info *);
@@ -7329,9 +7329,10 @@ sparc_function_value_1 (const_tree type, machine_mode mode,
mode = word_mode;
}
- /* We should only have pointer and integer types at this point. This must
- match sparc_promote_function_mode. */
+ /* We should only have pointer and integer types at this point, except with
+ -freg-struct-return. This must match sparc_promote_function_mode. */
else if (TARGET_ARCH32
+ && !(type && AGGREGATE_TYPE_P (type))
&& mclass == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
mode = word_mode;
@@ -8802,7 +8803,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
return;
case 'm':
/* Print the operand's address only. */
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 'r':
/* In this case we need a register. Use %g0 if the
@@ -8895,7 +8896,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
/* Operand must be a MEM; write its address. */
if (GET_CODE (x) != MEM)
output_operand_lossage ("invalid %%f operand");
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 's':
@@ -8933,7 +8934,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
/* Poor Sun assembler doesn't understand absolute addressing. */
if (CONSTANT_P (XEXP (x, 0)))
fputs ("%g0+", file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
fputc (']', file);
}
else if (GET_CODE (x) == HIGH)
@@ -8972,7 +8973,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
static void
-sparc_print_operand_address (FILE *file, rtx x)
+sparc_print_operand_address (FILE *file, machine_mode /*mode*/, rtx x)
{
register rtx base, index = 0;
int offset = 0;
@@ -8995,7 +8996,7 @@ sparc_print_operand_address (FILE *file, rtx x)
&& ! TARGET_CM_MEDMID);
output_operand (XEXP (base, 0), 0);
fputs ("+%lo(", file);
- output_address (XEXP (base, 1));
+ output_address (VOIDmode, XEXP (base, 1));
fprintf (file, ")+%d", offset);
}
else
@@ -9027,7 +9028,7 @@ sparc_print_operand_address (FILE *file, rtx x)
fputs ("+%l44(", file);
else
fputs ("+%lo(", file);
- output_address (XEXP (addr, 1));
+ output_address (VOIDmode, XEXP (addr, 1));
fputc (')', file);
}
else if (flag_pic
@@ -9868,14 +9869,12 @@ sparc_solaris_elf_asm_named_section (const char *name, unsigned int flags,
if (flags & SECTION_CODE)
fputs (",#execinstr", asm_out_file);
- /* Sun as only supports #nobits/#progbits since Solaris 10. */
- if (HAVE_AS_SPARC_NOBITS)
- {
- if (flags & SECTION_BSS)
- fputs (",#nobits", asm_out_file);
- else
- fputs (",#progbits", asm_out_file);
- }
+ if (flags & SECTION_NOTYPE)
+ ;
+ else if (flags & SECTION_BSS)
+ fputs (",#nobits", asm_out_file);
+ else
+ fputs (",#progbits", asm_out_file);
fputc ('\n', asm_out_file);
}
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index fa6dbef1233..31502fb67b4 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -1339,7 +1339,7 @@ print_operand (FILE * file, rtx x, int code)
/* Used in indirect function calls. */
fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
else
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
}
return;
@@ -1432,7 +1432,7 @@ print_operand (FILE * file, rtx x, int code)
if (xcode == REG)
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (xcode == MEM)
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
else if (xcode == CONST_VECTOR)
print_operand (file, CONST_VECTOR_ELT (x, 0), 0);
else
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 2867c396feb..f6268532254 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1662,7 +1662,8 @@ xstormy16_asm_out_constructor (rtx symbol, int priority)
Print a memory address as an operand to reference that memory location. */
static void
-xstormy16_print_operand_address (FILE *file, rtx address)
+xstormy16_print_operand_address (FILE *file, machine_mode /*mode*/,
+ rtx address)
{
HOST_WIDE_INT offset;
int pre_dec, post_inc;
@@ -1769,7 +1770,7 @@ xstormy16_print_operand (FILE *file, rtx x, int code)
else if (LABEL_P (x))
output_asm_label (x);
else
- xstormy16_print_operand_address (file, x);
+ xstormy16_print_operand_address (file, VOIDmode, x);
return;
case 'o':
@@ -1825,7 +1826,7 @@ xstormy16_print_operand (FILE *file, rtx x, int code)
break;
case MEM:
- xstormy16_print_operand_address (file, XEXP (x, 0));
+ xstormy16_print_operand_address (file, GET_MODE (x), XEXP (x, 0));
break;
default:
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 4ef2ca9375e..d2210622ae5 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -59,11 +59,6 @@
/* SYMBOL_REF for GOT */
static GTY(()) rtx g_got_symbol = NULL;
-/* In case of a POST_INC or POST_DEC memory reference, we must report
- the mode of the memory reference from TARGET_PRINT_OPERAND to
- TARGET_PRINT_OPERAND_ADDRESS. */
-static machine_mode output_memory_reference_mode;
-
/* Report whether we're printing out the first address fragment of a
POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
TARGET_PRINT_OPERAND_ADDRESS. */
@@ -5268,10 +5263,8 @@ tilegx_print_operand (FILE *file, rtx x, int code)
return;
}
- output_memory_reference_mode = GET_MODE (x);
output_memory_autoinc_first = true;
- output_address (XEXP (x, 0));
- output_memory_reference_mode = VOIDmode;
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 'i':
@@ -5282,10 +5275,8 @@ tilegx_print_operand (FILE *file, rtx x, int code)
return;
}
- output_memory_reference_mode = GET_MODE (x);
output_memory_autoinc_first = false;
- output_address (XEXP (x, 0));
- output_memory_reference_mode = VOIDmode;
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 'j':
@@ -5404,8 +5395,7 @@ tilegx_print_operand (FILE *file, rtx x, int code)
}
else if (MEM_P (x))
{
- output_memory_reference_mode = VOIDmode;
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
return;
}
else
@@ -5423,14 +5413,14 @@ tilegx_print_operand (FILE *file, rtx x, int code)
/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
static void
-tilegx_print_operand_address (FILE *file, rtx addr)
+tilegx_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
if (GET_CODE (addr) == POST_DEC
|| GET_CODE (addr) == POST_INC)
{
- int offset = GET_MODE_SIZE (output_memory_reference_mode);
+ int offset = GET_MODE_SIZE (mode);
- gcc_assert (output_memory_reference_mode != VOIDmode);
+ gcc_assert (mode != VOIDmode);
if (output_memory_autoinc_first)
fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
@@ -5440,7 +5430,7 @@ tilegx_print_operand_address (FILE *file, rtx addr)
}
else if (GET_CODE (addr) == POST_MODIFY)
{
- gcc_assert (output_memory_reference_mode != VOIDmode);
+ gcc_assert (mode != VOIDmode);
gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 4f95f6cb3b8..248b24e8385 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -59,11 +59,6 @@
/* SYMBOL_REF for GOT */
static GTY(()) rtx g_got_symbol = NULL;
-/* In case of a POST_INC or POST_DEC memory reference, we must report
- the mode of the memory reference from TARGET_PRINT_OPERAND to
- TARGET_PRINT_OPERAND_ADDRESS. */
-static machine_mode output_memory_reference_mode;
-
/* Report whether we're printing out the first address fragment of a
POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
TARGET_PRINT_OPERAND_ADDRESS. */
@@ -4594,10 +4589,8 @@ tilepro_print_operand (FILE *file, rtx x, int code)
return;
}
- output_memory_reference_mode = GET_MODE (x);
output_memory_autoinc_first = true;
- output_address (XEXP (x, 0));
- output_memory_reference_mode = VOIDmode;
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 'i':
@@ -4608,10 +4601,8 @@ tilepro_print_operand (FILE *file, rtx x, int code)
return;
}
- output_memory_reference_mode = GET_MODE (x);
output_memory_autoinc_first = false;
- output_address (XEXP (x, 0));
- output_memory_reference_mode = VOIDmode;
+ output_address (GET_MODE (x), XEXP (x, 0));
return;
case 'j':
@@ -4810,8 +4801,7 @@ tilepro_print_operand (FILE *file, rtx x, int code)
}
else if (MEM_P (x))
{
- output_memory_reference_mode = VOIDmode;
- output_address (XEXP (x, 0));
+ output_address (VOIDmode, XEXP (x, 0));
return;
}
else
@@ -4830,14 +4820,14 @@ tilepro_print_operand (FILE *file, rtx x, int code)
/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
static void
-tilepro_print_operand_address (FILE *file, rtx addr)
+tilepro_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
if (GET_CODE (addr) == POST_DEC
|| GET_CODE (addr) == POST_INC)
{
- int offset = GET_MODE_SIZE (output_memory_reference_mode);
+ int offset = GET_MODE_SIZE (mode);
- gcc_assert (output_memory_reference_mode != VOIDmode);
+ gcc_assert (mode != VOIDmode);
if (output_memory_autoinc_first)
fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
@@ -4847,7 +4837,7 @@ tilepro_print_operand_address (FILE *file, rtx addr)
}
else if (GET_CODE (addr) == POST_MODIFY)
{
- gcc_assert (output_memory_reference_mode != VOIDmode);
+ gcc_assert (mode != VOIDmode);
gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 64f80d9e9f9..d642eca207c 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -50,7 +50,7 @@
#define streq(a,b) (strcmp (a, b) == 0)
#endif
-static void v850_print_operand_address (FILE *, rtx);
+static void v850_print_operand_address (FILE *, machine_mode, rtx);
/* Names of the various data areas used on the v850. */
const char * GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
@@ -540,10 +540,13 @@ v850_print_operand (FILE * file, rtx x, int code)
fprintf (file, reg_names[REGNO (x) + 1]);
break;
case MEM:
- x = XEXP (adjust_address (x, SImode, 4), 0);
- v850_print_operand_address (file, x);
- if (GET_CODE (x) == CONST_INT)
- fprintf (file, "[r0]");
+ {
+ machine_mode mode = GET_MODE (x);
+ x = XEXP (adjust_address (x, SImode, 4), 0);
+ v850_print_operand_address (file, mode, x);
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "[r0]");
+ }
break;
case CONST_INT:
@@ -617,10 +620,11 @@ v850_print_operand (FILE * file, rtx x, int code)
{
case MEM:
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- output_address (gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, 0),
+ output_address (GET_MODE (x),
+ gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, 0),
XEXP (x, 0)));
else
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
break;
case REG:
@@ -638,7 +642,7 @@ v850_print_operand (FILE * file, rtx x, int code)
case CONST:
case LABEL_REF:
case CODE_LABEL:
- v850_print_operand_address (file, x);
+ v850_print_operand_address (file, VOIDmode, x);
break;
default:
gcc_unreachable ();
@@ -652,7 +656,7 @@ v850_print_operand (FILE * file, rtx x, int code)
/* Output assembly language output for the address ADDR to FILE. */
static void
-v850_print_operand_address (FILE * file, rtx addr)
+v850_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
{
switch (GET_CODE (addr))
{
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 26f4ae8527e..c059751915c 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -472,7 +472,7 @@ print_operand_address (FILE * file, rtx addr)
}
- output_address (offset);
+ output_address (VOIDmode, offset);
}
if (breg != 0)
@@ -527,7 +527,7 @@ print_operand (FILE *file, rtx x, int code)
else if (REG_P (x))
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (MEM_P (x))
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
{
char dstr[30];
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index d1b580ebc44..0bf275c454a 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -99,7 +99,6 @@ int visium_indent_opcode = 0;
given how unlikely it is to have a long branch in a leaf function. */
static unsigned int long_branch_regnum = 31;
-static void visium_output_address (FILE *, enum machine_mode, rtx);
static tree visium_handle_interrupt_attr (tree *, tree, tree, int, bool *);
static inline bool current_function_saves_fp (void);
static inline bool current_function_saves_lr (void);
@@ -157,6 +156,10 @@ static bool visium_legitimate_constant_p (enum machine_mode, rtx);
static bool visium_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool visium_print_operand_punct_valid_p (unsigned char);
+static void visium_print_operand (FILE *, rtx, int);
+static void visium_print_operand_address (FILE *, machine_mode, rtx);
+
static void visium_conditional_register_usage (void);
static rtx visium_legitimize_address (rtx, rtx, enum machine_mode);
@@ -227,6 +230,13 @@ static unsigned int visium_reorg (void);
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
+#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND visium_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
+
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE visium_attribute_table
@@ -3038,12 +3048,19 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
return output_branch (label, cond, insn);
}
-/* Helper function for PRINT_OPERAND (STREAM, X, CODE). Output to stdio
- stream FILE the assembler syntax for an instruction operand OP subject
- to the modifier LETTER. */
+/* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
-void
-print_operand (FILE *file, rtx op, int letter)
+static bool
+visium_print_operand_punct_valid_p (unsigned char code)
+{
+ return code == '#';
+}
+
+/* Implement TARGET_PRINT_OPERAND. Output to stdio stream FILE the assembler
+ syntax for an instruction operand OP subject to the modifier LETTER. */
+
+static void
+visium_print_operand (FILE *file, rtx op, int letter)
{
switch (letter)
{
@@ -3104,7 +3121,7 @@ print_operand (FILE *file, rtx op, int letter)
break;
case MEM:
- visium_output_address (file, GET_MODE (op), XEXP (op, 0));
+ visium_print_operand_address (file, GET_MODE (op), XEXP (op, 0));
break;
case CONST_INT:
@@ -3116,7 +3133,7 @@ print_operand (FILE *file, rtx op, int letter)
break;
case HIGH:
- print_operand (file, XEXP (op, 1), letter);
+ visium_print_operand (file, XEXP (op, 1), letter);
break;
default:
@@ -3124,11 +3141,12 @@ print_operand (FILE *file, rtx op, int letter)
}
}
-/* Output to stdio stream FILE the assembler syntax for an instruction operand
- that is a memory reference in MODE and whose address is ADDR. */
+/* Implement TARGET_PRINT_OPERAND_ADDRESS. Output to stdio stream FILE the
+ assembler syntax for an instruction operand that is a memory reference
+ whose address is ADDR. */
static void
-visium_output_address (FILE *file, enum machine_mode mode, rtx addr)
+visium_print_operand_address (FILE *file, enum machine_mode mode, rtx addr)
{
switch (GET_CODE (addr))
{
@@ -3205,16 +3223,6 @@ visium_output_address (FILE *file, enum machine_mode mode, rtx addr)
}
}
-/* Helper function for PRINT_OPERAND_ADDRESS (STREAM, X). Output to stdio
- stream FILE the assembler syntax for an instruction operand that is a
- memory reference whose address is ADDR. */
-
-void
-print_operand_address (FILE *file, rtx addr)
-{
- visium_output_address (file, QImode, addr);
-}
-
/* The Visium stack frames look like:
Before call After call
diff --git a/gcc/config/visium/visium.h b/gcc/config/visium/visium.h
index c5b65b4be34..9b92a74380b 100644
--- a/gcc/config/visium/visium.h
+++ b/gcc/config/visium/visium.h
@@ -1477,49 +1477,6 @@ do \
#define ADDITIONAL_REGISTER_NAMES \
{{"r22", HARD_FRAME_POINTER_REGNUM}, {"r23", STACK_POINTER_REGNUM}}
-/* `PRINT_OPERAND (STREAM, X, CODE)'
-
- A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand X. X is an RTL
- expression.
-
- CODE is a value that can be used to specify one of several ways of
- printing the operand. It is used when identical operands must be
- printed differently depending on the context. CODE comes from the
- `%' specification that was used to request printing of the operand.
- If the specification was just `%DIGIT' then CODE is 0; if the
- specification was `%LTR DIGIT' then CODE is the ASCII code for LTR.
-
- If X is a register, this macro should print the register's name.
- The names can be found in an array `reg_names' whose type is `char
- *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
-
- When the machine description has a specification `%PUNCT' (a `%'
- followed by a punctuation character), this macro is called with a
- null pointer for X and the punctuation character for CODE. */
-#define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE)
-
-/* `PRINT_OPERAND_PUNCT_VALID_P (CODE)'
-
- A C expression which evaluates to true if CODE is a valid
- punctuation character for use in the `PRINT_OPERAND' macro. If
- `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no
- punctuation characters (except for the standard one, `%') are used */
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#')
-
-/* `PRINT_OPERAND_ADDRESS (STREAM, X)'
-
- A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand that is a memory
- reference whose address is X. X is an RTL expression.
-
- On some machines, the syntax for a symbolic address depends on the
- section that the address refers to. On these machines, define the
- macro `ENCODE_SECTION_INFO' to store the information into the
- `symbol_ref', and then check for it here. */
-#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
- print_operand_address (STREAM, ADDR)
-
/* `REGISTER_PREFIX'
`LOCAL_LABEL_PREFIX'
`USER_LABEL_PREFIX'
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 8ef1512fede..0f58655d34e 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -2318,7 +2318,7 @@ print_operand (FILE *file, rtx x, int letter)
&& (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
{
x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
}
else
output_operand_lossage ("invalid %%N value");
@@ -2429,7 +2429,7 @@ print_operand (FILE *file, rtx x, int letter)
if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), XEXP (x, 0));
else if (GET_CODE (x) == CONST_INT)
fprintf (file, "%ld", INTVAL (x));
else
diff --git a/gcc/configure b/gcc/configure
index 1d2e8f2644d..0cd85fb8646 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -22930,43 +22930,96 @@ fi
gcc_cv_initfini_array=yes
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
- cat > conftest.s <<\EOF
-.section .dtors,"a",%progbits
+ case $target:$gas in
+ *:yes)
+ sh_flags='"a"'
+ sh_type='%progbits'
+ ;;
+ i?86-*-solaris2*:no | x86_64-*-solaris2*:no)
+ sh_flags='"a"'
+ sh_type='@progbits'
+ ;;
+ sparc*-*-solaris2*:no)
+ sh_flags='#alloc'
+ sh_type='#progbits'
+ sh_quote='"'
+ ;;
+ esac
+ case "$target:$gnu_ld" in
+ *:yes)
+ cat > conftest.s <<EOF
+.section .dtors,$sh_flags,$sh_type
.balign 4
.byte 'A', 'A', 'A', 'A'
-.section .ctors,"a",%progbits
+.section .ctors,$sh_flags,$sh_type
.balign 4
.byte 'B', 'B', 'B', 'B'
-.section .fini_array.65530,"a",%progbits
+.section .fini_array.65530,$sh_flags,$sh_type
.balign 4
.byte 'C', 'C', 'C', 'C'
-.section .init_array.65530,"a",%progbits
+.section .init_array.65530,$sh_flags,$sh_type
.balign 4
.byte 'D', 'D', 'D', 'D'
-.section .dtors.64528,"a",%progbits
+.section .dtors.64528,$sh_flags,$sh_type
.balign 4
.byte 'E', 'E', 'E', 'E'
-.section .ctors.64528,"a",%progbits
+.section .ctors.64528,$sh_flags,$sh_type
.balign 4
.byte 'F', 'F', 'F', 'F'
-.section .fini_array.01005,"a",%progbits
+.section .fini_array.01005,$sh_flags,$sh_type
.balign 4
.byte 'G', 'G', 'G', 'G'
-.section .init_array.01005,"a",%progbits
+.section .init_array.01005,$sh_flags,$sh_type
.balign 4
.byte 'H', 'H', 'H', 'H'
.text
.globl _start
_start:
EOF
- if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
- && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
- && $gcc_cv_objdump -s -j .init_array conftest \
- | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
- && $gcc_cv_objdump -s -j .fini_array conftest \
- | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
- gcc_cv_initfini_array=yes
- fi
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ *-*-solaris2*:no)
+ # When Solaris ld added constructor priority support, it was
+ # decided to only handle .init_array.N/.fini_array.N since
+ # there was no need for backwards compatibility with
+ # .ctors.N/.dtors.N. .ctors/.dtors remain as separate
+ # sections with correct execution order resp. to
+ # .init_array/.fini_array, while gld merges them into
+ # .init_array/.fini_array.
+ cat > conftest.s <<EOF
+.section $sh_quote.fini_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'C', 'C', 'C', 'C'
+.section $sh_quote.init_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'D', 'D', 'D', 'D'
+.section $sh_quote.fini_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'G', 'G', 'G', 'G'
+.section $sh_quote.init_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHDDDD > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGCCCC > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ esac
rm -f conftest conftest.*
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -23009,11 +23062,12 @@ $as_echo "$gcc_cv_initfini_array" >&6; }
fi
-if test $enable_initfini_array = yes; then
-$as_echo "#define HAVE_INITFINI_ARRAY_SUPPORT 1" >>confdefs.h
+cat >>confdefs.h <<_ACEOF
+#define HAVE_INITFINI_ARRAY_SUPPORT `if test $enable_initfini_array = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
-fi
# Check if we have .[us]leb128, and support symbol arithmetic with it.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .sleb128 and .uleb128" >&5
@@ -24667,39 +24721,6 @@ $as_echo "#define HAVE_AS_REGISTER_PSEUDO_OP 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for #nobits" >&5
-$as_echo_n "checking assembler for #nobits... " >&6; }
-if test "${gcc_cv_as_sparc_nobits+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- gcc_cv_as_sparc_nobits=no
- if test x$gcc_cv_as != x; then
- $as_echo '.section "nobits",#alloc,#write,#nobits
- .section "progbits",#alloc,#write,#progbits' > conftest.s
- if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }
- then
- gcc_cv_as_sparc_nobits=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_nobits" >&5
-$as_echo "$gcc_cv_as_sparc_nobits" >&6; }
-
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_AS_SPARC_NOBITS `if test $gcc_cv_as_sparc_nobits = yes; then echo 1; else echo 0; fi`
-_ACEOF
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -relax option" >&5
$as_echo_n "checking assembler for -relax option... " >&6; }
if test "${gcc_cv_as_sparc_relax+set}" = set; then :
@@ -26312,6 +26333,48 @@ $as_echo "#define HAVE_AS_POWER8 1" >>confdefs.h
fi
case $target in
+ *-*-aix*) conftest_s=' .machine "pwr9"
+ .csect .text[PR]';;
+ *) conftest_s=' .machine power9
+ .text';;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for power9 support" >&5
+$as_echo_n "checking assembler for power9 support... " >&6; }
+if test "${gcc_cv_as_powerpc_power9+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_power9=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+ then gcc_cv_as_powerpc_power9=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a32 -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_powerpc_power9=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_powerpc_power9" >&5
+$as_echo "$gcc_cv_as_powerpc_power9" >&6; }
+if test $gcc_cv_as_powerpc_power9 = yes; then
+
+$as_echo "#define HAVE_AS_POWER9 1" >>confdefs.h
+
+fi
+
+ case $target in
*-*-aix*) conftest_s=' .csect .text[PR]
lwsync';;
*) conftest_s=' .text
diff --git a/gcc/configure.ac b/gcc/configure.ac
index d03a0bd1c17..ed2e665b40c 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3754,13 +3754,6 @@ AS_HELP_STRING([--disable-fix-cortex-a53-843419],
[AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
[Define if your assembler supports .register.])])
- gcc_GAS_CHECK_FEATURE([@%:@nobits], gcc_cv_as_sparc_nobits,,,
- [.section "nobits",#alloc,#write,#nobits
- .section "progbits",#alloc,#write,#progbits])
- AC_DEFINE_UNQUOTED(HAVE_AS_SPARC_NOBITS,
- [`if test $gcc_cv_as_sparc_nobits = yes; then echo 1; else echo 0; fi`],
- [Define to 1 if your assembler supports #nobits, 0 otherwise.])
-
gcc_GAS_CHECK_FEATURE([-relax option], gcc_cv_as_sparc_relax,,
[-relax], [.text],,
[AC_DEFINE(HAVE_AS_RELAX_OPTION, 1,
@@ -4323,6 +4316,19 @@ LCF0:
[Define if your assembler supports POWER8 instructions.])])
case $target in
+ *-*-aix*) conftest_s=' .machine "pwr9"
+ .csect .text[[PR]]';;
+ *) conftest_s=' .machine power9
+ .text';;
+ esac
+
+ gcc_GAS_CHECK_FEATURE([power9 support],
+ gcc_cv_as_powerpc_power9, [2,19,2], -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_POWER9, 1,
+ [Define if your assembler supports POWER9 instructions.])])
+
+ case $target in
*-*-aix*) conftest_s=' .csect .text[[PR]]
lwsync';;
*) conftest_s=' .text
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 11ca9ab584a..859f3783e4f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,53 @@
+2015-11-09 Cesar Philippidis <cesar@codesourcery.com>
+
+ * parser.c (cp_finalize_oacc_routine): New boolean first argument.
+ (cp_ensure_no_oacc_routine): Update call to cp_finalize_oacc_routine.
+ (cp_parser_simple_declaration): Maintain a boolean first to keep track
+ of each new declarator. Propagate it to cp_parser_init_declarator.
+ (cp_parser_init_declarator): New boolean first argument. Propagate it
+ to cp_parser_save_member_function_body and cp_finalize_oacc_routine.
+ (cp_parser_member_declaration): Likewise.
+ (cp_parser_single_declaration): Update call to
+ cp_parser_init_declarator.
+ (cp_parser_save_member_function_body): New boolean first_decl argument.
+ Propagate it to cp_finalize_oacc_routine.
+ (cp_parser_finish_oacc_routine): New boolean first argument. Use it to
+ determine if multiple declarators follow a routine construct.
+ (cp_parser_oacc_routine): Update call to cp_parser_finish_oacc_routine.
+
+2015-10-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/67913
+ PR c++/67927
+ * call.c (build_operator_new_call): Do not assume size_check
+ is non-null, analogously to the top half of the function.
+ * init.c (build_new_1): Detect and diagnose array sizes in
+ excess of the maximum of roughly SIZE_MAX / 2.
+ Insert a runtime check only for arrays with a non-constant size.
+ (build_new): Detect and diagnose negative array sizes.
+
+2015-11-09 Thomas Schwinge <thomas@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+ James Norris <jnorris@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+ Nathan Sidwell <nathan@codesourcery.com>
+
+ * parser.h (struct cp_parser): Add oacc_routine field.
+ * parser.c (cp_ensure_no_oacc_routine): New.
+ (cp_parser_new): Initialize oacc_routine field.
+ (cp_parser_linkage_specification): Call cp_ensure_no_oacc_routine.
+ (cp_parser_namespace_definition,
+ cp_parser_class_specifier_1): Likewise.
+ (cp_parser_init_declarator): Call cp_finalize_oacc_routine.
+ (cp_parser_function_definition,
+ cp_parser_save_member_function_body): Likewise.
+ (OACC_ROUTINE_CLAUSE_MASK): New.
+ (cp_parser_finish_oacc_routine, cp_parser_oacc_routine,
+ cp_finalize_oacc_routine): New.
+ (cp_parser_pragma): Adjust omp_declare_simd checking. Call
+ cp_ensure_no_oacc_routine.
+ (cp_parser_pragma): Add OpenACC routine handling.
+
2015-11-08 Martin Sebor <msebor@redhat.com>
PR c++/67942
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f8ebf9b0084..c73ab2ca3a0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4241,10 +4241,13 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
{
/* Update the total size. */
*size = size_binop (PLUS_EXPR, original_size, *cookie_size);
- /* Set to (size_t)-1 if the size check fails. */
- gcc_assert (size_check != NULL_TREE);
- *size = fold_build3 (COND_EXPR, sizetype, size_check,
- *size, TYPE_MAX_VALUE (sizetype));
+ if (size_check)
+ {
+ /* Set to (size_t)-1 if the size check fails. */
+ gcc_assert (size_check != NULL_TREE);
+ *size = fold_build3 (COND_EXPR, sizetype, size_check,
+ *size, TYPE_MAX_VALUE (sizetype));
+ }
/* Update the argument list to reflect the adjusted size. */
(**args)[0] = *size;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b45281f517d..2e11acb6a67 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2482,7 +2482,11 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
- build_raw_new_expr. This may change PLACEMENT and INIT. */
+ build_raw_new_expr. This may change PLACEMENT and INIT.
+ TYPE is the type of the object being constructed, possibly an array
+ of NELTS elements when NELTS is non-null (in "new T[NELTS]", T may
+ be an array of the form U[inner], with the whole expression being
+ "new U[NELTS][inner]"). */
static tree
build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
@@ -2502,13 +2506,16 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
type.) */
tree pointer_type;
tree non_const_pointer_type;
+ /* The most significant array bound in int[OUTER_NELTS][inner]. */
tree outer_nelts = NULL_TREE;
- /* For arrays, a bounds checks on the NELTS parameter. */
+ /* For arrays with a non-constant number of elements, a bounds checks
+ on the NELTS parameter to avoid integer overflow at runtime. */
tree outer_nelts_check = NULL_TREE;
bool outer_nelts_from_type = false;
+ /* Number of the "inner" elements in "new T[OUTER_NELTS][inner]". */
offset_int inner_nelts_count = 1;
tree alloc_call, alloc_expr;
- /* Size of the inner array elements. */
+ /* Size of the inner array elements (those with constant dimensions). */
offset_int inner_size;
/* The address returned by the call to "operator new". This node is
a VAR_DECL and is therefore reusable. */
@@ -2702,20 +2709,41 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
}
max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
- /* Only keep the top-most seven bits, to simplify encoding the
- constant in the instruction stream. */
- {
- unsigned shift = (max_outer_nelts.get_precision ()) - 7
- - wi::clz (max_outer_nelts);
- max_outer_nelts = wi::lshift (wi::lrshift (max_outer_nelts, shift),
- shift);
- }
max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
- outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
- outer_nelts,
- max_outer_nelts_tree);
+
+ if (TREE_CONSTANT (outer_nelts))
+ {
+ if (tree_int_cst_lt (max_outer_nelts_tree, outer_nelts))
+ {
+ /* When the array size is constant, check it at compile time
+ to make sure it doesn't exceed the implementation-defined
+ maximum, as required by C++ 14 (in C++ 11 this requirement
+ isn't explicitly stated but it's enforced anyway -- see
+ grokdeclarator in cp/decl.c). */
+ if (complain & tf_error)
+ error ("size of array is too large");
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ /* When a runtime check is necessary because the array size
+ isn't constant, keep only the top-most seven bits (starting
+ with the most significant non-zero bit) of the maximum size
+ to compare the array size against, to simplify encoding the
+ constant maximum size in the instruction stream. */
+
+ unsigned shift = (max_outer_nelts.get_precision ()) - 7
+ - wi::clz (max_outer_nelts);
+ max_outer_nelts = wi::lshift (wi::lrshift (max_outer_nelts, shift),
+ shift);
+
+ outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
+ outer_nelts,
+ max_outer_nelts_tree);
+ }
}
alloc_fn = NULL_TREE;
@@ -3290,6 +3318,23 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
else
return error_mark_node;
}
+
+ /* Try to determine the constant value only for the purposes
+ of the diagnostic below but continue to use the original
+ value and handle const folding later. */
+ const_tree cst_nelts = maybe_constant_value (nelts);
+
+ /* The expression in a noptr-new-declarator is erroneous if it's of
+ non-class type and its value before converting to std::size_t is
+ less than zero. ... If the expression is a constant expression,
+ the program is ill-fomed. */
+ if (TREE_CONSTANT (cst_nelts) && tree_int_cst_sgn (cst_nelts) == -1)
+ {
+ if (complain & tf_error)
+ error ("size of array is negative");
+ return error_mark_node;
+ }
+
nelts = mark_rvalue_use (nelts);
nelts = cp_save_expr (cp_convert (sizetype, nelts, complain));
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bcf9031822b..f3c32a39e31 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -245,6 +245,8 @@ static bool cp_parser_omp_declare_reduction_exprs
(tree, cp_parser *);
static tree cp_parser_cilk_simd_vectorlength
(cp_parser *, tree, bool);
+static void cp_finalize_oacc_routine
+ (cp_parser *, tree, bool, bool);
/* Manifest constants. */
#define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
@@ -1320,6 +1322,15 @@ cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl)
}
}
}
+
+/* Diagnose if #pragma omp routine isn't followed immediately
+ by function declaration or definition. */
+
+static inline void
+cp_ensure_no_oacc_routine (cp_parser *parser)
+{
+ cp_finalize_oacc_routine (parser, NULL_TREE, false, true);
+}
/* Decl-specifiers. */
@@ -2124,7 +2135,7 @@ static tree cp_parser_decltype
static tree cp_parser_init_declarator
(cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
- bool, bool, int, bool *, tree *, location_t *);
+ bool, bool, int, bool *, tree *, bool, location_t *);
static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
static cp_declarator *cp_parser_direct_declarator
@@ -2434,7 +2445,7 @@ static tree cp_parser_single_declaration
static tree cp_parser_functional_cast
(cp_parser *, tree);
static tree cp_parser_save_member_function_body
- (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
+ (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree, bool);
static tree cp_parser_save_nsdmi
(cp_parser *);
static tree cp_parser_enclosed_template_argument_list
@@ -3620,6 +3631,9 @@ cp_parser_new (void)
parser->implicit_template_parms = 0;
parser->implicit_template_scope = 0;
+ /* Active OpenACC routine clauses. */
+ parser->oacc_routine = NULL;
+
/* Allow constrained-type-specifiers. */
parser->prevent_constrained_type_specifiers = 0;
@@ -11895,6 +11909,7 @@ cp_parser_simple_declaration (cp_parser* parser,
bool saw_declarator;
location_t comma_loc = UNKNOWN_LOCATION;
location_t init_loc = UNKNOWN_LOCATION;
+ bool first = true;
if (maybe_range_for_decl)
*maybe_range_for_decl = NULL_TREE;
@@ -11991,7 +12006,10 @@ cp_parser_simple_declaration (cp_parser* parser,
declares_class_or_enum,
&function_definition_p,
maybe_range_for_decl,
+ first,
&init_loc);
+ first = false;
+
/* If an error occurred while parsing tentatively, exit quickly.
(That usually happens when in the body of a function; each
statement is treated as a declaration-statement until proven
@@ -12090,6 +12108,9 @@ cp_parser_simple_declaration (cp_parser* parser,
done:
pop_deferring_access_checks ();
+
+ /* Reset any acc routine clauses. */
+ parser->oacc_routine = NULL;
}
/* Parse a decl-specifier-seq.
@@ -12541,6 +12562,7 @@ cp_parser_linkage_specification (cp_parser* parser)
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
cp_ensure_no_omp_declare_simd (parser);
+ cp_ensure_no_oacc_routine (parser);
/* Consume the `{' token. */
cp_lexer_consume_token (parser->lexer);
@@ -17059,6 +17081,7 @@ cp_parser_namespace_definition (cp_parser* parser)
int nested_definition_count = 0;
cp_ensure_no_omp_declare_simd (parser);
+ cp_ensure_no_oacc_routine (parser);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
{
maybe_warn_cpp0x (CPP0X_INLINE_NAMESPACES);
@@ -17828,6 +17851,8 @@ cp_parser_asm_definition (cp_parser* parser)
if present, will not be consumed. If returned, this declarator will be
created with SD_INITIALIZED but will not call cp_finish_decl.
+ FIRST indicates if this is the first declarator in a declaration sequence.
+
If INIT_LOC is not NULL, and *INIT_LOC is equal to UNKNOWN_LOCATION,
and there is an initializer, the pointed location_t is set to the
location of the '=' or `(', or '{' in C++11 token introducing the
@@ -17842,6 +17867,7 @@ cp_parser_init_declarator (cp_parser* parser,
int declares_class_or_enum,
bool* function_definition_p,
tree* maybe_range_for_decl,
+ bool first,
location_t* init_loc)
{
cp_token *token = NULL, *asm_spec_start_token = NULL,
@@ -17978,7 +18004,8 @@ cp_parser_init_declarator (cp_parser* parser,
decl = cp_parser_save_member_function_body (parser,
decl_specifiers,
declarator,
- prefix_attributes);
+ prefix_attributes,
+ true);
else
decl =
(cp_parser_function_definition_from_specifiers_and_declarator
@@ -18082,6 +18109,7 @@ cp_parser_init_declarator (cp_parser* parser,
range_for_decl_p? SD_INITIALIZED : is_initialized,
attributes, prefix_attributes, &pushed_scope);
cp_finalize_omp_declare_simd (parser, decl);
+ cp_finalize_oacc_routine (parser, decl, false, first);
/* Adjust location of decl if declarator->id_loc is more appropriate:
set, and decl wasn't merged with another decl, in which case its
location would be different from input_location, and more accurate. */
@@ -18195,6 +18223,7 @@ cp_parser_init_declarator (cp_parser* parser,
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
cp_finalize_omp_declare_simd (parser, decl);
+ cp_finalize_oacc_routine (parser, decl, false, first);
}
/* Finish processing the declaration. But, skip member
@@ -20801,6 +20830,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
}
cp_ensure_no_omp_declare_simd (parser);
+ cp_ensure_no_oacc_routine (parser);
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
@@ -21897,6 +21927,7 @@ cp_parser_member_declaration (cp_parser* parser)
else
{
bool assume_semicolon = false;
+ bool first = true;
/* Clear attributes from the decl_specifiers but keep them
around as prefix attributes that apply them to the entity
@@ -22084,7 +22115,10 @@ cp_parser_member_declaration (cp_parser* parser)
decl = cp_parser_save_member_function_body (parser,
&decl_specifiers,
declarator,
- attributes);
+ attributes,
+ first);
+ first = false;
+
if (parser->fully_implicit_function_template_p)
decl = finish_fully_implicit_template (parser, decl);
/* If the member was not a friend, declare it here. */
@@ -22114,6 +22148,8 @@ cp_parser_member_declaration (cp_parser* parser)
}
cp_finalize_omp_declare_simd (parser, decl);
+ cp_finalize_oacc_routine (parser, decl, false, first);
+ first = false;
/* Reset PREFIX_ATTRIBUTES. */
while (attributes && TREE_CHAIN (attributes) != first_attribute)
@@ -22176,6 +22212,9 @@ cp_parser_member_declaration (cp_parser* parser)
if (assume_semicolon)
goto out;
}
+
+ /* Reset any OpenACC routine clauses. */
+ parser->oacc_routine = NULL;
}
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -24717,6 +24756,8 @@ cp_parser_function_definition_from_specifiers_and_declarator
{
cp_finalize_omp_declare_simd (parser, current_function_decl);
parser->omp_declare_simd = NULL;
+ cp_finalize_oacc_routine (parser, current_function_decl, true, true);
+ parser->oacc_routine = NULL;
}
if (!success_p)
@@ -25281,7 +25322,7 @@ cp_parser_single_declaration (cp_parser* parser,
member_p,
declares_class_or_enum,
&function_definition_p,
- NULL, NULL);
+ NULL, true, NULL);
/* 7.1.1-1 [dcl.stc]
@@ -25383,14 +25424,15 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
/* Save the tokens that make up the body of a member function defined
in a class-specifier. The DECL_SPECIFIERS and DECLARATOR have
already been parsed. The ATTRIBUTES are any GNU "__attribute__"
- specifiers applied to the declaration. Returns the FUNCTION_DECL
- for the member function. */
+ specifiers applied to the declaration. FIRST_DECL indicates if
+ DECLARATOR is the first declarator in a declaration sequence. Returns
+ the FUNCTION_DECL for the member function. */
static tree
cp_parser_save_member_function_body (cp_parser* parser,
cp_decl_specifier_seq *decl_specifiers,
cp_declarator *declarator,
- tree attributes)
+ tree attributes, bool first_decl)
{
cp_token *first;
cp_token *last;
@@ -25399,6 +25441,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
/* Create the FUNCTION_DECL. */
fn = grokmethod (decl_specifiers, declarator, attributes);
cp_finalize_omp_declare_simd (parser, fn);
+ cp_finalize_oacc_routine (parser, fn, true, first_decl);
/* If something went badly wrong, bail out now. */
if (fn == error_mark_node)
{
@@ -35585,6 +35628,147 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
return ret;
}
+
+/* OpenACC 2.0:
+ # pragma acc routine oacc-routine-clause[optseq] new-line
+ function-definition
+
+ # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
+*/
+
+#define OACC_ROUTINE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ))
+
+/* Finalize #pragma acc routine clauses after direct declarator has
+ been parsed, and put that into "omp declare target" attribute. */
+
+static void
+cp_parser_finish_oacc_routine (cp_parser *ARG_UNUSED (parser), tree fndecl,
+ tree clauses, bool named, bool is_defn,
+ bool first)
+{
+ location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
+
+ if (named && fndecl && is_overloaded_fn (fndecl)
+ && (TREE_CODE (fndecl) != FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (fndecl)))
+ {
+ error_at (loc, "%<#pragma acc routine%> names a set of overloads");
+ return;
+ }
+
+ if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL
+ || (!named && !first))
+ {
+ error_at (loc, "%<#pragma acc routine%> %s",
+ named ? "does not refer to a function"
+ : "not followed by single function");
+ return;
+ }
+
+ /* Perhaps we should use the same rule as declarations in different
+ namespaces? */
+ if (named && !DECL_NAMESPACE_SCOPE_P (fndecl))
+ {
+ error_at (loc, "%<#pragma acc routine%> does not refer to a"
+ " namespace scope function");
+ return;
+ }
+
+ if (get_oacc_fn_attrib (fndecl))
+ error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+
+ if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ error_at (OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses)),
+ "%<#pragma acc routine%> must be applied before %s",
+ TREE_USED (fndecl) ? "use" : "definition");
+
+ /* Process for function attrib */
+ tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
+ replace_oacc_fn_attrib (fndecl, dims);
+
+ /* Also attach as a declare. */
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("omp declare target"),
+ clauses, DECL_ATTRIBUTES (fndecl));
+}
+
+/* Parse the OpenACC routine pragma. This has an optional '( name )'
+ component, which must resolve to a declared namespace-scope
+ function. The clauses are either processed directly (for a named
+ function), or defered until the immediatley following declaration
+ is parsed. */
+
+static void
+cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ tree decl = NULL_TREE;
+ /* Create a dummy claue, to record location. */
+ tree c_head = build_omp_clause (pragma_tok->location, OMP_CLAUSE_SEQ);
+
+ if (context != pragma_external)
+ cp_parser_error (parser, "%<#pragma acc routine%> not at file scope");
+
+ /* Look for optional '( name )'. */
+ if (cp_lexer_next_token_is (parser->lexer,CPP_OPEN_PAREN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ /* We parse the name as an id-expression. If it resolves to
+ anything other than a non-overloaded function at namespace
+ scope, it's an error. */
+ tree id = cp_parser_id_expression (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/false,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ decl = cp_parser_lookup_name_simple (parser, id, token->location);
+ if (id != error_mark_node && decl == error_mark_node)
+ cp_parser_name_lookup_error (parser, id, decl, NLE_NULL,
+ token->location);
+
+ if (decl == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+ }
+
+ /* Build a chain of clauses. */
+ parser->lexer->in_pragma = true;
+ tree clauses = NULL_TREE;
+ clauses = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+ "#pragma acc routine",
+ cp_lexer_peek_token (parser->lexer));
+
+ /* Force clauses to be non-null, by attaching context to it. */
+ clauses = tree_cons (c_head, clauses, NULL_TREE);
+
+ if (decl)
+ cp_parser_finish_oacc_routine (parser, decl, clauses, true, false, 0);
+ else
+ parser->oacc_routine = clauses;
+}
+
+/* Apply any saved OpenACC routine clauses to a just-parsed
+ declaration. */
+
+static void
+cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn,
+ bool first)
+{
+ if (parser->oacc_routine)
+ cp_parser_finish_oacc_routine (parser, fndecl, parser->oacc_routine,
+ false, is_defn, first);
+}
+
/* Main entry point to OpenMP statement pragmas. */
static void
@@ -36064,8 +36248,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
parser->lexer->in_pragma = true;
id = pragma_tok->pragma_kind;
- if (id != PRAGMA_OMP_DECLARE_REDUCTION)
+ if (id != PRAGMA_OMP_DECLARE_REDUCTION && id != PRAGMA_OACC_ROUTINE)
cp_ensure_no_omp_declare_simd (parser);
+ cp_ensure_no_oacc_routine (parser);
switch (id)
{
case PRAGMA_GCC_PCH_PREPROCESS:
@@ -36175,6 +36360,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
cp_parser_omp_declare (parser, pragma_tok, context);
return false;
+ case PRAGMA_OACC_ROUTINE:
+ cp_parser_oacc_routine (parser, pragma_tok, context);
+ return false;
+
case PRAGMA_OACC_ATOMIC:
case PRAGMA_OACC_CACHE:
case PRAGMA_OACC_DATA:
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index c7091c8e8e0..aa090b06544 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -373,6 +373,9 @@ typedef struct GTY(()) cp_parser {
necessary. */
cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
+ /* OpenACC routine clauses for subsequent decl/defn. */
+ tree oacc_routine;
+
/* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
template parameter. */
bool auto_is_implicit_function_template_parm_p;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 56f5d904a80..43d58a3475d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -949,8 +949,9 @@ See RS/6000 and PowerPC Options.
-mquad-memory-atomic -mno-quad-memory-atomic @gol
-mcompat-align-parm -mno-compat-align-parm @gol
-mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs -mno-upper-regs @gol
--mfloat128 -mno-float128}
+-mupper-regs -mno-upper-regs -mmodulo -mno-modulo @gol
+-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
+-mpower9-fusion -mno-mpower9-fusion -mpower9-vector -mno-power9-vector}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
@@ -7451,12 +7452,7 @@ The @var{number} should be different for every file you compile.
@item -fsched-verbose=@var{n}
@opindex fsched-verbose
On targets that use instruction scheduling, this option controls the
-amount of debugging output the scheduler prints. This information is
-written to standard error, unless @option{-fdump-rtl-sched1} or
-@option{-fdump-rtl-sched2} is specified, in which case it is output
-to the usual dump listing file, @file{.sched1} or @file{.sched2}
-respectively. However for @var{n} greater than nine, the output is
-always printed to standard error.
+amount of debugging output the scheduler prints to the dump files.
For @var{n} greater than zero, @option{-fsched-verbose} outputs the
same information as @option{-fdump-rtl-sched1} and @option{-fdump-rtl-sched2}.
@@ -19316,8 +19312,9 @@ Supported values for @var{cpu_type} are @samp{401}, @samp{403},
@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{e5500},
@samp{e6500}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
@samp{titan}, @samp{power3}, @samp{power4}, @samp{power5}, @samp{power5+},
-@samp{power6}, @samp{power6x}, @samp{power7}, @samp{power8}, @samp{powerpc},
-@samp{powerpc64}, @samp{powerpc64le}, and @samp{rs64}.
+@samp{power6}, @samp{power6x}, @samp{power7}, @samp{power8},
+@samp{power9}, @samp{powerpc}, @samp{powerpc64}, @samp{powerpc64le},
+and @samp{rs64}.
@option{-mcpu=powerpc}, @option{-mcpu=powerpc64}, and
@option{-mcpu=powerpc64le} specify pure 32-bit PowerPC (either
@@ -19337,7 +19334,8 @@ following options:
-mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float -mdouble-float @gol
-msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx @gol
-mcrypto -mdirect-move -mpower8-fusion -mpower8-vector @gol
--mquad-memory -mquad-memory-atomic}
+-mquad-memory -mquad-memory-atomic -mmodulo -mfloat128 -mfloat128-hardware @gol
+-mpower9-fusion -mpower9-vector}
The particular options set for any particular CPU varies between
compiler versions, depending on what setting seems to produce optimal
@@ -19574,12 +19572,45 @@ If the @option{-mno-upper-regs} option is used, it turns off both
@opindex mfloat128
@opindex mno-float128
Enable/disable the @var{__float128} keyword for IEEE 128-bit floating point
-and use software emulation for IEEE 128-bit floating point.
+and use either software emulation for IEEE 128-bit floating point or
+hardware instructions.
The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or
@option{-mcpu=power8}) must be enabled to use the @option{-mfloat128}
option.
+@item -mfloat128-hardware
+@itemx -mno-float128-hardware
+@opindex mfloat128-hardware
+@opindex mno-float128-hardware
+Enable/disable using ISA 3.0 hardware instructions to support the
+@var{__float128} data type.
+
+@item -mmodulo
+@itemx -mno-modulo
+@opindex mmodulo
+@opindex mno-module
+Generate code that uses (does not use) the ISA 3.0 integer modulo
+instructions. The @option{-mmodulo} option is enabled by default
+with the @option{-mcpu=power9} option.
+
+@item -mpower9-fusion
+@itemx -mno-power9-fusion
+@opindex mpower9-fusion
+@opindex mno-power9-fusion
+Generate code that keeps (does not keeps) some operations adjacent so
+that the instructions can be fused together on power9 and later
+processors.
+
+@item -mpower9-vector
+@itemx -mno-power9-vector
+@opindex mpower9-vector
+@opindex mno-power9-vector
+Generate code that uses (does not use) the vector and scalar
+instructions that were added in version 2.07 of the PowerPC ISA. Also
+enable the use of built-in functions that allow more direct access to
+the vector instructions.
+
@item -mfloat-gprs=@var{yes/single/double/no}
@itemx -mfloat-gprs
@opindex mfloat-gprs
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index ee629e23381..71a2791a602 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5805,6 +5805,21 @@ move operand 2 or (operands 2 + operand 3) into operand 0 according to the
comparison in operand 1. If the comparison is false, operand 2 is moved into
operand 0, otherwise (operand 2 + operand 3) is moved.
+@cindex @code{neg@var{mode}cc} instruction pattern
+@item @samp{neg@var{mode}cc}
+Similar to @samp{mov@var{mode}cc} but for conditional negation. Conditionally
+move the negation of operand 2 or the unchanged operand 3 into operand 0
+according to the comparison in operand 1. If the comparison is true, the negation
+of operand 2 is moved into operand 0, otherwise operand 3 is moved.
+
+@cindex @code{not@var{mode}cc} instruction pattern
+@item @samp{not@var{mode}cc}
+Similar to @samp{neg@var{mode}cc} but for conditional complement.
+Conditionally move the bitwise complement of operand 2 or the unchanged
+operand 3 into operand 0 according to the comparison in operand 1.
+If the comparison is true, the complement of operand 2 is moved into
+operand 0, otherwise operand 3 is moved.
+
@cindex @code{cstore@var{mode}4} instruction pattern
@item @samp{cstore@var{mode}4}
Store zero or nonzero in operand 0 according to whether a comparison
diff --git a/gcc/expr.c b/gcc/expr.c
index 050642daa4f..03936ee3ddb 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11128,9 +11128,15 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
if (TREE_CODE (ops->type) == VECTOR_TYPE)
{
tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
- tree if_true = constant_boolean_node (true, ops->type);
- tree if_false = constant_boolean_node (false, ops->type);
- return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target);
+ if (VECTOR_BOOLEAN_TYPE_P (ops->type))
+ return expand_vec_cmp_expr (ops->type, ifexp, target);
+ else
+ {
+ tree if_true = constant_boolean_node (true, ops->type);
+ tree if_false = constant_boolean_node (false, ops->type);
+ return expand_vec_cond_expr (ops->type, ifexp, if_true,
+ if_false, target);
+ }
}
/* Get the rtx comparison code to use. We know that EXP is a comparison
@@ -11417,6 +11423,40 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
return 1;
}
+/* Return a CONST_VECTOR rtx representing vector mask for
+ a VECTOR_CST of booleans. */
+static rtx
+const_vector_mask_from_tree (tree exp)
+{
+ rtvec v;
+ unsigned i;
+ int units;
+ tree elt;
+ machine_mode inner, mode;
+
+ mode = TYPE_MODE (TREE_TYPE (exp));
+ units = GET_MODE_NUNITS (mode);
+ inner = GET_MODE_INNER (mode);
+
+ v = rtvec_alloc (units);
+
+ for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
+ {
+ elt = VECTOR_CST_ELT (exp, i);
+
+ gcc_assert (TREE_CODE (elt) == INTEGER_CST);
+ if (integer_zerop (elt))
+ RTVEC_ELT (v, i) = CONST0_RTX (inner);
+ else if (integer_onep (elt)
+ || integer_minus_onep (elt))
+ RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
+ else
+ gcc_unreachable ();
+ }
+
+ return gen_rtx_CONST_VECTOR (mode, v);
+}
+
/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
static rtx
const_vector_from_tree (tree exp)
@@ -11432,6 +11472,9 @@ const_vector_from_tree (tree exp)
if (initializer_zerop (exp))
return CONST0_RTX (mode);
+ if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
+ return const_vector_mask_from_tree (exp);
+
units = GET_MODE_NUNITS (mode);
inner = GET_MODE_INNER (mode);
diff --git a/gcc/final.c b/gcc/final.c
index 35522f16125..30b38267e46 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3713,7 +3713,7 @@ output_asm_insn (const char *templ, rtx *operands)
else if (letter == 'l')
output_asm_label (operands[opnum]);
else if (letter == 'a')
- output_address (operands[opnum]);
+ output_address (VOIDmode, operands[opnum]);
else if (letter == 'c')
{
if (CONSTANT_ADDRESS_P (operands[opnum]))
@@ -3848,11 +3848,11 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED)
machine-dependent assembler syntax. */
void
-output_address (rtx x)
+output_address (machine_mode mode, rtx x)
{
bool changed = false;
walk_alter_subreg (&x, &changed);
- targetm.asm_out.print_operand_address (asm_out_file, x);
+ targetm.asm_out.print_operand_address (asm_out_file, mode, x);
}
/* Print an integer constant expression in assembler syntax.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index bbc9b23acdd..8bbf5be831a 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -2345,7 +2345,10 @@ record_temp_file (const char *filename, int always_delete, int fail_delete)
struct temp_file *temp;
for (temp = always_delete_queue; temp; temp = temp->next)
if (! filename_cmp (name, temp->name))
- goto already1;
+ {
+ free (name);
+ goto already1;
+ }
temp = XNEW (struct temp_file);
temp->next = always_delete_queue;
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index caadc11b6a4..e712110b2d8 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -203,17 +203,14 @@ static int modulo_last_stage;
/* sched-verbose controls the amount of debugging output the
scheduler prints. It is controlled by -fsched-verbose=N:
- N>0 and no -DSR : the output is directed to stderr.
- N>=10 will direct the printouts to stderr (regardless of -dSR).
- N=1: same as -dSR.
+ N=0: no debugging output.
+ N=1: default value.
N=2: bb's probabilities, detailed ready list info, unit/insn info.
N=3: rtl at abort point, control-flow, regions info.
N=5: dependences info. */
-
int sched_verbose = 0;
-/* Debugging file. All printouts are sent to dump, which is always set,
- either to stderr, or to the dump listing file (-dRS). */
+/* Debugging file. All printouts are sent to dump. */
FILE *sched_dump = 0;
/* This is a placeholder for the scheduler parameters common
@@ -5806,7 +5803,10 @@ autopref_multipass_dfa_lookahead_guard (rtx_insn *insn1, int ready_index)
{
int r = 0;
- if (PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) <= 0)
+ /* Exit early if the param forbids this or if we're not entering here through
+ normal haifa scheduling. This can happen if selective scheduling is
+ explicitly enabled. */
+ if (!insn_queue || PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) <= 0)
return 0;
if (sched_verbose >= 2 && ready_index == 0)
@@ -7219,17 +7219,14 @@ set_priorities (rtx_insn *head, rtx_insn *tail)
return n_insn;
}
-/* Set dump and sched_verbose for the desired debugging output. If no
- dump-file was specified, but -fsched-verbose=N (any N), print to stderr.
- For -fsched-verbose=N, N>=10, print everything to stderr. */
+/* Set sched_dump and sched_verbose for the desired debugging output. */
void
setup_sched_dump (void)
{
sched_verbose = sched_verbose_param;
- if (sched_verbose_param == 0 && dump_file)
- sched_verbose = 1;
- sched_dump = ((sched_verbose_param >= 10 || !dump_file)
- ? stderr : dump_file);
+ sched_dump = dump_file;
+ if (!dump_file)
+ sched_verbose = 0;
}
/* Allocate data for register pressure sensitive scheduling. */
@@ -7483,6 +7480,7 @@ haifa_sched_finish (void)
sched_deps_finish ();
sched_finish_luids ();
current_sched_info = NULL;
+ insn_queue = NULL;
sched_finish ();
}
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index fff62de02a0..56e4ed42576 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1168,6 +1168,83 @@ noce_try_store_flag (struct noce_if_info *if_info)
}
}
+
+/* Convert "if (test) x = -A; else x = A" into
+ x = A; if (test) x = -x if the machine can do the
+ conditional negate form of this cheaply.
+ Try this before noce_try_cmove that will just load the
+ immediates into two registers and do a conditional select
+ between them. If the target has a conditional negate or
+ conditional invert operation we can save a potentially
+ expensive constant synthesis. */
+
+static bool
+noce_try_inverse_constants (struct noce_if_info *if_info)
+{
+ if (!noce_simple_bbs (if_info))
+ return false;
+
+ if (!CONST_INT_P (if_info->a)
+ || !CONST_INT_P (if_info->b)
+ || !REG_P (if_info->x))
+ return false;
+
+ machine_mode mode = GET_MODE (if_info->x);
+
+ HOST_WIDE_INT val_a = INTVAL (if_info->a);
+ HOST_WIDE_INT val_b = INTVAL (if_info->b);
+
+ rtx cond = if_info->cond;
+
+ rtx x = if_info->x;
+ rtx target;
+
+ start_sequence ();
+
+ rtx_code code;
+ if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
+ code = NEG;
+ else if (val_a == ~val_b)
+ code = NOT;
+ else
+ {
+ end_sequence ();
+ return false;
+ }
+
+ rtx tmp = gen_reg_rtx (mode);
+ noce_emit_move_insn (tmp, if_info->a);
+
+ target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
+
+ if (target)
+ {
+ rtx_insn *seq = get_insns ();
+
+ if (!seq)
+ {
+ end_sequence ();
+ return false;
+ }
+
+ if (target != if_info->x)
+ noce_emit_move_insn (if_info->x, target);
+
+ seq = end_ifcvt_sequence (if_info);
+
+ if (!seq)
+ return false;
+
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATION (if_info->insn_a));
+ return true;
+ }
+
+ end_sequence ();
+ return false;
+}
+
+
/* Convert "if (test) x = a; else x = b", for A and B constant.
Also allow A = y + c1, B = y + c2, with a common y between A
and B. */
@@ -2017,38 +2094,29 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
emit might clobber the register used by B or A, so move it to a pseudo
first. */
+ rtx tmp_a = NULL_RTX;
+ rtx tmp_b = NULL_RTX;
+
if (b_simple || !else_bb)
- {
- rtx tmp_b = gen_reg_rtx (x_mode);
- /* Perform the simplest kind of set. The register allocator
- should remove it if it's not actually needed. If this set is not
- a valid insn (can happen on the is_mem path) then end_ifcvt_sequence
- will cancel the whole sequence. Don't try any of the fallback paths
- from noce_emit_move_insn since we want this to be the simplest kind
- of move. */
- emit_insn (gen_rtx_SET (tmp_b, b));
- b = tmp_b;
- }
+ tmp_b = gen_reg_rtx (x_mode);
if (a_simple || !then_bb)
- {
- rtx tmp_a = gen_reg_rtx (x_mode);
- emit_insn (gen_rtx_SET (tmp_a, a));
- a = tmp_a;
- }
+ tmp_a = gen_reg_rtx (x_mode);
orig_a = a;
orig_b = b;
rtx emit_a = NULL_RTX;
rtx emit_b = NULL_RTX;
-
+ rtx_insn *tmp_insn = NULL;
+ bool modified_in_a = false;
+ bool modified_in_b = false;
/* If either operand is complex, load it into a register first.
The best way to do this is to copy the original insn. In this
way we preserve any clobbers etc that the insn may have had.
This is of course not possible in the IS_MEM case. */
- if (! general_operand (a, GET_MODE (a)))
+ if (! general_operand (a, GET_MODE (a)) || tmp_a)
{
if (is_mem)
@@ -2056,36 +2124,51 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
rtx reg = gen_reg_rtx (GET_MODE (a));
emit_a = gen_rtx_SET (reg, a);
}
- else if (! insn_a)
- goto end_seq_and_fail;
else
{
- a = gen_reg_rtx (GET_MODE (a));
- rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
- rtx set = single_set (copy_of_a);
- SET_DEST (set) = a;
+ if (insn_a)
+ {
+ a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
+
+ rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
+ rtx set = single_set (copy_of_a);
+ SET_DEST (set) = a;
- emit_a = PATTERN (copy_of_a);
+ emit_a = PATTERN (copy_of_a);
+ }
+ else
+ {
+ rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
+ emit_a = gen_rtx_SET (tmp_reg, a);
+ a = tmp_reg;
+ }
}
}
- if (! general_operand (b, GET_MODE (b)))
+ if (! general_operand (b, GET_MODE (b)) || tmp_b)
{
if (is_mem)
{
rtx reg = gen_reg_rtx (GET_MODE (b));
emit_b = gen_rtx_SET (reg, b);
}
- else if (! insn_b)
- goto end_seq_and_fail;
else
{
- b = gen_reg_rtx (GET_MODE (b));
- rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
- rtx set = single_set (copy_of_b);
+ if (insn_b)
+ {
+ b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
+ rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
+ rtx set = single_set (copy_of_b);
- SET_DEST (set) = b;
- emit_b = PATTERN (copy_of_b);
+ SET_DEST (set) = b;
+ emit_b = PATTERN (copy_of_b);
+ }
+ else
+ {
+ rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
+ emit_b = gen_rtx_SET (tmp_reg, b);
+ b = tmp_reg;
+ }
}
}
@@ -2093,16 +2176,35 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
swap insn that sets up A with the one that sets up B. If even
that doesn't help, punt. */
- if (emit_a && modified_in_p (orig_b, emit_a))
- {
- if (modified_in_p (orig_a, emit_b))
- goto end_seq_and_fail;
+ modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
+ if (tmp_b && then_bb)
+ {
+ FOR_BB_INSNS (then_bb, tmp_insn)
+ if (modified_in_p (orig_b, tmp_insn))
+ {
+ modified_in_a = true;
+ break;
+ }
- if (else_bb && !b_simple)
+ }
+ if (emit_a && modified_in_a)
+ {
+ modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
+ if (tmp_b && else_bb)
{
- if (!noce_emit_bb (emit_b, else_bb, b_simple))
- goto end_seq_and_fail;
+ FOR_BB_INSNS (else_bb, tmp_insn)
+ if (modified_in_p (orig_a, tmp_insn))
+ {
+ modified_in_b = true;
+ break;
+ }
+
}
+ if (modified_in_b)
+ goto end_seq_and_fail;
+
+ if (!noce_emit_bb (emit_b, else_bb, b_simple))
+ goto end_seq_and_fail;
if (!noce_emit_bb (emit_a, then_bb, a_simple))
goto end_seq_and_fail;
@@ -3076,12 +3178,12 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
rtx_code cond_code = GET_CODE (cond);
/* The true targets for a conditional move. */
- vec<rtx> targets = vNULL;
+ auto_vec<rtx> targets;
/* The temporaries introduced to allow us to not consider register
overlap. */
- vec<rtx> temporaries = vNULL;
+ auto_vec<rtx> temporaries;
/* The insns we've emitted. */
- vec<rtx_insn *> unmodified_insns = vNULL;
+ auto_vec<rtx_insn *> unmodified_insns;
int count = 0;
FOR_BB_INSNS (then_bb, insn)
@@ -3472,6 +3574,8 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success;
if (noce_try_abs (if_info))
goto success;
+ if (noce_try_inverse_constants (if_info))
+ goto success;
if (!targetm.have_conditional_execution ()
&& noce_try_store_flag_constants (if_info))
goto success;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index afbfae815e5..79425ea6a0f 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -1889,7 +1889,9 @@ expand_MASK_LOAD (gcall *stmt)
create_output_operand (&ops[0], target, TYPE_MODE (type));
create_fixed_operand (&ops[1], mem);
create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
- expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops);
+ expand_insn (convert_optab_handler (maskload_optab, TYPE_MODE (type),
+ TYPE_MODE (TREE_TYPE (maskt))),
+ 3, ops);
}
static void
@@ -1912,7 +1914,9 @@ expand_MASK_STORE (gcall *stmt)
create_fixed_operand (&ops[0], mem);
create_input_operand (&ops[1], reg, TYPE_MODE (type));
create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
- expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops);
+ expand_insn (convert_optab_handler (maskstore_optab, TYPE_MODE (type),
+ TYPE_MODE (TREE_TYPE (maskt))),
+ 3, ops);
}
static void
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index c07b0da9007..8c8b8e3af84 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -2853,7 +2853,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
inline_summaries->get (node)->self_time = time;
inline_summaries->get (node)->self_size = size;
nonconstant_names.release ();
- fbi.bb_infos.release ();
+ ipa_release_body_info (&fbi);
if (opt_for_fn (node->decl, optimize))
{
if (!early)
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index d15f0ebed56..f379ea73909 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -2258,6 +2258,19 @@ analysis_dom_walker::before_dom_children (basic_block bb)
ipa_compute_jump_functions_for_bb (m_fbi, bb);
}
+/* Release body info FBI. */
+
+void
+ipa_release_body_info (struct ipa_func_body_info *fbi)
+{
+ int i;
+ struct ipa_bb_info *bi;
+
+ FOR_EACH_VEC_ELT (fbi->bb_infos, i, bi)
+ free_ipa_bb_info (bi);
+ fbi->bb_infos.release ();
+}
+
/* Initialize the array describing properties of formal parameters
of NODE, analyze their uses and compute jump functions associated
with actual arguments of calls from within NODE. */
@@ -2313,11 +2326,7 @@ ipa_analyze_node (struct cgraph_node *node)
analysis_dom_walker (&fbi).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- int i;
- struct ipa_bb_info *bi;
- FOR_EACH_VEC_ELT (fbi.bb_infos, i, bi)
- free_ipa_bb_info (bi);
- fbi.bb_infos.release ();
+ ipa_release_body_info (&fbi);
free_dominance_info (CDI_DOMINATORS);
pop_cfun ();
}
@@ -3306,6 +3315,7 @@ ipa_node_params::~ipa_node_params ()
free (lattices);
/* Lattice values and their sources are deallocated with their alocation
pool. */
+ known_csts.release ();
known_contexts.release ();
lattices = NULL;
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index b69ee8ab745..2fe824d35cf 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -775,7 +775,7 @@ bool ipa_modify_expr (tree *, bool, ipa_parm_adjustment_vec);
ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
ipa_parm_adjustment_vec,
bool);
-
+void ipa_release_body_info (struct ipa_func_body_info *);
/* From tree-sra.c: */
tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, bool, tree,
diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c
index 1655c4768c3..9453759a521 100644
--- a/gcc/lra-lives.c
+++ b/gcc/lra-lives.c
@@ -103,7 +103,7 @@ free_live_range_list (lra_live_range_t lr)
while (lr != NULL)
{
next = lr->next;
- delete lr;
+ lra_live_range_pool.remove (lr);
lr = next;
}
}
@@ -112,7 +112,7 @@ free_live_range_list (lra_live_range_t lr)
static lra_live_range_t
create_live_range (int regno, int start, int finish, lra_live_range_t next)
{
- lra_live_range_t p = new lra_live_range;
+ lra_live_range_t p = lra_live_range_pool.allocate ();
p->regno = regno;
p->start = start;
p->finish = finish;
@@ -124,7 +124,7 @@ create_live_range (int regno, int start, int finish, lra_live_range_t next)
static lra_live_range_t
copy_live_range (lra_live_range_t r)
{
- return new lra_live_range (*r);
+ return new (lra_live_range_pool) lra_live_range (*r);
}
/* Copy live range list given by its head R and return the result. */
@@ -167,7 +167,7 @@ lra_merge_live_ranges (lra_live_range_t r1, lra_live_range_t r2)
r1->start = r2->start;
lra_live_range_t temp = r2;
r2 = r2->next;
- delete temp;
+ lra_live_range_pool.remove (temp);
}
else
{
@@ -1081,7 +1081,7 @@ remove_some_program_points_and_update_live_ranges (void)
}
prev_r->start = r->start;
prev_r->next = next_r;
- delete r;
+ lra_live_range_pool.remove (r);
}
}
}
@@ -1240,7 +1240,9 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
dead_set = sparseset_alloc (max_regno);
unused_set = sparseset_alloc (max_regno);
curr_point = 0;
- point_freq_vec.create (get_max_uid () * 2);
+ unsigned new_length = get_max_uid () * 2;
+ if (point_freq_vec.length () < new_length)
+ point_freq_vec.safe_grow (new_length);
lra_point_freq = point_freq_vec.address ();
int *post_order_rev_cfg = XNEWVEC (int, last_basic_block_for_fn (cfun));
int n_blocks_inverted = inverted_post_order_compute (post_order_rev_cfg);
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index fc87a3f584e..0b6bd58e1b3 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -47,10 +47,6 @@ DEF_GOACC_BUILTIN (BUILT_IN_GOACC_UPDATE, "GOACC_update",
DEF_GOACC_BUILTIN (BUILT_IN_GOACC_WAIT, "GOACC_wait",
BT_FN_VOID_INT_INT_VAR,
ATTR_NOTHROW_LIST)
-DEF_GOACC_BUILTIN (BUILT_IN_GOACC_GET_THREAD_NUM, "GOACC_get_thread_num",
- BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_GOACC_BUILTIN (BUILT_IN_GOACC_GET_NUM_THREADS, "GOACC_get_num_threads",
- BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GOACC_BUILTIN_COMPILER (BUILT_IN_ACC_ON_DEVICE, "acc_on_device",
BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 547a74ad7c7..12ecf7df820 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5559,7 +5559,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
{
gimple_seq sub_seq = NULL;
gimple *stmt;
- tree x, c, tid = NULL_TREE;
+ tree x, c;
int count = 0;
/* OpenACC loop reductions are handled elsewhere. */
@@ -5589,17 +5589,6 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
if (count == 0)
return;
- /* Initialize thread info for OpenACC. */
- if (is_gimple_omp_oacc (ctx->stmt))
- {
- /* Get the current thread id. */
- tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
- tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
- gimple *stmt = gimple_build_call (call, 0);
- gimple_call_set_lhs (stmt, tid);
- gimple_seq_add_stmt (stmt_seqp, stmt);
- }
-
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
{
tree var, ref, new_var, orig_var;
@@ -12266,7 +12255,7 @@ expand_omp_atomic (struct omp_region *region)
}
-/* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
+/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
macro on gomp-constants.h. We do not check for overflow. */
static tree
@@ -12292,7 +12281,7 @@ oacc_launch_pack (unsigned code, tree device, unsigned op)
The attribute value is a TREE_LIST. A set of dimensions is
represented as a list of INTEGER_CST. Those that are runtime
- expres are represented as an INTEGER_CST of zero.
+ exprs are represented as an INTEGER_CST of zero.
TOOO. Normally the attribute will just contain a single such list. If
however it contains a list of lists, this will represent the use of
@@ -12361,6 +12350,50 @@ set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
}
}
+/* Process the routine's dimension clauess to generate an attribute
+ value. Issue diagnostics as appropriate. We default to SEQ
+ (OpenACC 2.5 clarifies this). All dimensions have a size of zero
+ (dynamic). TREE_PURPOSE is set to indicate whether that dimension
+ can have a loop partitioned on it. non-zero indicates
+ yes, zero indicates no. By construction once a non-zero has been
+ reached, further inner dimensions must also be non-zero. We set
+ TREE_VALUE to zero for the dimensions that may be partitioned and
+ 1 for the other ones -- if a loop is (erroneously) spawned at
+ an outer level, we don't want to try and partition it. */
+
+tree
+build_oacc_routine_dims (tree clauses)
+{
+ /* Must match GOMP_DIM ordering. */
+ static const omp_clause_code ids[] =
+ {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
+ int ix;
+ int level = -1;
+
+ for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
+ for (ix = GOMP_DIM_MAX + 1; ix--;)
+ if (OMP_CLAUSE_CODE (clauses) == ids[ix])
+ {
+ if (level >= 0)
+ error_at (OMP_CLAUSE_LOCATION (clauses),
+ "multiple loop axes specified for routine");
+ level = ix;
+ break;
+ }
+
+ /* Default to SEQ. */
+ if (level < 0)
+ level = GOMP_DIM_MAX;
+
+ tree dims = NULL_TREE;
+
+ for (ix = GOMP_DIM_MAX; ix--;)
+ dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
+ build_int_cst (integer_type_node, ix < level), dims);
+
+ return dims;
+}
+
/* Retrieve the oacc function attrib and return it. Non-oacc
functions will return NULL. */
@@ -14311,7 +14344,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_omp_for_clauses (stmt),
&oacc_head, &oacc_tail, ctx);
- /* Add OpenACC partitioning markers just before the loop */
+ /* Add OpenACC partitioning and reduction markers just before the loop */
if (oacc_head)
gimple_seq_add_seq (&body, oacc_head);
@@ -19524,7 +19557,7 @@ public:
return execute_oacc_device_lower ();
}
-}; // class pass_oacc_transform
+}; // class pass_oacc_device_lower
} // anon namespace
diff --git a/gcc/omp-low.h b/gcc/omp-low.h
index ee0f8ac1ad5..194b3d14d6b 100644
--- a/gcc/omp-low.h
+++ b/gcc/omp-low.h
@@ -30,6 +30,8 @@ extern tree omp_reduction_init (tree, tree);
extern bool make_gimple_omp_edges (basic_block, struct omp_region **, int *);
extern void omp_finish_file (void);
extern tree omp_member_access_dummy_var (tree);
+extern void replace_oacc_fn_attrib (tree, tree);
+extern tree build_oacc_routine_dims (tree);
extern tree get_oacc_fn_attrib (tree);
extern int get_oacc_ifn_dim_arg (const gimple *);
extern int get_oacc_fn_dim_size (tree, int);
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index 254089fec7e..c20597c7bcb 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -466,7 +466,9 @@ can_mult_highpart_p (machine_mode mode, bool uns_p)
/* Return true if target supports vector masked load/store for mode. */
bool
-can_vec_mask_load_store_p (machine_mode mode, bool is_load)
+can_vec_mask_load_store_p (machine_mode mode,
+ machine_mode mask_mode,
+ bool is_load)
{
optab op = is_load ? maskload_optab : maskstore_optab;
machine_mode vmode;
@@ -474,7 +476,7 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load)
/* If mode is vector mode, check it directly. */
if (VECTOR_MODE_P (mode))
- return optab_handler (op, mode) != CODE_FOR_nothing;
+ return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing;
/* Otherwise, return true if there is some vector mode with
the mask load/store supported. */
@@ -485,7 +487,12 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load)
if (!VECTOR_MODE_P (vmode))
return false;
- if (optab_handler (op, vmode) != CODE_FOR_nothing)
+ mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
+ GET_MODE_SIZE (vmode));
+ if (mask_mode == VOIDmode)
+ return false;
+
+ if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
return true;
vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
@@ -496,8 +503,10 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load)
if (cur <= GET_MODE_SIZE (mode))
continue;
vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
+ mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
+ cur);
if (VECTOR_MODE_P (vmode)
- && optab_handler (op, vmode) != CODE_FOR_nothing)
+ && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
return true;
}
return false;
diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
index 73f272946a7..162d2e9a7c3 100644
--- a/gcc/optabs-query.h
+++ b/gcc/optabs-query.h
@@ -74,6 +74,16 @@ trapv_binoptab_p (optab binoptab)
|| binoptab == smulv_optab);
}
+/* Return insn code for a comparison operator with VMODE
+ resultin MASK_MODE, unsigned if UNS is true. */
+
+static inline enum insn_code
+get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns)
+{
+ optab tab = uns ? vec_cmpu_optab : vec_cmp_optab;
+ return convert_optab_handler (tab, vmode, mask_mode);
+}
+
/* Return insn code for a conditional operator with a comparison in
mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
@@ -130,7 +140,7 @@ enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode,
machine_mode, int,
machine_mode *);
int can_mult_highpart_p (machine_mode, bool);
-bool can_vec_mask_load_store_p (machine_mode, bool);
+bool can_vec_mask_load_store_p (machine_mode, machine_mode, bool);
bool can_compare_and_swap_p (machine_mode, bool);
bool can_atomic_exchange_p (machine_mode, bool);
bool lshift_cheap_p (bool);
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 3b033382c18..aa863cfb941 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -320,6 +320,19 @@ supportable_convert_operation (enum tree_code code,
return false;
}
+/* Return TRUE if appropriate vector insn is available
+ for vector comparison expr with vector type VALUE_TYPE
+ and resulting mask with MASK_TYPE. */
+
+bool
+expand_vec_cmp_expr_p (tree value_type, tree mask_type)
+{
+ enum insn_code icode = get_vec_cmp_icode (TYPE_MODE (value_type),
+ TYPE_MODE (mask_type),
+ TYPE_UNSIGNED (value_type));
+ return (icode != CODE_FOR_nothing);
+}
+
/* Return TRUE iff, appropriate vector insns are available
for vector cond expr with vector type VALUE_TYPE and a comparison
with operand vector types in CMP_OP_TYPE. */
diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h
index bf6c9e31495..5b966ca92b8 100644
--- a/gcc/optabs-tree.h
+++ b/gcc/optabs-tree.h
@@ -39,6 +39,7 @@ optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
optab scalar_reduc_to_vector (optab, const_tree);
bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
enum tree_code *);
+bool expand_vec_cmp_expr_p (tree, tree);
bool expand_vec_cond_expr_p (tree, tree);
void init_tree_optimization_optabs (tree);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index fdcdc6a0735..f9fbfde967d 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4210,6 +4210,56 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
return NULL_RTX;
}
+
+/* Emit a conditional negate or bitwise complement using the
+ negcc or notcc optabs if available. Return NULL_RTX if such operations
+ are not available. Otherwise return the RTX holding the result.
+ TARGET is the desired destination of the result. COMP is the comparison
+ on which to negate. If COND is true move into TARGET the negation
+ or bitwise complement of OP1. Otherwise move OP2 into TARGET.
+ CODE is either NEG or NOT. MODE is the machine mode in which the
+ operation is performed. */
+
+rtx
+emit_conditional_neg_or_complement (rtx target, rtx_code code,
+ machine_mode mode, rtx cond, rtx op1,
+ rtx op2)
+{
+ optab op = unknown_optab;
+ if (code == NEG)
+ op = negcc_optab;
+ else if (code == NOT)
+ op = notcc_optab;
+ else
+ gcc_unreachable ();
+
+ insn_code icode = direct_optab_handler (op, mode);
+
+ if (icode == CODE_FOR_nothing)
+ return NULL_RTX;
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ rtx_insn *last = get_last_insn ();
+ struct expand_operand ops[4];
+
+ create_output_operand (&ops[0], target, mode);
+ create_fixed_operand (&ops[1], cond);
+ create_input_operand (&ops[2], op1, mode);
+ create_input_operand (&ops[3], op2, mode);
+
+ if (maybe_expand_insn (icode, 4, ops))
+ {
+ if (ops[0].value != target)
+ convert_move (target, ops[0].value, false);
+
+ return target;
+ }
+ delete_insns_since (last);
+ return NULL_RTX;
+}
+
/* Emit a conditional addition instruction if the machine supports one for that
condition and machine mode.
@@ -4838,6 +4888,33 @@ expand_fix (rtx to, rtx from, int unsignedp)
}
}
+
+/* Promote integer arguments for a libcall if necessary.
+ emit_library_call_value cannot do the promotion because it does not
+ know if it should do a signed or unsigned promotion. This is because
+ there are no tree types defined for libcalls. */
+
+static rtx
+prepare_libcall_arg (rtx arg, int uintp)
+{
+ machine_mode mode = GET_MODE (arg);
+ machine_mode arg_mode;
+ if (SCALAR_INT_MODE_P (mode))
+ {
+ /* If we need to promote the integer function argument we need to do
+ it here instead of inside emit_library_call_value because in
+ emit_library_call_value we don't know if we should do a signed or
+ unsigned promotion. */
+
+ int unsigned_p = 0;
+ arg_mode = promote_function_mode (NULL_TREE, mode,
+ &unsigned_p, NULL_TREE, 0);
+ if (arg_mode != mode)
+ return convert_to_mode (arg_mode, arg, uintp);
+ }
+ return arg;
+}
+
/* Generate code to convert FROM or TO a fixed-point.
If UINTP is true, either TO or FROM is an unsigned integer.
If SATP is true, we need to saturate the result. */
@@ -4880,6 +4957,9 @@ expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
gcc_assert (libfunc);
+ from = prepare_libcall_arg (from, uintp);
+ from_mode = GET_MODE (from);
+
start_sequence ();
value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
1, from, from_mode);
@@ -5100,11 +5180,13 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
}
/* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
- unsigned operators. Do not generate compare instruction. */
+ unsigned operators. OPNO holds an index of the first comparison
+ operand in insn with code ICODE. Do not generate compare instruction. */
static rtx
vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
- bool unsignedp, enum insn_code icode)
+ bool unsignedp, enum insn_code icode,
+ unsigned int opno)
{
struct expand_operand ops[2];
rtx rtx_op0, rtx_op1;
@@ -5130,7 +5212,7 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
create_input_operand (&ops[0], rtx_op0, m0);
create_input_operand (&ops[1], rtx_op1, m1);
- if (!maybe_legitimize_operands (icode, 4, 2, ops))
+ if (!maybe_legitimize_operands (icode, opno, 2, ops))
gcc_unreachable ();
return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
}
@@ -5365,7 +5447,6 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
op0a = TREE_OPERAND (op0, 0);
op0b = TREE_OPERAND (op0, 1);
tcode = TREE_CODE (op0);
- unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
}
else
{
@@ -5374,9 +5455,9 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
op0a = op0;
op0b = build_zero_cst (TREE_TYPE (op0));
tcode = LT_EXPR;
- unsignedp = false;
}
cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
+ unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
gcc_assert (GET_MODE_SIZE (mode) == GET_MODE_SIZE (cmp_op_mode)
@@ -5386,7 +5467,7 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
if (icode == CODE_FOR_nothing)
return 0;
- comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode);
+ comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode, 4);
rtx_op1 = expand_normal (op1);
rtx_op2 = expand_normal (op2);
@@ -5400,6 +5481,40 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
return ops[0].value;
}
+/* Generate insns for a vector comparison into a mask. */
+
+rtx
+expand_vec_cmp_expr (tree type, tree exp, rtx target)
+{
+ struct expand_operand ops[4];
+ enum insn_code icode;
+ rtx comparison;
+ machine_mode mask_mode = TYPE_MODE (type);
+ machine_mode vmode;
+ bool unsignedp;
+ tree op0a, op0b;
+ enum tree_code tcode;
+
+ op0a = TREE_OPERAND (exp, 0);
+ op0b = TREE_OPERAND (exp, 1);
+ tcode = TREE_CODE (exp);
+
+ unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
+ vmode = TYPE_MODE (TREE_TYPE (op0a));
+
+ icode = get_vec_cmp_icode (vmode, mask_mode, unsignedp);
+ if (icode == CODE_FOR_nothing)
+ return 0;
+
+ comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode, 2);
+ create_output_operand (&ops[0], target, mask_mode);
+ create_fixed_operand (&ops[1], comparison);
+ create_fixed_operand (&ops[2], XEXP (comparison, 0));
+ create_fixed_operand (&ops[3], XEXP (comparison, 1));
+ expand_insn (icode, 4, ops);
+ return ops[0].value;
+}
+
/* Expand a highpart multiply. */
rtx
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 888b21c4c64..c9e52a96a25 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -61,6 +61,10 @@ OPTAB_CD(vec_load_lanes_optab, "vec_load_lanes$a$b")
OPTAB_CD(vec_store_lanes_optab, "vec_store_lanes$a$b")
OPTAB_CD(vcond_optab, "vcond$a$b")
OPTAB_CD(vcondu_optab, "vcondu$a$b")
+OPTAB_CD(vec_cmp_optab, "vec_cmp$a$b")
+OPTAB_CD(vec_cmpu_optab, "vec_cmpu$a$b")
+OPTAB_CD(maskload_optab, "maskload$a$b")
+OPTAB_CD(maskstore_optab, "maskstore$a$b")
OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc)
OPTAB_NX(add_optab, "add$F$a3")
@@ -183,6 +187,8 @@ OPTAB_D (reload_out_optab, "reload_out$a")
OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE)
OPTAB_D (addcc_optab, "add$acc")
+OPTAB_D (negcc_optab, "neg$acc")
+OPTAB_D (notcc_optab, "not$acc")
OPTAB_D (movcc_optab, "mov$acc")
OPTAB_D (cmov_optab, "cmov$a6")
OPTAB_D (cstore_optab, "cstore$a4")
@@ -264,8 +270,6 @@ OPTAB_D (udot_prod_optab, "udot_prod$I$a")
OPTAB_D (usum_widen_optab, "widen_usum$I$a3")
OPTAB_D (usad_optab, "usad$I$a")
OPTAB_D (ssad_optab, "ssad$I$a")
-OPTAB_D (maskload_optab, "maskload$a")
-OPTAB_D (maskstore_optab, "maskstore$a")
OPTAB_D (vec_extract_optab, "vec_extract$a")
OPTAB_D (vec_init_optab, "vec_init$a")
OPTAB_D (vec_pack_sfix_trunc_optab, "vec_pack_sfix_trunc_$a")
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 3f29d1b6f79..78666f63b45 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -259,6 +259,10 @@ extern void emit_indirect_jump (rtx);
rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode,
rtx, rtx, machine_mode, int);
+/* Emit a conditional negate or bitwise complement operation. */
+rtx emit_conditional_neg_or_complement (rtx, rtx_code, machine_mode, rtx,
+ rtx, rtx);
+
rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
rtx, rtx, machine_mode, int);
@@ -300,6 +304,9 @@ extern rtx_insn *gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
/* Generate code for VEC_PERM_EXPR. */
extern rtx expand_vec_perm (machine_mode, rtx, rtx, rtx, rtx);
+/* Generate code for vector comparison. */
+extern rtx expand_vec_cmp_expr (tree, tree, rtx);
+
/* Generate code for VEC_COND_EXPR. */
extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
diff --git a/gcc/output.h b/gcc/output.h
index f9ff85886db..f6a576c22b8 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -108,9 +108,9 @@ extern void output_asm_label (rtx);
/* Marks SYMBOL_REFs in x as referenced through use of assemble_external. */
extern void mark_symbol_refs_as_used (rtx);
-/* Print a memory reference operand for address X
+/* Print a memory reference operand for address X with access mode MODE
using machine-dependent assembler syntax. */
-extern void output_address (rtx);
+extern void output_address (machine_mode, rtx);
/* Print an integer constant expression in assembler syntax.
Addition and subtraction are the only arithmetic
diff --git a/gcc/print-rtl.h b/gcc/print-rtl.h
index eb079afaa3c..f601d338cfb 100644
--- a/gcc/print-rtl.h
+++ b/gcc/print-rtl.h
@@ -30,6 +30,8 @@ extern void dump_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
int, int);
extern void print_value (pretty_printer *, const_rtx, int);
extern void print_pattern (pretty_printer *, const_rtx, int);
+extern void print_insn (pretty_printer *pp, const rtx_insn *x, int verbose);
+
extern void rtl_dump_bb_for_graph (pretty_printer *, basic_block);
extern const char *str_pattern_slim (const_rtx);
diff --git a/gcc/regrename.c b/gcc/regrename.c
index 5f383fc9ce2..d727dd9095b 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -130,6 +130,9 @@ static HARD_REG_SET live_hard_regs;
record_operand_use. */
static operand_rr_info *cur_operand;
+/* Set while scanning RTL if a register dies. Used to tie chains. */
+static struct du_head *terminated_this_insn;
+
/* Return the chain corresponding to id number ID. Take into account that
chains may have been merged. */
du_head_p
@@ -224,6 +227,8 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
head->nregs = this_nregs;
head->need_caller_save_reg = 0;
head->cannot_rename = 0;
+ head->renamed = 0;
+ head->tied_chain = NULL;
id_to_chain.safe_push (head);
head->id = current_id++;
@@ -366,6 +371,13 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
preferred_class
= (enum reg_class) targetm.preferred_rename_class (super_class);
+ /* Pick and check the register from the tied chain iff the tied chain
+ is not renamed. */
+ if (this_head->tied_chain && !this_head->tied_chain->renamed
+ && check_new_reg_p (old_reg, this_head->tied_chain->regno,
+ this_head, *unavailable))
+ return this_head->tied_chain->regno;
+
/* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
over registers that belong to PREFERRED_CLASS and try to find the
best register within the class. If that failed, we iterate in
@@ -960,6 +972,7 @@ regrename_do_replace (struct du_head *head, int reg)
return false;
mode = GET_MODE (*head->first->loc);
+ head->renamed = 1;
head->regno = reg;
head->nregs = hard_regno_nregs[reg][mode];
return true;
@@ -1043,7 +1056,34 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act
if (action == mark_write)
{
if (type == OP_OUT)
- create_new_chain (this_regno, this_nregs, loc, insn, cl);
+ {
+ du_head_p c;
+ rtx pat = PATTERN (insn);
+
+ c = create_new_chain (this_regno, this_nregs, loc, insn, cl);
+
+ /* We try to tie chains in a move instruction for
+ a single output. */
+ if (recog_data.n_operands == 2
+ && GET_CODE (pat) == SET
+ && GET_CODE (SET_DEST (pat)) == REG
+ && GET_CODE (SET_SRC (pat)) == REG
+ && terminated_this_insn)
+ {
+ gcc_assert (terminated_this_insn->regno
+ == REGNO (recog_data.operand[1]));
+
+ c->tied_chain = terminated_this_insn;
+ terminated_this_insn->tied_chain = c;
+
+ if (dump_file)
+ fprintf (dump_file, "Tying chain %s (%d) with %s (%d)\n",
+ reg_names[c->regno], c->id,
+ reg_names[terminated_this_insn->regno],
+ terminated_this_insn->id);
+ }
+ }
+
return;
}
@@ -1151,6 +1191,8 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act
SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
}
+ if (action == terminate_dead)
+ terminated_this_insn = *p;
*p = next;
if (dump_file)
fprintf (dump_file,
@@ -1707,6 +1749,8 @@ build_def_use (basic_block bb)
scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
OP_INOUT);
+ terminated_this_insn = NULL;
+
/* Step 4: Close chains for registers that die here, unless
the register is mentioned in a REG_UNUSED note. In that
case we keep the chain open until step #7 below to ensure
diff --git a/gcc/regrename.h b/gcc/regrename.h
index bbe156dbc4e..77cc2fe29c4 100644
--- a/gcc/regrename.h
+++ b/gcc/regrename.h
@@ -28,6 +28,8 @@ struct du_head
struct du_head *next_chain;
/* The first and last elements of this chain. */
struct du_chain *first, *last;
+ /* The chain that this chain is tied to. */
+ struct du_head *tied_chain;
/* Describes the register being tracked. */
unsigned regno;
int nregs;
@@ -45,6 +47,8 @@ struct du_head
such as the SET_DEST of a CALL_INSN or an asm operand that used
to be a hard register. */
unsigned int cannot_rename:1;
+ /* Nonzero if the chain has already been renamed. */
+ unsigned int renamed:1;
};
typedef struct du_head *du_head_p;
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index 86f582105f8..46003477720 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -1497,6 +1497,9 @@ extern void compute_priorities (void);
extern void increase_insn_priority (rtx_insn *, int);
extern void debug_rgn_dependencies (int);
extern void debug_dependencies (rtx_insn *, rtx_insn *);
+extern void dump_rgn_dependencies_dot (FILE *);
+extern void dump_rgn_dependencies_dot (const char *);
+
extern void free_rgn_deps (void);
extern int contributes_to_priority (rtx_insn *, rtx_insn *);
extern void extend_rgns (int *, int *, sbitmap, int *);
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index b9ffd7c983c..668f471cb29 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -63,6 +63,8 @@ along with GCC; see the file COPYING3. If not see
#include "sel-sched.h"
#include "tree-pass.h"
#include "dbgcnt.h"
+#include "pretty-print.h"
+#include "print-rtl.h"
#ifdef INSN_SCHEDULING
@@ -2863,6 +2865,108 @@ void debug_dependencies (rtx_insn *head, rtx_insn *tail)
fprintf (sched_dump, "\n");
}
+
+/* Dump dependency graph for the current region to a file using dot syntax. */
+
+void
+dump_rgn_dependencies_dot (FILE *file)
+{
+ rtx_insn *head, *tail, *con, *pro;
+ sd_iterator_def sd_it;
+ dep_t dep;
+ int bb;
+ pretty_printer pp;
+
+ pp.buffer->stream = file;
+ pp_printf (&pp, "digraph SchedDG {\n");
+
+ for (bb = 0; bb < current_nr_blocks; ++bb)
+ {
+ /* Begin subgraph (basic block). */
+ pp_printf (&pp, "subgraph cluster_block_%d {\n", bb);
+ pp_printf (&pp, "\t" "color=blue;" "\n");
+ pp_printf (&pp, "\t" "style=bold;" "\n");
+ pp_printf (&pp, "\t" "label=\"BB #%d\";\n", BB_TO_BLOCK (bb));
+
+ /* Setup head and tail (no support for EBBs). */
+ gcc_assert (EBB_FIRST_BB (bb) == EBB_LAST_BB (bb));
+ get_ebb_head_tail (EBB_FIRST_BB (bb), EBB_LAST_BB (bb), &head, &tail);
+ tail = NEXT_INSN (tail);
+
+ /* Dump all insns. */
+ for (con = head; con != tail; con = NEXT_INSN (con))
+ {
+ if (!INSN_P (con))
+ continue;
+
+ /* Pretty print the insn. */
+ pp_printf (&pp, "\t%d [label=\"{", INSN_UID (con));
+ pp_write_text_to_stream (&pp);
+ print_insn (&pp, con, /*verbose=*/false);
+ pp_write_text_as_dot_label_to_stream (&pp, /*for_record=*/true);
+ pp_write_text_to_stream (&pp);
+
+ /* Dump instruction attributes. */
+ pp_printf (&pp, "|{ uid:%d | luid:%d | prio:%d }}\",shape=record]\n",
+ INSN_UID (con), INSN_LUID (con), INSN_PRIORITY (con));
+
+ /* Dump all deps. */
+ FOR_EACH_DEP (con, SD_LIST_BACK, sd_it, dep)
+ {
+ int weight = 0;
+ const char *color;
+ pro = DEP_PRO (dep);
+
+ switch (DEP_TYPE (dep))
+ {
+ case REG_DEP_TRUE:
+ color = "black";
+ weight = 1;
+ break;
+ case REG_DEP_OUTPUT:
+ case REG_DEP_ANTI:
+ color = "orange";
+ break;
+ case REG_DEP_CONTROL:
+ color = "blue";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ pp_printf (&pp, "\t%d -> %d [color=%s",
+ INSN_UID (pro), INSN_UID (con), color);
+ if (int cost = dep_cost (dep))
+ pp_printf (&pp, ",label=%d", cost);
+ pp_printf (&pp, ",weight=%d", weight);
+ pp_printf (&pp, "];\n");
+ }
+ }
+ pp_printf (&pp, "}\n");
+ }
+
+ pp_printf (&pp, "}\n");
+ pp_flush (&pp);
+}
+
+/* Dump dependency graph for the current region to a file using dot syntax. */
+
+DEBUG_FUNCTION void
+dump_rgn_dependencies_dot (const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen (fname, "w");
+ if (!fp)
+ {
+ perror ("fopen");
+ return;
+ }
+
+ dump_rgn_dependencies_dot (fp);
+ fclose (fp);
+}
+
/* Returns true if all the basic blocks of the current region have
NOTE_DISABLE_SCHED_OF_BLOCK which means not to schedule that region. */
diff --git a/gcc/target.def b/gcc/target.def
index 0f7d3e5effb..61cb14b1b52 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -893,7 +893,7 @@ DEFHOOK_UNDOC
DEFHOOK_UNDOC
(print_operand_address,
"",
- void, (FILE *file, rtx addr),
+ void, (FILE *file, machine_mode mode, rtx addr),
default_print_operand_address)
/* Determine whether CODE is a valid punctuation character for the
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index c810525be92..c34b4e9ef6a 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -345,6 +345,7 @@ default_print_operand (FILE *stream ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
void
default_print_operand_address (FILE *stream ATTRIBUTE_UNUSED,
+ machine_mode /*mode*/,
rtx x ATTRIBUTE_UNUSED)
{
#ifdef PRINT_OPERAND_ADDRESS
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 8747f958535..c9d745b00d6 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -67,7 +67,7 @@ extern bool hook_callee_copies_named
(cumulative_args_t ca, machine_mode, const_tree, bool);
extern void default_print_operand (FILE *, rtx, int);
-extern void default_print_operand_address (FILE *, rtx);
+extern void default_print_operand_address (FILE *, machine_mode, rtx);
extern bool default_print_operand_punct_valid_p (unsigned char);
extern tree default_mangle_assembler_name (const char *);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4cd50cdef13..1ac009f2613 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,143 @@
+2015-11-10 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * gcc.target/i386/avx2-vec-mask-bit-not.c: New test.
+
+2015-11-10 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * gcc.dg/vect/slp-cond-5.c: New test.
+
+2015-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/68240
+ * gcc.dg/torture/pr68240.c: New testcase.
+
+2015-11-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56118
+ * gcc.target/i386/pr56118.c: New testcase.
+
+2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/cond_op_imm_1.c: New test.
+
+2015-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gfortran.dg/pr68251.f90: New test.
+
+2015-11-09 Cesar Philippidis <cesar@codesourcery.com>
+
+ * c-c++-common/goacc/routine-5.c: Enable c++ tests.
+
+2015-11-09 Martin Sebor <msebor@redhat.com>
+
+ * init/new45.C: New test to verify that operator new is invoked
+ with or without overhead for a cookie.
+
+ PR c++/67927
+ * init/new44.C: New test for placement new expressions for arrays
+ with excessive number of elements.
+
+ PR c++/67913
+ * init/new43.C: New test for placement new expressions for arrays
+ with negative number of elements.
+
+ * other/new-size-type.C: Expect array new expression with
+ an excessive number of elements to be rejected.
+
+2015-11-09 Nathan Sidwell <nathan@codesourcery.com>
+
+ * c-c++-common/goacc/routine-1.c: New.
+ * c-c++-common/goacc/routine-2.c: New.
+ * c-c++-common/goacc/routine-3.c: New.
+ * c-c++-common/goacc/routine-4.c: New.
+ * c-c++-common/goacc/routine-5.c: New.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/sparc-ret.c: Rename to...
+ * gcc.target/sparc/sparc-ret-1.c: ...this.
+ * gcc.target/sparc/sparc-ret-2.c: New test.
+
+2015-11-09 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * lib/target-supports.exp (check_p8vector_hw_available): Split
+ long line.
+ (check_vsx_hw_available): Likewise.
+ (check_p9vector_hw_available): Add new checks for ISA 3.0 hardware
+ support and for PowerPC float128 support.
+ (check_p9modulo_hw_available): Likewise.
+ (check_ppc_float128_sw_available): Likewise.
+ (check_ppc_float128_hw_available): Likewise.
+ (check_effective_target_powerpc_p9vector_ok): Likewise.
+ (check_effective_target_powerpc_p9modulo_ok): Likewise.
+ (check_effective_target_powerpc_float128_sw_ok): Likewise.
+ (check_effective_target_powerpc_float128_hw_ok): Likewise.
+ (is-effective-target): Add new PowerPc targets.
+ (is-effective-target-keyword): Likewise.
+ (check_vect_support_and_set_flags): If we have ISA 3.0 vector
+ instructions, use it.
+
+ * gcc.target/powerpc/mod-1.c: New test for ISA 3.0 instructions.
+ * gcc.target/powerpc/mod-2.c: Likewise.
+ * gcc.target/powerpc/ctz-1.c: Likewise.
+ * gcc.target/powerpc/ctz-2.c: Likewise.
+ * gcc.target/powerpc/extswsli-1.c: Likewise.
+ * gcc.target/powerpc/extswsli-2.c: Likewise.
+ * gcc.target/powerpc/extswsli-3.c: Likewise.
+
+ * gcc.target/powerpc/fusion.c (fusion_vector): Move to fusion2.c
+ and allow the test on PowerPC LE.
+ * gcc.target/powerpc/fusion2.c (fusion_vector): Likewise.
+ * gcc.target/powerpc/fusion3.c: New file, test power9 fusion.
+
+ * gcc.target/powerpc/float128-call.c: Use powerpc_float128_sw_ok
+ check instead of powerpc_vsx_ok.
+ * gcc.target/powerpc/float128-mix.c: Likewise.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/sso/*.c: Robustify dg-output directives.
+
+2015-11-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/ubsan/pr68259.C: New test.
+
+2015-11-09 Uros Bizjak <ubizjak@gmail.com>
+
+ * g++.dg/cilk-plus/CK/pr66326.cc: Do not include cilk.h.
+ (main): Use _Cilk_spawn instead of cilk_spawn.
+
+2015-11-09 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gcc.target/i386/addr-space-3.c: Fix quoting in dg-final
+ scan-assembler directive.
+
+2015-11-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/68129
+ * gcc.dg/pr68129_1.c: New test.
+
+2015-11-09 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ PR debug/67192
+ * gcc.dg/guality/pr67192.c (f3, f4): New functions.
+ (main): Invoke them.
+
+2015-11-09 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ PR debug/67192
+ * gcc.dg/guality/pr67192.c: New test.
+
+2015-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/68248
+ * gcc.dg/torture/pr68248.c: New testcase.
+
+2015-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/56118
+ * gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c: Adjust.
+
2015-11-09 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.target/arm/thumb2-slow-flash-data.c: Add missing typespec for
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-1.c b/gcc/testsuite/c-c++-common/goacc/routine-1.c
new file mode 100644
index 00000000000..a5e0d696f7c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-1.c
@@ -0,0 +1,34 @@
+
+#pragma acc routine gang
+void gang (void)
+{
+}
+
+#pragma acc routine worker
+void worker (void)
+{
+}
+
+#pragma acc routine vector
+void vector (void)
+{
+}
+
+#pragma acc routine seq
+void seq (void)
+{
+}
+
+int main ()
+{
+
+#pragma acc parallel num_gangs (32) num_workers (32) vector_length (32)
+ {
+ gang ();
+ worker ();
+ vector ();
+ seq ();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-2.c b/gcc/testsuite/c-c++-common/goacc/routine-2.c
new file mode 100644
index 00000000000..fc5eb11bb54
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-2.c
@@ -0,0 +1,21 @@
+#pragma acc routine gang worker /* { dg-error "multiple loop axes" } */
+void gang (void)
+{
+}
+
+#pragma acc routine worker vector /* { dg-error "multiple loop axes" } */
+void worker (void)
+{
+}
+
+#pragma acc routine vector seq /* { dg-error "multiple loop axes" } */
+void vector (void)
+{
+}
+
+#pragma acc routine seq gang /* { dg-error "multiple loop axes" } */
+void seq (void)
+{
+}
+
+#pragma acc routine (nothing) gang /* { dg-error "not been declared" } */
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-3.c b/gcc/testsuite/c-c++-common/goacc/routine-3.c
new file mode 100644
index 00000000000..e6f83bd151a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-3.c
@@ -0,0 +1,53 @@
+#pragma acc routine gang
+void gang (void) /* { dg-message "declared here" 3 } */
+{
+}
+
+#pragma acc routine worker
+void worker (void) /* { dg-message "declared here" 2 } */
+{
+}
+
+#pragma acc routine vector
+void vector (void) /* { dg-message "declared here" 1 } */
+{
+}
+
+#pragma acc routine seq
+void seq (void)
+{
+}
+
+int main ()
+{
+
+#pragma acc parallel num_gangs (32) num_workers (32) vector_length (32)
+ {
+ #pragma acc loop gang /* { dg-message "loop here" 1 } */
+ for (int i = 0; i < 10; i++)
+ {
+ gang (); /* { dg-error "routine call uses same" } */
+ worker ();
+ vector ();
+ seq ();
+ }
+ #pragma acc loop worker /* { dg-message "loop here" 2 } */
+ for (int i = 0; i < 10; i++)
+ {
+ gang (); /* { dg-error "routine call uses same" } */
+ worker (); /* { dg-error "routine call uses same" } */
+ vector ();
+ seq ();
+ }
+ #pragma acc loop vector /* { dg-message "loop here" 3 } */
+ for (int i = 0; i < 10; i++)
+ {
+ gang (); /* { dg-error "routine call uses same" } */
+ worker (); /* { dg-error "routine call uses same" } */
+ vector (); /* { dg-error "routine call uses same" } */
+ seq ();
+ }
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-4.c b/gcc/testsuite/c-c++-common/goacc/routine-4.c
new file mode 100644
index 00000000000..004d7132bf6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-4.c
@@ -0,0 +1,41 @@
+
+void gang (void);
+void worker (void);
+void vector (void);
+
+#pragma acc routine (gang) gang
+#pragma acc routine (worker) worker
+#pragma acc routine (vector) vector
+
+#pragma acc routine seq
+void seq (void)
+{
+ gang (); /* { dg-error "routine call uses" } */
+ worker (); /* { dg-error "routine call uses" } */
+ vector (); /* { dg-error "routine call uses" } */
+ seq ();
+}
+
+void vector (void) /* { dg-message "declared here" 1 } */
+{
+ gang (); /* { dg-error "routine call uses" } */
+ worker (); /* { dg-error "routine call uses" } */
+ vector ();
+ seq ();
+}
+
+void worker (void) /* { dg-message "declared here" 2 } */
+{
+ gang (); /* { dg-error "routine call uses" } */
+ worker ();
+ vector ();
+ seq ();
+}
+
+void gang (void) /* { dg-message "declared here" 3 } */
+{
+ gang ();
+ worker ();
+ vector ();
+ seq ();
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-5.c b/gcc/testsuite/c-c++-common/goacc/routine-5.c
new file mode 100644
index 00000000000..ccda0976a04
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-5.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+
+#pragma acc routine /* { dg-error "not followed by" } */
+int a;
+
+#pragma acc routine /* { dg-error "not followed by" } */
+void fn1 (void), fn1b (void);
+
+#pragma acc routine /* { dg-error "not followed by" } */
+int b, fn2 (void);
+
+#pragma acc routine /* { dg-error "not followed by" } */
+int fn3 (void), b2;
+
+#pragma acc routine /* { dg-error "not followed by" } */
+typedef struct c c;
+
+#pragma acc routine /* { dg-error "not followed by" } */
+struct d {} d;
+
+#pragma acc routine /* { dg-error "not followed by" } */
+#pragma acc routine
+int fn4 (void);
+
+int fn5a (void);
+
+#pragma acc routine /* { dg-error "not followed by" } */
+#pragma acc routine (fn5a)
+int fn5 (void);
+
+#ifdef __cplusplus
+
+#pragma acc routine /* { dg-error "not followed by" "" { target c++ } } */
+namespace f {}
+
+namespace g {}
+
+#pragma acc routine /* { dg-error "not followed by" "" { target c++ } } */
+using namespace g;
+
+#pragma acc routine (g) /* { dg-error "does not refer to" "" { target c++ } } */
+
+#endif
+
+#pragma acc routine (a) /* { dg-error "does not refer to" } */
+
+#pragma acc routine (c) /* { dg-error "does not refer to" } */
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc
index 1114ebdda82..057a9ced283 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc
@@ -2,7 +2,6 @@
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
-#include <cilk/cilk.h>
#include <vector>
#include <random>
@@ -23,8 +22,8 @@ auto compute() {
int main() {
std::vector<double> v1, v2, v3;
- cilk_spawn [&] { v1 = compute(); }();
- cilk_spawn [&] { v2 = compute(); }();
+ _Cilk_spawn [&] { v1 = compute(); }();
+ _Cilk_spawn [&] { v2 = compute(); }();
v3 = compute();
do_not_optimize_away(v1.data());
do_not_optimize_away(v2.data());
diff --git a/gcc/testsuite/g++.dg/init/new43.C b/gcc/testsuite/g++.dg/init/new43.C
new file mode 100644
index 00000000000..9b0866720fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new43.C
@@ -0,0 +1,164 @@
+/* { dg-do compile } */
+
+// Test for PR c++/67913 - new expression with negative size not diagnosed.
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void*);
+void* operator new[] (size_t, void*);
+
+struct A {
+ int a [4];
+};
+
+struct B {
+ int a [4];
+
+ void* operator new (size_t, void*);
+ void* operator new[] (size_t, void*);
+};
+
+void* operator new (size_t, B*);
+void* operator new[] (size_t, B*);
+
+void *p;
+
+void test_literal ()
+{
+ char c;
+ (void)c;
+
+ B b;
+
+ // Verify integer literal.
+ p = new char [-1]; // { dg-error "size of array is negative" }
+ p = new char [2][-3]; // { dg-error "size of array is negative" }
+ p = new char [-4][5]; // { dg-error "size of array is negative" }
+ p = new char [-6][-7]; // { dg-error "size of array is negative" }
+
+ p = new (p) char [-1]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) char [-4][5]; // { dg-error "size of array is negative" }
+ p = new (p) char [-6][-7]; // { dg-error "size of array is negative" }
+
+ p = new (p) A [-1]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) A [-4][5]; // { dg-error "size of array is negative" }
+ p = new (p) A [-6][-7]; // { dg-error "size of array is negative" }
+
+ p = new (p) B [-1]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) B [-4][5]; // { dg-error "size of array is negative" }
+ p = new (p) B [-6][-7]; // { dg-error "size of array is negative" }
+
+ p = new (&b) B [-1]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][-3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [-4][5]; // { dg-error "size of array is negative" }
+ p = new (&b) B [-6][-7]; // { dg-error "size of array is negative" }
+
+ p = new char [1 - 2]; // { dg-error "size of array is negative" }
+ p = new (p) char [2 - 3]; // { dg-error "size of array is negative" }
+ p = new A [2 < 1 ? -1 : -2]; // { dg-error "size of array is negative" }
+ p = new (p) B [2 - 3 * 2]; // { dg-error "size of array is negative" }
+ p = new (&b) B [1][2 - 3 * 2];// { dg-error "size of array is negative" }
+}
+
+void test_constant_expression ()
+{
+ char c;
+ (void)c;
+
+ B b;
+
+ static const signed char i1 = -1;
+ static const signed short i2 = -2;
+ static const signed int i3 = -3;
+ static const signed long i4 = -4;
+ static const signed long long i5 = -5;
+ static const int i6 = -6;
+ static const int i7 = -7;
+
+ // Verify constant expression.
+ p = new char [i1]; // { dg-error "size of array is negative" }
+ p = new char [2][i3]; // { dg-error "size of array is negative" }
+ p = new char [i4][5]; // { dg-error "size of array is negative" }
+ p = new char [i6][i7]; // { dg-error "size of array is negative" }
+
+ p = new (p) char [i1]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) char [i4][5]; // { dg-error "size of array is negative" }
+ p = new (p) char [i6][i7]; // { dg-error "size of array is negative" }
+
+ p = new (p) A [i1]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) A [i4][5]; // { dg-error "size of array is negative" }
+ p = new (p) A [i6][i7]; // { dg-error "size of array is negative" }
+
+ p = new (p) B [i1]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) B [i4][5]; // { dg-error "size of array is negative" }
+ p = new (p) B [i6][i7]; // { dg-error "size of array is negative" }
+
+ p = new (&b) B [i1]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][i3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [i4][5]; // { dg-error "size of array is negative" }
+ p = new (&b) B [i6][i7]; // { dg-error "size of array is negative" }
+
+ p = new short [i1 - 2]; // { dg-error "size of array is negative" }
+ p = new (p) bool [i2 - 3]; // { dg-error "size of array is negative" }
+ p = new A [2 < 1 ? i1 : i2]; // { dg-error "size of array is negative" }
+ p = new (p) B [2 + i3 * 2]; // { dg-error "size of array is negative" }
+ p = new (&b) B [1][i1 - 3 * 2];// { dg-error "size of array is negative" }
+}
+
+void test_constexpr ()
+{
+ B b;
+
+#if __cplusplus >= 201103L
+
+ // Verify that a constant expression that is "a prvalue core constant
+ // expression whose value is an object where, for that object and its
+ // subobjects each non-static data member of reference type refers to
+ // an object with static storage duration."
+ static constexpr struct S {
+ int i_;
+ constexpr S (int i): i_ (i) { }
+ constexpr operator int () const { return i_; }
+ } s1 (-1), s2 (-2), s3 (-3), s4 (-4), s5 (-5), s6 (-6), s7 (-7);
+#else
+ // C++ 11 constexpr is not available, fall back on plain ole enum.
+ enum { s1 = -1, s2 = -2, s3 = -3, s4 = -4, s5 = -5, s6 = -6, s7 = -7 };
+#endif
+
+ // Verify constant expression.
+ p = new char [s1]; // { dg-error "size of array is negative" }
+ p = new char [2][s3]; // { dg-error "size of array is negative" }
+ p = new char [s4][5]; // { dg-error "size of array is negative" }
+ p = new char [s6][s7]; // { dg-error "size of array is negative" }
+
+ p = new (p) char [s1]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) char [s4][5]; // { dg-error "size of array is negative" }
+ p = new (p) char [s6][s7]; // { dg-error "size of array is negative" }
+
+ p = new (p) A [s1]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) A [s4][5]; // { dg-error "size of array is negative" }
+ p = new (p) A [s6][s7]; // { dg-error "size of array is negative" }
+
+ p = new (p) B [s1]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) B [s4][5]; // { dg-error "size of array is negative" }
+ p = new (p) B [s6][s7]; // { dg-error "size of array is negative" }
+
+ p = new (&b) B [s1]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][s3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [s4][5]; // { dg-error "size of array is negative" }
+ p = new (&b) B [s6][s7]; // { dg-error "size of array is negative" }
+
+ p = new int [s1 + s2]; // { dg-error "size of array is negative" }
+ p = new (p) long [2 * s3]; // { dg-error "size of array is negative" }
+ p = new A [s2 < s1 ? s1 : s2]; // { dg-error "size of array is negative" }
+ p = new (p) B [s7 - s2 * 2]; // { dg-error "size of array is negative" }
+ p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "size of array is negative" }
+}
diff --git a/gcc/testsuite/g++.dg/init/new44.C b/gcc/testsuite/g++.dg/init/new44.C
new file mode 100644
index 00000000000..d6ff86a16c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new44.C
@@ -0,0 +1,532 @@
+// { dg-do compile }
+
+// Test for PR c++/67927 - array new expression with excessive number
+// of elements not diagnosed.
+
+// GCC uses a different maximum value at compile time and at runtime:
+// 1) The compile-time maximum, MAX, is SIZE_MAX / 2 minus the size
+// of a cookie (sizeof (size_t)). Exceeding the compile-time
+// maximum is ill-formed and diagnosed. This test verifies this
+// diagnostic.
+// 2) The runtime runtime maximum is the most significant 7 bits,
+// starting with the first most significant non-zero bit, of
+// the dividend of the compile-time constant MAX and the product
+// of the constant array dimensions and the element size, minus
+// the size of the "cookie." This is also roughly (though not
+// exactly) SIZE_MAX / 2. Exceeding the runtime maximum is
+// diagnosed at runtime by throwing a bad_array_new_length
+// exception.
+// The cookie is the number of elements in the array, and is
+// only added for non-POD types, but the its size factors into
+// the maximum size formula regardless.
+
+// See also PR c++/19351 - integer overflow in operator new[].
+
+// For convenience.
+#define MAX __SIZE_MAX__
+
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void*);
+void* operator new[] (size_t, void*);
+
+void *p;
+
+// Exercise new expression with one-dimensional arrays of char.
+static void __attribute__ ((used))
+test_one_dim_char_array ()
+{
+ p = new char [MAX]; // { dg-error "size of array" }
+ p = new char [MAX - 1]; // { dg-error "size of array" }
+ p = new char [MAX - 2]; // { dg-error "size of array" }
+ p = new char [MAX - 99]; // { dg-error "size of array" }
+ p = new char [MAX / 2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid testing the expressions below since whether or not they
+ // are accepted depends on the precision of size_t (which also
+ // determines the size of the cookie).
+ // p = new char [MAX / 2 - 3];
+ // p = new char [MAX / 2 - 4];
+ // p = new char [MAX / 2 - 5];
+ // p = new char [MAX / 2 - 6];
+
+ // The following expressions are accepted on ILP32 as well LP64
+ // (they will be diagnosed on LP128 if there ever is such a data
+ // model).
+ p = new char [MAX / 2 - 7]; // okay
+ p = new char [MAX / 2 - 8]; // okay
+}
+
+static void __attribute__ ((used))
+test_one_dim_short_array ()
+{
+ p = new short [MAX]; // { dg-error "size of array" }
+ p = new short [MAX - 1]; // { dg-error "size of array" }
+ p = new short [MAX - 2]; // { dg-error "size of array" }
+ p = new short [MAX - 99]; // { dg-error "size of array" }
+ p = new short [MAX / 2]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new short [MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new short [MAX / 4]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new short [MAX / 4 - 1];
+
+ p = new short [MAX / 4 - 4]; // okay
+}
+
+// Exercise new expression with two-dimensional arrays or char.
+static void __attribute__ ((used))
+test_two_dim_char_array ()
+{
+ p = new char [1][MAX]; // { dg-error "size of array" }
+ p = new char [1][MAX - 1]; // { dg-error "size of array" }
+ p = new char [1][MAX - 2]; // { dg-error "size of array" }
+ p = new char [1][MAX - 99]; // { dg-error "size of array" }
+ p = new char [1][MAX / 2]; // { dg-error "size of array" }
+ p = new char [1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [1][MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [1][MAX / 2 - 3];
+ // p = new char [1][MAX / 2 - 4];
+ // p = new char [1][MAX / 2 - 5];
+ // p = new char [1][MAX / 2 - 6];
+
+ p = new char [1][MAX / 2 - 7]; // okay
+ p = new char [1][MAX / 2 - 8]; // okay
+
+ p = new char [2][MAX]; // { dg-error "size of array" }
+ p = new char [2][MAX - 1]; // { dg-error "size of array" }
+ p = new char [2][MAX - 2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 8]; // { dg-error "size of array" }
+
+ p = new char [MAX][MAX]; // { dg-error "size of array" }
+ p = new char [MAX][MAX - 1]; // { dg-error "size of array" }
+ p = new char [MAX][MAX - 2]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new char [MAX][2]; // { dg-error "size of array" }
+ p = new char [MAX][1]; // { dg-error "size of array" }
+ p = new char [MAX / 2][1]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 1][1]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 2][1]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [MAX / 2 - 3][1];
+ // p = new char [MAX / 2 - 4][1];
+ // p = new char [MAX / 2 - 5][1];
+ // p = new char [MAX / 2 - 6][1];
+
+ p = new char [MAX / 2 - 7][1]; // okay
+ p = new char [MAX / 2 - 8][1]; // okay
+}
+
+
+// Exercise new expression with three-dimensional arrays.
+static __attribute__ ((used)) void
+test_three_dim_char_array ()
+{
+ p = new char [1][1][MAX]; // { dg-error "size of array" }
+ p = new char [1][1][MAX - 1]; // { dg-error "size of array" }
+ p = new char [1][1][MAX - 2]; // { dg-error "size of array" }
+ p = new char [1][1][MAX - 99]; // { dg-error "size of array" }
+ p = new char [1][1][MAX / 2]; // { dg-error "size of array" }
+ p = new char [1][1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [1][1][MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [1][1][MAX / 2 - 3];
+ // p = new char [1][1][MAX / 2 - 4];
+ // p = new char [1][1][MAX / 2 - 5];
+ // p = new char [1][1][MAX / 2 - 6];
+
+ p = new char [1][1][MAX / 2 - 7]; // okay
+ p = new char [1][1][MAX / 2 - 8]; // okay
+
+ p = new char [1][2][MAX]; // { dg-error "size of array" }
+ p = new char [1][2][MAX - 1]; // { dg-error "size of array" }
+ p = new char [1][2][MAX - 2]; // { dg-error "size of array" }
+ p = new char [1][2][MAX - 99]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new char [1][2][MAX / 4]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [1][2][MAX / 4 - 1];
+ // p = new char [1][2][MAX / 4 - 2];
+
+ p = new char [1][2][MAX / 4 - 3]; // okay
+ p = new char [1][2][MAX / 4 - 4]; // okay
+
+ p = new char [2][1][MAX]; // { dg-error "size of array" }
+ p = new char [2][1][MAX - 1]; // { dg-error "size of array" }
+ p = new char [2][1][MAX - 2]; // { dg-error "size of array" }
+ p = new char [2][1][MAX - 99]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new char [2][1][MAX / 4]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [2][1][MAX / 4 - 1];
+ // p = new char [2][1][MAX / 4 - 2];
+
+ p = new char [2][1][MAX / 4 - 3]; // okay
+ p = new char [2][1][MAX / 4 - 4]; // okay
+
+ p = new char [2][2][MAX]; // { dg-error "size of array" }
+ p = new char [2][2][MAX - 1]; // { dg-error "size of array" }
+ p = new char [2][2][MAX - 2]; // { dg-error "size of array" }
+ p = new char [2][2][MAX - 99]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 4]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 4 - 1]; // { dg-error "size of array" }
+ p = new char [2][2][MAX / 4 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [2][2][MAX / 8];
+ // p = new char [2][2][MAX / 8 - 1];
+
+ p = new char [2][2][MAX / 8 - 2];
+ p = new char [2][2][MAX / 8 - 3];
+
+ p = new char [2][MAX][2]; // { dg-error "size of array" }
+ p = new char [2][MAX - 1][2]; // { dg-error "size of array" }
+ p = new char [2][MAX - 2][2]; // { dg-error "size of array" }
+ p = new char [2][MAX - 99][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 1][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 2][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 3][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 4][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 5][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 6][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 7][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 2 - 8][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 4][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 4 - 1][2]; // { dg-error "size of array" }
+ p = new char [2][MAX / 4 - 2][2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [2][MAX / 8][2];
+ // p = new char [2][MAX / 8 - 1][2];
+
+ p = new char [2][MAX / 8 - 2][2];
+ p = new char [2][MAX / 8 - 3][2];
+
+ p = new char [MAX][2][2]; // { dg-error "size of array" }
+ p = new char [MAX - 1][2][2]; // { dg-error "size of array" }
+ p = new char [MAX - 2][2][2]; // { dg-error "size of array" }
+ p = new char [MAX - 99][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 1][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 2][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 3][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 4][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 5][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 6][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 7][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 2 - 8][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 4][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 4 - 1][2][2]; // { dg-error "size of array" }
+ p = new char [MAX / 4 - 2][2][2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new char [MAX / 8][2][2];
+ // p = new char [MAX / 8 - 1][2][2];
+
+ p = new char [MAX / 8 - 2][2][2];
+ p = new char [MAX / 8 - 3][2][2];
+
+ p = new char [MAX][MAX][MAX]; // { dg-error "size of array" }
+ p = new char [MAX][MAX][MAX / 2]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2][MAX]; // { dg-error "size of array" }
+ p = new char [MAX][MAX / 2][MAX / 2]; // { dg-error "size of array" }
+ p = new char [MAX / 2][MAX / 2][MAX / 2]; // { dg-error "size of array" }
+}
+
+// Exercise new expression with N-dimensional arrays where N is
+// sizeof(size_t).
+static __attribute__ ((used)) void
+test_N_dim_char_array ()
+{
+#if __SIZEOF_SIZE_T__ == 8
+ enum { N = 256 };
+#else
+ enum { N = 16 };
+#endif
+
+ p = new char [N][N][N][N][N][N][N];
+ p = new char [N / 2][2][N][N][N][N][N][N];
+ p = new char [N - 1][N / 2][N][N][N][N][N][N];
+ p = new char [N / 2][N][N][N][N][N][N][N]; // { dg-error "size of array" }
+ p = new char [N - 1][N][N][N][N][N][N][N]; // { dg-error "size of array" }
+ p = new char [N] [N][N][N][N][N][N][N]; // { dg-error "size of array" }
+}
+
+typedef struct Byte {
+ char c;
+
+ void* operator new (size_t, void*);
+ void* operator new[] (size_t, void*);
+} B;
+
+void* operator new (size_t, B*);
+void* operator new[] (size_t, B*);
+
+// Exercise placement new expression with one-dimensional arrays of a struct.
+static void __attribute__ ((used))
+test_one_dim_byte_array (void *p)
+{
+ p = new (p) B [MAX]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid testing the expressions below since whether or not they
+ // are accepted depends on the precision of size_t (which determines
+ // the size of the cookie).
+ // p = new (p) B [MAX / 2 - 3];
+ // p = new (p) B [MAX / 2 - 4];
+ // p = new (p) B [MAX / 2 - 5];
+ // p = new (p) B [MAX / 2 - 6];
+
+ // The following expressions are accepted on ILP32 as well LP64
+ // (they will be diagnosed on LP128 if there ever is such a data
+ // model).
+ p = new (p) B [MAX / 2 - 7]; // okay
+ p = new (p) B [MAX / 2 - 8]; // okay
+}
+
+// Exercise placement new expression with two-dimensional arrays.
+static void __attribute__ ((used))
+test_placement_two_dim_byte_struct_array (void *p)
+{
+ p = new (p) B [1][MAX]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [1][MAX / 2 - 3];
+ // p = new (p) B [1][MAX / 2 - 4];
+ // p = new (p) B [1][MAX / 2 - 5];
+ // p = new (p) B [1][MAX / 2 - 6];
+
+ p = new (p) B [1][MAX / 2 - 7]; // okay
+ p = new (p) B [1][MAX / 2 - 8]; // okay
+
+ p = new (p) B [2][MAX]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 8]; // { dg-error "size of array" }
+
+ p = new (p) B [MAX][MAX]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new (p) B [MAX][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new (p) B [MAX][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX][1]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2][1]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 1][1]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 2][1]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [MAX / 2 - 3][1];
+ // p = new (p) B [MAX / 2 - 4][1];
+ // p = new (p) B [MAX / 2 - 5][1];
+ // p = new (p) B [MAX / 2 - 6][1];
+
+ p = new (p) B [MAX / 2 - 7][1]; // okay
+ p = new (p) B [MAX / 2 - 8][1]; // okay
+}
+
+
+// Exercise placement new expression with three-dimensional arrays.
+static __attribute__ ((used)) void
+test_placement_three_dim_byte_struct_array (void *p)
+{
+ p = new (p) B [1][1][MAX]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][1][MAX / 2 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [1][1][MAX / 2 - 3];
+ // p = new (p) B [1][1][MAX / 2 - 4];
+ // p = new (p) B [1][1][MAX / 2 - 5];
+ // p = new (p) B [1][1][MAX / 2 - 6];
+
+ p = new (p) B [1][1][MAX / 2 - 7]; // okay
+ p = new (p) B [1][1][MAX / 2 - 8]; // okay
+
+ p = new (p) B [1][2][MAX]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new (p) B [1][2][MAX / 4]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [1][2][MAX / 4 - 1];
+ // p = new (p) B [1][2][MAX / 4 - 2];
+
+ p = new (p) B [1][2][MAX / 4 - 3]; // okay
+ p = new (p) B [1][2][MAX / 4 - 4]; // okay
+
+ p = new (p) B [2][1][MAX]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new (p) B [2][1][MAX / 4]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [2][1][MAX / 4 - 1];
+ // p = new (p) B [2][1][MAX / 4 - 2];
+
+ p = new (p) B [2][1][MAX / 4 - 3]; // okay
+ p = new (p) B [2][1][MAX / 4 - 4]; // okay
+
+ p = new (p) B [2][2][MAX]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX - 99]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 2]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 3]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 4]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 5]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 6]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 7]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 2 - 8]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 4]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 4 - 1]; // { dg-error "size of array" }
+ p = new (p) B [2][2][MAX / 4 - 2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [2][2][MAX / 8];
+ // p = new (p) B [2][2][MAX / 8 - 1];
+
+ p = new (p) B [2][2][MAX / 8 - 2];
+ p = new (p) B [2][2][MAX / 8 - 3];
+
+ p = new (p) B [2][MAX][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX - 1][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX - 2][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX - 99][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 1][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 2][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 3][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 4][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 5][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 6][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 7][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 2 - 8][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 4][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 4 - 1][2]; // { dg-error "size of array" }
+ p = new (p) B [2][MAX / 4 - 2][2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [2][MAX / 8][2];
+ // p = new (p) B [2][MAX / 8 - 1][2];
+
+ p = new (p) B [2][MAX / 8 - 2][2];
+ p = new (p) B [2][MAX / 8 - 3][2];
+
+ p = new (p) B [MAX][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 1][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 2][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX - 99][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 1][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 2][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 3][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 4][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 5][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 6][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 7][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 2 - 8][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 4][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 4 - 1][2][2]; // { dg-error "size of array" }
+ p = new (p) B [MAX / 4 - 2][2][2]; // { dg-error "size of array" }
+
+ // Avoid exercising data model-dependent expressions.
+ // p = new (p) B [MAX / 8][2][2];
+ // p = new (p) B [MAX / 8 - 1][2][2];
+
+ p = new (p) B [MAX / 8 - 2][2][2];
+ p = new (p) B [MAX / 8 - 3][2][2];
+}
diff --git a/gcc/testsuite/g++.dg/init/new45.C b/gcc/testsuite/g++.dg/init/new45.C
new file mode 100644
index 00000000000..92dac18a32e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new45.C
@@ -0,0 +1,106 @@
+// { dg-do compile }
+// { dg-options "-O1" }
+// { dg-final { scan-assembler-not "abort" } }
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void abort ();
+ void* malloc (size_t);
+}
+
+struct UDClass {
+ static int n;
+ UDClass () { ++n; }
+ virtual ~UDClass () { --n; }
+};
+
+int UDClass::n;
+
+struct POD {
+ char buf [sizeof (UDClass)];
+};
+
+enum { N = 123 };
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n)
+{
+ // Verify that array new is invoked with an argument large enough
+ // for the array and a size_t cookie to store the number of elements.
+ // (This holds for classes with user-defined types but not POD types).
+ if (n != N * sizeof (UDClass) + sizeof n) abort ();
+ return malloc (n);
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, void *p)
+{
+ // Verify that the default placement array new is invoked with
+ // an argument just large enough for the array (and no cookie),
+ // regardless of whether the type is a POD or class with a user
+ // defined ctor.
+ if (n != N * sizeof (UDClass)) abort ();
+ return p;
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, POD *p)
+{
+ // Verify that placement array new overload for a POD type is
+ // invoked with an argument large enough for the array and
+ // a cookie.
+ if (n != N * sizeof (POD)) abort ();
+ return p;
+}
+
+inline __attribute__ ((always_inline))
+void* operator new[] (size_t n, UDClass *p)
+{
+ // Verify that placement array new overload for a class type with
+ // a user-defined ctor and dtor is invoked with an argument large
+ // enough for the array and a cookie.
+ if (n != N * sizeof (UDClass) + sizeof n) abort ();
+ return p;
+}
+
+// UDClassllocate a sufficiently large buffer to construct arrays into.
+static unsigned char buf [N * N];
+
+POD* test_new_POD ()
+{
+ // Avoid testing PODs since for those, the global new is invoked
+ // without the overhead of a cookie.
+ // return new POD [N];
+ return 0;
+}
+
+POD* test_default_placement_new_POD ()
+{
+ // Vefify that no overhead is allocated.
+ return new (buf) POD [N];
+}
+
+POD* test_overloaded_placement_new_POD ()
+{
+ // Vefify that no overhead is allocated.
+ return new ((POD*)buf) POD [N];
+}
+
+UDClass* test_new_UDClass ()
+{
+ // Vefify that space for a cookie is allocated.
+ return new UDClass [N];
+}
+
+UDClass* test_default_placement_new_UDClass ()
+{
+ // Vefify that no overhead is allocated.
+ return new (buf) UDClass [N];
+}
+
+UDClass* test_overloaded_placement_new_UDClass ()
+{
+ // Vefify that space for a cookie is allocated.
+ return new ((UDClass*)buf) UDClass [N];
+}
diff --git a/gcc/testsuite/g++.dg/other/new-size-type.C b/gcc/testsuite/g++.dg/other/new-size-type.C
index 04933fd4a2c..ad4dc102c3b 100644
--- a/gcc/testsuite/g++.dg/other/new-size-type.C
+++ b/gcc/testsuite/g++.dg/other/new-size-type.C
@@ -5,6 +5,5 @@
const char*
foo()
{
- return new char[~static_cast<size_t>(0)];// { dg-bogus "large" }
+ return new char[~static_cast<size_t>(0)];// { dg-error "size of array" }
}
-
diff --git a/gcc/testsuite/g++.dg/ubsan/pr68259.C b/gcc/testsuite/g++.dg/ubsan/pr68259.C
new file mode 100644
index 00000000000..5137edd1f8b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr68259.C
@@ -0,0 +1,54 @@
+// PR middle-end/68259
+
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined -w" }
+
+namespace std {
+ template < typename _Tp > class allocator { };
+ template < typename _Tp, typename _Alloc
+= std::allocator < _Tp >
+>class vector {
+ public:
+typedef _Tp value_type;
+ void push_back (const value_type & __x) { }
+ };
+}
+class Foo;
+class FooBar {
+public:
+Foo * primitive_context;
+ FooBar () { }
+ FooBar (const FooBar & pnhp);
+};
+template < class KEY, class CONTENT > class AVLTreeNode { };
+template < class KEY, class CONTENT > class FooTree final
+{
+ FooBar insertPrimitive ();
+public:
+AVLTreeNode < KEY, CONTENT > *seek_no_lock (const KEY & key) { }
+ void primitive_patterns ( std::vector < FooBar > &patterns);
+};
+template < class KEY, class CONTENT > void FooTree < KEY,
+ CONTENT >::primitive_patterns ( std::vector <FooBar > &patterns)
+{
+ patterns.push_back (insertPrimitive());
+}
+template < class KEY, class CONTENT >
+FooBar FooTree < KEY, CONTENT >::insertPrimitive ()
+{
+ FooBar place;
+ seek_no_lock (place.primitive_context);
+ return place;
+}
+class ManuverResults { };
+class opc_info_t
+{
+public:
+FooTree < Foo *, ManuverResults > *primitivecache;
+};
+static void
+do_optical_prox_corr_tsafe (opc_info_t * opc_info)
+{
+ std::vector < FooBar > patterns;
+ opc_info->primitivecache->primitive_patterns (patterns);
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr67192.c b/gcc/testsuite/gcc.dg/guality/pr67192.c
new file mode 100644
index 00000000000..946e68f8faa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr67192.c
@@ -0,0 +1,79 @@
+/* PR debug/67192 */
+/* { dg-do run } */
+/* { dg-options "-g -Wmisleading-indentation" } */
+
+volatile int cnt = 0;
+
+__attribute__((noinline, noclone)) static int
+last (void)
+{
+ return ++cnt % 5 == 0;
+}
+
+__attribute__((noinline, noclone)) static void
+do_it (void)
+{
+ asm volatile ("" : : "r" (&cnt) : "memory");
+}
+
+__attribute__((noinline, noclone)) static void
+f1 (void)
+{
+ for (;; do_it())
+ {
+ if (last ())
+ break;
+ }
+ do_it (); /* { dg-final { gdb-test 27 "cnt" "5" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f2 (void)
+{
+ while (1)
+ {
+ if (last ())
+ break;
+ do_it ();
+ }
+ do_it (); /* { dg-final { gdb-test 39 "cnt" "10" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f3 (void)
+{
+ for (;; do_it())
+ if (last ())
+ break;
+ do_it (); /* { dg-final { gdb-test 48 "cnt" "15" } } */
+}
+
+__attribute__((noinline, noclone)) static void
+f4 (void)
+{
+ while (1) /* { dg-final { gdb-test 54 "cnt" "15" } } */
+ if (last ())
+ break;
+ else
+ do_it ();
+ do_it (); /* { dg-final { gdb-test 59 "cnt" "20" } } */
+}
+
+void (*volatile fnp1) (void) = f1;
+void (*volatile fnp2) (void) = f2;
+void (*volatile fnp3) (void) = f3;
+void (*volatile fnp4) (void) = f4;
+
+int
+main ()
+{
+ asm volatile ("" : : "r" (&fnp1) : "memory");
+ asm volatile ("" : : "r" (&fnp2) : "memory");
+ asm volatile ("" : : "r" (&fnp3) : "memory");
+ asm volatile ("" : : "r" (&fnp4) : "memory");
+ fnp1 ();
+ fnp2 ();
+ fnp3 ();
+ fnp4 ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr68129_1.c b/gcc/testsuite/gcc.dg/pr68129_1.c
new file mode 100644
index 00000000000..112331e665d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr68129_1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-split-wide-types" } */
+
+typedef int V __attribute__ ((vector_size (8 * sizeof (int))));
+
+void
+foo (V *p, V *q)
+{
+ *p = (*p == *q);
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p1.c b/gcc/testsuite/gcc.dg/sso/p1.c
index ab6ac5ae4b2..bf14ffe9502 100644
--- a/gcc/testsuite/gcc.dg/sso/p1.c
+++ b/gcc/testsuite/gcc.dg/sso/p1.c
@@ -13,52 +13,52 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 78 56 34 12\n" } */
+ /* { dg-output "My_R1 : 78 56 34 12.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 12 34 56 78\n" } */
+ /* { dg-output "My_R2 : 12 34 56 78.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78.*\n" } */
Local_R1.I = 0x12345678;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12.*\n" } */
Local_R2.I = 0x12345678;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78.*\n" } */
Local_R1.I = Local_R2.I;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12.*\n" } */
Local_R2.I = Local_R1.I;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p13.c b/gcc/testsuite/gcc.dg/sso/p13.c
index 08ecf292e44..fa1af6939fb 100644
--- a/gcc/testsuite/gcc.dg/sso/p13.c
+++ b/gcc/testsuite/gcc.dg/sso/p13.c
@@ -13,52 +13,52 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "My_R1 : db 0f 49 40 db 0f 49 c0.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "My_R2 : 40 49 0f db c0 49 0f db.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db.*\n" } */
Local_R1.F = Pi - Pi * I;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0.*\n" } */
Local_R2.F = Pi - Pi * I;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db.*\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0.*\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p2.c b/gcc/testsuite/gcc.dg/sso/p2.c
index 6d605379c15..2d929469252 100644
--- a/gcc/testsuite/gcc.dg/sso/p2.c
+++ b/gcc/testsuite/gcc.dg/sso/p2.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x12345678;
@@ -43,7 +43,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x12345678;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
Local_R1.S1 = Local_R2.S1;
Local_R1.I = Local_R2.I;
@@ -69,7 +69,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
Local_R2.S1 = Local_R1.S1;
Local_R2.I = Local_R1.I;
@@ -82,7 +82,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p3.c b/gcc/testsuite/gcc.dg/sso/p3.c
index ce47dbd2443..fb715965d53 100644
--- a/gcc/testsuite/gcc.dg/sso/p3.c
+++ b/gcc/testsuite/gcc.dg/sso/p3.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "My_R1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "My_R2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x78ABCDEF;
@@ -43,7 +43,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x78ABCDEF;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
Local_R1.S1 = Local_R2.S1;
Local_R1.I = Local_R2.I;
@@ -69,7 +69,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
Local_R2.S1 = Local_R1.S1;
Local_R2.I = Local_R1.I;
@@ -82,7 +82,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p4.c b/gcc/testsuite/gcc.dg/sso/p4.c
index 7d7224d9b30..ba0775fc84c 100644
--- a/gcc/testsuite/gcc.dg/sso/p4.c
+++ b/gcc/testsuite/gcc.dg/sso/p4.c
@@ -13,52 +13,52 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : db 0f 49 40\n" } */
+ /* { dg-output "My_R1 : db 0f 49 40.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 40 49 0f db\n" } */
+ /* { dg-output "My_R2 : 40 49 0f db.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db.*\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40.*\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db.*\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40.*\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p5.c b/gcc/testsuite/gcc.dg/sso/p5.c
index 91bd6ba0a48..fc8b7e18d03 100644
--- a/gcc/testsuite/gcc.dg/sso/p5.c
+++ b/gcc/testsuite/gcc.dg/sso/p5.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.A[0] = 0xAB0012;
@@ -39,7 +39,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.A[0] = 0xAB0012;
@@ -48,7 +48,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = Local_R2.I;
Local_R1.A[0] = Local_R2.A[0];
@@ -58,7 +58,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = Local_R1.I;
Local_R2.A[0] = Local_R1.A[0];
@@ -68,7 +68,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p6.c b/gcc/testsuite/gcc.dg/sso/p6.c
index 8681c303c40..90805a7a698 100644
--- a/gcc/testsuite/gcc.dg/sso/p6.c
+++ b/gcc/testsuite/gcc.dg/sso/p6.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.A[0] = 0xAB0012;
@@ -39,7 +39,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.A[0] = 0xAB0012;
@@ -48,7 +48,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.A[0] = Local_R2.N.A[0];
@@ -58,7 +58,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.A[0] = Local_R1.N.A[0];
@@ -68,7 +68,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p7.c b/gcc/testsuite/gcc.dg/sso/p7.c
index e6bfa136574..e347ecf7c4d 100644
--- a/gcc/testsuite/gcc.dg/sso/p7.c
+++ b/gcc/testsuite/gcc.dg/sso/p7.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
@@ -39,7 +39,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
@@ -48,7 +48,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.C1 = Local_R2.N.C1;
@@ -58,7 +58,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.C1 = Local_R1.N.C1;
@@ -68,7 +68,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p8.c b/gcc/testsuite/gcc.dg/sso/p8.c
index d2e7bd1b95d..d66c7da3fec 100644
--- a/gcc/testsuite/gcc.dg/sso/p8.c
+++ b/gcc/testsuite/gcc.dg/sso/p8.c
@@ -13,24 +13,24 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
@@ -39,7 +39,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
@@ -48,7 +48,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.C1 = Local_R2.N.C1;
@@ -58,7 +58,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.C1 = Local_R1.N.C1;
@@ -68,7 +68,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/p9.c b/gcc/testsuite/gcc.dg/sso/p9.c
index c3bee117cdc..ce565e9c699 100644
--- a/gcc/testsuite/gcc.dg/sso/p9.c
+++ b/gcc/testsuite/gcc.dg/sso/p9.c
@@ -13,52 +13,52 @@ int main (void)
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "My_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "My_R1 : 18 2d 44 54 fb 21 09 40.*\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "My_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "My_R2 : 40 09 21 fb 54 44 2d 18.*\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40.*\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18.*\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40.*\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18.*\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40.*\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/q1.c b/gcc/testsuite/gcc.dg/sso/q1.c
index 6da5a5f4533..f61398ba1f8 100644
--- a/gcc/testsuite/gcc.dg/sso/q1.c
+++ b/gcc/testsuite/gcc.dg/sso/q1.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12\n" } */
+ /* { dg-output "A1 : 78 56 34 12.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 78 56 34 12\n" } */
+ /* { dg-output "B1 : 78 56 34 12.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78\n" } */
+ /* { dg-output "A2 : 12 34 56 78.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 12 34 56 78\n" } */
+ /* { dg-output "B2 : 12 34 56 78.*\n" } */
if (A1.I != B1.I) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/q13.c b/gcc/testsuite/gcc.dg/sso/q13.c
index ee34bb2289d..c00701dcc0e 100644
--- a/gcc/testsuite/gcc.dg/sso/q13.c
+++ b/gcc/testsuite/gcc.dg/sso/q13.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "A1 : db 0f 49 40 db 0f 49 c0.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "B1 : db 0f 49 40 db 0f 49 c0.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "A2 : 40 49 0f db c0 49 0f db.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "B2 : 40 49 0f db c0 49 0f db.*\n" } */
if (A1.F != B1.F) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/q2.c b/gcc/testsuite/gcc.dg/sso/q2.c
index 9e1d1d27ff3..35e2839bdd7 100644
--- a/gcc/testsuite/gcc.dg/sso/q2.c
+++ b/gcc/testsuite/gcc.dg/sso/q2.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "A2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "B2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
if (A1.S1 != B1.S1) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/q3.c b/gcc/testsuite/gcc.dg/sso/q3.c
index 6e72d7efc45..31d395a37ed 100644
--- a/gcc/testsuite/gcc.dg/sso/q3.c
+++ b/gcc/testsuite/gcc.dg/sso/q3.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "B1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "B2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
if (A1.S1 != B1.S1) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/q4.c b/gcc/testsuite/gcc.dg/sso/q4.c
index 6966c8f7211..72a1366ff03 100644
--- a/gcc/testsuite/gcc.dg/sso/q4.c
+++ b/gcc/testsuite/gcc.dg/sso/q4.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : db 0f 49 40\n" } */
+ /* { dg-output "A1 : db 0f 49 40.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : db 0f 49 40\n" } */
+ /* { dg-output "B1 : db 0f 49 40.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 40 49 0f db\n" } */
+ /* { dg-output "A2 : 40 49 0f db.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 40 49 0f db\n" } */
+ /* { dg-output "B2 : 40 49 0f db.*\n" } */
if (A1.F != B1.F) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/q5.c b/gcc/testsuite/gcc.dg/sso/q5.c
index 03dfdb7c35c..678c3d36be8 100644
--- a/gcc/testsuite/gcc.dg/sso/q5.c
+++ b/gcc/testsuite/gcc.dg/sso/q5.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
if (A1.I != B1.I || A1.A[0] != B1.A[0]) abort();
diff --git a/gcc/testsuite/gcc.dg/sso/q6.c b/gcc/testsuite/gcc.dg/sso/q6.c
index 1292f6af7bd..f69bad0698d 100644
--- a/gcc/testsuite/gcc.dg/sso/q6.c
+++ b/gcc/testsuite/gcc.dg/sso/q6.c
@@ -21,21 +21,21 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
if (A1.I != B1.I || A1.N.A[0] != B1.N.A[0]) abort();
diff --git a/gcc/testsuite/gcc.dg/sso/q7.c b/gcc/testsuite/gcc.dg/sso/q7.c
index c088f05a0c7..0c3dbc517d4 100644
--- a/gcc/testsuite/gcc.dg/sso/q7.c
+++ b/gcc/testsuite/gcc.dg/sso/q7.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
diff --git a/gcc/testsuite/gcc.dg/sso/q8.c b/gcc/testsuite/gcc.dg/sso/q8.c
index 108afc1822f..3846cb14751 100644
--- a/gcc/testsuite/gcc.dg/sso/q8.c
+++ b/gcc/testsuite/gcc.dg/sso/q8.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
diff --git a/gcc/testsuite/gcc.dg/sso/q9.c b/gcc/testsuite/gcc.dg/sso/q9.c
index ac6c8dd7f8f..aafb81c9518 100644
--- a/gcc/testsuite/gcc.dg/sso/q9.c
+++ b/gcc/testsuite/gcc.dg/sso/q9.c
@@ -21,22 +21,22 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "A1 : 18 2d 44 54 fb 21 09 40.*\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
- /* { dg-output "B1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "B1 : 18 2d 44 54 fb 21 09 40.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "A2 : 40 09 21 fb 54 44 2d 18.*\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
- /* { dg-output "B2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "B2 : 40 09 21 fb 54 44 2d 18.*\n" } */
if (A1.F != B1.F) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/r3.c b/gcc/testsuite/gcc.dg/sso/r3.c
index 82b55bda73b..b9a0cc49fa3 100644
--- a/gcc/testsuite/gcc.dg/sso/r3.c
+++ b/gcc/testsuite/gcc.dg/sso/r3.c
@@ -44,12 +44,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
if (Get_Elem1 (A1) != 0x78ABCDEF) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/r5.c b/gcc/testsuite/gcc.dg/sso/r5.c
index 6911408eb31..1323325c721 100644
--- a/gcc/testsuite/gcc.dg/sso/r5.c
+++ b/gcc/testsuite/gcc.dg/sso/r5.c
@@ -44,12 +44,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/r6.c b/gcc/testsuite/gcc.dg/sso/r6.c
index 904dd5c0ac3..452a10670ac 100644
--- a/gcc/testsuite/gcc.dg/sso/r6.c
+++ b/gcc/testsuite/gcc.dg/sso/r6.c
@@ -44,12 +44,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/r7.c b/gcc/testsuite/gcc.dg/sso/r7.c
index a6450eed8e3..3c46e61d1c0 100644
--- a/gcc/testsuite/gcc.dg/sso/r7.c
+++ b/gcc/testsuite/gcc.dg/sso/r7.c
@@ -44,12 +44,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/r8.c b/gcc/testsuite/gcc.dg/sso/r8.c
index 448da504a7e..0ea3a614e59 100644
--- a/gcc/testsuite/gcc.dg/sso/r8.c
+++ b/gcc/testsuite/gcc.dg/sso/r8.c
@@ -44,12 +44,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
diff --git a/gcc/testsuite/gcc.dg/sso/s3.c b/gcc/testsuite/gcc.dg/sso/s3.c
index 33a07c169bc..6a629377cdb 100644
--- a/gcc/testsuite/gcc.dg/sso/s3.c
+++ b/gcc/testsuite/gcc.dg/sso/s3.c
@@ -20,12 +20,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
N1 = A1.N;
C1 = N1.C1;
@@ -33,13 +33,13 @@ int main (void)
C3 = N1.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 18\n" } */
+ /* { dg-output "C1 : 18.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 52\n" } */
+ /* { dg-output "C2 : 52.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 86\n" } */
+ /* { dg-output "C3 : 86.*\n" } */
N1.C1 = C1;
N1.C2 = C2;
@@ -52,13 +52,13 @@ int main (void)
C3 = N2.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 18\n" } */
+ /* { dg-output "C1 : 18.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 52\n" } */
+ /* { dg-output "C2 : 52.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 86\n" } */
+ /* { dg-output "C3 : 86.*\n" } */
N2.C1 = C1;
N2.C2 = C2;
@@ -68,12 +68,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/s5.c b/gcc/testsuite/gcc.dg/sso/s5.c
index f7f63befc46..f29f634e3b6 100644
--- a/gcc/testsuite/gcc.dg/sso/s5.c
+++ b/gcc/testsuite/gcc.dg/sso/s5.c
@@ -32,12 +32,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
__builtin_memcpy (N1.A, A1.A, sizeof (int) * 3);
C1 = N1.A[0];
@@ -45,13 +45,13 @@ int main (void)
C3 = N1.A[2];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N1.A[0] = C1;
N1.A[1] = C2;
@@ -64,13 +64,13 @@ int main (void)
C3 = N2.A[2];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N2.A[0] = C1;
N2.A[1] = C2;
@@ -80,12 +80,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/s6.c b/gcc/testsuite/gcc.dg/sso/s6.c
index acd8e3d0d95..a1d0494554b 100644
--- a/gcc/testsuite/gcc.dg/sso/s6.c
+++ b/gcc/testsuite/gcc.dg/sso/s6.c
@@ -22,12 +22,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
__builtin_memcpy (N1.A, A1.N.A, sizeof (int) * 3);
C1 = N1.A[0];
@@ -35,13 +35,13 @@ int main (void)
C3 = N1.A[2];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N1.A[0] = C1;
N1.A[1] = C2;
@@ -54,13 +54,13 @@ int main (void)
C3 = N2.A[2];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N2.A[0] = C1;
N2.A[1] = C2;
@@ -70,12 +70,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/s7.c b/gcc/testsuite/gcc.dg/sso/s7.c
index 88e074117da..37d07c7fed6 100644
--- a/gcc/testsuite/gcc.dg/sso/s7.c
+++ b/gcc/testsuite/gcc.dg/sso/s7.c
@@ -20,12 +20,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
N1 = A1.N;
C1 = N1.C1;
@@ -33,13 +33,13 @@ int main (void)
C3 = N1.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N1.C1 = C1;
N1.C2 = C2;
@@ -52,13 +52,13 @@ int main (void)
C3 = N2.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N2.C1 = C1;
N2.C2 = C2;
@@ -68,12 +68,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/s8.c b/gcc/testsuite/gcc.dg/sso/s8.c
index 1154da3b7f4..5ff9c36ca7f 100644
--- a/gcc/testsuite/gcc.dg/sso/s8.c
+++ b/gcc/testsuite/gcc.dg/sso/s8.c
@@ -20,12 +20,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
N1 = A1.N;
C1 = N1.C1;
@@ -33,13 +33,13 @@ int main (void)
C3 = N1.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N1.C1 = C1;
N1.C2 = C2;
@@ -52,13 +52,13 @@ int main (void)
C3 = N2.C3;
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 11206674\n" } */
+ /* { dg-output "C1 : 11206674.*\n" } */
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
printf ("C3 : %d\n", C3);
- /* { dg-output "C3 : 15663190\n" } */
+ /* { dg-output "C3 : 15663190.*\n" } */
N2.C1 = C1;
N2.C2 = C2;
@@ -68,12 +68,12 @@ int main (void)
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
- /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
- /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t1.c b/gcc/testsuite/gcc.dg/sso/t1.c
index 6f7881ee0ed..6f4a5870ba0 100644
--- a/gcc/testsuite/gcc.dg/sso/t1.c
+++ b/gcc/testsuite/gcc.dg/sso/t1.c
@@ -15,42 +15,42 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12.*\n" } */
Local_R2.I = My_R2.I + 1;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79.*\n" } */
Local_R1.I = 0x12345678;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12.*\n" } */
Local_R2.I = 0x12345678;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78.*\n" } */
Local_R1.I = Local_R1.I + 1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12.*\n" } */
Local_R2.I = Local_R2.I + 1;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t13.c b/gcc/testsuite/gcc.dg/sso/t13.c
index a0f43413449..077f0c90da6 100644
--- a/gcc/testsuite/gcc.dg/sso/t13.c
+++ b/gcc/testsuite/gcc.dg/sso/t13.c
@@ -15,42 +15,42 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+ /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0.*\n" } */
Local_R2.F = My_R2.F + (1.0f + 1.0f * I);
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db.*\n" } */
Local_R1.F = Pi - Pi * I;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0.*\n" } */
Local_R2.F = Pi - Pi * I;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db.*\n" } */
Local_R1.F = Local_R1.F + (1.0f + 1.0f * I);
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+ /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0.*\n" } */
Local_R2.F = Local_R2.F + (1.0f + 1.0f * I);
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t2.c b/gcc/testsuite/gcc.dg/sso/t2.c
index 816363284db..9d9d2aff537 100644
--- a/gcc/testsuite/gcc.dg/sso/t2.c
+++ b/gcc/testsuite/gcc.dg/sso/t2.c
@@ -21,7 +21,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" } */
+ /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03.*\n" } */
Local_R2.S1 = My_R2.S1 - 1;
Local_R2.I = My_R2.I + 1;
@@ -34,7 +34,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" } */
+ /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e.*\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x12345678;
@@ -47,7 +47,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x12345678;
@@ -60,7 +60,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df.*\n" } */
Local_R1.S1 = Local_R1.S1 - 1;
Local_R1.I = Local_R1.I + 1;
@@ -73,7 +73,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" } */
+ /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03.*\n" } */
Local_R2.S1 = Local_R2.S1 - 1;
Local_R2.I = Local_R2.I + 1;
@@ -86,7 +86,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" } */
+ /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t3.c b/gcc/testsuite/gcc.dg/sso/t3.c
index e2f40704724..5a5a54fbd8d 100644
--- a/gcc/testsuite/gcc.dg/sso/t3.c
+++ b/gcc/testsuite/gcc.dg/sso/t3.c
@@ -21,7 +21,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01\n" } */
+ /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01.*\n" } */
Local_R2.S1 = My_R2.S1 - 1;
Local_R2.I = My_R2.I + 1;
@@ -34,7 +34,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30\n" } */
+ /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30.*\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x78ABCDEF;
@@ -47,7 +47,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95.*\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x78ABCDEF;
@@ -60,7 +60,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4.*\n" } */
Local_R1.S1 = Local_R1.S1 - 1;
Local_R1.I = Local_R1.I + 1;
@@ -73,7 +73,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01\n" } */
+ /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01.*\n" } */
Local_R2.S1 = Local_R2.S1 - 1;
Local_R2.I = Local_R2.I + 1;
@@ -86,7 +86,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30\n" } */
+ /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t4.c b/gcc/testsuite/gcc.dg/sso/t4.c
index f5a7eb01627..e166247519c 100644
--- a/gcc/testsuite/gcc.dg/sso/t4.c
+++ b/gcc/testsuite/gcc.dg/sso/t4.c
@@ -15,42 +15,42 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : ee 87 84 40\n" } */
+ /* { dg-output "Local_R1 : ee 87 84 40.*\n" } */
Local_R2.F = My_R2.F + 1.0f;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 84 87 ee\n" } */
+ /* { dg-output "Local_R2 : 40 84 87 ee.*\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+ /* { dg-output "Local_R1 : db 0f 49 40.*\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+ /* { dg-output "Local_R2 : 40 49 0f db.*\n" } */
Local_R1.F = Local_R1.F + 1.0f;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : ee 87 84 40\n" } */
+ /* { dg-output "Local_R1 : ee 87 84 40.*\n" } */
Local_R2.F = Local_R2.F + 1.0f;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 84 87 ee\n" } */
+ /* { dg-output "Local_R2 : 40 84 87 ee.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t5.c b/gcc/testsuite/gcc.dg/sso/t5.c
index 7cefb203dd8..1d506db7162 100644
--- a/gcc/testsuite/gcc.dg/sso/t5.c
+++ b/gcc/testsuite/gcc.dg/sso/t5.c
@@ -18,7 +18,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R2.I = My_R2.I + 1;
Local_R2.A[0] = My_R2.A[0] + 1;
@@ -28,7 +28,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.A[0] = 0xAB0012;
@@ -37,7 +37,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.A[0] = 0xAB0012;
@@ -46,7 +46,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = Local_R1.I + 1;
Local_R1.A[0] = Local_R1.A[0] + 1;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R2.I = Local_R2.I + 1;
Local_R2.A[0] = Local_R2.A[0] + 1;
@@ -66,7 +66,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t6.c b/gcc/testsuite/gcc.dg/sso/t6.c
index 8fb550b0ff1..018f9bda900 100644
--- a/gcc/testsuite/gcc.dg/sso/t6.c
+++ b/gcc/testsuite/gcc.dg/sso/t6.c
@@ -18,7 +18,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R2.I = My_R2.I + 1;
Local_R2.N.A[0] = My_R2.N.A[0] + 1;
@@ -28,7 +28,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.A[0] = 0xAB0012;
@@ -37,7 +37,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.A[0] = 0xAB0012;
@@ -46,7 +46,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = Local_R1.I + 1;
Local_R1.N.A[0] = Local_R1.N.A[0] + 1;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R2.I = Local_R2.I + 1;
Local_R2.N.A[0] = Local_R2.N.A[0] + 1;
@@ -66,7 +66,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t7.c b/gcc/testsuite/gcc.dg/sso/t7.c
index 59df566cd80..6e6443bc7e0 100644
--- a/gcc/testsuite/gcc.dg/sso/t7.c
+++ b/gcc/testsuite/gcc.dg/sso/t7.c
@@ -18,7 +18,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R2.I = My_R2.I + 1;
Local_R2.N.C1 = My_R2.N.C1 + 1;
@@ -28,7 +28,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
@@ -37,7 +37,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
@@ -46,7 +46,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R1.I = Local_R1.I + 1;
Local_R1.N.C1 = Local_R1.N.C1 + 1;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R2.I = Local_R2.I + 1;
Local_R2.N.C1 = Local_R2.N.C1 + 1;
@@ -66,7 +66,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t8.c b/gcc/testsuite/gcc.dg/sso/t8.c
index 28a0bf35640..8fbb8170adb 100644
--- a/gcc/testsuite/gcc.dg/sso/t8.c
+++ b/gcc/testsuite/gcc.dg/sso/t8.c
@@ -18,7 +18,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R2.I = My_R2.I + 1;
Local_R2.N.C1 = My_R2.N.C1 + 1;
@@ -28,7 +28,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
@@ -37,7 +37,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
@@ -46,7 +46,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R1.I = Local_R1.I + 1;
Local_R1.N.C1 = Local_R1.N.C1 + 1;
@@ -56,7 +56,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57.*\n" } */
Local_R2.I = Local_R2.I + 1;
Local_R2.N.C1 = Local_R2.N.C1 + 1;
@@ -66,7 +66,7 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/t9.c b/gcc/testsuite/gcc.dg/sso/t9.c
index 1060bb43f3c..2985bfce9e7 100644
--- a/gcc/testsuite/gcc.dg/sso/t9.c
+++ b/gcc/testsuite/gcc.dg/sso/t9.c
@@ -15,42 +15,42 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" } */
+ /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40.*\n" } */
Local_R2.F = My_R2.F + 1.0;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" } */
+ /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c.*\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40.*\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18.*\n" } */
Local_R1.F = Local_R1.F + 1.0;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" } */
+ /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40.*\n" } */
Local_R2.F = Local_R2.F + 1.0;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" } */
+ /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/u5.c b/gcc/testsuite/gcc.dg/sso/u5.c
index 01ca8b58f13..8b9d09719da 100644
--- a/gcc/testsuite/gcc.dg/sso/u5.c
+++ b/gcc/testsuite/gcc.dg/sso/u5.c
@@ -19,7 +19,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 01 00 00 00 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R1 : 01 00 00 00 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
Local_R2.I = 1;
Local_R2.A[0] = 0xAB0012;
@@ -28,25 +28,25 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 00 00 00 01 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R2 : 00 00 00 01 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
C1 = Local_R1.A[Local_R1.I];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 13434932\n" } */
+ /* { dg-output "C1 : 13434932.*\n" } */
Local_R1.I++;
C1 = Local_R1.A[Local_R1.I];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 15663190\n" } */
+ /* { dg-output "C1 : 15663190.*\n" } */
C2 = Local_R2.A[Local_R2.I];
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
Local_R2.I++;
C2 = Local_R2.A[Local_R2.I];
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 15663190\n" } */
+ /* { dg-output "C2 : 15663190.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/sso/u6.c b/gcc/testsuite/gcc.dg/sso/u6.c
index ae8172e1ffe..4b2ca1c9f13 100644
--- a/gcc/testsuite/gcc.dg/sso/u6.c
+++ b/gcc/testsuite/gcc.dg/sso/u6.c
@@ -19,7 +19,7 @@ int main (void)
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
- /* { dg-output "Local_R1 : 01 00 00 00 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ /* { dg-output "Local_R1 : 01 00 00 00 00 ab 00 12 00 cd 00 34 00 ef 00 56.*\n" } */
Local_R2.I = 1;
Local_R2.N.A[0] = 0xAB0012;
@@ -28,25 +28,25 @@ int main (void)
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
- /* { dg-output "Local_R2 : 00 00 00 01 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+ /* { dg-output "Local_R2 : 00 00 00 01 12 00 ab 00 34 00 cd 00 56 00 ef 00.*\n" } */
C1 = Local_R1.N.A[Local_R1.I];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 13434932\n" } */
+ /* { dg-output "C1 : 13434932.*\n" } */
Local_R1.I++;
C1 = Local_R1.N.A[Local_R1.I];
printf ("C1 : %d\n", C1);
- /* { dg-output "C1 : 15663190\n" } */
+ /* { dg-output "C1 : 15663190.*\n" } */
C2 = Local_R2.N.A[Local_R2.I];
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 13434932\n" } */
+ /* { dg-output "C2 : 13434932.*\n" } */
Local_R2.I++;
C2 = Local_R2.N.A[Local_R2.I];
printf ("C2 : %d\n", C2);
- /* { dg-output "C2 : 15663190\n" } */
+ /* { dg-output "C2 : 15663190.*\n" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/torture/pr68240.c b/gcc/testsuite/gcc.dg/torture/pr68240.c
new file mode 100644
index 00000000000..b6d97902300
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr68240.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int a, b, f;
+
+void
+fn1 ()
+{
+ int c = 1, d, e = 1;
+ a = 1;
+ for (; f;)
+ b = (c && (d = (e && a)));
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr68248.c b/gcc/testsuite/gcc.dg/torture/pr68248.c
new file mode 100644
index 00000000000..0e8ab4904aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr68248.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+
+int
+fn1 (int p1)
+{
+ return a > 0 ? p1 : p1 >> a;
+}
+
+void
+fn2 ()
+{
+ char e;
+ for (; c; c++)
+ {
+ e = fn1 (!d ^ 2);
+ b ^= e;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c
index e7328fcdd21..8fe67f45faa 100644
--- a/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c
+++ b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c
@@ -13,4 +13,4 @@ A sum(A a,A b)
return a;
}
-/* { dg-final { scan-tree-dump-times "not vectorized: more than one data ref in stmt" 0 "slp2" } } */
+/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-cond-5.c b/gcc/testsuite/gcc.dg/vect/slp-cond-5.c
new file mode 100644
index 00000000000..5ade7d1fbad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/slp-cond-5.c
@@ -0,0 +1,81 @@
+/* { dg-require-effective-target vect_condition } */
+
+#include "tree-vect.h"
+
+#define N 128
+
+static inline int
+foo (int x, int y, int a, int b)
+{
+ if (x >= y && a > b)
+ return a;
+ else
+ return b;
+}
+
+__attribute__((noinline, noclone)) void
+bar (int * __restrict__ a, int * __restrict__ b,
+ int * __restrict__ c, int * __restrict__ d,
+ int * __restrict__ e, int w)
+{
+ int i;
+ for (i = 0; i < N/16; i++, a += 16, b += 16, c += 16, d += 16, e += 16)
+ {
+ e[0] = foo (c[0], d[0], a[0] * w, b[0] * w);
+ e[1] = foo (c[1], d[1], a[1] * w, b[1] * w);
+ e[2] = foo (c[2], d[2], a[2] * w, b[2] * w);
+ e[3] = foo (c[3], d[3], a[3] * w, b[3] * w);
+ e[4] = foo (c[4], d[4], a[4] * w, b[4] * w);
+ e[5] = foo (c[5], d[5], a[5] * w, b[5] * w);
+ e[6] = foo (c[6], d[6], a[6] * w, b[6] * w);
+ e[7] = foo (c[7], d[7], a[7] * w, b[7] * w);
+ e[8] = foo (c[8], d[8], a[8] * w, b[8] * w);
+ e[9] = foo (c[9], d[9], a[9] * w, b[9] * w);
+ e[10] = foo (c[10], d[10], a[10] * w, b[10] * w);
+ e[11] = foo (c[11], d[11], a[11] * w, b[11] * w);
+ e[12] = foo (c[12], d[12], a[12] * w, b[12] * w);
+ e[13] = foo (c[13], d[13], a[13] * w, b[13] * w);
+ e[14] = foo (c[14], d[14], a[14] * w, b[14] * w);
+ e[15] = foo (c[15], d[15], a[15] * w, b[15] * w);
+ }
+}
+
+
+int a[N], b[N], c[N], d[N], e[N];
+
+int main ()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ a[i] = i;
+ b[i] = 5;
+ e[i] = 0;
+
+ switch (i % 9)
+ {
+ case 0: asm (""); c[i] = i; d[i] = i + 1; break;
+ case 1: c[i] = 0; d[i] = 0; break;
+ case 2: c[i] = i + 1; d[i] = i - 1; break;
+ case 3: c[i] = i; d[i] = i + 7; break;
+ case 4: c[i] = i; d[i] = i; break;
+ case 5: c[i] = i + 16; d[i] = i + 3; break;
+ case 6: c[i] = i - 5; d[i] = i; break;
+ case 7: c[i] = i; d[i] = i; break;
+ case 8: c[i] = i; d[i] = i - 7; break;
+ }
+ }
+
+ bar (a, b, c, d, e, 2);
+ for (i = 0; i < N; i++)
+ if (e[i] != ((i % 3) == 0 || i <= 5 ? 10 : 2 * i))
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { i?86-*-* x86_64-*-* } } } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/cond_op_imm_1.c b/gcc/testsuite/gcc.target/aarch64/cond_op_imm_1.c
new file mode 100644
index 00000000000..e93a69329c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cond_op_imm_1.c
@@ -0,0 +1,99 @@
+/* { dg-do run } */
+/* { dg-options "-save-temps -O2 -fno-inline" } */
+
+extern void abort (void);
+
+#define N 30
+#define M 25089992
+
+int
+foonegsi (int a)
+{
+ return a ? N : -N;
+}
+
+/* { dg-final { scan-assembler "csneg\tw\[0-9\]*.*" } } */
+
+
+int
+fooinvsi (int a)
+{
+ return a ? N : ~N;
+}
+
+/* { dg-final { scan-assembler "csinv\tw\[0-9\]*.*" } } */
+
+
+long long
+foonegdi (long long a)
+{
+ return a ? N : -N;
+}
+
+long long
+largefooneg (long long a)
+{
+ return a ? M : -M;
+}
+
+/* { dg-final { scan-assembler "csneg\tx\[0-9\]*.*" } } */
+
+long long
+fooinvdi (long long a)
+{
+ return a ? N : ~N;
+}
+
+long long
+largefooinv (long long a)
+{
+ return a ? M : ~M;
+}
+
+/* { dg-final { scan-assembler "csinv\tx\[0-9\]*.*" } } */
+
+
+int
+main (void)
+{
+ if (foonegsi (1) != N)
+ abort ();
+
+ if (foonegsi (0) != -N)
+ abort ();
+
+ if (fooinvsi (1) != N)
+ abort ();
+
+ if (fooinvsi (0) != ~N)
+ abort ();
+
+ if (foonegdi (1) != N)
+ abort ();
+
+ if (foonegdi (0) != -N)
+ abort ();
+
+ if (fooinvdi (1) != N)
+ abort ();
+
+ if (fooinvdi (0) != ~N)
+ abort ();
+
+ if (largefooinv (0) != ~M)
+ abort ();
+
+ if (largefooneg (0) != -M)
+ abort ();
+
+ if (largefooinv (1) != M)
+ abort ();
+
+ if (largefooneg (1) != M)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "csel\tx\[0-9\]*.*" } } */
+/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-3.c b/gcc/testsuite/gcc.target/i386/addr-space-3.c
index 63f1f031a08..2b6f47eee6a 100644
--- a/gcc/testsuite/gcc.target/i386/addr-space-3.c
+++ b/gcc/testsuite/gcc.target/i386/addr-space-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O" } */
-/* { dg-final { scan-assembler "[fg]s:0" } } */
+/* { dg-final { scan-assembler "\[fg]s:0" } } */
void test(int *y)
{
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vec-mask-bit-not.c b/gcc/testsuite/gcc.target/i386/avx2-vec-mask-bit-not.c
new file mode 100644
index 00000000000..0c946ca0eae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vec-mask-bit-not.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-mavx2 -O3 -fopenmp-simd -fdump-tree-vect-details" } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
+#define N 1024
+
+int a[N], b[N], c[N], d[N], e[N];
+
+void
+test (void)
+{
+ int i;
+ #pragma omp simd
+ for (i = 0; i < N; i++)
+ if (!(a[i] > b[i] && c[i] < d[i]))
+ e[i] = 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr56118.c b/gcc/testsuite/gcc.target/i386/pr56118.c
new file mode 100644
index 00000000000..11a543cafe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr56118.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse2" } */
+
+#include <emmintrin.h>
+
+__m128d f()
+{
+ __m128d r={3,4};
+ r[0]=1;
+ r[1]=2;
+ return r;
+}
+
+/* We want to "vectorize" this to a aligned vector load from the
+ constant pool. */
+
+/* { dg-final { scan-assembler "movapd" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ctz-1.c b/gcc/testsuite/gcc.target/powerpc/ctz-1.c
new file mode 100644
index 00000000000..9948ad7555b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ctz-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+int i_trailing_zero (int a) { return __builtin_ctz (a); }
+int l_trailing_zero (long a) { return __builtin_ctzl (a); }
+int ll_trailing_zero (long long a) { return __builtin_ctzll (a); }
+
+/* { dg-final { scan-assembler "cnttzw " } } */
+/* { dg-final { scan-assembler "cnttzd " } } */
+/* { dg-final { scan-assembler-not "cntlzw " } } */
+/* { dg-final { scan-assembler-not "cntlzd " } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ctz-2.c b/gcc/testsuite/gcc.target/powerpc/ctz-2.c
new file mode 100644
index 00000000000..7ee4d46195a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ctz-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+int i_trailing_zero (int a) { return __builtin_ctz (a); }
+
+/* { dg-final { scan-assembler "cnttzw " } } */
+/* { dg-final { scan-assembler-not "cntlzw " } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/extswsli-1.c b/gcc/testsuite/gcc.target/powerpc/extswsli-1.c
new file mode 100644
index 00000000000..2d7aac33123
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/extswsli-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+static int mem;
+int *ptr = &mem;
+
+long
+add (long *p, int reg)
+{
+ __asm__ (" #foo %0" : "+r" (reg));
+ return p[reg] + p[mem];
+}
+
+/* { dg-final { scan-assembler-times "extswsli " 2 } } */
+/* { dg-final { scan-assembler-times "lwz " 1 } } */
+/* { dg-final { scan-assembler-not "lwa " } } */
+/* { dg-final { scan-assembler-not "sldi " } } */
+/* { dg-final { scan-assembler-not "extsw " } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/extswsli-2.c b/gcc/testsuite/gcc.target/powerpc/extswsli-2.c
new file mode 100644
index 00000000000..b92a537b735
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/extswsli-2.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+long
+func1 (int reg, int *is_zero)
+{
+ long value;
+
+ __asm__ (" #foo %0" : "+r" (reg));
+ value = ((long)reg) << 4;
+
+ if (!value)
+ *is_zero = 1;
+
+ return value;
+}
+
+long
+func2 (int *ptr, int *is_zero)
+{
+ int reg = *ptr;
+ long value = ((long)reg) << 4;
+
+ if (!value)
+ *is_zero = 1;
+
+ return value;
+}
+
+/* { dg-final { scan-assembler "extswsli\\. " } } */
+/* { dg-final { scan-assembler "lwz " } } */
+/* { dg-final { scan-assembler-not "lwa " } } */
+/* { dg-final { scan-assembler-not "sldi " } } */
+/* { dg-final { scan-assembler-not "sldi\\. " } } */
+/* { dg-final { scan-assembler-not "extsw " } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/extswsli-3.c b/gcc/testsuite/gcc.target/powerpc/extswsli-3.c
new file mode 100644
index 00000000000..d7e01e13bfe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/extswsli-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+long
+do_ext_add (int *p, long a, long b)
+{
+ long l = *p;
+ long l2 = l << 4;
+ return l2 + ((l2 == 0) ? a : b);
+}
+
+long
+do_ext (int *p, long a, long b)
+{
+ long l = *p;
+ long l2 = l << 4;
+ return ((l2 == 0) ? a : b);
+}
+
+/* { dg-final { scan-assembler "extswsli\\. "} } */
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-call.c b/gcc/testsuite/gcc.target/powerpc/float128-call.c
index 382b2926e90..bcb5d24e379 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-call.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-call.c
@@ -1,6 +1,5 @@
/* { dg-do compile { target { powerpc*-*-linux* } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-require-effective-target powerpc_float128_sw_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
/* { dg-options "-O2 -mcpu=power7 -mfloat128 -mno-regnames" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-mix.c b/gcc/testsuite/gcc.target/powerpc/float128-mix.c
index 466be907524..23cb9d5f3a2 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-mix.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-mix.c
@@ -1,6 +1,5 @@
/* { dg-do compile { target { powerpc*-*-linux* } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-require-effective-target powerpc_float128_sw_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion.c b/gcc/testsuite/gcc.target/powerpc/fusion.c
index b577a39e774..ed35006f4d8 100644
--- a/gcc/testsuite/gcc.target/powerpc/fusion.c
+++ b/gcc/testsuite/gcc.target/powerpc/fusion.c
@@ -1,6 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
-/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
/* { dg-options "-mcpu=power7 -mtune=power8 -O3" } */
@@ -14,10 +13,7 @@ int fusion_short (short *p){ return p[LARGE]; }
int fusion_int (int *p){ return p[LARGE]; }
unsigned fusion_uns (unsigned *p){ return p[LARGE]; }
-vector double fusion_vector (vector double *p) { return p[2]; }
-
/* { dg-final { scan-assembler-times "gpr load fusion" 6 } } */
-/* { dg-final { scan-assembler-times "vector load fusion" 1 } } */
/* { dg-final { scan-assembler-times "lbz" 2 } } */
/* { dg-final { scan-assembler-times "extsb" 1 } } */
/* { dg-final { scan-assembler-times "lhz" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion2.c b/gcc/testsuite/gcc.target/powerpc/fusion2.c
new file mode 100644
index 00000000000..bb74f882ea1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fusion2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-mcpu=power7 -mtune=power8 -O3" } */
+
+vector double fusion_vector (vector double *p) { return p[2]; }
+
+/* { dg-final { scan-assembler-times "vector load fusion" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion3.c b/gcc/testsuite/gcc.target/powerpc/fusion3.c
new file mode 100644
index 00000000000..8eca640d257
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fusion3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-mcpu=power7 -mtune=power9 -O3" } */
+
+#define LARGE 0x12345
+
+int fusion_float_read (float *p){ return p[LARGE]; }
+int fusion_double_read (double *p){ return p[LARGE]; }
+
+void fusion_float_write (float *p, float f){ p[LARGE] = f; }
+void fusion_double_write (double *p, double d){ p[LARGE] = d; }
+
+/* { dg-final { scan-assembler "load fusion, type SF" } } */
+/* { dg-final { scan-assembler "load fusion, type DF" } } */
+/* { dg-final { scan-assembler "store fusion, type SF" } } */
+/* { dg-final { scan-assembler "store fusion, type DF" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/mod-1.c b/gcc/testsuite/gcc.target/powerpc/mod-1.c
new file mode 100644
index 00000000000..3954b09bdef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mod-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+int ismod (int a, int b) { return a%b; }
+long lsmod (long a, long b) { return a%b; }
+unsigned int iumod (unsigned int a, unsigned int b) { return a%b; }
+unsigned long lumod (unsigned long a, unsigned long b) { return a%b; }
+
+/* { dg-final { scan-assembler-times "modsw " 1 } } */
+/* { dg-final { scan-assembler-times "modsd " 1 } } */
+/* { dg-final { scan-assembler-times "moduw " 1 } } */
+/* { dg-final { scan-assembler-times "modud " 1 } } */
+/* { dg-final { scan-assembler-not "mullw " } } */
+/* { dg-final { scan-assembler-not "mulld " } } */
+/* { dg-final { scan-assembler-not "divw " } } */
+/* { dg-final { scan-assembler-not "divd " } } */
+/* { dg-final { scan-assembler-not "divwu " } } */
+/* { dg-final { scan-assembler-not "divdu " } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/mod-2.c b/gcc/testsuite/gcc.target/powerpc/mod-2.c
new file mode 100644
index 00000000000..7cf6a4f8aa2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mod-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */
+/* { dg-require-effective-target powerpc_p9modulo_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+int ismod (int a, int b) { return a%b; }
+unsigned int iumod (unsigned int a, unsigned int b) { return a%b; }
+
+/* { dg-final { scan-assembler-times "modsw " 1 } } */
+/* { dg-final { scan-assembler-times "moduw " 1 } } */
+/* { dg-final { scan-assembler-not "mullw " } } */
+/* { dg-final { scan-assembler-not "divw " } } */
+/* { dg-final { scan-assembler-not "divwu " } } */
diff --git a/gcc/testsuite/gcc.target/sparc/sparc-ret.c b/gcc/testsuite/gcc.target/sparc/sparc-ret-1.c
index 808e8a98f0e..808e8a98f0e 100644
--- a/gcc/testsuite/gcc.target/sparc/sparc-ret.c
+++ b/gcc/testsuite/gcc.target/sparc/sparc-ret-1.c
diff --git a/gcc/testsuite/gcc.target/sparc/sparc-ret-2.c b/gcc/testsuite/gcc.target/sparc/sparc-ret-2.c
new file mode 100644
index 00000000000..536b9b75a4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/sparc-ret-2.c
@@ -0,0 +1,13 @@
+/* PR target/57845 */
+
+/* { dg-do compile } */
+/* { dg-options "-freg-struct-return" } */
+
+struct S { short int i; };
+
+struct S foo (short int i)
+{
+ struct S s;
+ s.i = i;
+ return s;
+}
diff --git a/gcc/testsuite/gfortran.dg/pr68251.f90 b/gcc/testsuite/gfortran.dg/pr68251.f90
new file mode 100644
index 00000000000..590c99a8718
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68251.f90
@@ -0,0 +1,1048 @@
+! PR middle-end/68251
+! Reduced testcase by Joost VandeVondele <Joost.VandeVondele@mat.ethz.ch>
+
+! { dg-do compile }
+! { dg-options "-O3" }
+
+MODULE hfx_contract_block
+ INTEGER, PARAMETER :: dp=8
+CONTAINS
+ SUBROUTINE contract_block(ma_max,mb_max,mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(mb_max*md_max), kbc(mb_max*mc_max), &
+ kad(ma_max*md_max), kac(ma_max*mc_max), pbd(mb_max*md_max), &
+ pbc(mb_max*mc_max), pad(ma_max*md_max), pac(ma_max*mc_max), &
+ prim(ma_max*mb_max*mc_max*md_max), scale
+ SELECT CASE(ma_max)
+ CASE(1)
+ SELECT CASE(mb_max)
+ CASE(1)
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_1_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_1_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_1_11(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(2)
+ CALL block_1_2_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_1_7(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_2_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_4_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_2_6_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_2_7_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_3_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_2_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_3_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_3_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_3_5(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_3_5(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_4_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_4_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_4_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_4_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_5_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_6_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_6_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_1_6_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_1_6_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ END SELECT
+ END SELECT
+ END SELECT
+ SELECT CASE(mb_max)
+ CASE(1)
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_2_1_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_1_2_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_2_2_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_2_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_2_2_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(7)
+ CALL block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_3_5_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ CALL block_3_9(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(mb_max)
+ CASE(1)
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_4_1_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_4_2_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_4_3_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ CALL block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ SELECT CASE(md_max)
+ CASE(1)
+ CALL block_4_4_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ SELECT CASE(mc_max)
+ CASE(1)
+ SELECT CASE(md_max)
+ END SELECT
+ END SELECT
+ END SELECT
+ SELECT CASE(mb_max)
+ CASE(1)
+ CALL block_15_15(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ END SELECT
+ END SELECT
+ END SUBROUTINE contract_block
+ SUBROUTINE block_1_1_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*1), kbc(1*1), kad(1*1), kac(1*1), pbd(1*1), &
+ pbc(1*1), pad(1*1), pac(1*1), prim(1*1*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,1
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_1_1_1
+ SUBROUTINE block_1_1_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*2), kbc(1*1), kad(1*2), kac(1*1), pbd(1*2), &
+ pbc(1*1), pad(1*2), pac(1*1), prim(1*1*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,1
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_1_1_2
+ SUBROUTINE block_1_1_11(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*md_max), kbc(1*11), kad(1*md_max), kac(1*11), &
+ pbd(1*md_max), pbc(1*11), pad(1*md_max), pac(1*11), &
+ prim(1*1*11*md_max), scale
+ DO md = 1,md_max
+ DO mc = 1,11
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_1_11
+ SUBROUTINE block_1_2_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*2), kbc(2*1), kad(1*2), kac(1*1), pbd(2*2), &
+ pbc(2*1), pad(1*2), pac(1*1), prim(1*2*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_2
+ SUBROUTINE block_1_2_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*3), kbc(2*1), kad(1*3), kac(1*1), pbd(2*3), &
+ pbc(2*1), pad(1*3), pac(1*1), prim(1*2*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_3
+ SUBROUTINE block_1_2_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*4), kbc(2*1), kad(1*4), kac(1*1), pbd(2*4), &
+ pbc(2*1), pad(1*4), pac(1*1), prim(1*2*1*4), scale
+ DO md = 1,4
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_4
+ SUBROUTINE block_1_2_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*5), kbc(2*1), kad(1*5), kac(1*1), pbd(2*5), &
+ pbc(2*1), pad(1*5), pac(1*1), prim(1*2*1*5), scale
+ DO md = 1,5
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_5
+ SUBROUTINE block_1_2_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*6), kbc(2*1), kad(1*6), kac(1*1), pbd(2*6), &
+ pbc(2*1), pad(1*6), pac(1*1), prim(1*2*1*6), scale
+ DO md = 1,6
+ DO mc = 1,1
+ DO mb = 1,2
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_6
+ SUBROUTINE block_1_2_1_7(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*7), kbc(2*1), kad(1*7), kac(1*1), pbd(2*7), &
+ pbc(2*1), pad(1*7), pac(1*1), prim(1*2*1*7), scale
+ DO md = 1,7
+ DO mc = 1,1
+ DO mb = 1,2
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_1_7
+ SUBROUTINE block_1_2_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*2), kbc(2*2), kad(1*2), kac(1*2), pbd(2*2), &
+ pbc(2*2), pad(1*2), pac(1*2), prim(1*2*2*2), scale
+ DO md = 1,2
+ DO mc = 1,2
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_2_2
+ SUBROUTINE block_1_2_2_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*4), kbc(2*2), kad(1*4), kac(1*2), pbd(2*4), &
+ pbc(2*2), pad(1*4), pac(1*2), prim(1*2*2*4), scale
+ DO md = 1,4
+ DO mc = 1,2
+ DO mb = 1,2
+ kbd((md-1)*2+mb) = kbd((md-1)*2+mb) - ks_bd
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_2_4
+ SUBROUTINE block_1_2_4_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*4), kad(1*1), kac(1*4), pbd(2*1), &
+ pbc(2*4), pad(1*1), pac(1*4), prim(1*2*4*1), scale
+ DO md = 1,1
+ DO mc = 1,4
+ DO mb = 1,2
+ kbd((md-1)*2+mb) = kbd((md-1)*2+mb) - ks_bd
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_4_1
+ SUBROUTINE block_1_2_6_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*6), kad(1*1), kac(1*6), pbd(2*1), &
+ pbc(2*6), pad(1*1), pac(1*6), prim(1*2*6*1), scale
+ DO md = 1,1
+ DO mc = 1,6
+ DO mb = 1,2
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_6_1
+ SUBROUTINE block_1_2_7_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*7), kad(1*1), kac(1*7), pbd(2*1), &
+ pbc(2*7), pad(1*1), pac(1*7), prim(1*2*7*1), scale
+ DO md = 1,1
+ DO mc = 1,7
+ DO mb = 1,2
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_2_7_1
+ SUBROUTINE block_1_3_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*1), kbc(3*1), kad(1*1), kac(1*1), pbd(3*1), &
+ pbc(3*1), pad(1*1), pac(1*1), prim(1*3*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1_1
+ SUBROUTINE block_1_3_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*3), kbc(3*1), kad(1*3), kac(1*1), pbd(3*3), &
+ pbc(3*1), pad(1*3), pac(1*1), prim(1*3*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,3
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1_3
+ SUBROUTINE block_1_3_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*4), kbc(3*1), kad(1*4), kac(1*1), pbd(3*4), &
+ pbc(3*1), pad(1*4), pac(1*1), prim(1*3*1*4), scale
+ DO md = 1,4
+ DO mc = 1,1
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1_4
+ SUBROUTINE block_1_3_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*5), kbc(3*1), kad(1*5), kac(1*1), pbd(3*5), &
+ pbc(3*1), pad(1*5), pac(1*1), prim(1*3*1*5), scale
+ DO md = 1,5
+ DO mc = 1,1
+ DO mb = 1,3
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1_5
+ SUBROUTINE block_1_3_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*6), kbc(3*1), kad(1*6), kac(1*1), pbd(3*6), &
+ pbc(3*1), pad(1*6), pac(1*1), prim(1*3*1*6), scale
+ DO md = 1,6
+ DO mc = 1,1
+ DO mb = 1,3
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1_6
+ SUBROUTINE block_1_3_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*md_max), kbc(3*1), kad(1*md_max), kac(1*1), &
+ pbd(3*md_max), pbc(3*1), pad(1*md_max), pac(1*1), prim(1*3*1*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,1
+ DO mb = 1,3
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_1
+ SUBROUTINE block_1_3_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*1), kbc(3*2), kad(1*1), kac(1*2), pbd(3*1), &
+ pbc(3*2), pad(1*1), pac(1*2), prim(1*3*2*1), scale
+ DO md = 1,1
+ DO mc = 1,2
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_2_1
+ SUBROUTINE block_1_3_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*2), kbc(3*2), kad(1*2), kac(1*2), pbd(3*2), &
+ pbc(3*2), pad(1*2), pac(1*2), prim(1*3*2*2), scale
+ DO md = 1,2
+ DO mc = 1,2
+ DO mb = 1,3
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_2_2
+ SUBROUTINE block_1_3_2_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*3), kbc(3*2), kad(1*3), kac(1*2), pbd(3*3), &
+ pbc(3*2), pad(1*3), pac(1*2), prim(1*3*2*3), scale
+ kbc(1:3*2) = 0.0_dp
+ DO md = 1,3
+ DO mc = 1,2
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_2_3
+ SUBROUTINE block_1_3_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*1), kbc(3*3), kad(1*1), kac(1*3), pbd(3*1), &
+ pbc(3*3), pad(1*1), pac(1*3), prim(1*3*3*1), scale
+ DO md = 1,1
+ DO mc = 1,3
+ DO mb = 1,3
+ kbd((md-1)*3+mb) = kbd((md-1)*3+mb) - ks_bd
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_3_1
+ SUBROUTINE block_1_3_3_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*2), kbc(3*3), kad(1*2), kac(1*3), pbd(3*2), &
+ pbc(3*3), pad(1*2), pac(1*3), prim(1*3*3*2), scale
+ DO md = 1,2
+ DO mc = 1,3
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_3_3_2
+ SUBROUTINE block_1_3_5(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*md_max), kbc(3*5), kad(1*md_max), kac(1*5), &
+ pbd(3*md_max), pbc(3*5), pad(1*md_max), pac(1*5), prim(1*3*5*md_max), &
+ scale
+ kbd(1:3*md_max) = 0.0_dp
+ DO md = 1,md_max
+ END DO
+ END SUBROUTINE block_1_3_5
+ SUBROUTINE block_1_3_6(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ DO md = 1,md_max
+ END DO
+ END SUBROUTINE block_1_3_6
+ SUBROUTINE block_1_4_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*1), kbc(4*1), kad(1*1), kac(1*1), pbd(4*1), &
+ pbc(4*1), pad(1*1), pac(1*1), prim(1*4*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,4
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_1_1
+ SUBROUTINE block_1_4_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*2), kbc(4*1), kad(1*2), kac(1*1), pbd(4*2), &
+ pbc(4*1), pad(1*2), pac(1*1), prim(1*4*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_1_2
+ SUBROUTINE block_1_4_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*3), kbc(4*1), kad(1*3), kac(1*1), pbd(4*3), &
+ pbc(4*1), pad(1*3), pac(1*1), prim(1*4*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_1_3
+ SUBROUTINE block_1_4_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*1), kbc(4*2), kad(1*1), kac(1*2), pbd(4*1), &
+ pbc(4*2), pad(1*1), pac(1*2), prim(1*4*2*1), scale
+ DO md = 1,1
+ DO mc = 1,2
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_2_1
+ SUBROUTINE block_1_4_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*2), kbc(4*2), kad(1*2), kac(1*2), pbd(4*2), &
+ pbc(4*2), pad(1*2), pac(1*2), prim(1*4*2*2), scale
+ DO md = 1,2
+ DO mc = 1,2
+ DO mb = 1,4
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_2_2
+ SUBROUTINE block_1_4_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*1), kbc(4*3), kad(1*1), kac(1*3), pbd(4*1), &
+ pbc(4*3), pad(1*1), pac(1*3), prim(1*4*3*1), scale
+ DO md = 1,1
+ DO mc = 1,3
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_3_1
+ SUBROUTINE block_1_4_3(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*md_max), kbc(4*3), kad(1*md_max), kac(1*3), &
+ pbd(4*md_max), pbc(4*3), pad(1*md_max), pac(1*3), prim(1*4*3*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,3
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_3
+ SUBROUTINE block_1_4_4_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*1), kbc(4*4), kad(1*1), kac(1*4), pbd(4*1), &
+ pbc(4*4), pad(1*1), pac(1*4), prim(1*4*4*1), scale
+ DO md = 1,1
+ DO mc = 1,4
+ DO mb = 1,4
+ kbc((mc-1)*4+mb) = kbc((mc-1)*4+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_4_1
+ SUBROUTINE block_1_4_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*md_max), kbc(4*4), kad(1*md_max), kac(1*4), &
+ pbd(4*md_max), pbc(4*4), pad(1*md_max), pac(1*4), prim(1*4*4*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,4
+ DO mb = 1,4
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_4_4
+ SUBROUTINE block_1_5_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(5*3), kbc(5*1), kad(1*3), kac(1*1), pbd(5*3), &
+ pbc(5*1), pad(1*3), pac(1*1), prim(1*5*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,5
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_5_1_3
+ SUBROUTINE block_1_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(5*md_max), kbc(5*1), kad(1*md_max), kac(1*1), &
+ pbd(5*md_max), pbc(5*1), pad(1*md_max), pac(1*1), prim(1*5*1*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,1
+ DO mb = 1,5
+ kbc((mc-1)*5+mb) = kbc((mc-1)*5+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_5_1
+ SUBROUTINE block_1_6_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(6*1), kbc(6*1), kad(1*1), kac(1*1), pbd(6*1), &
+ pbc(6*1), pad(1*1), pac(1*1), prim(1*6*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,6
+ DO ma = 1,1
+ kac((mc-1)*1+ma) = kac((mc-1)*1+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_6_1_1
+ SUBROUTINE block_1_6_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(6*2), kbc(6*1), kad(1*2), kac(1*1), pbd(6*2), &
+ pbc(6*1), pad(1*2), pac(1*1), prim(1*6*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,6
+ DO ma = 1,1
+ kad((md-1)*1+ma) = kad((md-1)*1+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_6_1_2
+ SUBROUTINE block_1_6_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(6*3), kbc(6*1), kad(1*3), kac(1*1), pbd(6*3), &
+ pbc(6*1), pad(1*3), pac(1*1), prim(1*6*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,6
+ kbc((mc-1)*6+mb) = kbc((mc-1)*6+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_6_1_3
+ SUBROUTINE block_1_6_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(6*1), kbc(6*2), kad(1*1), kac(1*2), pbd(6*1), &
+ pbc(6*2), pad(1*1), pac(1*2), prim(1*6*2*1), scale
+ DO md = 1,1
+ DO mc = 1,2
+ DO mb = 1,6
+ kbc((mc-1)*6+mb) = kbc((mc-1)*6+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_1_6_2_1
+ SUBROUTINE block_2_1_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*3), kbc(1*1), kad(2*3), kac(2*1), pbd(1*3), &
+ pbc(1*1), pad(2*3), pac(2*1), prim(2*1*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,1
+ DO ma = 1,2
+ kac((mc-1)*2+ma) = kac((mc-1)*2+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_1_3
+ SUBROUTINE block_2_1_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*4), kbc(1*1), kad(2*4), kac(2*1), pbd(1*4), &
+ pbc(1*1), pad(2*4), pac(2*1), prim(2*1*1*4), scale
+ DO md = 1,4
+ DO mc = 1,1
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_1_4
+ SUBROUTINE block_2_1_1_5(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*5), kbc(1*1), kad(2*5), kac(2*1), pbd(1*5), &
+ pbc(1*1), pad(2*5), pac(2*1), prim(2*1*1*5), scale
+ DO md = 1,5
+ DO mc = 1,1
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_1_5
+ SUBROUTINE block_2_1_1_6(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*6), kbc(1*1), kad(2*6), kac(2*1), pbd(1*6), &
+ pbc(1*1), pad(2*6), pac(2*1), prim(2*1*1*6), scale
+ DO md = 1,6
+ DO mc = 1,1
+ DO mb = 1,1
+ DO ma = 1,2
+ kad((md-1)*2+ma) = kad((md-1)*2+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_1_6
+ SUBROUTINE block_2_1_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*1), kbc(1*2), kad(2*1), kac(2*2), pbd(1*1), &
+ pbc(1*2), pad(2*1), pac(2*2), prim(2*1*2*1), scale
+ DO md = 1,1
+ DO mc = 1,2
+ DO mb = 1,1
+ DO ma = 1,2
+ kac((mc-1)*2+ma) = kac((mc-1)*2+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_2_1
+ SUBROUTINE block_2_1_2_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*2), kbc(1*2), kad(2*2), kac(2*2), pbd(1*2), &
+ pbc(1*2), pad(2*2), pac(2*2), prim(2*1*2*2), scale
+ DO md = 1,2
+ DO mc = 1,2
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_2_2
+ SUBROUTINE block_2_1_2_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*4), kbc(1*2), kad(2*4), kac(2*2), pbd(1*4), &
+ pbc(1*2), pad(2*4), pac(2*2), prim(2*1*2*4), scale
+ DO md = 1,4
+ DO mc = 1,2
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_1_2_4
+ SUBROUTINE block_2_2_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*1), kad(2*1), kac(2*1), pbd(2*1), &
+ pbc(2*1), pad(2*1), pac(2*1), prim(2*2*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_2_1_1
+ SUBROUTINE block_2_2_2_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*2), kad(2*1), kac(2*2), pbd(2*1), &
+ pbc(2*2), pad(2*1), pac(2*2), prim(2*2*2*1), scale
+ DO md = 1,1
+ DO mc = 1,2
+ DO mb = 1,2
+ kbd((md-1)*2+mb) = kbd((md-1)*2+mb) - ks_bd
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_2_2_1
+ SUBROUTINE block_2_2_3_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*1), kbc(2*3), kad(2*1), kac(2*3), pbd(2*1), &
+ pbc(2*3), pad(2*1), pac(2*3), prim(2*2*3*1), scale
+ DO md = 1,1
+ DO mc = 1,3
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_2_2_3_1
+ SUBROUTINE block_3_2_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*md_max), kbc(2*1), kad(3*md_max), kac(3*1), &
+ pbd(2*md_max), pbc(2*1), pad(3*md_max), pac(3*1), prim(3*2*1*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,1
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_3_2_1
+ SUBROUTINE block_3_5_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(5*1), kbc(5*1), kad(3*1), kac(3*1), pbd(5*1), &
+ pbc(5*1), pad(3*1), pac(3*1), prim(3*5*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,5
+ DO ma = 1,3
+ kad((md-1)*3+ma) = kad((md-1)*3+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_3_5_1_1
+ SUBROUTINE block_3_5_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(5*md_max), kbc(5*1), kad(3*md_max), kac(3*1), &
+ pbd(5*md_max), pbc(5*1), pad(3*md_max), pac(3*1), prim(3*5*1*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,1
+ DO mb = 1,5
+ kbc((mc-1)*5+mb) = kbc((mc-1)*5+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_3_5_1
+ SUBROUTINE block_3_6(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(6*md_max), kbc(6*mc_max), kad(3*md_max), &
+ kac(3*mc_max), pbd(6*md_max), pbc(6*mc_max), pad(3*md_max), &
+ pac(3*mc_max), prim(3*6*mc_max*md_max), scale
+ kbd(1:6*md_max) = 0.0_dp
+ END SUBROUTINE block_3_6
+ SUBROUTINE block_3_9(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(9*md_max), kbc(9*mc_max), kad(3*md_max), &
+ kac(3*mc_max), pbd(9*md_max), pbc(9*mc_max), pad(3*md_max), &
+ pac(3*mc_max), prim(3*9*mc_max*md_max), scale
+ DO md = 1,md_max
+ DO mc = 1,mc_max
+ DO mb = 1,9
+ DO ma = 1,3
+ kac((mc-1)*3+ma) = kac((mc-1)*3+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_3_9
+ SUBROUTINE block_4_1_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*2), kbc(1*1), kad(4*2), kac(4*1), pbd(1*2), &
+ pbc(1*1), pad(4*2), pac(4*1), prim(4*1*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,1
+ DO ma = 1,4
+ kac((mc-1)*4+ma) = kac((mc-1)*4+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_1_1_2
+ SUBROUTINE block_4_1_1_3(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*3), kbc(1*1), kad(4*3), kac(4*1), pbd(1*3), &
+ pbc(1*1), pad(4*3), pac(4*1), prim(4*1*1*3), scale
+ DO md = 1,3
+ DO mc = 1,1
+ DO mb = 1,1
+ kbd((md-1)*1+mb) = kbd((md-1)*1+mb) - ks_bd
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_1_1_3
+ SUBROUTINE block_4_1_1_4(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*4), kbc(1*1), kad(4*4), kac(4*1), pbd(1*4), &
+ pbc(1*1), pad(4*4), pac(4*1), prim(4*1*1*4), scale
+ DO md = 1,4
+ DO mc = 1,1
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_1_1_4
+ SUBROUTINE block_4_1_1(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*md_max), kbc(1*1), kad(4*md_max), kac(4*1), &
+ pbd(1*md_max), pbc(1*1), pad(4*md_max), pac(4*1), prim(4*1*1*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,1
+ DO mb = 1,1
+ kbc((mc-1)*1+mb) = kbc((mc-1)*1+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_1_1
+ SUBROUTINE block_4_1_4(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(1*md_max), kbc(1*4), kad(4*md_max), kac(4*4), &
+ pbd(1*md_max), pbc(1*4), pad(4*md_max), pac(4*4), prim(4*1*4*md_max), &
+ scale
+ kbd(1:1*md_max) = 0.0_dp
+ END SUBROUTINE block_4_1_4
+ SUBROUTINE block_4_2_1_2(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*2), kbc(2*1), kad(4*2), kac(4*1), pbd(2*2), &
+ pbc(2*1), pad(4*2), pac(4*1), prim(4*2*1*2), scale
+ DO md = 1,2
+ DO mc = 1,1
+ DO mb = 1,2
+ DO ma = 1,4
+ kac((mc-1)*4+ma) = kac((mc-1)*4+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_2_1_2
+ SUBROUTINE block_4_2_2(md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(2*md_max), kbc(2*2), kad(4*md_max), kac(4*2), &
+ pbd(2*md_max), pbc(2*2), pad(4*md_max), pac(4*2), prim(4*2*2*md_max), &
+ scale
+ DO md = 1,md_max
+ DO mc = 1,2
+ DO mb = 1,2
+ kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_2_2
+ SUBROUTINE block_4_3_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*1), kbc(3*1), kad(4*1), kac(4*1), pbd(3*1), &
+ pbc(3*1), pad(4*1), pac(4*1), prim(4*3*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,3
+ DO ma = 1,4
+ kac((mc-1)*4+ma) = kac((mc-1)*4+ma)-tmp*p_bd
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_3_1_1
+ SUBROUTINE block_4_3(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(3*md_max), kbc(3*mc_max), kad(4*md_max), &
+ kac(4*mc_max), pbd(3*md_max), pbc(3*mc_max), pad(4*md_max), &
+ pac(4*mc_max), prim(4*3*mc_max*md_max), scale
+ DO md = 1,md_max
+ DO mc = 1,mc_max
+ DO mb = 1,3
+ kbc((mc-1)*3+mb) = kbc((mc-1)*3+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_3
+ SUBROUTINE block_4_4_1_1(kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(4*1), kbc(4*1), kad(4*1), kac(4*1), pbd(4*1), &
+ pbc(4*1), pad(4*1), pac(4*1), prim(4*4*1*1), scale
+ DO md = 1,1
+ DO mc = 1,1
+ DO mb = 1,4
+ DO ma = 1,4
+ kad((md-1)*4+ma) = kad((md-1)*4+ma)-tmp*p_bc
+ END DO
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_4_4_1_1
+ SUBROUTINE block_15_15(mc_max,md_max,kbd,kbc,kad,kac,pbd,pbc,pad,pac,prim,scale)
+ REAL(KIND=dp) :: kbd(15*md_max), kbc(15*mc_max), kad(15*md_max), &
+ kac(15*mc_max), pbd(15*md_max), pbc(15*mc_max), pad(15*md_max), &
+ pac(15*mc_max), prim(15*15*mc_max*md_max), scale
+ DO md = 1,md_max
+ DO mc = 1,mc_max
+ DO mb = 1,15
+ kbc((mc-1)*15+mb) = kbc((mc-1)*15+mb) - ks_bc
+ END DO
+ END DO
+ END DO
+ END SUBROUTINE block_15_15
+END MODULE hfx_contract_block
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 5389350307f..e0df1d2ff04 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1592,7 +1592,9 @@ proc check_p8vector_hw_available { } {
return [check_cached_effective_target p8vector_hw_available {
# Some simulators are known to not support VSX/power8 instructions.
# For now, disable on Darwin
- if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mpower8-vector"
@@ -1611,6 +1613,112 @@ proc check_p8vector_hw_available { } {
}]
}
+# Return 1 if the target supports executing power9 vector instructions, 0
+# otherwise. Cache the result.
+
+proc check_p9vector_hw_available { } {
+ return [check_cached_effective_target p9vector_hw_available {
+ # Some simulators are known to not support VSX/power8/power9
+ # instructions. For now, disable on Darwin.
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mpower9-vector"
+ check_runtime_nocache p9vector_hw_available {
+ int main()
+ {
+ long e = -1;
+ vector double v = (vector double) { 0.0, 0.0 };
+ asm ("xsxexpdp %0,%1" : "+r" (e) : "wa" (v));
+ return e;
+ }
+ } $options
+ }
+ }]
+}
+
+# Return 1 if the target supports executing power9 modulo instructions, 0
+# otherwise. Cache the result.
+
+proc check_p9modulo_hw_available { } {
+ return [check_cached_effective_target p9modulo_hw_available {
+ # Some simulators are known to not support VSX/power8/power9
+ # instructions. For now, disable on Darwin.
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mmodulo"
+ check_runtime_nocache p9modulo_hw_available {
+ int main()
+ {
+ int i = 5, j = 3, r = -1;
+ asm ("modsw %0,%1,%2" : "+r" (r) : "r" (i), "r" (j));
+ return (r == 2);
+ }
+ } $options
+ }
+ }]
+}
+
+# Return 1 if the target supports executing __float128 on PowerPC via software
+# emulation, 0 otherwise. Cache the result.
+
+proc check_ppc_float128_sw_available { } {
+ return [check_cached_effective_target ppc_float128_sw_available {
+ # Some simulators are known to not support VSX/power8/power9
+ # instructions. For now, disable on Darwin.
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mfloat128 -mvsx"
+ check_runtime_nocache ppc_float128_sw_available {
+ volatile __float128 x = 1.0q;
+ volatile __float128 y = 2.0q;
+ int main()
+ {
+ __float128 z = x + y;
+ return (z == 3.0q);
+ }
+ } $options
+ }
+ }]
+}
+
+# Return 1 if the target supports executing __float128 on PowerPC via power9
+# hardware instructions, 0 otherwise. Cache the result.
+
+proc check_ppc_float128_hw_available { } {
+ return [check_cached_effective_target ppc_float128_hw_available {
+ # Some simulators are known to not support VSX/power8/power9
+ # instructions. For now, disable on Darwin.
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ set options "-mfloat128-hardware"
+ check_runtime_nocache ppc_float128_hw_available {
+ volatile __float128 x = 1.0q;
+ volatile __float128 y = 2.0q;
+ int main()
+ {
+ __float128 z = x + y;
+ __float128 w = -1.0q;
+
+ __asm__ ("xsaddqp %0,%1,%2" : "+v" (w) : "v" (x), "v" (y));
+ return ((z == 3.0q) && (z == w);
+ }
+ } $options
+ }
+ }]
+}
+
# Return 1 if the target supports executing VSX instructions, 0
# otherwise. Cache the result.
@@ -1618,7 +1726,9 @@ proc check_vsx_hw_available { } {
return [check_cached_effective_target vsx_hw_available {
# Some simulators are known to not support VSX instructions.
# For now, disable on Darwin
- if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
+ if { [istarget powerpc-*-eabi]
+ || [istarget powerpc*-*-eabispe]
+ || [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mvsx"
@@ -3334,6 +3444,108 @@ proc check_effective_target_powerpc_p8vector_ok { } {
}
}
+# Return 1 if this is a PowerPC target supporting -mpower9-vector
+
+proc check_effective_target_powerpc_p9vector_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # AltiVec is not supported on AIX before 5.3.
+ if { [istarget powerpc*-*-aix4*]
+ || [istarget powerpc*-*-aix5.1*]
+ || [istarget powerpc*-*-aix5.2*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_p9vector_ok object {
+ int main (void) {
+ long e = -1;
+ vector double v = (vector double) { 0.0, 0.0 };
+ asm ("xsxexpdp %0,%1" : "+r" (e) : "wa" (v));
+ return e;
+ }
+ } "-mpower9-vector"]
+ } else {
+ return 0
+ }
+}
+
+# Return 1 if this is a PowerPC target supporting -mmodulo
+
+proc check_effective_target_powerpc_p9modulo_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # AltiVec is not supported on AIX before 5.3.
+ if { [istarget powerpc*-*-aix4*]
+ || [istarget powerpc*-*-aix5.1*]
+ || [istarget powerpc*-*-aix5.2*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_p9modulo_ok object {
+ int main (void) {
+ int i = 5, j = 3, r = -1;
+ asm ("modsw %0,%1,%2" : "+r" (r) : "r" (i), "r" (j));
+ return (r == 2);
+ }
+ } "-mmodulo"]
+ } else {
+ return 0
+ }
+}
+
+# Return 1 if this is a PowerPC target supporting -mfloat128 via either
+# software emulation on power7/power8 systems or hardware support on power9.
+
+proc check_effective_target_powerpc_float128_sw_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # AltiVec is not supported on AIX before 5.3.
+ if { [istarget powerpc*-*-aix4*]
+ || [istarget powerpc*-*-aix5.1*]
+ || [istarget powerpc*-*-aix5.2*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_float128_sw_ok object {
+ volatile __float128 x = 1.0q;
+ volatile __float128 y = 2.0q;
+ int main() {
+ __float128 z = x + y;
+ return (z == 3.0q);
+ }
+ } "-mfloat128 -mvsx"]
+ } else {
+ return 0
+ }
+}
+
+# Return 1 if this is a PowerPC target supporting -mfloat128 via hardware
+# support on power9.
+
+proc check_effective_target_powerpc_float128_hw_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # AltiVec is not supported on AIX before 5.3.
+ if { [istarget powerpc*-*-aix4*]
+ || [istarget powerpc*-*-aix5.1*]
+ || [istarget powerpc*-*-aix5.2*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_float128_hw_ok object {
+ volatile __float128 x = 1.0q;
+ volatile __float128 y = 2.0q;
+ int main() {
+ __float128 z;
+ __asm__ ("xsaddqp %0,%1,%2" : "=v" (z) : "v" (x), "v" (y));
+ return (z == 3.0q);
+ }
+ } "-mfloat128-hardware"]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is a PowerPC target supporting -mvsx
proc check_effective_target_powerpc_vsx_ok { } {
@@ -5435,6 +5647,10 @@ proc is-effective-target { arg } {
"vmx_hw" { set selected [check_vmx_hw_available] }
"vsx_hw" { set selected [check_vsx_hw_available] }
"p8vector_hw" { set selected [check_p8vector_hw_available] }
+ "p9vector_hw" { set selected [check_p9vector_hw_available] }
+ "p9modulo_hw" { set selected [check_p9modulo_hw_available] }
+ "ppc_float128_sw" { set selected [check_ppc_float128_sw_available] }
+ "ppc_float128_hw" { set selected [check_ppc_float128_hw_available] }
"ppc_recip_hw" { set selected [check_ppc_recip_hw_available] }
"dfp_hw" { set selected [check_dfp_hw_available] }
"htm_hw" { set selected [check_htm_hw_available] }
@@ -5459,6 +5675,10 @@ proc is-effective-target-keyword { arg } {
"vmx_hw" { return 1 }
"vsx_hw" { return 1 }
"p8vector_hw" { return 1 }
+ "p9vector_hw" { return 1 }
+ "p9modulo_hw" { return 1 }
+ "ppc_float128_sw" { return 1 }
+ "ppc_float128_hw" { return 1 }
"ppc_recip_hw" { return 1 }
"dfp_hw" { return 1 }
"htm_hw" { return 1 }
@@ -6162,7 +6382,9 @@ proc check_vect_support_and_set_flags { } {
}
lappend DEFAULT_VECTCFLAGS "-maltivec"
- if [check_p8vector_hw_available] {
+ if [check_p9vector_hw_available] {
+ lappend DEFAULT_VECTCFLAGS "-mpower9-vector"
+ } elseif [check_p8vector_hw_available] {
lappend DEFAULT_VECTCFLAGS "-mpower8-vector"
} elseif [check_vsx_hw_available] {
lappend DEFAULT_VECTCFLAGS "-mvsx" "-mno-allow-movmisalign"
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index d7b4ca4914a..ff061ef8637 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1157,9 +1157,6 @@ struct GTY(()) tree_base {
TYPE_SATURATING in
other types
- REF_REVERSE_STORAGE_ORDER in
- BIT_FIELD_REF, MEM_REF
-
VAR_DECL_IS_VIRTUAL_OPERAND in
VAR_DECL
@@ -1174,6 +1171,9 @@ struct GTY(()) tree_base {
default_def_flag:
+ TYPE_FINAL_P in
+ RECORD_TYPE, UNION_TYPE and QUAL_UNION_TYPE
+
TYPE_VECTOR_OPAQUE in
VECTOR_TYPE
@@ -1183,8 +1183,8 @@ struct GTY(()) tree_base {
DECL_NONLOCAL_FRAME in
VAR_DECL
- TYPE_FINAL_P in
- RECORD_TYPE, UNION_TYPE and QUAL_UNION_TYPE
+ REF_REVERSE_STORAGE_ORDER in
+ BIT_FIELD_REF, MEM_REF
*/
struct GTY(()) tree_typed {
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 617d6579948..9f68f31d091 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1362,7 +1362,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
int return_index, eh_index, fallthru_index;
int nlabels, ndests, j, last_case_index;
tree last_case;
- vec<tree> case_label_vec;
+ auto_vec<tree> case_label_vec;
gimple_seq switch_body = NULL;
gimple *x;
geh_else *eh_else;
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 61ec39040f6..88b6405a7be 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -799,7 +799,7 @@ ifcvt_can_use_mask_load_store (gimple *stmt)
|| VECTOR_MODE_P (mode))
return false;
- if (can_vec_mask_load_store_p (mode, is_load))
+ if (can_vec_mask_load_store_p (mode, VOIDmode, is_load))
return true;
return false;
@@ -2056,8 +2056,9 @@ predicate_mem_writes (loop_p loop)
{
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
- tree ref, addr, ptr, masktype, mask_op0, mask_op1, mask;
+ tree ref, addr, ptr, mask;
gimple *new_stmt;
+ gimple_seq stmts = NULL;
int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs)));
ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs;
mark_addressable (ref);
@@ -2070,16 +2071,27 @@ predicate_mem_writes (loop_p loop)
mask = vect_masks[index];
else
{
- masktype = build_nonstandard_integer_type (bitsize, 1);
- mask_op0 = build_int_cst (masktype, swap ? 0 : -1);
- mask_op1 = build_int_cst (masktype, swap ? -1 : 0);
- cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
- is_gimple_condexpr,
- NULL_TREE,
- true, GSI_SAME_STMT);
- mask = fold_build_cond_expr (masktype, unshare_expr (cond),
- mask_op0, mask_op1);
- mask = ifc_temp_var (masktype, mask, &gsi);
+ if (COMPARISON_CLASS_P (cond))
+ mask = gimple_build (&stmts, TREE_CODE (cond),
+ boolean_type_node,
+ TREE_OPERAND (cond, 0),
+ TREE_OPERAND (cond, 1));
+ else
+ {
+ gcc_assert (TREE_CODE (cond) == SSA_NAME);
+ mask = cond;
+ }
+
+ if (swap)
+ {
+ tree true_val
+ = constant_boolean_node (true, TREE_TYPE (mask));
+ mask = gimple_build (&stmts, BIT_XOR_EXPR,
+ TREE_TYPE (mask), mask, true_val);
+ }
+ gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
+
+ mask = ifc_temp_var (TREE_TYPE (mask), mask, &gsi);
/* Save mask and its size for further use. */
vect_sizes.safe_push (bitsize);
vect_masks.safe_push (mask);
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index a89630876c7..30aee19aae7 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -674,6 +674,12 @@ sra_deinitialize (void)
assign_link_pool.release ();
obstack_free (&name_obstack, NULL);
+ /* TODO: hash_map does not support traits that can release
+ value type of the hash_map. */
+ for (hash_map<tree, auto_vec<access_p> >::iterator it =
+ base_access_vec->begin (); it != base_access_vec->end (); ++it)
+ (*it).second.release ();
+
delete base_access_vec;
}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 2ea4079989e..f848c512dc7 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -121,8 +121,8 @@ static void dump_dominator_optimization_stats (FILE *file,
/* Free the edge_info data attached to E, if it exists. */
-static void
-free_edge_info (edge e)
+void
+free_dom_edge_info (edge e)
{
struct edge_info *edge_info = (struct edge_info *)e->aux;
@@ -142,7 +142,7 @@ allocate_edge_info (edge e)
struct edge_info *edge_info;
/* Free the old one, if it exists. */
- free_edge_info (e);
+ free_dom_edge_info (e);
edge_info = XCNEW (struct edge_info);
@@ -167,7 +167,7 @@ free_all_edge_infos (void)
{
FOR_EACH_EDGE (e, ei, bb->preds)
{
- free_edge_info (e);
+ free_dom_edge_info (e);
e->aux = NULL;
}
}
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 9585f905438..2ac382842d3 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -2760,11 +2760,15 @@ cond_stmts_equal_p (gcond *cond1, gcond *cond2, bool *inverted_p)
else
return false;
- if (! expressions_equal_p (vn_valueize (lhs1), vn_valueize (lhs2))
- || ! expressions_equal_p (vn_valueize (rhs1), vn_valueize (rhs2)))
- return false;
-
- return true;
+ lhs1 = vn_valueize (lhs1);
+ rhs1 = vn_valueize (rhs1);
+ lhs2 = vn_valueize (lhs2);
+ rhs2 = vn_valueize (rhs2);
+ return ((expressions_equal_p (lhs1, lhs2)
+ && expressions_equal_p (rhs1, rhs2))
+ || (commutative_tree_code (code1)
+ && expressions_equal_p (lhs1, rhs2)
+ && expressions_equal_p (rhs1, lhs2)));
}
/* Compare two phi entries for equality, ignoring VN_TOP arguments. */
@@ -3379,6 +3383,7 @@ visit_phi (gimple *phi)
tree result;
tree sameval = VN_TOP;
bool allsame = true;
+ unsigned n_executable = 0;
/* TODO: We could check for this in init_sccvn, and replace this
with a gcc_assert. */
@@ -3394,6 +3399,7 @@ visit_phi (gimple *phi)
{
tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
+ ++n_executable;
if (TREE_CODE (def) == SSA_NAME)
def = SSA_VAL (def);
if (def == VN_TOP)
@@ -3408,9 +3414,11 @@ visit_phi (gimple *phi)
}
/* If none of the edges was executable or all incoming values are
- undefined keep the value-number at VN_TOP. */
- if (sameval == VN_TOP)
- return set_ssa_val_to (PHI_RESULT (phi), VN_TOP);
+ undefined keep the value-number at VN_TOP. If only a single edge
+ is exectuable use its value. */
+ if (sameval == VN_TOP
+ || n_executable == 1)
+ return set_ssa_val_to (PHI_RESULT (phi), sameval);
/* First see if it is equivalent to a phi node in this block. We prefer
this as it allows IV elimination - see PRs 66502 and 67167. */
@@ -4610,6 +4618,10 @@ expressions_equal_p (tree e1, tree e2)
if (e1 == e2)
return true;
+ /* If either one is VN_TOP consider them equal. */
+ if (e1 == VN_TOP || e2 == VN_TOP)
+ return true;
+
/* If only one of them is null, they cannot be equal. */
if (!e1 || !e2)
return false;
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 184cf3402a9..c527206409a 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -290,7 +290,10 @@ remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e->dest != dest_bb)
- remove_edge (e);
+ {
+ free_dom_edge_info (e);
+ remove_edge (e);
+ }
else
ei_next (&ei);
}
@@ -2522,6 +2525,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
delete_jump_thread_path (path);
paths.unordered_remove (i);
+ free (region);
}
/* Remove from PATHS all the jump-threads starting with an edge already
diff --git a/gcc/tree-ssa-threadupdate.h b/gcc/tree-ssa-threadupdate.h
index 984b6c4d972..e0eb3f5c724 100644
--- a/gcc/tree-ssa-threadupdate.h
+++ b/gcc/tree-ssa-threadupdate.h
@@ -46,4 +46,5 @@ extern void register_jump_thread (vec <class jump_thread_edge *> *);
extern void remove_jump_threads_including (edge);
extern void delete_jump_thread_path (vec <class jump_thread_edge *> *);
extern void remove_ctrl_stmt_and_useless_edges (basic_block, basic_block);
+extern void free_dom_edge_info (edge);
#endif
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 096b75b10e0..b599bb5bf12 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -124,17 +124,13 @@ ssanames_print_statistics (void)
DEBUG_FUNCTION void
verify_ssaname_freelists (struct function *fun)
{
- /* Do nothing if we are in RTL format. */
- basic_block bb;
- FOR_EACH_BB_FN (bb, fun)
- {
- if (bb->flags & BB_RTL)
- return;
- }
+ if (!gimple_in_ssa_p (fun))
+ return;
bitmap names_in_il = BITMAP_ALLOC (NULL);
/* Walk the entire IL noting every SSA_NAME we see. */
+ basic_block bb;
FOR_EACH_BB_FN (bb, fun)
{
tree t;
@@ -163,8 +159,7 @@ verify_ssaname_freelists (struct function *fun)
ssa_op_iter iter;
gimple *stmt = gsi_stmt (gsi);
FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, SSA_OP_ALL_OPERANDS)
- if (TREE_CODE (t) == SSA_NAME)
- bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t));
+ bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t));
}
}
@@ -218,7 +213,7 @@ verify_ssaname_freelists (struct function *fun)
debug/non-debug compilations have the same SSA_NAMEs. So for each
lost SSA_NAME, see if it's likely one from that wart. These will always
be marked as default definitions. So we loosely assume that anything
- marked as a default definition isn't leaked by pretening they are
+ marked as a default definition isn't leaked by pretending they are
in the IL. */
for (unsigned int i = UNUSED_NAME_VERSION + 1; i < num_ssa_names; i++)
if (ssa_name (i) && SSA_NAME_IS_DEFAULT_DEF (ssa_name (i)))
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 7417eaf81e7..65a1ce3bef4 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -143,7 +143,10 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8);
}
else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
- REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
+ {
+ REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
+ bp_unpack_value (bp, 8);
+ }
else if (TREE_CODE (expr) == SSA_NAME)
{
SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 9ca02719a19..d0b7f6db171 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -117,7 +117,10 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8);
}
else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
- bp_pack_value (bp, REF_REVERSE_STORAGE_ORDER (expr), 1);
+ {
+ bp_pack_value (bp, REF_REVERSE_STORAGE_ORDER (expr), 1);
+ bp_pack_value (bp, 0, 8);
+ }
else if (TREE_CODE (expr) == SSA_NAME)
{
bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 11bce795a5e..87936ddee1d 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -559,6 +559,50 @@ vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
}
+/* Analyze dependences involved in the transform of SLP NODE. */
+
+static bool
+vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node)
+{
+ /* This walks over all stmts involved in the SLP load/store done
+ in NODE verifying we can sink them up to the last stmt in the
+ group. */
+ gimple *last_access = vect_find_last_scalar_stmt_in_slp (node);
+ for (unsigned k = 0; k < SLP_INSTANCE_GROUP_SIZE (instance); ++k)
+ {
+ gimple *access = SLP_TREE_SCALAR_STMTS (node)[k];
+ if (access == last_access)
+ continue;
+ data_reference *dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (access));
+ for (gimple_stmt_iterator gsi = gsi_for_stmt (access);
+ gsi_stmt (gsi) != last_access; gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (! gimple_vuse (stmt)
+ || (DR_IS_READ (dr_a) && ! gimple_vdef (stmt)))
+ continue;
+
+ /* If we couldn't record a (single) data reference for this
+ stmt we have to give up. */
+ data_reference *dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
+ if (!dr_b)
+ return false;
+
+ ddr_p ddr = initialize_data_dependence_relation (dr_a, dr_b, vNULL);
+ if (vect_slp_analyze_data_ref_dependence (ddr))
+ {
+ /* ??? If the dependence analysis failed we can resort to the
+ alias oracle which can handle more kinds of stmts. */
+ free_dependence_relation (ddr);
+ return false;
+ }
+ free_dependence_relation (ddr);
+ }
+ }
+ return true;
+}
+
+
/* Function vect_analyze_data_ref_dependences.
Examine all the data references in the basic-block, and make sure there
@@ -568,21 +612,45 @@ vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
bool
vect_slp_analyze_data_ref_dependences (bb_vec_info bb_vinfo)
{
- struct data_dependence_relation *ddr;
- unsigned int i;
-
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"=== vect_slp_analyze_data_ref_dependences ===\n");
- if (!compute_all_dependences (BB_VINFO_DATAREFS (bb_vinfo),
- &BB_VINFO_DDRS (bb_vinfo),
- vNULL, true))
- return false;
+ slp_instance instance;
+ slp_tree load;
+ unsigned int i, j;
+ for (i = 0; BB_VINFO_SLP_INSTANCES (bb_vinfo).iterate (i, &instance); )
+ {
+ bool remove = false;
+ /* Verify we can sink loads to the vectorized stmt insert location. */
+ FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), j, load)
+ if (! vect_slp_analyze_node_dependences (instance, load))
+ {
+ remove = true;
+ break;
+ }
+ /* Verify we can sink stores to the vectorized stmt insert location. */
+ slp_tree store = SLP_INSTANCE_TREE (instance);
+ if (!remove
+ && STMT_VINFO_DATA_REF
+ (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (store)[0]))
+ && ! vect_slp_analyze_node_dependences (instance, store))
+ remove = true;
+ if (remove)
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "removing SLP instance operations starting from: ");
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
+ SLP_TREE_SCALAR_STMTS
+ (SLP_INSTANCE_TREE (instance))[0], 0);
+ vect_free_slp_instance (instance);
+ BB_VINFO_SLP_INSTANCES (bb_vinfo).ordered_remove (i);
+ }
+ i++;
+ }
- FOR_EACH_VEC_ELT (BB_VINFO_DDRS (bb_vinfo), i, ddr)
- if (vect_slp_analyze_data_ref_dependence (ddr))
- return false;
+ if (!BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
+ return false;
return true;
}
@@ -3674,7 +3742,12 @@ again:
}
if (is_a <bb_vec_info> (vinfo))
- break;
+ {
+ /* No vector type is fine, the ref can still participate
+ in dependence analysis, we just can't vectorize it. */
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ continue;
+ }
if (gatherscatter != SG_NONE || simd_lane_access)
{
@@ -3790,6 +3863,9 @@ vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
case vect_scalar_var:
prefix = "stmp";
break;
+ case vect_mask_var:
+ prefix = "mask";
+ break;
case vect_pointer_var:
prefix = "vectp";
break;
@@ -4379,7 +4455,11 @@ vect_create_destination_var (tree scalar_dest, tree vectype)
tree type;
enum vect_var_kind kind;
- kind = vectype ? vect_simple_var : vect_scalar_var;
+ kind = vectype
+ ? VECTOR_BOOLEAN_TYPE_P (vectype)
+ ? vect_mask_var
+ : vect_simple_var
+ : vect_scalar_var;
type = vectype ? vectype : TREE_TYPE (scalar_dest);
gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index c64fdc4d46a..5883db8abd6 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -346,7 +346,8 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
tree op1, enum tree_code code)
{
tree t;
- if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
+ if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type)
+ && !expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
t = expand_vector_piecewise (gsi, do_compare, type,
TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
else
@@ -1527,6 +1528,8 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
tree srhs1, srhs2 = NULL_TREE;
if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
&& (rhs2 == NULL_TREE
+ || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
+ && (srhs2 = rhs2))
|| (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
/* As we query direct optabs restrict to non-convert operations. */
&& TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 43ada18ac7c..cbf0073ffcf 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -178,19 +178,21 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
- int nbbs = loop->num_nodes;
+ unsigned nbbs = loop->num_nodes;
unsigned int vectorization_factor = 0;
tree scalar_type;
gphi *phi;
tree vectype;
unsigned int nunits;
stmt_vec_info stmt_info;
- int i;
+ unsigned i;
HOST_WIDE_INT dummy;
gimple *stmt, *pattern_stmt = NULL;
gimple_seq pattern_def_seq = NULL;
gimple_stmt_iterator pattern_def_si = gsi_none ();
bool analyze_pattern_stmt = false;
+ bool bool_result;
+ auto_vec<stmt_vec_info> mask_producers;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -409,6 +411,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
return false;
}
+ bool_result = false;
+
if (STMT_VINFO_VECTYPE (stmt_info))
{
/* The only case when a vectype had been already set is for stmts
@@ -429,6 +433,32 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
scalar_type = TREE_TYPE (gimple_call_arg (stmt, 3));
else
scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
+
+ /* Bool ops don't participate in vectorization factor
+ computation. For comparison use compared types to
+ compute a factor. */
+ if (TREE_CODE (scalar_type) == BOOLEAN_TYPE)
+ {
+ mask_producers.safe_push (stmt_info);
+ bool_result = true;
+
+ if (gimple_code (stmt) == GIMPLE_ASSIGN
+ && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+ == tcc_comparison
+ && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+ != BOOLEAN_TYPE)
+ scalar_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ else
+ {
+ if (!analyze_pattern_stmt && gsi_end_p (pattern_def_si))
+ {
+ pattern_def_seq = NULL;
+ gsi_next (&si);
+ }
+ continue;
+ }
+ }
+
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
@@ -451,7 +481,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
return false;
}
- STMT_VINFO_VECTYPE (stmt_info) = vectype;
+ if (!bool_result)
+ STMT_VINFO_VECTYPE (stmt_info) = vectype;
if (dump_enabled_p ())
{
@@ -464,8 +495,9 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
/* The vectorization factor is according to the smallest
scalar type (or the largest vector size, but we only
support one vector size per loop). */
- scalar_type = vect_get_smallest_scalar_type (stmt, &dummy,
- &dummy);
+ if (!bool_result)
+ scalar_type = vect_get_smallest_scalar_type (stmt, &dummy,
+ &dummy);
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
@@ -540,6 +572,99 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
}
LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
+ for (i = 0; i < mask_producers.length (); i++)
+ {
+ tree mask_type = NULL;
+
+ stmt = STMT_VINFO_STMT (mask_producers[i]);
+
+ if (gimple_code (stmt) == GIMPLE_ASSIGN
+ && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
+ && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt))) != BOOLEAN_TYPE)
+ {
+ scalar_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ mask_type = get_mask_type_for_scalar_type (scalar_type);
+
+ if (!mask_type)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: unsupported mask\n");
+ return false;
+ }
+ }
+ else
+ {
+ tree rhs;
+ ssa_op_iter iter;
+ gimple *def_stmt;
+ enum vect_def_type dt;
+
+ FOR_EACH_SSA_TREE_OPERAND (rhs, stmt, iter, SSA_OP_USE)
+ {
+ if (!vect_is_simple_use (rhs, mask_producers[i]->vinfo,
+ &def_stmt, &dt, &vectype))
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: can't compute mask type "
+ "for statement, ");
+ dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt,
+ 0);
+ dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ }
+ return false;
+ }
+
+ /* No vectype probably means external definition.
+ Allow it in case there is another operand which
+ allows to determine mask type. */
+ if (!vectype)
+ continue;
+
+ if (!mask_type)
+ mask_type = vectype;
+ else if (TYPE_VECTOR_SUBPARTS (mask_type)
+ != TYPE_VECTOR_SUBPARTS (vectype))
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: different sized masks "
+ "types in statement, ");
+ dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
+ mask_type);
+ dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
+ dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
+ vectype);
+ dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ }
+ return false;
+ }
+ }
+ }
+
+ /* No mask_type should mean loop invariant predicate.
+ This is probably a subject for optimization in
+ if-conversion. */
+ if (!mask_type)
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: can't compute mask type "
+ "for statement, ");
+ dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt,
+ 0);
+ dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ }
+ return false;
+ }
+
+ STMT_VINFO_VECTYPE (mask_producers[i]) = mask_type;
+ }
+
return true;
}
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index d003d335f5d..e91c6e008a0 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -2849,7 +2849,9 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
/* Helper function of vect_recog_bool_pattern. Called recursively, return
- true if bool VAR can be optimized that way. */
+ true if bool VAR can and should be optimized that way. Assume it shouldn't
+ in case it's a result of a comparison which can be directly vectorized into
+ a vector comparison. */
static bool
check_bool_pattern (tree var, vec_info *vinfo)
@@ -2898,7 +2900,7 @@ check_bool_pattern (tree var, vec_info *vinfo)
default:
if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
{
- tree vecitype, comp_vectype;
+ tree vecitype, comp_vectype, mask_type;
/* If the comparison can throw, then is_gimple_condexpr will be
false and we can't make a COND_EXPR/VEC_COND_EXPR out of it. */
@@ -2909,6 +2911,11 @@ check_bool_pattern (tree var, vec_info *vinfo)
if (comp_vectype == NULL_TREE)
return false;
+ mask_type = get_mask_type_for_scalar_type (TREE_TYPE (rhs1));
+ if (mask_type
+ && expand_vec_cmp_expr_p (comp_vectype, mask_type))
+ return false;
+
if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE)
{
machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
@@ -3133,6 +3140,73 @@ adjust_bool_pattern (tree var, tree out_type, tree trueval,
}
+/* Return the proper type for converting bool VAR into
+ an integer value or NULL_TREE if no such type exists.
+ The type is chosen so that converted value has the
+ same number of elements as VAR's vector type. */
+
+static tree
+search_type_for_mask (tree var, vec_info *vinfo)
+{
+ gimple *def_stmt;
+ enum vect_def_type dt;
+ tree rhs1;
+ enum tree_code rhs_code;
+ tree res = NULL_TREE;
+
+ if (TREE_CODE (var) != SSA_NAME)
+ return NULL_TREE;
+
+ if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
+ || !TYPE_UNSIGNED (TREE_TYPE (var)))
+ && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
+ return NULL_TREE;
+
+ if (!vect_is_simple_use (var, vinfo, &def_stmt, &dt))
+ return NULL_TREE;
+
+ if (dt != vect_internal_def)
+ return NULL_TREE;
+
+ if (!is_gimple_assign (def_stmt))
+ return NULL_TREE;
+
+ rhs_code = gimple_assign_rhs_code (def_stmt);
+ rhs1 = gimple_assign_rhs1 (def_stmt);
+
+ switch (rhs_code)
+ {
+ case SSA_NAME:
+ case BIT_NOT_EXPR:
+ CASE_CONVERT:
+ res = search_type_for_mask (rhs1, vinfo);
+ break;
+
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (!(res = search_type_for_mask (rhs1, vinfo)))
+ res = search_type_for_mask (gimple_assign_rhs2 (def_stmt), vinfo);
+ break;
+
+ default:
+ if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
+ {
+ if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
+ || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+ {
+ machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+ res = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
+ }
+ else
+ res = TREE_TYPE (rhs1);
+ }
+ }
+
+ return res;
+}
+
+
/* Function vect_recog_bool_pattern
Try to find pattern like following:
@@ -3190,6 +3264,7 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
enum tree_code rhs_code;
tree var, lhs, rhs, vectype;
stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
+ stmt_vec_info new_stmt_info;
vec_info *vinfo = stmt_vinfo->vinfo;
gimple *pattern_stmt;
@@ -3214,16 +3289,52 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
if (vectype == NULL_TREE)
return NULL;
- if (!check_bool_pattern (var, vinfo))
- return NULL;
-
- rhs = adjust_bool_pattern (var, TREE_TYPE (lhs), NULL_TREE, stmts);
- lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
- if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
- pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
+ if (check_bool_pattern (var, vinfo))
+ {
+ rhs = adjust_bool_pattern (var, TREE_TYPE (lhs), NULL_TREE, stmts);
+ lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
+ else
+ pattern_stmt
+ = gimple_build_assign (lhs, NOP_EXPR, rhs);
+ }
else
- pattern_stmt
- = gimple_build_assign (lhs, NOP_EXPR, rhs);
+ {
+ tree type = search_type_for_mask (var, vinfo);
+ tree cst0, cst1, cmp, tmp;
+
+ if (!type)
+ return NULL;
+
+ /* We may directly use cond with narrowed type to avoid
+ multiple cond exprs with following result packing and
+ perform single cond with packed mask instead. In case
+ of widening we better make cond first and then extract
+ results. */
+ if (TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (lhs)))
+ type = TREE_TYPE (lhs);
+
+ cst0 = build_int_cst (type, 0);
+ cst1 = build_int_cst (type, 1);
+ tmp = vect_recog_temp_ssa_var (type, NULL);
+ cmp = build2 (NE_EXPR, boolean_type_node,
+ var, build_int_cst (TREE_TYPE (var), 0));
+ pattern_stmt = gimple_build_assign (tmp, COND_EXPR, cmp, cst1, cst0);
+
+ if (!useless_type_conversion_p (type, TREE_TYPE (lhs)))
+ {
+ tree new_vectype = get_vectype_for_scalar_type (type);
+ new_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo);
+ set_vinfo_for_stmt (pattern_stmt, new_stmt_info);
+ STMT_VINFO_VECTYPE (new_stmt_info) = new_vectype;
+ new_pattern_def_seq (stmt_vinfo, pattern_stmt);
+
+ lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ pattern_stmt = gimple_build_assign (lhs, CONVERT_EXPR, tmp);
+ }
+ }
+
*type_out = vectype;
*type_in = vectype;
stmts->safe_push (last_stmt);
@@ -3252,15 +3363,19 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
if (get_vectype_for_scalar_type (type) == NULL_TREE)
return NULL;
- if (!check_bool_pattern (var, vinfo))
- return NULL;
+ if (check_bool_pattern (var, vinfo))
+ {
+ rhs = adjust_bool_pattern (var, type, NULL_TREE, stmts);
+ rhs = build2 (NE_EXPR, boolean_type_node,
+ rhs, build_int_cst (type, 0));
+ }
+ else
+ rhs = build2 (NE_EXPR, boolean_type_node,
+ var, build_int_cst (TREE_TYPE (var), 0)),
- rhs = adjust_bool_pattern (var, type, NULL_TREE, stmts);
lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
pattern_stmt
- = gimple_build_assign (lhs, COND_EXPR,
- build2 (NE_EXPR, boolean_type_node,
- rhs, build_int_cst (type, 0)),
+ = gimple_build_assign (lhs, COND_EXPR, rhs,
gimple_assign_rhs2 (last_stmt),
gimple_assign_rhs3 (last_stmt));
*type_out = vectype;
@@ -3280,16 +3395,43 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
gcc_assert (vectype != NULL_TREE);
if (!VECTOR_MODE_P (TYPE_MODE (vectype)))
return NULL;
- if (!check_bool_pattern (var, vinfo))
- return NULL;
- rhs = adjust_bool_pattern (var, TREE_TYPE (vectype), NULL_TREE, stmts);
+ if (check_bool_pattern (var, vinfo))
+ rhs = adjust_bool_pattern (var, TREE_TYPE (vectype),
+ NULL_TREE, stmts);
+ else
+ {
+ tree type = search_type_for_mask (var, vinfo);
+ tree cst0, cst1, cmp, new_vectype;
+
+ if (!type)
+ return NULL;
+
+ if (TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (vectype)))
+ type = TREE_TYPE (vectype);
+
+ cst0 = build_int_cst (type, 0);
+ cst1 = build_int_cst (type, 1);
+ new_vectype = get_vectype_for_scalar_type (type);
+
+ rhs = vect_recog_temp_ssa_var (type, NULL);
+ cmp = build2 (NE_EXPR, boolean_type_node,
+ var, build_int_cst (TREE_TYPE (var), 0));
+ pattern_stmt = gimple_build_assign (rhs, COND_EXPR,
+ cmp, cst1, cst0);
+
+ pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo);
+ set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
+ STMT_VINFO_VECTYPE (pattern_stmt_info) = new_vectype;
+ append_pattern_def_seq (stmt_vinfo, pattern_stmt);
+ }
+
lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (vectype), lhs);
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
{
tree rhs2 = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
gimple *cast_stmt = gimple_build_assign (rhs2, NOP_EXPR, rhs);
- new_pattern_def_seq (stmt_vinfo, cast_stmt);
+ append_pattern_def_seq (stmt_vinfo, cast_stmt);
rhs = rhs2;
}
pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index cfdfc2936a1..fe838282777 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -792,6 +792,7 @@ vect_build_slp_tree_1 (vec_info *vinfo,
if (TREE_CODE_CLASS (rhs_code) != tcc_binary
&& TREE_CODE_CLASS (rhs_code) != tcc_unary
&& TREE_CODE_CLASS (rhs_code) != tcc_expression
+ && TREE_CODE_CLASS (rhs_code) != tcc_comparison
&& rhs_code != CALL_EXPR)
{
if (dump_enabled_p ())
@@ -1426,7 +1427,7 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
/* Find the last store in SLP INSTANCE. */
-static gimple *
+gimple *
vect_find_last_scalar_stmt_in_slp (slp_tree node)
{
gimple *last = NULL, *stmt;
@@ -2317,9 +2318,12 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo)
dump_printf (MSG_NOTE, " Scalar cost of basic block: %d\n", scalar_cost);
}
- /* Vectorization is profitable if its cost is less than the cost of scalar
- version. */
- if (vec_outside_cost + vec_inside_cost >= scalar_cost)
+ /* Vectorization is profitable if its cost is more than the cost of scalar
+ version. Note that we err on the vector side for equal cost because
+ the cost estimate is otherwise quite pessimistic (constant uses are
+ free on the scalar side but cost a load on the vector side for
+ example). */
+ if (vec_outside_cost + vec_inside_cost > scalar_cost)
return false;
return true;
@@ -2637,7 +2641,14 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
struct loop *loop;
gimple_seq ctor_seq = NULL;
- vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+ /* Check if vector type is a boolean vector. */
+ if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+ && (VECTOR_BOOLEAN_TYPE_P (STMT_VINFO_VECTYPE (stmt_vinfo))
+ || (code == COND_EXPR && op_num < 2)))
+ vector_type
+ = build_same_sized_truth_vector_type (STMT_VINFO_VECTYPE (stmt_vinfo));
+ else
+ vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
nunits = TYPE_VECTOR_SUBPARTS (vector_type);
if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
@@ -2809,8 +2820,21 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
{
if (CONSTANT_CLASS_P (op))
{
- op = fold_unary (VIEW_CONVERT_EXPR,
- TREE_TYPE (vector_type), op);
+ if (VECTOR_BOOLEAN_TYPE_P (vector_type))
+ {
+ /* Can't use VIEW_CONVERT_EXPR for booleans because
+ of possibly different sizes of scalar value and
+ vector element. */
+ if (integer_zerop (op))
+ op = build_int_cst (TREE_TYPE (vector_type), 0);
+ else if (integer_onep (op))
+ op = build_int_cst (TREE_TYPE (vector_type), 1);
+ else
+ gcc_unreachable ();
+ }
+ else
+ op = fold_unary (VIEW_CONVERT_EXPR,
+ TREE_TYPE (vector_type), op);
gcc_assert (op && CONSTANT_CLASS_P (op));
}
else
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 51dff9eb19e..bdf16faff79 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1300,7 +1300,7 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
{
if (CONSTANT_CLASS_P (val))
- val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+ val = fold_convert (TREE_TYPE (type), val);
else
{
new_temp = make_ssa_name (TREE_TYPE (type));
@@ -1328,16 +1328,18 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
In case OP is an invariant or constant, a new stmt that creates a vector def
- needs to be introduced. */
+ needs to be introduced. VECTYPE may be used to specify a required type for
+ vector invariant. */
tree
-vect_get_vec_def_for_operand (tree op, gimple *stmt)
+vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
{
tree vec_oprnd;
gimple *vec_stmt;
gimple *def_stmt;
stmt_vec_info def_stmt_info = NULL;
stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+ tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
enum vect_def_type dt;
bool is_simple_use;
@@ -1372,7 +1374,14 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt)
case vect_constant_def:
case vect_external_def:
{
- vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+ if (vectype)
+ vector_type = vectype;
+ else if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE
+ && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
+ vector_type = build_same_sized_truth_vector_type (stmt_vectype);
+ else
+ vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+
gcc_assert (vector_type);
return vect_init_vector (stmt, op, vector_type, NULL);
}
@@ -1679,6 +1688,7 @@ vectorizable_mask_load_store (gimple *stmt, gimple_stmt_iterator *gsi,
bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ tree mask_vectype;
tree elem_type;
gimple *new_stmt;
tree dummy;
@@ -1705,8 +1715,8 @@ vectorizable_mask_load_store (gimple *stmt, gimple_stmt_iterator *gsi,
is_store = gimple_call_internal_fn (stmt) == IFN_MASK_STORE;
mask = gimple_call_arg (stmt, 2);
- if (TYPE_PRECISION (TREE_TYPE (mask))
- != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vectype))))
+
+ if (TREE_CODE (TREE_TYPE (mask)) != BOOLEAN_TYPE)
return false;
/* FORNOW. This restriction should be relaxed. */
@@ -1735,6 +1745,18 @@ vectorizable_mask_load_store (gimple *stmt, gimple_stmt_iterator *gsi,
if (STMT_VINFO_STRIDED_P (stmt_info))
return false;
+ if (TREE_CODE (mask) != SSA_NAME)
+ return false;
+
+ if (!vect_is_simple_use (mask, loop_vinfo, &def_stmt, &dt, &mask_vectype))
+ return false;
+
+ if (!mask_vectype)
+ mask_vectype = get_mask_type_for_scalar_type (TREE_TYPE (vectype));
+
+ if (!mask_vectype)
+ return false;
+
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
gimple *def_stmt;
@@ -1766,13 +1788,9 @@ vectorizable_mask_load_store (gimple *stmt, gimple_stmt_iterator *gsi,
: DR_STEP (dr), size_zero_node) <= 0)
return false;
else if (!VECTOR_MODE_P (TYPE_MODE (vectype))
- || !can_vec_mask_load_store_p (TYPE_MODE (vectype), !is_store))
- return false;
-
- if (TREE_CODE (mask) != SSA_NAME)
- return false;
-
- if (!vect_is_simple_use (mask, loop_vinfo, &def_stmt, &dt))
+ || !can_vec_mask_load_store_p (TYPE_MODE (vectype),
+ TYPE_MODE (mask_vectype),
+ !is_store))
return false;
if (is_store)
@@ -4679,8 +4697,9 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
/* Most operations cannot handle bit-precision types without extra
truncations. */
- if ((TYPE_PRECISION (TREE_TYPE (scalar_dest))
- != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
+ && (TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
/* Exception are bitwise binary operations. */
&& code != BIT_IOR_EXPR
&& code != BIT_XOR_EXPR
@@ -7329,13 +7348,14 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
{
gimple *gtemp;
vec_cond_lhs =
- vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt);
+ vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
+ stmt, comp_vectype);
vect_is_simple_use (TREE_OPERAND (cond_expr, 0),
loop_vinfo, &gtemp, &dts[0]);
vec_cond_rhs =
vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
- stmt);
+ stmt, comp_vectype);
vect_is_simple_use (TREE_OPERAND (cond_expr, 1),
loop_vinfo, &gtemp, &dts[1]);
if (reduc_index == 1)
@@ -7416,6 +7436,185 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
return true;
}
+/* vectorizable_comparison.
+
+ Check if STMT is comparison expression that can be vectorized.
+ If VEC_STMT is also passed, vectorize the STMT: create a vectorized
+ comparison, put it in VEC_STMT, and insert it at GSI.
+
+ Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+
+bool
+vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
+ gimple **vec_stmt, tree reduc_def,
+ slp_tree slp_node)
+{
+ tree lhs, rhs1, rhs2;
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ tree vec_rhs1 = NULL_TREE, vec_rhs2 = NULL_TREE;
+ tree new_temp;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ enum vect_def_type dts[2] = {vect_unknown_def_type, vect_unknown_def_type};
+ unsigned nunits;
+ int ncopies;
+ enum tree_code code;
+ stmt_vec_info prev_stmt_info = NULL;
+ int i, j;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ vec<tree> vec_oprnds0 = vNULL;
+ vec<tree> vec_oprnds1 = vNULL;
+ gimple *def_stmt;
+ tree mask_type;
+ tree mask;
+
+ if (!VECTOR_BOOLEAN_TYPE_P (vectype))
+ return false;
+
+ mask_type = vectype;
+ nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+ if (slp_node || PURE_SLP_STMT (stmt_info))
+ ncopies = 1;
+ else
+ ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
+
+ gcc_assert (ncopies >= 1);
+ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
+ return false;
+
+ if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
+ && !(STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle
+ && reduc_def))
+ return false;
+
+ if (STMT_VINFO_LIVE_P (stmt_info))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "value used after loop.\n");
+ return false;
+ }
+
+ if (!is_gimple_assign (stmt))
+ return false;
+
+ code = gimple_assign_rhs_code (stmt);
+
+ if (TREE_CODE_CLASS (code) != tcc_comparison)
+ return false;
+
+ rhs1 = gimple_assign_rhs1 (stmt);
+ rhs2 = gimple_assign_rhs2 (stmt);
+
+ if (!vect_is_simple_use (rhs1, stmt_info->vinfo, &def_stmt,
+ &dts[0], &vectype1))
+ return false;
+
+ if (!vect_is_simple_use (rhs2, stmt_info->vinfo, &def_stmt,
+ &dts[1], &vectype2))
+ return false;
+
+ if (vectype1 && vectype2
+ && TYPE_VECTOR_SUBPARTS (vectype1) != TYPE_VECTOR_SUBPARTS (vectype2))
+ return false;
+
+ vectype = vectype1 ? vectype1 : vectype2;
+
+ /* Invariant comparison. */
+ if (!vectype)
+ {
+ vectype = build_vector_type (TREE_TYPE (rhs1), nunits);
+ if (tree_to_shwi (TYPE_SIZE_UNIT (vectype)) != current_vector_size)
+ return false;
+ }
+ else if (nunits != TYPE_VECTOR_SUBPARTS (vectype))
+ return false;
+
+ if (!vec_stmt)
+ {
+ STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
+ vect_model_simple_cost (stmt_info, ncopies, dts, NULL, NULL);
+ return expand_vec_cmp_expr_p (vectype, mask_type);
+ }
+
+ /* Transform. */
+ if (!slp_node)
+ {
+ vec_oprnds0.create (1);
+ vec_oprnds1.create (1);
+ }
+
+ /* Handle def. */
+ lhs = gimple_assign_lhs (stmt);
+ mask = vect_create_destination_var (lhs, mask_type);
+
+ /* Handle cmp expr. */
+ for (j = 0; j < ncopies; j++)
+ {
+ gassign *new_stmt = NULL;
+ if (j == 0)
+ {
+ if (slp_node)
+ {
+ auto_vec<tree, 2> ops;
+ auto_vec<vec<tree>, 2> vec_defs;
+
+ ops.safe_push (rhs1);
+ ops.safe_push (rhs2);
+ vect_get_slp_defs (ops, slp_node, &vec_defs, -1);
+ vec_oprnds1 = vec_defs.pop ();
+ vec_oprnds0 = vec_defs.pop ();
+ }
+ else
+ {
+ vec_rhs1 = vect_get_vec_def_for_operand (rhs1, stmt, NULL);
+ vec_rhs2 = vect_get_vec_def_for_operand (rhs2, stmt, NULL);
+ }
+ }
+ else
+ {
+ vec_rhs1 = vect_get_vec_def_for_stmt_copy (dts[0],
+ vec_oprnds0.pop ());
+ vec_rhs2 = vect_get_vec_def_for_stmt_copy (dts[1],
+ vec_oprnds1.pop ());
+ }
+
+ if (!slp_node)
+ {
+ vec_oprnds0.quick_push (vec_rhs1);
+ vec_oprnds1.quick_push (vec_rhs2);
+ }
+
+ /* Arguments are ready. Create the new vector stmt. */
+ FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_rhs1)
+ {
+ vec_rhs2 = vec_oprnds1[i];
+
+ new_temp = make_ssa_name (mask);
+ new_stmt = gimple_build_assign (new_temp, code, vec_rhs1, vec_rhs2);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (slp_node)
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ }
+
+ if (slp_node)
+ continue;
+
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+
+ prev_stmt_info = vinfo_for_stmt (new_stmt);
+ }
+
+ vec_oprnds0.release ();
+ vec_oprnds1.release ();
+
+ return true;
+}
/* Make sure the statement is vectorizable. */
@@ -7619,7 +7818,8 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
|| vectorizable_call (stmt, NULL, NULL, node)
|| vectorizable_store (stmt, NULL, NULL, node)
|| vectorizable_reduction (stmt, NULL, NULL, node)
- || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node));
+ || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node)
+ || vectorizable_comparison (stmt, NULL, NULL, NULL, node));
else
{
if (bb_vinfo)
@@ -7631,7 +7831,8 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node)
|| vectorizable_load (stmt, NULL, NULL, node, NULL)
|| vectorizable_call (stmt, NULL, NULL, node)
|| vectorizable_store (stmt, NULL, NULL, node)
- || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node));
+ || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node)
+ || vectorizable_comparison (stmt, NULL, NULL, NULL, node));
}
if (!ok)
@@ -7747,6 +7948,11 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
gcc_assert (done);
break;
+ case comparison_vec_info_type:
+ done = vectorizable_comparison (stmt, gsi, &vec_stmt, NULL, slp_node);
+ gcc_assert (done);
+ break;
+
case call_vec_info_type:
done = vectorizable_call (stmt, gsi, &vec_stmt, slp_node);
stmt = gsi_stmt (*gsi);
@@ -8080,6 +8286,23 @@ get_vectype_for_scalar_type (tree scalar_type)
return vectype;
}
+/* Function get_mask_type_for_scalar_type.
+
+ Returns the mask type corresponding to a result of comparison
+ of vectors of specified SCALAR_TYPE as supported by target. */
+
+tree
+get_mask_type_for_scalar_type (tree scalar_type)
+{
+ tree vectype = get_vectype_for_scalar_type (scalar_type);
+
+ if (!vectype)
+ return NULL;
+
+ return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (vectype),
+ current_vector_size);
+}
+
/* Function get_same_sized_vectype
Returns a vector type corresponding to SCALAR_TYPE of size
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 970be31f054..9bf7949e081 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see
enum vect_var_kind {
vect_simple_var,
vect_pointer_var,
- vect_scalar_var
+ vect_scalar_var,
+ vect_mask_var
};
/* Defines type of operation. */
@@ -420,6 +421,7 @@ enum stmt_vec_info_type {
call_simd_clone_vec_info_type,
assignment_vec_info_type,
condition_vec_info_type,
+ comparison_vec_info_type,
reduc_vec_info_type,
induc_vec_info_type,
type_promotion_vec_info_type,
@@ -944,6 +946,7 @@ extern bool vect_can_advance_ivs_p (loop_vec_info);
/* In tree-vect-stmts.c. */
extern unsigned int current_vector_size;
extern tree get_vectype_for_scalar_type (tree);
+extern tree get_mask_type_for_scalar_type (tree);
extern tree get_same_sized_vectype (tree, tree);
extern bool vect_is_simple_use (tree, vec_info *, gimple **,
enum vect_def_type *);
@@ -975,7 +978,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
extern void vect_finish_stmt_generation (gimple *, gimple *,
gimple_stmt_iterator *);
extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
-extern tree vect_get_vec_def_for_operand (tree, gimple *);
+extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
extern tree vect_init_vector (gimple *, tree, tree,
gimple_stmt_iterator *);
extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);
@@ -985,6 +988,8 @@ extern void vect_remove_stores (gimple *);
extern bool vect_analyze_stmt (gimple *, bool *, slp_tree);
extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *,
gimple **, tree, int, slp_tree);
+extern bool vectorizable_comparison (gimple *, gimple_stmt_iterator *,
+ gimple **, tree, int, slp_tree);
extern void vect_get_load_cost (struct data_reference *, int, bool,
unsigned int *, unsigned int *,
stmt_vector_for_cost *,
@@ -1075,6 +1080,7 @@ extern void vect_detect_hybrid_slp (loop_vec_info);
extern void vect_get_slp_defs (vec<tree> , slp_tree,
vec<vec<tree> > *, int);
extern bool vect_slp_bb (basic_block);
+extern gimple *vect_find_last_scalar_stmt_in_slp (slp_tree);
/* In tree-vect-patterns.c. */
/* Pattern recognition functions.
diff --git a/gcc/tree.c b/gcc/tree.c
index ff414f7a62d..50e1db019d3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1439,7 +1439,7 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
case BOOLEAN_TYPE:
/* Cache false or true. */
limit = 2;
- if (hwi < 2)
+ if (IN_RANGE (hwi, 0, 1))
ix = hwi;
break;
@@ -8072,7 +8072,7 @@ build_nonstandard_boolean_type (unsigned HOST_WIDE_INT precision)
type = make_node (BOOLEAN_TYPE);
TYPE_PRECISION (type) = precision;
- fixup_unsigned_type (type);
+ fixup_signed_type (type);
if (precision <= MAX_INT_CACHED_PREC)
nonstandard_boolean_type_cache[precision] = type;
diff --git a/gcc/tree.h b/gcc/tree.h
index e71eba43d50..1bb59f2ac8c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -927,7 +927,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
But, of course, the storage order must be preserved when the accesses
themselves are rewritten or transformed. */
#define REF_REVERSE_STORAGE_ORDER(NODE) \
- (TREE_CHECK2 (NODE, BIT_FIELD_REF, MEM_REF)->base.u.bits.saturating_flag)
+ (TREE_CHECK2 (NODE, BIT_FIELD_REF, MEM_REF)->base.default_def_flag)
/* These flags are available for each language front end to use internally. */
#define TREE_LANG_FLAG_0(NODE) \
@@ -4387,8 +4387,9 @@ reverse_storage_order_for_component_p (tree t)
{
case ARRAY_REF:
case COMPONENT_REF:
- /* ??? Fortran can take COMPONENT_REF of a void type. */
- return !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
+ /* ??? Fortran can take COMPONENT_REF of a VOID_TYPE. */
+ /* ??? UBSan can take COMPONENT_REF of a REFERENCE_TYPE. */
+ return AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
&& TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (t, 0)));
case BIT_FIELD_REF:
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index e4fb81bad0b..13ed8133857 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/ia64/crtbegin.S: Check HAVE_INITFINI_ARRAY_SUPPORT
+ value.
+ * config/ia64/crtend.S: Likewise.
+
2015-11-07 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
* config/visium/lib2funcs.c (__set_trampoline_parity): Use
diff --git a/libgcc/config/ia64/crtbegin.S b/libgcc/config/ia64/crtbegin.S
index ec8ed7b5bb3..477b383f112 100644
--- a/libgcc/config/ia64/crtbegin.S
+++ b/libgcc/config/ia64/crtbegin.S
@@ -61,7 +61,7 @@ __dso_handle:
.hidden __dso_handle
-#ifdef HAVE_INITFINI_ARRAY_SUPPORT
+#if HAVE_INITFINI_ARRAY_SUPPORT
.section .fini_array, "a"
data8 @fptr(__do_global_dtors_aux)
diff --git a/libgcc/config/ia64/crtend.S b/libgcc/config/ia64/crtend.S
index a1a559560d1..d9c65c0765d 100644
--- a/libgcc/config/ia64/crtend.S
+++ b/libgcc/config/ia64/crtend.S
@@ -39,7 +39,7 @@ __DTOR_END__:
__JCR_END__:
data8 0
-#ifdef HAVE_INITFINI_ARRAY_SUPPORT
+#if HAVE_INITFINI_ARRAY_SUPPORT
.global __do_global_ctors_aux
.hidden __do_global_ctors_aux
#else /* !HAVE_INITFINI_ARRAY_SUPPORT */
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index ab2a25a1133..08d467b1055 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,12 @@
+2015-11-09 Nathan Sidwell <nathan@codesourcery.com>
+
+ * testsuite/libgomp.oacc-c-c++-common/firstprivate-1.c: New.
+ * testsuite/libgomp.oacc-c-c++-common/routine-g-1.c: New.
+ * testsuite/libgomp.oacc-c-c++-common/routine-gwv-1.c: New.
+ * testsuite/libgomp.oacc-c-c++-common/routine-v-1.c: New.
+ * testsuite/libgomp.oacc-c-c++-common/routine-w-1.c: New.
+ * testsuite/libgomp.oacc-c-c++-common/routine-wv-1.c: New.
+
2015-11-06 Thomas Schwinge <thomas@codesourcery.com>
* testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c: XFAIL.
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-1.c
new file mode 100644
index 00000000000..7f5d3d37617
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-1.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+
+#include <openacc.h>
+
+int main ()
+{
+ int ok = 1;
+ int val = 2;
+ int ary[32];
+ int ondev = 0;
+
+ for (int i = 0; i < 32; i++)
+ ary[i] = ~0;
+
+#pragma acc parallel num_gangs (32) copy (ok) firstprivate (val) copy(ary, ondev)
+ {
+ ondev = acc_on_device (acc_device_not_host);
+#pragma acc loop gang(static:1)
+ for (unsigned i = 0; i < 32; i++)
+ {
+ if (val != 2)
+ ok = 0;
+ val += i;
+ ary[i] = val;
+ }
+ }
+
+ if (ondev)
+ {
+ if (!ok)
+ return 1;
+ if (val != 2)
+ return 1;
+
+ for (int i = 0; i < 32; i++)
+ if (ary[i] != 2 + i)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-g-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-g-1.c
new file mode 100644
index 00000000000..b1f238a7f18
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-g-1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2" */
+
+#include <stdio.h>
+
+#define N (32*32*32+17)
+
+#pragma acc routine gang
+void __attribute__ ((noinline)) gang (int ary[N])
+{
+#pragma acc loop gang
+ for (unsigned ix = 0; ix < N; ix++)
+ {
+ if (__builtin_acc_on_device (5))
+ {
+ int g = 0, w = 0, v = 0;
+
+ __asm__ volatile ("mov.u32 %0,%%ctaid.x;" : "=r" (g));
+ __asm__ volatile ("mov.u32 %0,%%tid.y;" : "=r" (w));
+ __asm__ volatile ("mov.u32 %0,%%tid.x;" : "=r" (v));
+ ary[ix] = (g << 16) | (w << 8) | v;
+ }
+ else
+ ary[ix] = ix;
+ }
+}
+
+int main ()
+{
+ int ary[N];
+ int ix;
+ int exit = 0;
+ int ondev = 0;
+
+ for (ix = 0; ix < N;ix++)
+ ary[ix] = -1;
+
+#pragma acc parallel num_gangs(32) vector_length(32) copy(ary) copy(ondev)
+ {
+ ondev = __builtin_acc_on_device (5);
+ gang (ary);
+ }
+
+ for (ix = 0; ix < N; ix++)
+ {
+ int expected = ix;
+ if(ondev)
+ {
+ int g = ix / ((N + 31) / 32);
+ int w = 0;
+ int v = 0;
+
+ expected = (g << 16) | (w << 8) | v;
+ }
+
+ if (ary[ix] != expected)
+ {
+ exit = 1;
+ printf ("ary[%d]=%x expected %x\n", ix, ary[ix], expected);
+ }
+ }
+
+ return exit;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-gwv-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-gwv-1.c
new file mode 100644
index 00000000000..5980747f137
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-gwv-1.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2" */
+
+#include <stdio.h>
+
+#define N (32*32*32+17)
+
+#pragma acc routine gang
+void __attribute__ ((noinline)) gang (int ary[N])
+{
+#pragma acc loop gang worker vector
+ for (unsigned ix = 0; ix < N; ix++)
+ {
+ if (__builtin_acc_on_device (5))
+ {
+ int g = 0, w = 0, v = 0;
+
+ __asm__ volatile ("mov.u32 %0,%%ctaid.x;" : "=r" (g));
+ __asm__ volatile ("mov.u32 %0,%%tid.y;" : "=r" (w));
+ __asm__ volatile ("mov.u32 %0,%%tid.x;" : "=r" (v));
+ ary[ix] = (g << 16) | (w << 8) | v;
+ }
+ else
+ ary[ix] = ix;
+ }
+}
+
+int main ()
+{
+ int ary[N];
+ int ix;
+ int exit = 0;
+ int ondev = 0;
+
+ for (ix = 0; ix < N;ix++)
+ ary[ix] = -1;
+
+#pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) copy(ary) copy(ondev)
+ {
+ ondev = __builtin_acc_on_device (5);
+ gang (ary);
+ }
+
+ for (ix = 0; ix < N; ix++)
+ {
+ int expected = ix;
+ if(ondev)
+ {
+ int chunk_size = (N + 32*32*32 - 1) / (32*32*32);
+
+ int g = ix / (chunk_size * 32 * 32);
+ int w = ix / 32 % 32;
+ int v = ix % 32;
+
+ expected = (g << 16) | (w << 8) | v;
+ }
+
+ if (ary[ix] != expected)
+ {
+ exit = 1;
+ printf ("ary[%d]=%x expected %x\n", ix, ary[ix], expected);
+ }
+ }
+
+ return exit;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-v-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-v-1.c
new file mode 100644
index 00000000000..29e0f9017a5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-v-1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2" */
+
+#include <stdio.h>
+
+#define N (32*32*32+17)
+
+#pragma acc routine vector
+void __attribute__ ((noinline)) vector (int ary[N])
+{
+#pragma acc loop vector
+ for (unsigned ix = 0; ix < N; ix++)
+ {
+ if (__builtin_acc_on_device (5))
+ {
+ int g = 0, w = 0, v = 0;
+
+ __asm__ volatile ("mov.u32 %0,%%ctaid.x;" : "=r" (g));
+ __asm__ volatile ("mov.u32 %0,%%tid.y;" : "=r" (w));
+ __asm__ volatile ("mov.u32 %0,%%tid.x;" : "=r" (v));
+ ary[ix] = (g << 16) | (w << 8) | v;
+ }
+ else
+ ary[ix] = ix;
+ }
+}
+
+int main ()
+{
+ int ary[N];
+ int ix;
+ int exit = 0;
+ int ondev = 0;
+
+ for (ix = 0; ix < N;ix++)
+ ary[ix] = -1;
+
+#pragma acc parallel vector_length(32) copy(ary) copy(ondev)
+ {
+ ondev = __builtin_acc_on_device (5);
+ vector (ary);
+ }
+
+ for (ix = 0; ix < N; ix++)
+ {
+ int expected = ix;
+ if(ondev)
+ {
+ int g = 0;
+ int w = 0;
+ int v = ix % 32;
+
+ expected = (g << 16) | (w << 8) | v;
+ }
+
+ if (ary[ix] != expected)
+ {
+ exit = 1;
+ printf ("ary[%d]=%x expected %x\n", ix, ary[ix], expected);
+ }
+ }
+
+ return exit;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-w-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-w-1.c
new file mode 100644
index 00000000000..95e717452c9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-w-1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2" */
+
+#include <stdio.h>
+
+#define N (32*32*32+17)
+
+#pragma acc routine worker
+void __attribute__ ((noinline)) worker (int ary[N])
+{
+#pragma acc loop worker
+ for (unsigned ix = 0; ix < N; ix++)
+ {
+ if (__builtin_acc_on_device (5))
+ {
+ int g = 0, w = 0, v = 0;
+
+ __asm__ volatile ("mov.u32 %0,%%ctaid.x;" : "=r" (g));
+ __asm__ volatile ("mov.u32 %0,%%tid.y;" : "=r" (w));
+ __asm__ volatile ("mov.u32 %0,%%tid.x;" : "=r" (v));
+ ary[ix] = (g << 16) | (w << 8) | v;
+ }
+ else
+ ary[ix] = ix;
+ }
+}
+
+int main ()
+{
+ int ary[N];
+ int ix;
+ int exit = 0;
+ int ondev = 0;
+
+ for (ix = 0; ix < N;ix++)
+ ary[ix] = -1;
+
+#pragma acc parallel num_workers(32) vector_length(32) copy(ary) copy(ondev)
+ {
+ ondev = __builtin_acc_on_device (5);
+ worker (ary);
+ }
+
+ for (ix = 0; ix < N; ix++)
+ {
+ int expected = ix;
+ if(ondev)
+ {
+ int g = 0;
+ int w = ix % 32;
+ int v = 0;
+
+ expected = (g << 16) | (w << 8) | v;
+ }
+
+ if (ary[ix] != expected)
+ {
+ exit = 1;
+ printf ("ary[%d]=%x expected %x\n", ix, ary[ix], expected);
+ }
+ }
+
+ return exit;
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-wv-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-wv-1.c
new file mode 100644
index 00000000000..3e8dcdeb317
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/routine-wv-1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2" */
+
+#include <stdio.h>
+
+#define N (32*32*32+17)
+
+#pragma acc routine worker
+void __attribute__ ((noinline)) worker (int ary[N])
+{
+#pragma acc loop worker vector
+ for (unsigned ix = 0; ix < N; ix++)
+ {
+ if (__builtin_acc_on_device (5))
+ {
+ int g = 0, w = 0, v = 0;
+
+ __asm__ volatile ("mov.u32 %0,%%ctaid.x;" : "=r" (g));
+ __asm__ volatile ("mov.u32 %0,%%tid.y;" : "=r" (w));
+ __asm__ volatile ("mov.u32 %0,%%tid.x;" : "=r" (v));
+ ary[ix] = (g << 16) | (w << 8) | v;
+ }
+ else
+ ary[ix] = ix;
+ }
+}
+
+int main ()
+{
+ int ary[N];
+ int ix;
+ int exit = 0;
+ int ondev = 0;
+
+ for (ix = 0; ix < N;ix++)
+ ary[ix] = -1;
+
+#pragma acc parallel num_workers(32) vector_length(32) copy(ary) copy(ondev)
+ {
+ ondev = __builtin_acc_on_device (5);
+ worker (ary);
+ }
+
+ for (ix = 0; ix < N; ix++)
+ {
+ int expected = ix;
+ if(ondev)
+ {
+ int g = 0;
+ int w = (ix / 32) % 32;
+ int v = ix % 32;
+
+ expected = (g << 16) | (w << 8) | v;
+ }
+
+ if (ary[ix] != expected)
+ {
+ exit = 1;
+ printf ("ary[%d]=%x expected %x\n", ix, ary[ix], expected);
+ }
+ }
+
+ return exit;
+}
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index 69492d813a4..0564345903b 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,3 +1,17 @@
+2015-11-09 Torvald Riegel <triegel@redhat.com>
+
+ * alloc_cpp.cc (_ZdlPvX, _ZdlPvXRKSt9nothrow_t, _ZGTtdlPvX,
+ _ZGTtdlPvXRKSt9nothrow_t, delsz_opnt): New.
+ * libitm.map: Add _ZGTtdlPvX and _ZGTtdlPvXRKSt9nothrow_t.
+ * libitm_i.h (gtm_alloc_action): Add free_fn_sz and sz. Add comments.
+ (gtm_thread::forget_allocations): New overload with size_t argument.
+ * alloc.c (gtm_thread::forget_allocation): Define new overload and
+ adapt existing one.
+ (gtm_thread::record_allocation): Adapt.
+ (gtm_thread::commit_allocations_1): Adapt.
+ (gtm_thread::commit_allocations_2): Adapt.
+ * testsuite/libitm.c++/newdelete.C: New.
+
2015-10-27 Daniel Jacobowitz <dan@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
Mark Shinwell <shinwell@codesourcery.com>
diff --git a/libitm/alloc.cc b/libitm/alloc.cc
index bb292da88dd..7b8786c5ec5 100644
--- a/libitm/alloc.cc
+++ b/libitm/alloc.cc
@@ -29,26 +29,38 @@ namespace GTM HIDDEN {
void
gtm_thread::record_allocation (void *ptr, void (*free_fn)(void *))
{
- uintptr_t iptr = (uintptr_t) ptr;
-
- gtm_alloc_action *a = this->alloc_actions.find(iptr);
- if (a == 0)
- a = this->alloc_actions.insert(iptr);
+ // We do not deallocate before outermost commit, so we should never have
+ // an existing log entry for a new allocation.
+ gtm_alloc_action *a = this->alloc_actions.insert((uintptr_t) ptr);
a->free_fn = free_fn;
+ a->free_fn_sz = 0;
a->allocated = true;
}
void
gtm_thread::forget_allocation (void *ptr, void (*free_fn)(void *))
{
- uintptr_t iptr = (uintptr_t) ptr;
-
- gtm_alloc_action *a = this->alloc_actions.find(iptr);
- if (a == 0)
- a = this->alloc_actions.insert(iptr);
-
+ // We do not deallocate before outermost commit, so we should never have
+ // an existing log entry for a deallocation at the same address. We may
+ // have an existing entry for a matching allocation, but this is handled
+ // correctly because both are complementary in that only one of these will
+ // cause an action at commit or abort.
+ gtm_alloc_action *a = this->alloc_actions.insert((uintptr_t) ptr);
a->free_fn = free_fn;
+ a->free_fn_sz = 0;
+ a->allocated = false;
+}
+
+void
+gtm_thread::forget_allocation (void *ptr, size_t sz,
+ void (*free_fn_sz)(void *, size_t))
+{
+ // Same as forget_allocation but with a size.
+ gtm_alloc_action *a = this->alloc_actions.insert((uintptr_t) ptr);
+ a->free_fn = 0;
+ a->free_fn_sz = free_fn_sz;
+ a->sz = sz;
a->allocated = false;
}
@@ -67,31 +79,27 @@ commit_allocations_2 (uintptr_t key, gtm_alloc_action *a, void *data)
if (cb_data->revert_p)
{
- // Roll back nested allocations.
+ // Roll back nested allocations, discard deallocations.
if (a->allocated)
- a->free_fn (ptr);
+ {
+ if (a->free_fn_sz != 0)
+ a->free_fn_sz (ptr, a->sz);
+ else
+ a->free_fn (ptr);
+ }
}
else
{
- if (a->allocated)
- {
- // Add nested allocations to parent transaction.
- gtm_alloc_action* a_parent = cb_data->parent->insert(key);
- *a_parent = *a;
- }
- else
- {
- // ??? We could eliminate a parent allocation that matches this
- // memory release, if we had support for removing all accesses
- // to this allocation from the transaction's undo and redo logs
- // (otherwise, the parent transaction's undo or redo might write to
- // data that is already shared again because of calling free()).
- // We don't have this support currently, and the benefit of this
- // optimization is unknown, so just add it to the parent.
- gtm_alloc_action* a_parent;
- a_parent = cb_data->parent->insert(key);
- *a_parent = *a;
- }
+ // Add allocations and deallocations to parent.
+ // ??? We could eliminate a (parent) allocation that matches this
+ // a deallocation, if we had support for removing all accesses
+ // to this allocation from the transaction's undo and redo logs
+ // (otherwise, the parent transaction's undo or redo might write to
+ // data that is already shared again because of calling free()).
+ // We don't have this support currently, and the benefit of this
+ // optimization is unknown, so just add it to the parent.
+ gtm_alloc_action* a_parent = cb_data->parent->insert(key);
+ *a_parent = *a;
}
}
@@ -99,10 +107,15 @@ static void
commit_allocations_1 (uintptr_t key, gtm_alloc_action *a, void *cb_data)
{
void *ptr = (void *)key;
- uintptr_t revert_p = (uintptr_t) cb_data;
+ bool revert_p = (bool) (uintptr_t) cb_data;
- if (a->allocated == revert_p)
- a->free_fn (ptr);
+ if (revert_p == a->allocated)
+ {
+ if (a->free_fn_sz != 0)
+ a->free_fn_sz (ptr, a->sz);
+ else
+ a->free_fn (ptr);
+ }
}
/* Permanently commit allocated memory during transaction.
diff --git a/libitm/alloc_cpp.cc b/libitm/alloc_cpp.cc
index 85146189ff2..13185a785d8 100644
--- a/libitm/alloc_cpp.cc
+++ b/libitm/alloc_cpp.cc
@@ -35,41 +35,50 @@ using namespace GTM;
#define _ZnwX S(_Znw,MANGLE_SIZE_T)
#define _ZnaX S(_Zna,MANGLE_SIZE_T)
+#define _ZdlPvX S(_ZdlPv,MANGLE_SIZE_T)
#define _ZnwXRKSt9nothrow_t S(S(_Znw,MANGLE_SIZE_T),RKSt9nothrow_t)
#define _ZnaXRKSt9nothrow_t S(S(_Zna,MANGLE_SIZE_T),RKSt9nothrow_t)
+#define _ZdlPvXRKSt9nothrow_t S(S(_ZdlPv,MANGLE_SIZE_T),RKSt9nothrow_t)
#define _ZGTtnwX S(_ZGTtnw,MANGLE_SIZE_T)
#define _ZGTtnaX S(_ZGTtna,MANGLE_SIZE_T)
+#define _ZGTtdlPvX S(_ZGTtdlPv,MANGLE_SIZE_T)
#define _ZGTtnwXRKSt9nothrow_t S(S(_ZGTtnw,MANGLE_SIZE_T),RKSt9nothrow_t)
#define _ZGTtnaXRKSt9nothrow_t S(S(_ZGTtna,MANGLE_SIZE_T),RKSt9nothrow_t)
+#define _ZGTtdlPvXRKSt9nothrow_t S(S(_ZGTtdlPv,MANGLE_SIZE_T),RKSt9nothrow_t)
/* Everything from libstdc++ is weak, to avoid requiring that library
to be linked into plain C applications using libitm.so. */
extern "C" {
-extern void *_ZnwX (size_t) __attribute__((weak));
-extern void _ZdlPv (void *) __attribute__((weak));
-extern void *_ZnaX (size_t) __attribute__((weak));
-extern void _ZdaPv (void *) __attribute__((weak));
+extern void *_ZnwX (size_t) __attribute__((weak));
+extern void _ZdlPv (void *) __attribute__((weak));
+extern void _ZdlPvX (void *, size_t) __attribute__((weak));
+extern void *_ZnaX (size_t) __attribute__((weak));
+extern void _ZdaPv (void *) __attribute__((weak));
typedef const struct nothrow_t { } *c_nothrow_p;
extern void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak));
extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
+extern void _ZdlPvXRKSt9nothrow_t
+(void *, size_t, c_nothrow_p) __attribute__((weak));
extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak));
extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
#if !defined (HAVE_ELF_STYLE_WEAKREF)
-void *_ZnwX (size_t) { return NULL; }
-void _ZdlPv (void *) { return; }
-void *_ZnaX (size_t) { return NULL; }
-void _ZdaPv (void *) { return; }
-
-void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
-void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
-void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
-void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
+void *_ZnwX (size_t) { return NULL; }
+void _ZdlPv (void *) { return; }
+void _ZdlPvX (void *, size_t) { return; }
+void *_ZnaX (size_t) { return NULL; }
+void _ZdaPv (void *) { return; }
+
+void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
+void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
+void _ZdlPvXRKSt9nothrow_t (void *, size_t, c_nothrow_p) { return; }
+void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
+void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
#endif /* HAVE_ELF_STYLE_WEAKREF */
/* Wrap the delete nothrow symbols for usage with a single argument.
@@ -89,6 +98,12 @@ del_opvnt (void *ptr)
_ZdaPvRKSt9nothrow_t (ptr, NULL);
}
+static void
+delsz_opnt (void *ptr, size_t sz)
+{
+ _ZdlPvXRKSt9nothrow_t (ptr, sz, NULL);
+}
+
/* Wrap: operator new (std::size_t sz) */
void *
_ZGTtnwX (size_t sz)
@@ -161,4 +176,20 @@ _ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED)
gtm_thr()->forget_allocation (ptr, del_opvnt);
}
+/* Wrap: operator delete(void* ptr, std::size_t sz) */
+void
+_ZGTtdlPvX (void *ptr, size_t sz)
+{
+ if (ptr)
+ gtm_thr()->forget_allocation (ptr, sz, _ZdlPvX);
+}
+
+/* Wrap: operator delete (void *ptr, std::size_t sz, const std::nothrow_t&) */
+void
+_ZGTtdlPvXRKSt9nothrow_t (void *ptr, size_t sz, c_nothrow_p nt UNUSED)
+{
+ if (ptr)
+ gtm_thr()->forget_allocation (ptr, sz, delsz_opnt);
+}
+
} // extern "C"
diff --git a/libitm/libitm.map b/libitm/libitm.map
index 21bcfdfcfab..ac371dedee6 100644
--- a/libitm/libitm.map
+++ b/libitm/libitm.map
@@ -182,3 +182,8 @@ LIBITM_1.0 {
local:
*;
};
+LIBITM_1.1 {
+ global:
+ _ZGTtdlPv?;
+ _ZGTtdlPv?RKSt9nothrow_t;
+} LIBITM_1.0;
diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h
index 0eda01bacc5..bf8d4d1897e 100644
--- a/libitm/libitm_i.h
+++ b/libitm/libitm_i.h
@@ -97,11 +97,25 @@ enum gtm_restart_reason
namespace GTM HIDDEN {
+// A log of (de)allocation actions. We defer handling of some actions until
+// a commit of the outermost transaction. We also rely on potentially having
+// both an allocation and a deallocation for the same piece of memory in the
+// log; the order in which such entries are processed does not matter because
+// the actions are not in conflict (see below).
// This type is private to alloc.c, but needs to be defined so that
// the template used inside gtm_thread can instantiate.
struct gtm_alloc_action
{
- void (*free_fn)(void *);
+ // Iff free_fn_sz is nonzero, it must be used instead of free_fn.
+ union
+ {
+ void (*free_fn)(void *);
+ void (*free_fn_sz)(void *, size_t);
+ };
+ size_t sz;
+ // If true, this is an allocation; we discard the log entry on outermost
+ // commit, and deallocate on abort. If false, this is a deallocation and
+ // we deallocate on outermost commit and discard the log entry on abort.
bool allocated;
};
@@ -269,6 +283,7 @@ struct gtm_thread
void commit_allocations (bool, aa_tree<uintptr_t, gtm_alloc_action>*);
void record_allocation (void *, void (*)(void *));
void forget_allocation (void *, void (*)(void *));
+ void forget_allocation (void *, size_t, void (*)(void *, size_t));
void drop_references_allocations (const void *ptr)
{
this->alloc_actions.erase((uintptr_t) ptr);
diff --git a/libitm/testsuite/libitm.c++/newdelete.C b/libitm/testsuite/libitm.c++/newdelete.C
new file mode 100644
index 00000000000..10eba4f66d9
--- /dev/null
+++ b/libitm/testsuite/libitm.c++/newdelete.C
@@ -0,0 +1,12 @@
+// { dg-do run }
+
+int main ()
+{
+ atomic_commit {
+ int* data = new int;
+ delete data;
+ data = new int[10];
+ delete[] data;
+ }
+ return 0;
+}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9b50f1cd17e..540041d63dd 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,18 @@
+2015-11-10 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/functional_hash.h: Fix grammar in comment.
+
+2015-11-09 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_algo.h
+ (partial_sort_copy): Instantiate std::iterator_traits only if concept
+ checks.
+ (lower_bound): Likewise.
+ (upper_bound): Likewise.
+ (equal_range): Likewise.
+ (binary_search): Likewise.
+ * include/bits/stl_heap.h (pop_heap): Likewise.
+
2015-11-06 Kai Tietz <ktietz70@googlemail.com>
* testsuite/26_numerics/complex/requirements/constexpr.cc
diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h
index 88937bdc4af..bc192c8dcfb 100644
--- a/libstdc++-v3/include/bits/functional_hash.h
+++ b/libstdc++-v3/include/bits/functional_hash.h
@@ -239,9 +239,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// @} group hashes
- // Hint about performance of hash functor. If not fast the hash based
+ // Hint about performance of hash functor. If not fast the hash-based
// containers will cache the hash code.
- // Default behavior is to consider that hasher are fast unless specified
+ // Default behavior is to consider that hashers are fast unless specified
// otherwise.
template<typename _Hash>
struct __is_fast_hash : public std::true_type
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index f7f3e84dc82..e0c51dfa90b 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -56,7 +56,7 @@
#ifndef _STL_ALGO_H
#define _STL_ALGO_H 1
-#include <cstdlib> // for rand
+#include <cstdlib> // for rand
#include <bits/algorithmfwd.h>
#include <bits/stl_heap.h>
#include <bits/stl_tempbuf.h> // for _Temporary_buffer
@@ -306,7 +306,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
while (__unary_pred(--__backTrack))
{
if (--__remainder == 0)
- return (__first - __count); // Success
+ return (__first - __count); // Success
}
__remainder = __count + 1 - (__first - __backTrack);
}
@@ -314,7 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _ForwardIterator, typename _Integer,
- typename _UnaryPredicate>
+ typename _UnaryPredicate>
_ForwardIterator
__search_n(_ForwardIterator __first, _ForwardIterator __last,
_Integer __count,
@@ -859,15 +859,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__first = std::__find_if(__first, __last, __pred);
if (__first == __last)
- return __first;
+ return __first;
_ForwardIterator __result = __first;
++__first;
for (; __first != __last; ++__first)
- if (!__pred(__first))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
+ if (!__pred(__first))
+ {
+ *__result = _GLIBCXX_MOVE(*__first);
+ ++__result;
+ }
return __result;
}
@@ -1020,7 +1020,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator, typename _BinaryPredicate>
inline _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last,
- _BinaryPredicate __binary_pred)
+ _BinaryPredicate __binary_pred)
{
// concept requirements
__glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
@@ -1466,7 +1466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator, typename _OutputIterator>
inline _OutputIterator
rotate_copy(_ForwardIterator __first, _ForwardIterator __middle,
- _ForwardIterator __last, _OutputIterator __result)
+ _ForwardIterator __last, _OutputIterator __result)
{
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -1476,7 +1476,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__middle, __last);
return std::copy(__first, __middle,
- std::copy(__middle, __last, __result));
+ std::copy(__middle, __last, __result));
}
/// This is a helper function...
@@ -1735,19 +1735,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator __result_first,
_RandomAccessIterator __result_last)
{
+#ifdef _GLIBCXX_CONCEPT_CHECKS
typedef typename iterator_traits<_InputIterator>::value_type
_InputValueType;
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_OutputValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
+#endif
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_function_requires(_ConvertibleConcept<_InputValueType,
_OutputValueType>)
__glibcxx_function_requires(_LessThanOpConcept<_InputValueType,
- _OutputValueType>)
+ _OutputValueType>)
__glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);
@@ -1786,12 +1786,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator __result_last,
_Compare __comp)
{
+#ifdef _GLIBCXX_CONCEPT_CHECKS
typedef typename iterator_traits<_InputIterator>::value_type
_InputValueType;
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_OutputValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
+#endif
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
@@ -2020,13 +2020,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
lower_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType, _Tp>)
+ typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
__glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
@@ -2078,12 +2075,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
upper_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
__glibcxx_requires_irreflexive2(__first, __last);
@@ -2111,13 +2106,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
upper_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _Tp, _ValueType>)
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
__glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
@@ -2186,13 +2178,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
equal_range(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
__glibcxx_requires_irreflexive2(__first, __last);
@@ -2224,15 +2215,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
equal_range(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType, _Tp>)
+ typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _Tp, _ValueType>)
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
__glibcxx_requires_partitioned_upper_pred(__first, __last,
@@ -2259,14 +2247,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator, typename _Tp>
bool
binary_search(_ForwardIterator __first, _ForwardIterator __last,
- const _Tp& __val)
+ const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
__glibcxx_requires_irreflexive2(__first, __last);
@@ -2295,15 +2281,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator, typename _Tp, typename _Compare>
bool
binary_search(_ForwardIterator __first, _ForwardIterator __last,
- const _Tp& __val, _Compare __comp)
+ const _Tp& __val, _Compare __comp)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _Tp, _ValueType>)
+ _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
__glibcxx_requires_partitioned_upper_pred(__first, __last,
@@ -2434,7 +2417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Pointer, typename _Compare>
void
__merge_adaptive(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
+ _BidirectionalIterator __middle,
_BidirectionalIterator __last,
_Distance __len1, _Distance __len2,
_Pointer __buffer, _Distance __buffer_size,
@@ -2495,7 +2478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Compare>
void
__merge_without_buffer(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
+ _BidirectionalIterator __middle,
_BidirectionalIterator __last,
_Distance __len1, _Distance __len2,
_Compare __comp)
@@ -2550,9 +2533,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Compare __comp)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type
- _ValueType;
+ _ValueType;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type
- _DistanceType;
+ _DistanceType;
if (__first == __middle || __middle == __last)
return;
@@ -2725,7 +2708,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
__merge_sort_with_buffer(_RandomAccessIterator __first,
_RandomAccessIterator __last,
- _Pointer __buffer, _Compare __comp)
+ _Pointer __buffer, _Compare __comp)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
_Distance;
@@ -2752,8 +2735,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
__stable_sort_adaptive(_RandomAccessIterator __first,
_RandomAccessIterator __last,
- _Pointer __buffer, _Distance __buffer_size,
- _Compare __comp)
+ _Pointer __buffer, _Distance __buffer_size,
+ _Compare __comp)
{
const _Distance __len = (__last - __first + 1) / 2;
const _RandomAccessIterator __middle = __first + __len;
@@ -3326,7 +3309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
return __b < __a ? pair<const _Tp&, const _Tp&>(__b, __a)
- : pair<const _Tp&, const _Tp&>(__a, __b);
+ : pair<const _Tp&, const _Tp&>(__a, __b);
}
/**
@@ -3344,7 +3327,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
minmax(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a)
- : pair<const _Tp&, const _Tp&>(__a, __b);
+ : pair<const _Tp&, const _Tp&>(__a, __b);
}
template<typename _ForwardIterator, typename _Compare>
@@ -4151,7 +4134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* consecutive elements for which the predicate returns true.
*/
template<typename _ForwardIterator, typename _Integer, typename _Tp,
- typename _BinaryPredicate>
+ typename _BinaryPredicate>
inline _ForwardIterator
search_n(_ForwardIterator __first, _ForwardIterator __last,
_Integer __count, const _Tp& __val,
@@ -4193,8 +4176,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- // "the type returned by a _UnaryOperation"
- __typeof__(__unary_op(*__first))>)
+ // "the type returned by a _UnaryOperation"
+ __typeof__(__unary_op(*__first))>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first, (void)++__result)
@@ -4232,8 +4215,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- // "the type returned by a _BinaryOperation"
- __typeof__(__binary_op(*__first1,*__first2))>)
+ // "the type returned by a _BinaryOperation"
+ __typeof__(__binary_op(*__first1,*__first2))>)
__glibcxx_requires_valid_range(__first1, __last1);
for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result)
@@ -4355,8 +4338,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
{
// concept requirements
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- // "the type returned by a _Generator"
- __typeof__(__gen())>)
+ // "the type returned by a _Generator"
+ __typeof__(__gen())>)
for (__decltype(__n + 0) __niter = __n;
__niter > 0; --__niter, ++__first)
diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h
index e13b6bed9ae..bbca322acd4 100644
--- a/libstdc++-v3/include/bits/stl_heap.h
+++ b/libstdc++-v3/include/bits/stl_heap.h
@@ -264,13 +264,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_non_empty_range(__first, __last);
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);