aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgfunck <gfunck@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-19 02:45:42 +0000
committergfunck <gfunck@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-19 02:45:42 +0000
commita2036660d18e8afb820656836e361031b814d709 (patch)
tree5617f80c01ed23001d556da7f693eedc5ce21c70
parent9f0cee084e7e56462f92561a5c02bdd3664a3484 (diff)
parenta050099a416f013bda35832b878d9a57b0cbb231 (diff)
Merge trunk version 235033 into gupc branch.gupc-6-branchpoint
This trunk version is the origin of the GCC 6 branch. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gupc@235183 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog11
-rw-r--r--MAINTAINERS1
-rw-r--r--Makefile.in5
-rw-r--r--Makefile.tpl5
-rw-r--r--contrib/ChangeLog5
-rwxr-xr-xcontrib/check_GNU_style.sh5
-rw-r--r--gcc/ChangeLog311
-rw-r--r--gcc/ChangeLog.upc8
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/c-family/ChangeLog12
-rw-r--r--gcc/c-family/c-common.c14
-rw-r--r--gcc/c-family/c-indentation.c9
-rw-r--r--gcc/c/ChangeLog48
-rw-r--r--gcc/c/c-parser.c355
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c51
-rw-r--r--gcc/common/config/aarch64/aarch64-common.c116
-rw-r--r--gcc/config.gcc14
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def36
-rw-r--r--gcc/config/aarch64/aarch64-protos.h25
-rw-r--r--gcc/config/aarch64/aarch64.c87
-rw-r--r--gcc/config/aarch64/aarch64.h2
-rw-r--r--gcc/config/aarch64/driver-aarch64.c192
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c41
-rw-r--r--gcc/config/i386/i386.md18
-rw-r--r--gcc/config/i386/sse.md15
-rw-r--r--gcc/config/nvptx/nvptx.opt2
-rw-r--r--gcc/config/rs6000/rs6000.c34
-rw-r--r--gcc/config/rs6000/rs6000.md8
-rw-r--r--gcc/config/sparc/sparc.c17
-rw-r--r--gcc/cp/ChangeLog168
-rw-r--r--gcc/cp/class.c13
-rw-r--r--gcc/cp/constexpr.c114
-rw-r--r--gcc/cp/cp-gimplify.c12
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c72
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/mangle.c9
-rw-r--r--gcc/cp/parser.c288
-rw-r--r--gcc/cp/pt.c52
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/tree.c8
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/cp/typeck2.c11
-rw-r--r--gcc/doc/extend.texi10
-rw-r--r--gcc/doc/invoke.texi2
-rw-r--r--gcc/explow.c36
-rw-r--r--gcc/fortran/ChangeLog12
-rw-r--r--gcc/fortran/gfortran.texi14
-rw-r--r--gcc/fortran/intrinsic.texi10
-rw-r--r--gcc/gimplify.c6
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/graphite-isl-ast-to-gimple.c2
-rw-r--r--gcc/ipa-polymorphic-call.c21
-rw-r--r--gcc/ipa-pure-const.c17
-rw-r--r--gcc/ipa-utils.h1
-rw-r--r--gcc/lra-spills.c7
-rw-r--r--gcc/omp-low.c1678
-rw-r--r--gcc/omp-simd-clone.c1654
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/simplify-rtx.c18
-rw-r--r--gcc/testsuite/ChangeLog215
-rw-r--r--gcc/testsuite/c-c++-common/Wmisleading-indentation-4.c11
-rw-r--r--gcc/testsuite/c-c++-common/Wparentheses-1.c39
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c69
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c41
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c174
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c338
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c452
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c338
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c452
-rw-r--r--gcc/testsuite/c-c++-common/pr70651.c9
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag20.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto47.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist10.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template9.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum_base3.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-array2.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr70528.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/pr70571.C10
-rw-r--r--gcc/testsuite/g++.dg/init/pr70501.C11
-rw-r--r--gcc/testsuite/g++.dg/opt/pr70641.C10
-rw-r--r--gcc/testsuite/g++.dg/opt/ptrmem7.C31
-rw-r--r--gcc/testsuite/g++.dg/parse/pr68722.C9
-rw-r--r--gcc/testsuite/g++.dg/parse/pr70635.C25
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-expr10.C8
-rw-r--r--gcc/testsuite/g++.dg/template/pr70610-2.C21
-rw-r--r--gcc/testsuite/g++.dg/template/pr70610-3.C21
-rw-r--r--gcc/testsuite/g++.dg/template/pr70610-4.C19
-rw-r--r--gcc/testsuite/g++.dg/template/pr70610.C21
-rw-r--r--gcc/testsuite/g++.dg/torture/pr70029.C12
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr70633.c12
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr70602.c23
-rw-r--r--gcc/testsuite/gcc.dg/Wparentheses-12.c135
-rw-r--r--gcc/testsuite/gcc.dg/Wparentheses-13.c67
-rw-r--r--gcc/testsuite/gcc.dg/bitfld-22.c18
-rw-r--r--gcc/testsuite/gcc.dg/graphite/pr68756.c26
-rw-r--r--gcc/testsuite/gcc.dg/ifcvt-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr10474.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr70623-2.c41
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr70623.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr70628.c46
-rw-r--r--gcc/testsuite/gcc.dg/vect/O3-pr70130.c94
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/target_attr_15.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-6.c276
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-kunpckdq-2.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-kunpckwd-2.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-kunpckbw-2.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/pr46470.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70596.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70662.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-1.c147
-rw-r--r--gcc/testsuite/gcc.target/powerpc/float128-2.c226
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr70640.c11
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr70669.c22
-rw-r--r--gcc/testsuite/lib/target-supports.exp6
-rw-r--r--gcc/tree-pretty-print.c102
-rw-r--r--gcc/tree-scalar-evolution.c5
-rw-r--r--gcc/tree-sra.c5
-rw-r--r--gcc/tree-ssa-live.c18
-rw-r--r--gcc/tree-ssa-loop-ivopts.c6
-rw-r--r--gcc/tree-ssa-loop-niter.c9
-rw-r--r--gcc/tree-ssa-loop-unswitch.c4
-rw-r--r--gcc/tree-ssa-pre.c97
-rw-r--r--gcc/tree-vect-data-refs.c17
-rw-r--r--gcc/tree-vect-loop.c2
-rw-r--r--gcc/tree.c4
-rw-r--r--libcpp/ChangeLog7
-rw-r--r--libcpp/directives.c6
-rw-r--r--libgcc/ChangeLog8
-rw-r--r--libgcc/configure22
-rw-r--r--libgcc/configure.ac18
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/go/crypto/dsa/dsa.go4
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa.go11
-rw-r--r--libgo/go/crypto/rsa/rsa.go5
-rw-r--r--libgo/go/go/build/deps_test.go6
-rw-r--r--libgo/go/internal/syscall/windows/registry/syscall.go2
-rw-r--r--libgo/go/internal/syscall/windows/registry/zsyscall_windows.go5
-rw-r--r--libgo/go/internal/syscall/windows/syscall_windows.go2
-rw-r--r--libgo/go/internal/syscall/windows/sysdll/sysdll.go28
-rw-r--r--libgo/go/internal/syscall/windows/zsyscall_windows.go5
-rw-r--r--libgo/go/reflect/all_test.go6
-rw-r--r--libgo/go/reflect/value.go8
-rw-r--r--libgo/go/runtime/export_windows_test.go4
-rw-r--r--libgomp/ChangeLog69
-rw-r--r--libgomp/libgomp.h2
-rw-r--r--libgomp/libgomp_g.h7
-rw-r--r--libgomp/target.c92
-rw-r--r--libgomp/task.c2
-rw-r--r--libgomp/testsuite/libgomp.c/target-25.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gang-np-1.c45
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gv-np-1.c30
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gw-np-1.c30
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-1.c28
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-2.c34
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-3.c33
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-4.c55
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-1.c43
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-2.c41
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-worker-p-1.c43
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-1.c41
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-2.c45
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-3.c38
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c4
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-1.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-2.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-7.c351
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/non-scalar-data.f908
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/pr70643.f9051
-rw-r--r--libstdc++-v3/ChangeLog45
-rw-r--r--libstdc++-v3/include/bits/specfun.h846
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/rotate/moveable2.cc3
183 files changed, 8758 insertions, 3125 deletions
diff --git a/ChangeLog b/ChangeLog
index b745e68b394..a82e275ab62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2016-04-13 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR bootstrap/70173
+ * Makefile.tpl (local-distclean): Delete the libcc1, gnattools,
+ and gotools directories. Delete the stage_final file.
+ * Makefile.in: Regenerate.
+
+2016-04-12 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
2016-04-09 Steven G. Kargl <kargl@gcc.gnu.org>
* MAINTAINERS (Fortran maintainer): Remove myself.
diff --git a/MAINTAINERS b/MAINTAINERS
index 88d78e7b7df..a9dec344e59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -606,6 +606,7 @@ Joost VandeVondele <joost.vandevondele@mat.ethz.ch>
Andre Vehreschild <vehre@gmx.de>
Alex Velenko <alex.velenko@arm.com>
Ilya Verbin <iverbin@gmail.com>
+Andre Vieira <andre.simoesdiasvieira@arm.com>
Kugan Vivekanandarajah <kuganv@linaro.org>
Ville Voutilainen <ville.voutilainen@gmail.com>
Tom de Vries <tom@codesourcery.com>
diff --git a/Makefile.in b/Makefile.in
index 244e0fa4b1f..691371e988c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2344,7 +2344,7 @@ local-clean:
local-distclean:
-rm -f Makefile config.status config.cache mh-frag mt-frag
- -rm -f maybedep.tmp serdep.tmp
+ -rm -f maybedep.tmp serdep.tmp stage_final
-if [ "$(TARGET_SUBDIR)" != "." ]; then \
rm -rf $(TARGET_SUBDIR); \
else true; fi
@@ -2356,7 +2356,8 @@ local-distclean:
-rm -f texinfo/doc/Makefile texinfo/po/POTFILES
-rmdir texinfo/doc texinfo/info texinfo/intl texinfo/lib 2>/dev/null
-rmdir texinfo/makeinfo texinfo/po texinfo/util 2>/dev/null
- -rmdir fastjar gcc libiberty texinfo zlib 2>/dev/null
+ -rmdir fastjar gcc gnattools gotools libcc1 libiberty 2>/dev/null
+ -rmdir texinfo zlib 2>/dev/null
-find . -name config.cache -exec rm -f {} \; \; 2>/dev/null
local-maintainer-clean:
diff --git a/Makefile.tpl b/Makefile.tpl
index 53cc2b4d8cd..1abca0b9418 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -821,7 +821,7 @@ local-clean:
local-distclean:
-rm -f Makefile config.status config.cache mh-frag mt-frag
- -rm -f maybedep.tmp serdep.tmp
+ -rm -f maybedep.tmp serdep.tmp stage_final
-if [ "$(TARGET_SUBDIR)" != "." ]; then \
rm -rf $(TARGET_SUBDIR); \
else true; fi
@@ -833,7 +833,8 @@ local-distclean:
-rm -f texinfo/doc/Makefile texinfo/po/POTFILES
-rmdir texinfo/doc texinfo/info texinfo/intl texinfo/lib 2>/dev/null
-rmdir texinfo/makeinfo texinfo/po texinfo/util 2>/dev/null
- -rmdir fastjar gcc libiberty texinfo zlib 2>/dev/null
+ -rmdir fastjar gcc gnattools gotools libcc1 libiberty 2>/dev/null
+ -rmdir texinfo zlib 2>/dev/null
-find . -name config.cache -exec rm -f {} \; \; 2>/dev/null
local-maintainer-clean:
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 54f9d5e72b2..56f2fec809f 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,8 @@
+2016-04-13 Martin Sebor <msebor@redhat.com>
+
+ * check_GNU_style.sh: Avoid false posivies in trailing operator
+ checks.
+
2016-03-07 Martin Sebor <msebor@redhat.com>
* check_GNU_style.sh (color): New global variable.
diff --git a/contrib/check_GNU_style.sh b/contrib/check_GNU_style.sh
index fbf6cb2465d..a7478f8f573 100755
--- a/contrib/check_GNU_style.sh
+++ b/contrib/check_GNU_style.sh
@@ -240,6 +240,7 @@ g 'There should be no space before closing parenthesis.' \
g 'Braces should be on a separate line.' \
'(\)|else)[[:blank:]]*{'
-# Does this apply to definition of aggregate objects?
-g 'Trailing operator.' \
+# Does this apply to definitions of aggregate objects?
+ag 'Trailing operator.' \
+ '^[1-9][0-9]*:\+[[:space:]]' \
'(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$'
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8d9a94d61f3..a73fa882e9e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,314 @@
+2016-04-15 Jason Merrill <jason@redhat.com>
+ Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70594
+ * constexpr.c (constexpr_call_table): Preserve in GC.
+ (struct fundef_copy, struct fundef_copies_table_t): Delete.
+ (fundef_copies_table): Preserve in GC. Change to pointer to
+ tree->tree hash.
+ (maybe_initialize_fundef_copies_table): Adjust.
+ (get_fundef_copy): Return a TREE_LIST. Use non-inserting search.
+ (save_fundef_copy): Adjust for a TREE_LIST.
+ (cxx_eval_call_expression): Adjust for a fundef_copy TREE_LIST.
+ (fini_constexpr): New.
+ * cp-tree.h (fini_constexpr): Declare.
+ * decl2.c (c_parse_final_cleanups): Call fini_constexpr.
+
+2016-04-15 Alexander Monakov <amonakov@ispras.ru>
+
+ * config/nvptx/nvptx.opt (moptimize): Add a period at end of help text.
+
+2016-04-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * doc/invoke.texi (ARM Options): Add note on deprecation of pre-ARMv4T
+ architecture revisions.
+
+2016-04-15 Bernd Schmidt <bschmidt@redhat.com>
+
+ * config/i386/i386-protos.h (ix86_using_red_zone): Declare.
+ * config/i386/i386.c (ix86_using_red_zone): No longer static.
+ * config/i386/i386.md (stack decrement to push peepholes): Guard
+ with !x86_using_red_zone ().
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70675
+ * tree-pretty-print.c (do_niy): Add FLAGS argument, pass it down
+ to dump_generic_node.
+ (NIY): Pass also flags to do_niy.
+
+2016-04-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (simd_clone_struct_alloc, simd_clone_struct_copy)
+ (simd_clone_vector_of_formal_parm_types)
+ (simd_clone_clauses_extract, simd_clone_compute_base_data_type)
+ (simd_clone_mangle, simd_clone_create)
+ (simd_clone_adjust_return_type, create_tmp_simd_array)
+ (simd_clone_adjust_argument_types, simd_clone_init_simd_arrays)
+ (struct modify_stmt_info, ipa_simd_modify_stmt_ops)
+ (ipa_simd_modify_function_body, simd_clone_linear_addend)
+ (simd_clone_adjust, expand_simd_clones, ipa_omp_simd_clone)
+ (pass_data_omp_simd_clone, class pass_omp_simd_clone)
+ (pass_omp_simd_clone::gate, make_pass_omp_simd_clone): Move
+ into...
+ * omp-simd-clone.c: ... this new file.
+ (simd_clone_vector_of_formal_parm_types): Make it static.
+ * Makefile.in (OBJS): Add omp-simd-clone.o.
+
+2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/70662
+ * config/i386/sse.md: Use proper memory operand
+ modifiers.
+
+
+2016-04-15 Richard Biener <rguenther@suse.de>
+ Alan Modra <amodra@gmail.com>
+
+ PR tree-optimization/70130
+ * tree-vect-data-refs.c (vect_supportable_dr_alignment): Detect
+ when alignment stays not the same and no not use the realign
+ scheme then.
+
+2016-04-14 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70669
+ * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Add
+ direct move handlers for KFmode. Change TFmode handlers test from
+ FLOAT128_IEEE_P to FLOAT128_VECTOR_P.
+
+2016-04-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70594
+ * ipa-utils.h (polymorphic_ctor_dtor_p): New prototype.
+ * ipa-polymorphic-call.c (polymorphic_ctor_dtor_p): New function.
+ (inlined_polymorphic_ctor_dtor_block_p): Use it.
+ * tree-ssa-live.c (remove_unused_scope_block_p): When
+ in_ctor_dtor_block, avoid discarding not just BLOCKs with
+ BLOCK_ABSTRACT_ORIGIN being FUNCTION_DECL, but even when
+ block_ultimate_origin is FUNCTION_DECL.
+ (remove_unused_locals): If current_function_decl is
+ polymorphic_ctor_dtor_p, pass initial true to
+ remove_unused_scope_block_p' is_ctor_dtor_block.
+
+2016-04-14 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * doc/extend.texi (Variable Length): Revert.
+
+2016-04-14 Marek Polacek <polacek@redhat.com>
+ Jan Hubicka <hubicka@ucw.cz>
+
+ PR c++/70029
+ * tree.c (verify_type): Disable the canonical type of main variant
+ check.
+
+2016-04-14 Jason Merrill <jason@redhat.com>
+
+ * cfgexpand.c, expr.c: Revert previous change.
+
+2016-04-14 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR middle-end/70643
+ * omp-low.c (lower_oacc_reductions): Check for TREE_CONSTANT
+ when building a mem ref for the incoming reduction variable.
+
+2016-04-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/70614
+ * tree-scalar-evolution.c (analyze_evolution_in_loop): Terminate
+ loop if the evolution dropped to chrec_dont_know.
+ (interpret_condition_phi): Likewise.
+
+2016-04-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/70623
+ * tree-ssa-pre.c (changed_blocks): Make global ...
+ (compute_antic): ... local here. Move and fix worklist
+ handling here. Do not clear EDGE_DFS_BACK or call mark_dfs_back_edges.
+ (compute_antic_aux): Add dumping for MAX assumed succs. Remove
+ worklist handling, dump when ANTIC_IN changed.
+ (compute_partial_antic_aux): Remove worklist handling.
+ (init_pre): Do not compute post dominators. Add a comment about
+ the CFG order chosen.
+ (fini_pre): Do not free post dominators.
+
+2016-04-13 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * doc/extend.texi (Variable Length): Document C++ specifics.
+
+2016-04-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70641
+ * ipa-pure-const.c (pass_nothrow::execute): Call maybe_clean_eh_stmt
+ on all recursive call stmts. Return TODO_cleanup_cfg if any dead
+ eh edges have been purged.
+
+ PR c++/70594
+ * tree-sra.c (create_access_replacement,
+ get_replaced_param_substitute): Set DECL_NAMELESS on repl if it
+ gets fancy name.
+ * tree-pretty-print.c (dump_fancy_name): New function.
+ (dump_decl_name, dump_generic_node): Use it.
+
+2016-04-13 Jason Merrill <jason@redhat.com>
+
+ * cfgexpand.c (pass_expand::execute): Handle attribute "abi warning".
+ * expr.c (expand_expr_real_1): Likewise.
+
+2016-04-13 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * config/i386/i386.md (kunpckhi): Swap operands.
+ (kunpcksi): Likewise.
+ (kunpckdi): Likewise.
+ * config/i386/sse.md (vec_pack_trunc_qi): Likewise.
+ (vec_pack_trunc_<mode>): Likewise.
+
+2016-04-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/70628
+ * explow.c (convert_memory_address_addr_space_1): Formatting fix.
+
+ PR middle-end/70633
+ * gimplify.c (gimplify_init_constructor): Clear TREE_STATIC if
+ gimplification turns some element into non-constant.
+
+ PR debug/70628
+ * rtl.h (convert_memory_address_addr_space_1): New prototype.
+ * explow.c (convert_memory_address_addr_space_1): No longer static,
+ add NO_EMIT argument and don't call convert_modes if true, pass
+ it down recursively, remove break after return.
+ (convert_memory_address_addr_space): Adjust caller.
+ * simplify-rtx.c (simplify_unary_operation_1): Call
+ convert_memory_address_addr_space_1 instead of convert_memory_address,
+ if it returns NULL, don't simplify.
+
+2016-04-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/70630
+ * config/sparc/sparc.c (sparc_compute_frame_size): Add parentheses.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen):
+ Bump the upper SIMDLEN limits, so that if the return type or
+ characteristic type if the return type is void can be passed in
+ all available SSE2/AVX/AVX2/AVX512-F registers, the SIMDLEN is
+ allowed.
+
+2016-04-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70640
+ * config/rs6000/rs6000.md (ieee_128bit_vsx_neg<mode>2_internal):
+ Do not use "=" constraint on an input constraint.
+ (ieee_128bit_vsx_abs<mode>2_internal): Likewise.
+ (ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
+ (ieee_128bit_vsx_nabs<mode>2): Correct splitter so that it
+ generates (neg (abs ...)) instead of (abs ...).
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/70596
+ * lra-spills.c (spill_pseudos): Don't delete debug insns, instead
+ just invalidate LRA data and reset them. Adjust dump wording.
+
+2016-04-12 Martin Liska <mliska@suse.cz>
+
+ Revert
+ 2016-03-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-loop-niter.c (idx_infer_loop_bounds): We can't get realistic
+ estimates here.
+ * tree-ssa-loop-unswitch.c (tree_unswitch_single_loop): Use also
+ max_loop_iterations_int.
+ (tree_unswitch_outer_loop): Likewise.
+ * tree-ssa-loop-ivopts.c (avg_loop_niter): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_2): Likewise.
+
+2016-04-12 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/68756
+ * graphite-isl-ast-to-gimple.c (copy_cond_phi_args): Use new_expr
+ instead of new_name.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/70602
+ * tree-sra.c (generate_subtree_copies): Don't write anything into
+ constant pool decls.
+
+ * omp-low.c (lower_omp_target): Use GOMP_MAP_FIRSTPRIVATE_INT
+ regardless whether there are depend clauses or not.
+
+2016-04-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70381
+ * config/rs6000/rs6000.c (rs6000_opt_masks): Disable using the
+ target attribute and pragma from changing the -mfloat128
+ and -mfloat128-hardware options.
+
+ * doc/extend.texi (Additional Floating Types): Document PowerPC
+ __float128 restrictions.
+
+2016-04-11 James Greenhalgh <james.greenhalgh@arm.com>
+
+ PR target/70133
+ * config/aarch64/driver-aarch64.c
+ (aarch64_get_extension_string_for_isa_flags): New.
+ (arch_extension): Rename to...
+ (aarch64_arch_extension): ...This.
+ (ext_to_feat_string): Rename to...
+ (aarch64_extensions): ...This.
+ (aarch64_core_data): Keep track of architecture extension flags.
+ (cpu_data): Rename to...
+ (aarch64_cpu_data): ...This.
+ (aarch64_arch_driver_info): Keep track of architecture extension
+ flags.
+ (get_arch_name_from_id): Rename to...
+ (get_arch_from_id): ...This, change return type.
+ (host_detect_local_cpu): Update and reformat for renames, handle
+ extensions through common infrastructure.
+
+2016-04-11 James Greenhalgh <james.greenhalgh@arm.com>
+
+ PR target/70133
+ * config/aarch64/aarch64-common.c (aarch64_option_extension): Keep
+ track of a canonical flag name.
+ (all_extensions): Likewise.
+ (arch_to_arch_name): Also track extension flags enabled by the arch.
+ (all_architectures): Likewise.
+ (aarch64_parse_extension): Move to here.
+ (aarch64_get_extension_string_for_isa_flags): Take a new argument,
+ rework.
+ (aarch64_rewrite_selected_cpu): Update for above change.
+ * config/aarch64/aarch64-option-extensions.def: Rework the way flags
+ are handled, such that the single explicit value enabled by an
+ extension is kept seperate from the implicit values it also enables.
+ * config/aarch64/aarch64-protos.h (aarch64_parse_opt_result): Move
+ to here.
+ (aarch64_parse_extension): New.
+ * config/aarch64/aarch64.c (aarch64_parse_opt_result): Move from
+ here to config/aarch64/aarch64-protos.h.
+ (aarch64_parse_extension): Move from here to
+ common/config/aarch64/aarch64-common.c.
+ (aarch64_option_print): Update.
+ (aarch64_declare_function_name): Likewise.
+ (aarch64_start_file): Likewise.
+ * config/aarch64/driver-aarch64.c (arch_extension): Keep track of
+ the canonical flag for extensions.
+ * config.gcc (aarch64*-*-*): Extend regex for capturing extension
+ flags.
+
+2016-04-11 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.h (AARCH64_FL_FOR_ARCH8_1): Also add
+ AARCH64_FL_CRC.
+
2016-04-09 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/68953
diff --git a/gcc/ChangeLog.upc b/gcc/ChangeLog.upc
index 405ce4277ca..8ea86fdbb7f 100644
--- a/gcc/ChangeLog.upc
+++ b/gcc/ChangeLog.upc
@@ -1,3 +1,11 @@
+2016-04-18 Gary Funck <gary@intrepid.com>
+
+ Merge trunk version 235033 into gupc branch.
+ This trunk version is the origin of the GCC 6 branch.
+
+ c/c-parser.c: Adjust calls to c_parser_pragm() and
+ c_parser_c99_block_statement(), passing null 'if_p' pointer.
+
2016-04-11 Gary Funck <gary@intrepid.com>
Merge trunk version 234874 into gupc branch.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index dda5b9a94f7..8460464baaa 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20160411
+20160415
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 696f4eba995..15276fdea05 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1369,6 +1369,7 @@ OBJS = \
modulo-sched.o \
multiple_target.o \
omp-low.o \
+ omp-simd-clone.o \
optabs.o \
optabs-libfuncs.o \
optabs-query.o \
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 26b1dabd6ee..ec79edbaa93 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,15 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70651
+ * c-common.c (build_va_arg): Change two asserts into errors and return
+ error_mark_node.
+
+2016-04-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/70639
+ * c-indentation.c (should_warn_for_misleading_indentation): Bail out
+ for switch statements, too.
+
2016-03-28 Jason Merrill <jason@redhat.com>
* c-cppbuiltin.c (c_cpp_builtins): Update __cpp_range_based_for.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 371a43578fa..9afa214c0cf 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5832,7 +5832,12 @@ build_va_arg (location_t loc, tree expr, tree type)
/* Verify that &ap is still recognized as having va_list type. */
tree canon_expr_type
= targetm.canonical_va_list_type (TREE_TYPE (expr));
- gcc_assert (canon_expr_type != NULL_TREE);
+ if (canon_expr_type == NULL_TREE)
+ {
+ error_at (loc,
+ "first argument to %<va_arg%> not of type %<va_list%>");
+ return error_mark_node;
+ }
return build_va_arg_1 (loc, type, expr);
}
@@ -5900,7 +5905,12 @@ build_va_arg (location_t loc, tree expr, tree type)
/* Verify that &ap is still recognized as having va_list type. */
tree canon_expr_type
= targetm.canonical_va_list_type (TREE_TYPE (expr));
- gcc_assert (canon_expr_type != NULL_TREE);
+ if (canon_expr_type == NULL_TREE)
+ {
+ error_at (loc,
+ "first argument to %<va_arg%> not of type %<va_list%>");
+ return error_mark_node;
+ }
}
else
{
diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
index 1da3f6824c1..8c336867d8c 100644
--- a/gcc/c-family/c-indentation.c
+++ b/gcc/c-family/c-indentation.c
@@ -239,10 +239,11 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
if (line_table->seen_line_directive)
return false;
- /* We can't usefully warn about do-while statements since the bodies of these
- statements are always explicitly delimited at both ends, so control flow is
- quite obvious. */
- if (guard_tinfo.keyword == RID_DO)
+ /* We can't usefully warn about do-while and switch statements since the
+ bodies of these statements are always explicitly delimited at both ends,
+ so control flow is quite obvious. */
+ if (guard_tinfo.keyword == RID_DO
+ || guard_tinfo.keyword == RID_SWITCH)
return false;
/* If the token following the body is a close brace or an "else"
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 56e0b4d8863..7257f79e0b2 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,51 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70671
+ * c-typeck.c (build_unary_op): Pass location down to error and
+ warning call.
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/70436
+ * c-parser.c (c_parser_pragma): Add IF_P argument, pass it down
+ where needed.
+ (c_parser_external_declaration, c_parser_struct_or_union_specifier,
+ c_parser_parameter_declaration, c_parser_compound_statement_nostart,
+ c_parser_objc_class_instance_variables, c_parser_objc_methodprotolist):
+ Adjust c_parser_pragma callers.
+ (c_parser_statement_after_labels): Likewise. Adjust c_parser_cilk_for
+ caller.
+ (c_parser_omp_structured_block): Add IF_P argument, pass it down to
+ c_parser_statement.
+ (c_parser_oacc_data, c_parser_oacc_host_data, c_parser_oacc_loop,
+ c_parser_oacc_kernels_parallel, c_parser_omp_critical,
+ c_parser_omp_simd, c_parser_omp_for, c_parser_omp_master,
+ c_parser_omp_ordered, c_parser_omp_parallel, c_parser_omp_single,
+ c_parser_omp_task, c_parser_omp_taskgroup, c_parser_omp_distribute,
+ c_parser_omp_teams, c_parser_omp_target_data, c_parser_omp_target,
+ c_parser_omp_taskloop, c_parser_omp_construct, c_parser_cilk_grainsize,
+ c_parser_cilk_simd, c_parser_cilk_for): Add IF_P argument, pass it
+ down where needed.
+ (c_parser_omp_for_loop): Likewise. Clear IF_P if nbraces.
+ (c_parser_omp_sections_scope): Adjust c_parser_omp_structured_block
+ calls.
+
+2016-04-13 Marek Polacek <polacek@redhat.com>
+
+ PR c/70436
+ * c-parser.c (c_parser_statement_after_labels): Add IF_P argument and
+ adjust callers.
+ (c_parser_statement): Likewise.
+ (c_parser_c99_block_statement): Likewise.
+ (c_parser_while_statement): Likewise.
+ (c_parser_for_statement): Likewise.
+ (c_parser_if_body): Don't set IF_P here.
+ (c_parser_if_statement): Add IF_P argument. Set IF_P here. Warn
+ about dangling else here.
+ * c-tree.h (c_finish_if_stmt): Adjust declaration.
+ * c-typeck.c (c_finish_if_stmt): Remove NESTED_IF parameter. Don't
+ warn about dangling else here.
+
2016-04-04 Marek Polacek <polacek@redhat.com>
PR c/70307
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 702aca015e4..ed63081cc1f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1322,13 +1322,14 @@ static void c_parser_initval (c_parser *, struct c_expr *,
static tree c_parser_compound_statement (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *);
-static void c_parser_statement (c_parser *);
-static void c_parser_statement_after_labels (c_parser *, vec<tree> * = NULL);
-static void c_parser_if_statement (c_parser *, vec<tree> *);
+static void c_parser_statement (c_parser *, bool *);
+static void c_parser_statement_after_labels (c_parser *, bool *,
+ vec<tree> * = NULL);
+static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
static void c_parser_switch_statement (c_parser *);
-static void c_parser_while_statement (c_parser *, bool);
+static void c_parser_while_statement (c_parser *, bool, bool *);
static void c_parser_do_statement (c_parser *, bool);
-static void c_parser_for_statement (c_parser *, bool);
+static void c_parser_for_statement (c_parser *, bool, bool *);
static tree c_parser_asm_statement (c_parser *);
static tree c_parser_asm_operands (c_parser *);
static tree c_parser_asm_goto_operands (c_parser *);
@@ -1362,12 +1363,12 @@ static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
static void c_parser_oacc_declare (c_parser *);
static void c_parser_oacc_enter_exit_data (c_parser *, bool);
static void c_parser_oacc_update (c_parser *);
-static void c_parser_omp_construct (c_parser *);
+static void c_parser_omp_construct (c_parser *, bool *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_flush (c_parser *);
static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
- tree, tree *);
+ tree, tree *, bool *);
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_cancel (c_parser *);
@@ -1375,11 +1376,11 @@ static void c_parser_omp_cancellation_point (c_parser *);
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
-static bool c_parser_pragma (c_parser *, enum pragma_context);
-static bool c_parser_omp_target (c_parser *, enum pragma_context);
+static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
+static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
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 bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
/* These Objective-C parser functions are only ever called when
@@ -1410,12 +1411,12 @@ static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
/* Cilk Plus supporting routines. */
-static void c_parser_cilk_simd (c_parser *);
-static void c_parser_cilk_for (c_parser *, tree);
+static void c_parser_cilk_simd (c_parser *, bool *);
+static void c_parser_cilk_for (c_parser *, tree, bool *);
static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
-static void c_parser_cilk_grainsize (c_parser *);
+static void c_parser_cilk_grainsize (c_parser *, bool *);
/* These UPC parser functions are only ever called when
compiling UPC. */
@@ -1555,7 +1556,7 @@ c_parser_external_declaration (c_parser *parser)
break;
case CPP_PRAGMA:
mark_valid_location_for_stdc_pragma (true);
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
mark_valid_location_for_stdc_pragma (false);
break;
case CPP_PLUS:
@@ -2966,7 +2967,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
/* Accept #pragmas at struct scope. */
if (c_parser_next_token_is (parser, CPP_PRAGMA))
{
- c_parser_pragma (parser, pragma_struct);
+ c_parser_pragma (parser, pragma_struct, NULL);
continue;
}
/* Parse some comma-separated declarations, but not the
@@ -3835,7 +3836,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
/* Accept #pragmas between parameter declarations. */
while (c_parser_next_token_is (parser, CPP_PRAGMA))
- c_parser_pragma (parser, pragma_param);
+ c_parser_pragma (parser, pragma_param, NULL);
if (!c_parser_next_token_starts_declspecs (parser))
{
@@ -4803,7 +4804,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
while (c_parser_next_token_is (parser, CPP_PRAGMA))
{
location_t loc ATTRIBUTE_UNUSED = c_parser_peek_token (parser)->location;
- if (c_parser_pragma (parser, pragma_compound))
+ if (c_parser_pragma (parser, pragma_compound, NULL))
last_label = false, last_stmt = true;
parser->error = false;
}
@@ -4876,7 +4877,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
places that would turn into syntax errors if the directive
were ignored. */
if (c_parser_pragma (parser,
- last_label ? pragma_stmt : pragma_compound))
+ last_label ? pragma_stmt : pragma_compound,
+ NULL))
last_label = false, last_stmt = true;
}
else if (c_parser_next_token_is (parser, CPP_EOF))
@@ -4906,7 +4908,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_label = false;
last_stmt = true;
mark_valid_location_for_stdc_pragma (false);
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, NULL);
}
parser->error = false;
@@ -5149,25 +5151,35 @@ c_parser_label (c_parser *parser)
statement:
transaction-statement
transaction-cancel-statement
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_statement (c_parser *parser)
+c_parser_statement (c_parser *parser, bool *if_p)
{
c_parser_all_labels (parser);
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, if_p, NULL);
}
/* Parse a statement, other than a labeled statement. CHAIN is a vector
- of if-else-if conditions. */
+ of if-else-if conditions.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain)
+c_parser_statement_after_labels (c_parser *parser, bool *if_p,
+ vec<tree> *chain)
{
location_t loc = c_parser_peek_token (parser)->location;
tree stmt = NULL_TREE;
bool in_if_block = parser->in_if_block;
parser->in_if_block = false;
+ if (if_p != NULL)
+ *if_p = false;
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_BRACE:
@@ -5177,19 +5189,19 @@ c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain)
switch (c_parser_peek_token (parser)->keyword)
{
case RID_IF:
- c_parser_if_statement (parser, chain);
+ c_parser_if_statement (parser, if_p, chain);
break;
case RID_SWITCH:
c_parser_switch_statement (parser);
break;
case RID_WHILE:
- c_parser_while_statement (parser, false);
+ c_parser_while_statement (parser, false, if_p);
break;
case RID_DO:
c_parser_do_statement (parser, false);
break;
case RID_FOR:
- c_parser_for_statement (parser, false);
+ c_parser_for_statement (parser, false, if_p);
break;
case RID_CILK_FOR:
if (!flag_cilkplus)
@@ -5199,7 +5211,7 @@ c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain)
c_parser_skip_to_end_of_block_or_statement (parser);
}
else
- c_parser_cilk_for (parser, integer_zero_node);
+ c_parser_cilk_for (parser, integer_zero_node, if_p);
break;
case RID_CILK_SYNC:
c_parser_consume_token (parser);
@@ -5335,7 +5347,7 @@ c_parser_statement_after_labels (c_parser *parser, vec<tree> *chain)
c_parser_consume_token (parser);
break;
case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_stmt);
+ c_parser_pragma (parser, pragma_stmt, if_p);
break;
default:
expr_stmt:
@@ -5391,14 +5403,18 @@ c_parser_paren_condition (c_parser *parser)
return cond;
}
-/* Parse a statement which is a block in C99. */
+/* Parse a statement which is a block in C99.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static tree
-c_parser_c99_block_statement (c_parser *parser)
+c_parser_c99_block_statement (c_parser *parser, bool *if_p)
{
tree block = c_begin_compound_stmt (flag_isoc99);
location_t loc = c_parser_peek_token (parser)->location;
- c_parser_statement (parser);
+ c_parser_statement (parser, if_p);
return c_end_compound_stmt (loc, block, flag_isoc99);
}
@@ -5408,7 +5424,11 @@ c_parser_c99_block_statement (c_parser *parser)
we handle an empty body specially for the sake of -Wempty-body
warnings, and (d) we call parser_compound_statement directly
because c_parser_statement_after_labels resets
- parser->in_if_block. */
+ parser->in_if_block.
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static tree
c_parser_if_body (c_parser *parser, bool *if_p,
@@ -5420,7 +5440,6 @@ c_parser_if_body (c_parser *parser, bool *if_p,
= get_token_indent_info (c_parser_peek_token (parser));
c_parser_all_labels (parser);
- *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
location_t loc = c_parser_peek_token (parser)->location;
@@ -5433,7 +5452,7 @@ c_parser_if_body (c_parser *parser, bool *if_p,
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
- c_parser_statement_after_labels (parser);
+ c_parser_statement_after_labels (parser, if_p);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5467,7 +5486,7 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
c_parser_consume_token (parser);
}
else
- c_parser_statement_after_labels (parser, chain);
+ c_parser_statement_after_labels (parser, NULL, chain);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5482,15 +5501,18 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
if ( expression ) statement
if ( expression ) statement else statement
- CHAIN is a vector of if-else-if conditions. */
+ CHAIN is a vector of if-else-if conditions.
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_if_statement (c_parser *parser, vec<tree> *chain)
+c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
{
tree block;
location_t loc;
tree cond;
- bool first_if = false;
+ bool nested_if = false;
tree first_body, second_body;
bool in_if_block;
tree if_stmt;
@@ -5509,7 +5531,7 @@ c_parser_if_statement (c_parser *parser, vec<tree> *chain)
}
in_if_block = parser->in_if_block;
parser->in_if_block = true;
- first_body = c_parser_if_body (parser, &first_if, if_tinfo);
+ first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
parser->in_if_block = in_if_block;
if (warn_duplicated_cond)
@@ -5540,10 +5562,22 @@ c_parser_if_statement (c_parser *parser, vec<tree> *chain)
}
}
second_body = c_parser_else_body (parser, else_tinfo, chain);
+ /* Set IF_P to true to indicate that this if statement has an
+ else clause. This may trigger the Wparentheses warning
+ below when we get back up to the parent if statement. */
+ if (if_p != NULL)
+ *if_p = true;
}
else
{
second_body = NULL_TREE;
+
+ /* Diagnose an ambiguous else if if-then-else is nested inside
+ if-then. */
+ if (nested_if)
+ warning_at (loc, OPT_Wparentheses,
+ "suggest explicit braces to avoid ambiguous %<else%>");
+
if (warn_duplicated_cond)
{
/* This if statement does not have an else clause. We don't
@@ -5552,7 +5586,7 @@ c_parser_if_statement (c_parser *parser, vec<tree> *chain)
chain = NULL;
}
}
- c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
+ c_finish_if_stmt (loc, cond, first_body, second_body);
if_stmt = c_end_compound_stmt (loc, block, flag_isoc99);
/* If the if statement contains array notations, then we expand them. */
@@ -5603,7 +5637,7 @@ c_parser_switch_statement (c_parser *parser)
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, NULL/*if??*/);
c_finish_case (body, ce.original_type);
if (c_break_label)
{
@@ -5620,10 +5654,13 @@ c_parser_switch_statement (c_parser *parser)
while-statement:
while (expression) statement
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_while_statement (c_parser *parser, bool ivdep)
+c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
{
tree block, cond, body, save_break, save_cont;
location_t loc;
@@ -5650,7 +5687,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, if_p);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
@@ -5685,7 +5722,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep)
c_break_label = NULL_TREE;
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, NULL);
c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
new_break = c_break_label;
c_break_label = save_break;
@@ -5760,10 +5797,13 @@ c_parser_do_statement (c_parser *parser, bool ivdep)
like the beginning of the for-statement, and we can tell it is a
foreach-statement only because the initial declaration or
expression is terminated by 'in' instead of ';'.
-*/
+
+ IF_P is used to track whether there's a (possibly labeled) if statement
+ which is not enclosed in braces and has an else clause. This is used to
+ implement -Wparentheses. */
static void
-c_parser_for_statement (c_parser *parser, bool ivdep)
+c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
{
tree block, cond, incr, save_break, save_cont, body;
/* The following are only used when parsing an ObjC foreach statement. */
@@ -5939,7 +5979,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep)
token_indent_info body_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, if_p);
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
@@ -8996,7 +9036,7 @@ c_parser_objc_class_instance_variables (c_parser *parser)
}
else if (c_parser_next_token_is (parser, CPP_PRAGMA))
{
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
continue;
}
@@ -9267,7 +9307,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
c_parser_objc_methodproto (parser);
break;
case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
break;
case CPP_EOF:
return;
@@ -10440,7 +10480,7 @@ c_parser_upc_forall_statement (c_parser *parser)
c_break_label = NULL_TREE;
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser);
+ body = c_parser_c99_block_statement (parser, NULL);
if (profile_upc_forall)
{
const tree gasp_start = upc_instrument_forall (loc, 1 /* start */);
@@ -10538,7 +10578,7 @@ c_parser_upc_sync_statement (c_parser *parser, int sync_kind)
true if we actually parsed such a pragma. */
static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context)
+c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
{
unsigned int id;
@@ -10645,7 +10685,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
case PRAGMA_OMP_TARGET:
- return c_parser_omp_target (parser, context);
+ return c_parser_omp_target (parser, context, if_p);
case PRAGMA_OMP_END_DECLARE_TARGET:
c_parser_omp_end_declare_target (parser);
@@ -10663,7 +10703,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
case PRAGMA_OMP_ORDERED:
- return c_parser_omp_ordered (parser, context);
+ return c_parser_omp_ordered (parser, context, if_p);
case PRAGMA_IVDEP:
c_parser_consume_pragma (parser);
@@ -10676,9 +10716,9 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
}
if (c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_for_statement (parser, true);
+ c_parser_for_statement (parser, true, if_p);
else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
- c_parser_while_statement (parser, true);
+ c_parser_while_statement (parser, true, if_p);
else
c_parser_do_statement (parser, true);
return false;
@@ -10692,7 +10732,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
if (!c_parser_cilk_verify_simd (parser, context))
return false;
c_parser_consume_pragma (parser);
- c_parser_cilk_simd (parser);
+ c_parser_cilk_simd (parser, if_p);
return false;
case PRAGMA_CILK_GRAINSIZE:
if (!flag_cilkplus)
@@ -10709,7 +10749,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
- c_parser_cilk_grainsize (parser);
+ c_parser_cilk_grainsize (parser, if_p);
return false;
default:
@@ -10722,7 +10762,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
- c_parser_omp_construct (parser);
+ c_parser_omp_construct (parser, if_p);
return true;
}
break;
@@ -13996,10 +14036,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
c_parser_statement calls add_stmt. */
static tree
-c_parser_omp_structured_block (c_parser *parser)
+c_parser_omp_structured_block (c_parser *parser, bool *if_p)
{
tree stmt = push_stmt_list ();
- c_parser_statement (parser);
+ c_parser_statement (parser, if_p);
return pop_stmt_list (stmt);
}
@@ -14049,7 +14089,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) )
static tree
-c_parser_oacc_data (location_t loc, c_parser *parser)
+c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, clauses, block;
@@ -14057,7 +14097,7 @@ c_parser_oacc_data (location_t loc, c_parser *parser)
"#pragma acc data");
block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
stmt = c_finish_oacc_data (loc, clauses, block);
@@ -14303,7 +14343,7 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
static tree
-c_parser_oacc_host_data (location_t loc, c_parser *parser)
+c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, clauses, block;
@@ -14311,7 +14351,7 @@ c_parser_oacc_host_data (location_t loc, c_parser *parser)
"#pragma acc host_data");
block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
stmt = c_finish_oacc_host_data (loc, clauses, block);
return stmt;
}
@@ -14338,7 +14378,7 @@ c_parser_oacc_host_data (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
static tree
c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
- omp_clause_mask mask, tree *cclauses)
+ omp_clause_mask mask, tree *cclauses, bool *if_p)
{
strcat (p_name, " loop");
mask |= OACC_LOOP_CLAUSE_MASK;
@@ -14355,7 +14395,8 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
}
tree block = c_begin_compound_stmt (true);
- tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL);
+ tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -14414,7 +14455,8 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
static tree
c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
- enum pragma_kind p_kind, char *p_name)
+ enum pragma_kind p_kind, char *p_name,
+ bool *if_p)
{
omp_clause_mask mask;
enum tree_code code;
@@ -14444,7 +14486,7 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
tree block = c_begin_omp_parallel ();
tree clauses;
- c_parser_oacc_loop (loc, parser, p_name, mask, &clauses);
+ c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
return c_finish_omp_construct (loc, code, block, clauses);
}
}
@@ -14452,7 +14494,7 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name);
tree block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
return c_finish_omp_construct (loc, code, block, clauses);
}
@@ -15095,7 +15137,7 @@ c_parser_omp_barrier (c_parser *parser)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
static tree
-c_parser_omp_critical (location_t loc, c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, name = NULL_TREE, clauses = NULL_TREE;
@@ -15122,7 +15164,7 @@ c_parser_omp_critical (location_t loc, c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
}
- stmt = c_parser_omp_structured_block (parser);
+ stmt = c_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (loc, stmt, name, clauses);
}
@@ -15154,7 +15196,7 @@ c_parser_omp_flush (c_parser *parser)
static tree
c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
- tree clauses, tree *cclauses)
+ tree clauses, tree *cclauses, bool *if_p)
{
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
tree declv, condv, incrv, initv, ret = NULL_TREE;
@@ -15384,6 +15426,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
nbraces += bracecount;
}
+ if (nbraces)
+ if_p = NULL;
+
save_break = c_break_label;
if (code == CILK_SIMD)
c_break_label = build_int_cst (size_type_node, 2);
@@ -15401,7 +15446,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
add_stmt (c_end_compound_stmt (here, stmt, true));
}
else
- add_stmt (c_parser_c99_block_statement (parser));
+ add_stmt (c_parser_c99_block_statement (parser, if_p));
if (c_cont_label)
{
tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
@@ -15544,7 +15589,8 @@ omp_split_clauses (location_t loc, enum tree_code code,
static tree
c_parser_omp_simd (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree block, clauses, ret;
@@ -15568,7 +15614,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -15599,7 +15645,8 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
static tree
c_parser_omp_for (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree block, clauses, ret;
@@ -15623,9 +15670,10 @@ c_parser_omp_for (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL_TREE)
return ret;
@@ -15656,7 +15704,7 @@ c_parser_omp_for (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -15671,10 +15719,11 @@ c_parser_omp_for (location_t loc, c_parser *parser,
*/
static tree
-c_parser_omp_master (location_t loc, c_parser *parser)
+c_parser_omp_master (location_t loc, c_parser *parser, bool *if_p)
{
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
+ return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
+ if_p));
}
/* OpenMP 2.5:
@@ -15695,7 +15744,8 @@ c_parser_omp_master (location_t loc, c_parser *parser)
(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
static bool
-c_parser_omp_ordered (c_parser *parser, enum pragma_context context)
+c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
+ bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
@@ -15734,7 +15784,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context)
tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
"#pragma omp ordered");
c_finish_omp_ordered (loc, clauses,
- c_parser_omp_structured_block (parser));
+ c_parser_omp_structured_block (parser, if_p));
return true;
}
@@ -15768,7 +15818,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
{
- substmt = c_parser_omp_structured_block (parser);
+ substmt = c_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -15794,7 +15844,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
error_suppress = true;
}
- substmt = c_parser_omp_structured_block (parser);
+ substmt = c_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -15882,7 +15932,8 @@ c_parser_omp_sections (location_t loc, c_parser *parser,
static tree
c_parser_omp_parallel (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree stmt, clauses, block;
@@ -15901,9 +15952,9 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
stmt
= c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
block);
@@ -15955,7 +16006,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
}
block = c_begin_omp_parallel ();
- c_parser_statement (parser);
+ c_parser_statement (parser, if_p);
stmt = c_finish_omp_parallel (loc, clauses, block);
return stmt;
@@ -15975,7 +16026,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_single (location_t loc, c_parser *parser)
+c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt = make_node (OMP_SINGLE);
SET_EXPR_LOCATION (stmt, loc);
@@ -15984,7 +16035,7 @@ c_parser_omp_single (location_t loc, c_parser *parser)
OMP_SINGLE_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
"#pragma omp single");
- OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
+ OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -16008,7 +16059,7 @@ c_parser_omp_single (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
static tree
-c_parser_omp_task (location_t loc, c_parser *parser)
+c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
{
tree clauses, block;
@@ -16016,7 +16067,7 @@ c_parser_omp_task (location_t loc, c_parser *parser)
"#pragma omp task");
block = c_begin_omp_task ();
- c_parser_statement (parser);
+ c_parser_statement (parser, if_p);
return c_finish_omp_task (loc, clauses, block);
}
@@ -16053,11 +16104,12 @@ c_parser_omp_taskyield (c_parser *parser)
*/
static tree
-c_parser_omp_taskgroup (c_parser *parser)
+c_parser_omp_taskgroup (c_parser *parser, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser));
+ return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser,
+ if_p));
}
/* OpenMP 4.0:
@@ -16141,7 +16193,8 @@ c_parser_omp_cancellation_point (c_parser *parser)
static tree
c_parser_omp_distribute (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -16167,16 +16220,19 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
if (!flag_openmp) /* flag_openmp_simd */
{
if (simd)
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
else
return c_parser_omp_parallel (loc, parser, p_name, mask,
- cclauses);
+ cclauses, if_p);
}
block = c_begin_compound_stmt (true);
if (simd)
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
else
- ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -16203,7 +16259,8 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -16225,7 +16282,8 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
static tree
c_parser_omp_teams (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -16243,9 +16301,11 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_distribute (loc, parser, p_name, mask,
+ cclauses, if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -16274,7 +16334,7 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
OMP_TEAMS_CLAUSES (stmt) = clauses;
- OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser);
+ OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -16290,7 +16350,7 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR))
static tree
-c_parser_omp_target_data (location_t loc, c_parser *parser)
+c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
{
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -16339,7 +16399,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser)
OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
keep_next_level ();
tree block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -16579,7 +16639,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
static bool
-c_parser_omp_target (c_parser *parser, enum pragma_context context)
+c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
@@ -16619,17 +16679,17 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
case OMP_TEAMS:
stmt = c_parser_omp_teams (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_PARALLEL:
stmt = c_parser_omp_parallel (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_SIMD:
stmt = c_parser_omp_simd (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
default:
gcc_unreachable ();
@@ -16642,15 +16702,18 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
{
case OMP_TEAMS:
ret = c_parser_omp_teams (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_PARALLEL:
ret = c_parser_omp_parallel (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_SIMD:
ret = c_parser_omp_simd (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -16701,7 +16764,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
else if (strcmp (p, "data") == 0)
{
c_parser_consume_token (parser);
- c_parser_omp_target_data (loc, parser);
+ c_parser_omp_target_data (loc, parser, if_p);
return true;
}
else if (strcmp (p, "enter") == 0)
@@ -16732,7 +16795,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -17541,7 +17604,8 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
static tree
c_parser_omp_taskloop (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -17560,9 +17624,10 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION);
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -17589,7 +17654,7 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -17599,7 +17664,7 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
/* Main entry point to parsing most OpenMP pragmas. */
static void
-c_parser_omp_construct (c_parser *parser)
+c_parser_omp_construct (c_parser *parser, bool *if_p)
{
enum pragma_kind p_kind;
location_t loc;
@@ -17621,19 +17686,20 @@ c_parser_omp_construct (c_parser *parser)
stmt = c_parser_oacc_cache (loc, parser);
break;
case PRAGMA_OACC_DATA:
- stmt = c_parser_oacc_data (loc, parser);
+ stmt = c_parser_oacc_data (loc, parser, if_p);
break;
case PRAGMA_OACC_HOST_DATA:
- stmt = c_parser_oacc_host_data (loc, parser);
+ stmt = c_parser_oacc_host_data (loc, parser, if_p);
break;
case PRAGMA_OACC_KERNELS:
case PRAGMA_OACC_PARALLEL:
strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_kernels_parallel (loc, parser, p_kind, p_name);
+ stmt = c_parser_oacc_kernels_parallel (loc, parser, p_kind, p_name,
+ if_p);
break;
case PRAGMA_OACC_LOOP:
strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OACC_WAIT:
strcpy (p_name, "#pragma wait");
@@ -17643,22 +17709,22 @@ c_parser_omp_construct (c_parser *parser)
c_parser_omp_atomic (loc, parser);
return;
case PRAGMA_OMP_CRITICAL:
- stmt = c_parser_omp_critical (loc, parser);
+ stmt = c_parser_omp_critical (loc, parser, if_p);
break;
case PRAGMA_OMP_DISTRIBUTE:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_FOR:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_MASTER:
- stmt = c_parser_omp_master (loc, parser);
+ stmt = c_parser_omp_master (loc, parser, if_p);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_SECTIONS:
strcpy (p_name, "#pragma omp");
@@ -17666,24 +17732,24 @@ c_parser_omp_construct (c_parser *parser)
break;
case PRAGMA_OMP_SIMD:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_SINGLE:
- stmt = c_parser_omp_single (loc, parser);
+ stmt = c_parser_omp_single (loc, parser, if_p);
break;
case PRAGMA_OMP_TASK:
- stmt = c_parser_omp_task (loc, parser);
+ stmt = c_parser_omp_task (loc, parser, if_p);
break;
case PRAGMA_OMP_TASKGROUP:
- stmt = c_parser_omp_taskgroup (parser);
+ stmt = c_parser_omp_taskgroup (parser, if_p);
break;
case PRAGMA_OMP_TASKLOOP:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_TEAMS:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
break;
default:
gcc_unreachable ();
@@ -18010,7 +18076,7 @@ c_parser_cilk_all_clauses (c_parser *parser)
*/
static void
-c_parser_cilk_grainsize (c_parser *parser)
+c_parser_cilk_grainsize (c_parser *parser, bool *if_p)
{
extern tree convert_to_integer (tree, tree);
@@ -18035,7 +18101,7 @@ c_parser_cilk_grainsize (c_parser *parser)
{
if (grain == NULL_TREE || grain == error_mark_node)
grain = integer_zero_node;
- c_parser_cilk_for (parser, grain);
+ c_parser_cilk_for (parser, grain, if_p);
}
else
warning (0, "%<#pragma cilk grainsize%> is not followed by "
@@ -18048,12 +18114,12 @@ c_parser_cilk_grainsize (c_parser *parser)
/* Main entry point for parsing Cilk Plus <#pragma simd> for loops. */
static void
-c_parser_cilk_simd (c_parser *parser)
+c_parser_cilk_simd (c_parser *parser, bool *if_p)
{
tree clauses = c_parser_cilk_all_clauses (parser);
tree block = c_begin_compound_stmt (true);
location_t loc = c_parser_peek_token (parser)->location;
- c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL);
+ c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
}
@@ -18078,7 +18144,7 @@ c_get_temp_regvar (tree type, tree init)
GRAIN is the grain value passed in through pragma or 0. */
static void
-c_parser_cilk_for (c_parser *parser, tree grain)
+c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
{
tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
@@ -18088,7 +18154,8 @@ c_parser_cilk_for (c_parser *parser, tree grain)
tree block = c_begin_compound_stmt (true);
tree sb = push_stmt_list ();
location_t loc = c_parser_peek_token (parser)->location;
- tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL);
+ tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL,
+ if_p);
sb = pop_stmt_list (sb);
if (omp_for)
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 7391fc9d558..511badff3f2 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -653,7 +653,7 @@ extern tree build_asm_stmt (tree, tree);
extern int c_types_compatible_p (tree, tree);
extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (location_t, tree, bool);
-extern void c_finish_if_stmt (location_t, tree, tree, tree, bool);
+extern void c_finish_if_stmt (location_t, tree, tree, tree);
extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
extern tree c_begin_stmt_expr (void);
extern tree c_finish_stmt_expr (location_t, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index b0526124906..a8ea76354c7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4518,8 +4518,8 @@ build_unary_op (location_t location,
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
{
- error ("cannot take address of bit-field %qD",
- TREE_OPERAND (arg, 1));
+ error_at (location, "cannot take address of bit-field %qD",
+ TREE_OPERAND (arg, 1));
return error_mark_node;
}
@@ -4531,15 +4531,16 @@ build_unary_op (location_t location,
if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
&& !VECTOR_TYPE_P (TREE_TYPE (arg)))
{
- error ("cannot take address of scalar with reverse storage "
- "order");
+ error_at (location, "cannot take address of scalar with "
+ "reverse storage order");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
&& TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
- warning (OPT_Wscalar_storage_order, "address of array with "
- "reverse scalar storage order requested");
+ warning_at (location, OPT_Wscalar_storage_order,
+ "address of array with reverse scalar storage "
+ "order requested");
}
default:
@@ -10235,12 +10236,11 @@ c_finish_case (tree body, tree type)
/* Emit an if statement. IF_LOCUS is the location of the 'if'. COND,
THEN_BLOCK and ELSE_BLOCK are expressions to be used; ELSE_BLOCK
- may be null. NESTED_IF is true if THEN_BLOCK contains another IF
- statement, and was not surrounded with parenthesis. */
+ may be null. */
void
c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
- tree else_block, bool nested_if)
+ tree else_block)
{
tree stmt;
@@ -10272,39 +10272,6 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
return;
}
}
- /* Diagnose an ambiguous else if if-then-else is nested inside if-then. */
- if (warn_parentheses && nested_if && else_block == NULL)
- {
- tree inner_if = then_block;
-
- /* We know from the grammar productions that there is an IF nested
- within THEN_BLOCK. Due to labels and c99 conditional declarations,
- it might not be exactly THEN_BLOCK, but should be the last
- non-container statement within. */
- while (1)
- switch (TREE_CODE (inner_if))
- {
- case COND_EXPR:
- goto found;
- case BIND_EXPR:
- inner_if = BIND_EXPR_BODY (inner_if);
- break;
- case STATEMENT_LIST:
- inner_if = expr_last (then_block);
- break;
- case TRY_FINALLY_EXPR:
- case TRY_CATCH_EXPR:
- inner_if = TREE_OPERAND (inner_if, 0);
- break;
- default:
- gcc_unreachable ();
- }
- found:
-
- if (COND_EXPR_ELSE (inner_if))
- warning_at (if_locus, OPT_Wparentheses,
- "suggest explicit braces to avoid ambiguous %<else%>");
- }
stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
SET_EXPR_LOCATION (stmt, if_locus);
diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
index 4969f07fef4..08e79593420 100644
--- a/gcc/common/config/aarch64/aarch64-common.c
+++ b/gcc/common/config/aarch64/aarch64-common.c
@@ -112,6 +112,7 @@ struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
struct aarch64_option_extension
{
const char *const name;
+ const unsigned long flag_canonical;
const unsigned long flags_on;
const unsigned long flags_off;
};
@@ -119,11 +120,11 @@ struct aarch64_option_extension
/* ISA extensions in AArch64. */
static const struct aarch64_option_extension all_extensions[] =
{
-#define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
- {NAME, FLAGS_ON, FLAGS_OFF},
+#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
+ {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
#include "config/aarch64/aarch64-option-extensions.def"
#undef AARCH64_OPT_EXTENSION
- {NULL, 0, 0}
+ {NULL, 0, 0, 0}
};
struct processor_name_to_arch
@@ -137,6 +138,7 @@ struct arch_to_arch_name
{
const enum aarch64_arch arch;
const std::string arch_name;
+ const unsigned long flags;
};
/* Map processor names to the architecture revision they implement and
@@ -155,26 +157,111 @@ static const struct processor_name_to_arch all_cores[] =
static const struct arch_to_arch_name all_architectures[] =
{
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \
- {AARCH64_ARCH_##ARCH_IDENT, NAME},
+ {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS},
#include "config/aarch64/aarch64-arches.def"
#undef AARCH64_ARCH
- {aarch64_no_arch, ""}
+ {aarch64_no_arch, "", 0}
};
-/* Return a string representation of ISA_FLAGS. */
+/* Parse the architecture extension string STR and update ISA_FLAGS
+ with the architecture features turned on or off. Return a
+ aarch64_parse_opt_result describing the result. */
+
+enum aarch64_parse_opt_result
+aarch64_parse_extension (const char *str, unsigned long *isa_flags)
+{
+ /* The extension string is parsed left to right. */
+ const struct aarch64_option_extension *opt = NULL;
+
+ /* Flag to say whether we are adding or removing an extension. */
+ int adding_ext = -1;
+
+ while (str != NULL && *str != 0)
+ {
+ const char *ext;
+ size_t len;
+
+ str++;
+ ext = strchr (str, '+');
+
+ if (ext != NULL)
+ len = ext - str;
+ else
+ len = strlen (str);
+
+ if (len >= 2 && strncmp (str, "no", 2) == 0)
+ {
+ adding_ext = 0;
+ len -= 2;
+ str += 2;
+ }
+ else if (len > 0)
+ adding_ext = 1;
+
+ if (len == 0)
+ return AARCH64_PARSE_MISSING_ARG;
+
+
+ /* Scan over the extensions table trying to find an exact match. */
+ for (opt = all_extensions; opt->name != NULL; opt++)
+ {
+ if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
+ {
+ /* Add or remove the extension. */
+ if (adding_ext)
+ *isa_flags |= (opt->flags_on | opt->flag_canonical);
+ else
+ *isa_flags &= ~(opt->flags_off | opt->flag_canonical);
+ break;
+ }
+ }
+
+ if (opt->name == NULL)
+ {
+ /* Extension not found in list. */
+ return AARCH64_PARSE_INVALID_FEATURE;
+ }
+
+ str = ext;
+ };
+
+ return AARCH64_PARSE_OK;
+}
+
+/* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
+ gives the default set of flags which are implied by whatever -march
+ we'd put out. Our job is to figure out the minimal set of "+" and
+ "+no" feature flags to put out, and to put them out grouped such
+ that all the "+" flags come before the "+no" flags. */
std::string
-aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags)
+aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
+ unsigned long default_arch_flags)
{
const struct aarch64_option_extension *opt = NULL;
std::string outstr = "";
+ /* Pass one: Find all the things we need to turn on. As a special case,
+ we always want to put out +crc if it is enabled. */
for (opt = all_extensions; opt->name != NULL; opt++)
- if ((isa_flags & opt->flags_on) == opt->flags_on)
+ if ((isa_flags & opt->flag_canonical
+ && !(default_arch_flags & opt->flag_canonical))
+ || (default_arch_flags & opt->flag_canonical
+ && opt->flag_canonical == AARCH64_ISA_CRC))
{
outstr += "+";
outstr += opt->name;
}
+
+ /* Pass two: Find all the things we need to turn off. */
+ for (opt = all_extensions; opt->name != NULL; opt++)
+ if ((~isa_flags) & opt->flag_canonical
+ && !((~default_arch_flags) & opt->flag_canonical))
+ {
+ outstr += "+no";
+ outstr += opt->name;
+ }
+
return outstr;
}
@@ -186,7 +273,7 @@ const char *
aarch64_rewrite_selected_cpu (const char *name)
{
std::string original_string (name);
- std::string extensions;
+ std::string extension_str;
std::string processor;
size_t extension_pos = original_string.find_first_of ('+');
@@ -194,8 +281,8 @@ aarch64_rewrite_selected_cpu (const char *name)
if (extension_pos != std::string::npos)
{
processor = original_string.substr (0, extension_pos);
- extensions = original_string.substr (extension_pos,
- std::string::npos);
+ extension_str = original_string.substr (extension_pos,
+ std::string::npos);
}
else
{
@@ -227,9 +314,12 @@ aarch64_rewrite_selected_cpu (const char *name)
|| a_to_an->arch == aarch64_no_arch)
fatal_error (input_location, "unknown value %qs for -mcpu", name);
+ unsigned long extensions = p_to_a->flags;
+ aarch64_parse_extension (extension_str.c_str (), &extensions);
+
std::string outstr = a_to_an->arch_name
- + aarch64_get_extension_string_for_isa_flags (p_to_a->flags)
- + extensions;
+ + aarch64_get_extension_string_for_isa_flags (extensions,
+ a_to_an->flags);
/* We are going to memory leak here, nobody elsewhere
in the callchain is going to clean up after us. The alternative is
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 67222601e1c..f66e48cd1ca 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3620,22 +3620,28 @@ case "${target}" in
${srcdir}/config/aarch64/aarch64-option-extensions.def \
> /dev/null; then
- ext_on=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ext_canon=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
${srcdir}/config/aarch64/aarch64-option-extensions.def | \
sed -e 's/^[^,]*,[ ]*//' | \
sed -e 's/,.*$//'`
- ext_off=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ext_on=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
${srcdir}/config/aarch64/aarch64-option-extensions.def | \
sed -e 's/^[^,]*,[ ]*[^,]*,[ ]*//' | \
sed -e 's/,.*$//' | \
sed -e 's/).*$//'`
+ ext_off=`grep "^AARCH64_OPT_EXTENSION(\"$base_ext\"," \
+ ${srcdir}/config/aarch64/aarch64-option-extensions.def | \
+ sed -e 's/^[^,]*,[ ]*[^,]*,[ ]*[^,]*,[ ]*//' | \
+ sed -e 's/,.*$//' | \
+ sed -e 's/).*$//'`
+
if [ $ext = $base_ext ]; then
# Adding extension
- ext_mask="("$ext_mask") | ("$ext_on")"
+ ext_mask="("$ext_mask") | ("$ext_on" | "$ext_canon")"
else
# Removing extension
- ext_mask="("$ext_mask") & ~("$ext_off")"
+ ext_mask="("$ext_mask") & ~("$ext_off" | "$ext_canon")"
fi
true
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index fbf9a53283c..e8706d1c2e7 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -21,23 +21,37 @@
Before using #include to read this file, define a macro:
- AARCH64_OPT_EXTENSION(EXT_NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING)
+ AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, FEATURE_STRING)
EXT_NAME is the name of the extension, represented as a string constant.
- FLAGS_ON are the bitwise-or of the features that the extension adds.
- FLAGS_OFF are the bitwise-or of the features that the extension removes.
+ FLAGS_CANONICAL is the canonical internal name for this flag.
+ FLAGS_ON are the bitwise-or of the features that enabling the extension
+ adds, or zero if enabling this extension has no effect on other features.
+ FLAGS_OFF are the bitwise-or of the features that disabling the extension
+ removes, or zero if disabling this extension has no effect on other
+ features.
FEAT_STRING is a string containing the entries in the 'Features' field of
/proc/cpuinfo on a GNU/Linux system that correspond to this architecture
extension being available. Sometimes multiple entries are needed to enable
the extension (for example, the 'crypto' extension depends on four
entries: aes, pmull, sha1, sha2 being present). In that case this field
- should contain a whitespace-separated list of the strings in 'Features'
+ should contain a space (" ") separated list of the strings in 'Features'
that are required. Their order is not important. */
-AARCH64_OPT_EXTENSION ("fp", AARCH64_FL_FP,
- AARCH64_FL_FPSIMD | AARCH64_FL_CRYPTO, "fp")
-AARCH64_OPT_EXTENSION ("simd", AARCH64_FL_FPSIMD,
- AARCH64_FL_SIMD | AARCH64_FL_CRYPTO, "asimd")
-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO | AARCH64_FL_FPSIMD, AARCH64_FL_CRYPTO, "aes pmull sha1 sha2")
-AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, AARCH64_FL_CRC, "crc32")
-AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, AARCH64_FL_LSE, "atomics")
+/* Enabling "fp" just enables "fp".
+ Disabling "fp" also disables "simd", "crypto". */
+AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO, "fp")
+
+/* Enabling "simd" also enables "fp".
+ Disabling "simd" also disables "crypto". */
+AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO, "asimd")
+
+/* Enabling "crypto" also enables "fp", "simd".
+ Disabling "crypto" just disables "crypto". */
+AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "aes pmull sha1 sha2")
+
+/* Enabling or disabling "crc" only changes "crc". */
+AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, "crc32")
+
+/* Enabling or disabling "lse" only changes "lse". */
+AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, "atomics")
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 58c9d0d01d8..f22a31c2830 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -263,6 +263,18 @@ enum aarch64_extra_tuning_flags
};
#undef AARCH64_EXTRA_TUNING_OPTION
+/* Enum describing the various ways that the
+ aarch64_parse_{arch,tune,cpu,extension} functions can fail.
+ This way their callers can choose what kind of error to give. */
+
+enum aarch64_parse_opt_result
+{
+ AARCH64_PARSE_OK, /* Parsing was successful. */
+ AARCH64_PARSE_MISSING_ARG, /* Missing argument. */
+ AARCH64_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
+ AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
+};
+
extern struct tune_params aarch64_tune_params;
HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
@@ -280,8 +292,6 @@ bool aarch64_float_const_zero_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
bool aarch64_gen_movmemqi (rtx *);
bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
-bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
- const struct cl_decoded_option *, location_t);
bool aarch64_is_extend_from_extract (machine_mode, rtx, rtx);
bool aarch64_is_long_call_p (rtx);
bool aarch64_is_noplt_call_p (rtx);
@@ -315,7 +325,6 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT);
bool aarch64_use_return_insn_p (void);
const char *aarch64_mangle_builtin_type (const_tree);
const char *aarch64_output_casesi (rtx *);
-const char *aarch64_rewrite_selected_cpu (const char *name);
enum aarch64_symbol_type aarch64_classify_symbol (rtx, rtx);
enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
@@ -338,7 +347,6 @@ rtx aarch64_simd_gen_const_vector_dup (machine_mode, int);
bool aarch64_simd_mem_operand_p (rtx);
rtx aarch64_simd_vect_par_cnst_half (machine_mode, bool);
rtx aarch64_tls_get_addr (void);
-std::string aarch64_get_extension_string_for_isa_flags (unsigned long);
tree aarch64_fold_builtin (tree, int, tree *, bool);
unsigned aarch64_dbx_register_number (unsigned);
unsigned aarch64_trampoline_size (void);
@@ -433,4 +441,13 @@ extern bool aarch64_nopcrelative_literal_loads;
extern void aarch64_asm_output_pool_epilogue (FILE *, const char *,
tree, HOST_WIDE_INT);
+/* Defined in common/config/aarch64-common.c. */
+bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
+ const struct cl_decoded_option *, location_t);
+const char *aarch64_rewrite_selected_cpu (const char *name);
+enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
+ unsigned long *);
+std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
+ unsigned long);
+
#endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index b7086dd4667..999549426e6 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -666,7 +666,7 @@ struct aarch64_option_extension
/* ISA extensions in AArch64. */
static const struct aarch64_option_extension all_extensions[] =
{
-#define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
+#define AARCH64_OPT_EXTENSION(NAME, X, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
{NAME, FLAGS_ON, FLAGS_OFF},
#include "aarch64-option-extensions.def"
#undef AARCH64_OPT_EXTENSION
@@ -7673,83 +7673,6 @@ aarch64_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
static void initialize_aarch64_code_model (struct gcc_options *);
-/* Enum describing the various ways that the
- aarch64_parse_{arch,tune,cpu,extension} functions can fail.
- This way their callers can choose what kind of error to give. */
-
-enum aarch64_parse_opt_result
-{
- AARCH64_PARSE_OK, /* Parsing was successful. */
- AARCH64_PARSE_MISSING_ARG, /* Missing argument. */
- AARCH64_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
- AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
-};
-
-/* Parse the architecture extension string STR and update ISA_FLAGS
- with the architecture features turned on or off. Return a
- aarch64_parse_opt_result describing the result. */
-
-static enum aarch64_parse_opt_result
-aarch64_parse_extension (char *str, unsigned long *isa_flags)
-{
- /* The extension string is parsed left to right. */
- const struct aarch64_option_extension *opt = NULL;
-
- /* Flag to say whether we are adding or removing an extension. */
- int adding_ext = -1;
-
- while (str != NULL && *str != 0)
- {
- char *ext;
- size_t len;
-
- str++;
- ext = strchr (str, '+');
-
- if (ext != NULL)
- len = ext - str;
- else
- len = strlen (str);
-
- if (len >= 2 && strncmp (str, "no", 2) == 0)
- {
- adding_ext = 0;
- len -= 2;
- str += 2;
- }
- else if (len > 0)
- adding_ext = 1;
-
- if (len == 0)
- return AARCH64_PARSE_MISSING_ARG;
-
-
- /* Scan over the extensions table trying to find an exact match. */
- for (opt = all_extensions; opt->name != NULL; opt++)
- {
- if (strlen (opt->name) == len && strncmp (opt->name, str, len) == 0)
- {
- /* Add or remove the extension. */
- if (adding_ext)
- *isa_flags |= opt->flags_on;
- else
- *isa_flags &= ~(opt->flags_off);
- break;
- }
- }
-
- if (opt->name == NULL)
- {
- /* Extension not found in list. */
- return AARCH64_PARSE_INVALID_FEATURE;
- }
-
- str = ext;
- };
-
- return AARCH64_PARSE_OK;
-}
-
/* Parse the TO_PARSE string and put the architecture struct that it
selects into RES and the architectural features into ISA_FLAGS.
Return an aarch64_parse_opt_result describing the parse result.
@@ -8550,7 +8473,7 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
unsigned long isa_flags = ptr->x_aarch64_isa_flags;
const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch);
std::string extension
- = aarch64_get_extension_string_for_isa_flags (isa_flags);
+ = aarch64_get_extension_string_for_isa_flags (isa_flags, arch->flags);
fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name);
fprintf (file, "%*sselected arch = %s%s\n", indent, "",
@@ -11213,7 +11136,8 @@ aarch64_declare_function_name (FILE *stream, const char* name,
unsigned long isa_flags = targ_options->x_aarch64_isa_flags;
std::string extension
- = aarch64_get_extension_string_for_isa_flags (isa_flags);
+ = aarch64_get_extension_string_for_isa_flags (isa_flags,
+ this_arch->flags);
/* Only update the assembler .arch string if it is distinct from the last
such string we printed. */
std::string to_print = this_arch->name + extension;
@@ -11253,7 +11177,8 @@ aarch64_start_file (void)
= aarch64_get_arch (default_options->x_explicit_arch);
unsigned long default_isa_flags = default_options->x_aarch64_isa_flags;
std::string extension
- = aarch64_get_extension_string_for_isa_flags (default_isa_flags);
+ = aarch64_get_extension_string_for_isa_flags (default_isa_flags,
+ default_arch->flags);
aarch64_last_printed_arch_string = default_arch->name + extension;
aarch64_last_printed_tune_string = "";
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 7750d1c060d..15d7e4019ad 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -145,7 +145,7 @@ extern unsigned aarch64_architecture_version;
/* Architecture flags that effect instruction selection. */
#define AARCH64_FL_FOR_ARCH8 (AARCH64_FL_FPSIMD)
#define AARCH64_FL_FOR_ARCH8_1 \
- (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_V8_1)
+ (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC | AARCH64_FL_V8_1)
/* Macros to test ISA flags. */
diff --git a/gcc/config/aarch64/driver-aarch64.c b/gcc/config/aarch64/driver-aarch64.c
index 317a8a9872e..ce771ec7ac1 100644
--- a/gcc/config/aarch64/driver-aarch64.c
+++ b/gcc/config/aarch64/driver-aarch64.c
@@ -18,17 +18,25 @@
<http://www.gnu.org/licenses/>. */
#include "config.h"
+#define INCLUDE_STRING
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
-struct arch_extension
+/* Defined in common/config/aarch64/aarch64-common.c. */
+std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
+ unsigned long);
+
+struct aarch64_arch_extension
{
const char *ext;
+ unsigned int flag;
const char *feat_string;
};
-#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
- { EXT_NAME, FEATURE_STRING },
-static struct arch_extension ext_to_feat_string[] =
+#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
+ { EXT_NAME, FLAG_CANONICAL, FEATURE_STRING },
+static struct aarch64_arch_extension aarch64_extensions[] =
{
#include "aarch64-option-extensions.def"
};
@@ -41,15 +49,16 @@ struct aarch64_core_data
const char* arch;
const char* implementer_id;
const char* part_no;
+ const unsigned long flags;
};
#define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART) \
- { CORE_NAME, #ARCH, IMP, PART },
+ { CORE_NAME, #ARCH, IMP, PART, FLAGS },
-static struct aarch64_core_data cpu_data [] =
+static struct aarch64_core_data aarch64_cpu_data[] =
{
#include "aarch64-cores.def"
- { NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, 0 }
};
#undef AARCH64_CORE
@@ -58,37 +67,37 @@ struct aarch64_arch_driver_info
{
const char* id;
const char* name;
+ const unsigned long flags;
};
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
- { #ARCH_IDENT, NAME },
+ { #ARCH_IDENT, NAME, FLAGS },
-static struct aarch64_arch_driver_info aarch64_arches [] =
+static struct aarch64_arch_driver_info aarch64_arches[] =
{
#include "aarch64-arches.def"
- {NULL, NULL}
+ {NULL, NULL, 0}
};
#undef AARCH64_ARCH
-/* Return the full architecture name string corresponding to the
- identifier ID. */
+/* Return an aarch64_arch_driver_info for the architecture described
+ by ID, or NULL if ID describes something we don't know about. */
-static const char*
-get_arch_name_from_id (const char* id)
+static struct aarch64_arch_driver_info*
+get_arch_from_id (const char* id)
{
unsigned int i = 0;
for (i = 0; aarch64_arches[i].id != NULL; i++)
{
if (strcmp (id, aarch64_arches[i].id) == 0)
- return aarch64_arches[i].name;
+ return &aarch64_arches[i];
}
return NULL;
}
-
/* Check wether the string CORE contains the same CPU part numbers
as BL_STRING. For example CORE="{0xd03, 0xd07}" and BL_STRING="0xd07.0xd03"
should return true. */
@@ -97,7 +106,7 @@ static bool
valid_bL_string_p (const char** core, const char* bL_string)
{
return strstr (bL_string, core[0]) != NULL
- && strstr (bL_string, core[1]) != NULL;
+ && strstr (bL_string, core[1]) != NULL;
}
/* Return true iff ARR contains STR in one of its two elements. */
@@ -141,7 +150,7 @@ host_detect_local_cpu (int argc, const char **argv)
{
const char *arch_id = NULL;
const char *res = NULL;
- static const int num_exts = ARRAY_SIZE (ext_to_feat_string);
+ static const int num_exts = ARRAY_SIZE (aarch64_extensions);
char buf[128];
FILE *f = NULL;
bool arch = false;
@@ -155,6 +164,8 @@ host_detect_local_cpu (int argc, const char **argv)
unsigned int n_imps = 0;
bool processed_exts = false;
const char *ext_string = "";
+ unsigned long extension_flags = 0;
+ unsigned long default_flags = 0;
gcc_assert (argc);
@@ -183,60 +194,71 @@ host_detect_local_cpu (int argc, const char **argv)
{
if (strstr (buf, "implementer") != NULL)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- if (strstr (buf, cpu_data[i].implementer_id) != NULL
- && !contains_string_p (imps, cpu_data[i].implementer_id))
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (strstr (buf, aarch64_cpu_data[i].implementer_id) != NULL
+ && !contains_string_p (imps,
+ aarch64_cpu_data[i].implementer_id))
{
- if (n_imps == 2)
- goto not_found;
+ if (n_imps == 2)
+ goto not_found;
- imps[n_imps++] = cpu_data[i].implementer_id;
+ imps[n_imps++] = aarch64_cpu_data[i].implementer_id;
- break;
+ break;
}
- continue;
+ continue;
}
if (strstr (buf, "part") != NULL)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- if (strstr (buf, cpu_data[i].part_no) != NULL
- && !contains_string_p (cores, cpu_data[i].part_no))
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (strstr (buf, aarch64_cpu_data[i].part_no) != NULL
+ && !contains_string_p (cores, aarch64_cpu_data[i].part_no))
{
- if (n_cores == 2)
- goto not_found;
+ if (n_cores == 2)
+ goto not_found;
- cores[n_cores++] = cpu_data[i].part_no;
- core_idx = i;
- arch_id = cpu_data[i].arch;
- break;
+ cores[n_cores++] = aarch64_cpu_data[i].part_no;
+ core_idx = i;
+ arch_id = aarch64_cpu_data[i].arch;
+ break;
}
- continue;
- }
+ continue;
+ }
if (!tune && !processed_exts && strstr (buf, "Features") != NULL)
- {
- for (i = 0; i < num_exts; i++)
- {
- bool enabled = true;
- char *p = NULL;
- char *feat_string = concat (ext_to_feat_string[i].feat_string, NULL);
-
- p = strtok (feat_string, " ");
-
- while (p != NULL)
- {
- if (strstr (buf, p) == NULL)
- {
- enabled = false;
- break;
- }
- p = strtok (NULL, " ");
- }
- ext_string = concat (ext_string, "+", enabled ? "" : "no",
- ext_to_feat_string[i].ext, NULL);
- }
- processed_exts = true;
- }
+ {
+ for (i = 0; i < num_exts; i++)
+ {
+ char *p = NULL;
+ char *feat_string
+ = concat (aarch64_extensions[i].feat_string, NULL);
+ bool enabled = true;
+
+ /* This may be a multi-token feature string. We need
+ to match all parts, which could be in any order.
+ If this isn't a multi-token feature string, strtok is
+ just going to return a pointer to feat_string. */
+ p = strtok (feat_string, " ");
+ while (p != NULL)
+ {
+ if (strstr (buf, p) == NULL)
+ {
+ /* Failed to match this token. Turn off the
+ features we'd otherwise enable. */
+ enabled = false;
+ break;
+ }
+ p = strtok (NULL, " ");
+ }
+
+ if (enabled)
+ extension_flags |= aarch64_extensions[i].flag;
+ else
+ extension_flags &= ~(aarch64_extensions[i].flag);
+ }
+
+ processed_exts = true;
+ }
}
fclose (f);
@@ -251,44 +273,56 @@ host_detect_local_cpu (int argc, const char **argv)
if (arch)
{
- const char* arch_name = get_arch_name_from_id (arch_id);
+ struct aarch64_arch_driver_info* arch_info = get_arch_from_id (arch_id);
/* We got some arch indentifier that's not in aarch64-arches.def? */
- if (!arch_name)
- goto not_found;
+ if (!arch_info)
+ goto not_found;
- res = concat ("-march=", arch_name, NULL);
+ res = concat ("-march=", arch_info->name, NULL);
+ default_flags = arch_info->flags;
}
/* We have big.LITTLE. */
else if (n_cores == 2)
{
- for (i = 0; cpu_data[i].name != NULL; i++)
- {
- if (strchr (cpu_data[i].part_no, '.') != NULL
- && strncmp (cpu_data[i].implementer_id, imps[0], strlen (imps[0]) - 1) == 0
- && valid_bL_string_p (cores, cpu_data[i].part_no))
- {
- res = concat ("-m", cpu ? "cpu" : "tune", "=", cpu_data[i].name, NULL);
- break;
- }
- }
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ {
+ if (strchr (aarch64_cpu_data[i].part_no, '.') != NULL
+ && strncmp (aarch64_cpu_data[i].implementer_id,
+ imps[0],
+ strlen (imps[0]) - 1) == 0
+ && valid_bL_string_p (cores, aarch64_cpu_data[i].part_no))
+ {
+ res = concat ("-m",
+ cpu ? "cpu" : "tune", "=",
+ aarch64_cpu_data[i].name,
+ NULL);
+ default_flags = aarch64_cpu_data[i].flags;
+ break;
+ }
+ }
if (!res)
- goto not_found;
+ goto not_found;
}
/* The simple, non-big.LITTLE case. */
else
{
- if (strncmp (cpu_data[core_idx].implementer_id, imps[0],
- strlen (imps[0]) - 1) != 0)
- goto not_found;
+ if (strncmp (aarch64_cpu_data[core_idx].implementer_id, imps[0],
+ strlen (imps[0]) - 1) != 0)
+ goto not_found;
res = concat ("-m", cpu ? "cpu" : "tune", "=",
- cpu_data[core_idx].name, NULL);
+ aarch64_cpu_data[core_idx].name, NULL);
+ default_flags = aarch64_cpu_data[core_idx].flags;
}
if (tune)
return res;
+ ext_string
+ = aarch64_get_extension_string_for_isa_flags (extension_flags,
+ default_flags).c_str ();
+
res = concat (res, ext_string, NULL);
return res;
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e4652f37ea6..ff47bc15600 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -44,6 +44,8 @@ extern bool ix86_use_pseudo_pic_reg (void);
extern void ix86_reset_previous_fndecl (void);
+extern bool ix86_using_red_zone (void);
+
#ifdef RTX_CODE
extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c2394c8a1a9..3e06cc53993 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3709,7 +3709,7 @@ make_pass_stv (gcc::context *ctxt)
/* Return true if a red-zone is in use. */
-static inline bool
+bool
ix86_using_red_zone (void)
{
return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
@@ -53776,7 +53776,7 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
if (clonei->simdlen
&& (clonei->simdlen < 2
- || clonei->simdlen > 128
+ || clonei->simdlen > 1024
|| (clonei->simdlen & (clonei->simdlen - 1)) != 0))
{
warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
@@ -53882,21 +53882,28 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node,
clonei->simdlen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
}
else if (clonei->simdlen > 16)
- switch (clonei->vecsize_int)
- {
- case 512:
- /* For AVX512-F, support VLEN up to 128. */
- break;
- case 256:
- /* For AVX2, support VLEN up to 32. */
- if (clonei->simdlen <= 32)
- break;
- /* FALLTHRU */
- default:
- /* Otherwise, support VLEN up to 16. */
- warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
- "unsupported simdlen %d", clonei->simdlen);
- return 0;
+ {
+ /* For compatibility with ICC, use the same upper bounds
+ for simdlen. In particular, for CTYPE below, use the return type,
+ unless the function returns void, in that case use the characteristic
+ type. If it is possible for given SIMDLEN to pass CTYPE value
+ in registers (8 [XYZ]MM* regs for 32-bit code, 16 [XYZ]MM* regs
+ for 64-bit code), accept that SIMDLEN, otherwise warn and don't
+ emit corresponding clone. */
+ tree ctype = ret_type;
+ if (TREE_CODE (ret_type) == VOID_TYPE)
+ ctype = base_type;
+ int cnt = GET_MODE_BITSIZE (TYPE_MODE (ctype)) * clonei->simdlen;
+ if (SCALAR_INT_MODE_P (TYPE_MODE (ctype)))
+ cnt /= clonei->vecsize_int;
+ else
+ cnt /= clonei->vecsize_float;
+ if (cnt > (TARGET_64BIT ? 16 : 8))
+ {
+ warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
+ "unsupported simdlen %d", clonei->simdlen);
+ return 0;
+ }
}
return ret;
}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 09da69e7e44..cf29e5d39d5 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -8907,7 +8907,7 @@
(const_int 8))
(zero_extend:HI (match_operand:QI 2 "register_operand" "k"))))]
"TARGET_AVX512F"
- "kunpckbw\t{%1, %2, %0|%0, %2, %1}"
+ "kunpckbw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "mode" "HI")
(set_attr "type" "msklog")
(set_attr "prefix" "vex")])
@@ -8920,7 +8920,7 @@
(const_int 16))
(zero_extend:SI (match_operand:HI 2 "register_operand" "k"))))]
"TARGET_AVX512BW"
- "kunpckwd\t{%1, %2, %0|%0, %2, %1}"
+ "kunpckwd\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "mode" "SI")])
(define_insn "kunpckdi"
@@ -8931,7 +8931,7 @@
(const_int 32))
(zero_extend:DI (match_operand:SI 2 "register_operand" "k"))))]
"TARGET_AVX512BW"
- "kunpckdq\t{%1, %2, %0|%0, %2, %1}"
+ "kunpckdq\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "mode" "DI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
@@ -18240,7 +18240,8 @@
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
@@ -18253,7 +18254,8 @@
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
@@ -18267,7 +18269,8 @@
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
@@ -18278,7 +18281,8 @@
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 5132955564b..4d2927e5c29 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -11747,16 +11747,16 @@
(define_expand "vec_pack_trunc_qi"
[(set (match_operand:HI 0 ("register_operand"))
- (ior:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 ("register_operand")))
+ (ior:HI (ashift:HI (zero_extend:HI (match_operand:QI 2 ("register_operand")))
(const_int 8))
- (zero_extend:HI (match_operand:QI 2 ("register_operand")))))]
+ (zero_extend:HI (match_operand:QI 1 ("register_operand")))))]
"TARGET_AVX512F")
(define_expand "vec_pack_trunc_<mode>"
[(set (match_operand:<DOUBLEMASKMODE> 0 ("register_operand"))
- (ior:<DOUBLEMASKMODE> (ashift:<DOUBLEMASKMODE> (zero_extend:<DOUBLEMASKMODE> (match_operand:SWI24 1 ("register_operand")))
+ (ior:<DOUBLEMASKMODE> (ashift:<DOUBLEMASKMODE> (zero_extend:<DOUBLEMASKMODE> (match_operand:SWI24 2 ("register_operand")))
(match_dup 3))
- (zero_extend:<DOUBLEMASKMODE> (match_operand:SWI24 2 ("register_operand")))))]
+ (zero_extend:<DOUBLEMASKMODE> (match_operand:SWI24 1 ("register_operand")))))]
"TARGET_AVX512BW"
{
operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));
@@ -17262,9 +17262,12 @@
/* There is no DF broadcast (in AVX-512*) to 128b register.
Mimic it with integer variant. */
if (<MODE>mode == V2DFmode)
- return "vpbroadcastq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}";
+ return "vpbroadcastq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}";
+
+ if (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) == 32)
+ return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %k1}";
else
- return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}";
+ return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}";
}
[(set_attr "type" "ssemov")
(set_attr "prefix" "evex")
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index 056b9b2d003..601cf124e36 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -31,4 +31,4 @@ Link in code for a __main kernel.
moptimize
Target Report Var(nvptx_optimize) Init(-1)
-Optimize partition neutering
+Optimize partition neutering.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 03d7df9b977..8f6504ee21f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3132,8 +3132,6 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_di_load;
reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_di_store;
reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_di_load;
- reg_addr[KFmode].reload_store = CODE_FOR_reload_kf_di_store;
- reg_addr[KFmode].reload_load = CODE_FOR_reload_kf_di_load;
reg_addr[DFmode].reload_store = CODE_FOR_reload_df_di_store;
reg_addr[DFmode].reload_load = CODE_FOR_reload_df_di_load;
reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_di_store;
@@ -3141,7 +3139,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_di_store;
reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_di_load;
- if (FLOAT128_IEEE_P (TFmode))
+ if (FLOAT128_VECTOR_P (KFmode))
+ {
+ reg_addr[KFmode].reload_store = CODE_FOR_reload_kf_di_store;
+ reg_addr[KFmode].reload_load = CODE_FOR_reload_kf_di_load;
+ }
+
+ if (FLOAT128_VECTOR_P (TFmode))
{
reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_di_store;
reg_addr[TFmode].reload_load = CODE_FOR_reload_tf_di_load;
@@ -3182,6 +3186,18 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[V8HImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv8hi;
reg_addr[V16QImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv16qi;
reg_addr[SFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprsf;
+
+ if (FLOAT128_VECTOR_P (KFmode))
+ {
+ reg_addr[KFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxkf;
+ reg_addr[KFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprkf;
+ }
+
+ if (FLOAT128_VECTOR_P (TFmode))
+ {
+ reg_addr[TFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxtf;
+ reg_addr[TFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprtf;
+ }
}
}
else
@@ -3200,8 +3216,6 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_si_load;
reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_si_store;
reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_si_load;
- reg_addr[KFmode].reload_store = CODE_FOR_reload_kf_si_store;
- reg_addr[KFmode].reload_load = CODE_FOR_reload_kf_si_load;
reg_addr[DFmode].reload_store = CODE_FOR_reload_df_si_store;
reg_addr[DFmode].reload_load = CODE_FOR_reload_df_si_load;
reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_si_store;
@@ -3209,6 +3223,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_si_store;
reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_si_load;
+ if (FLOAT128_VECTOR_P (KFmode))
+ {
+ reg_addr[KFmode].reload_store = CODE_FOR_reload_kf_si_store;
+ reg_addr[KFmode].reload_load = CODE_FOR_reload_kf_si_load;
+ }
+
if (FLOAT128_IEEE_P (TFmode))
{
reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_si_store;
@@ -34412,8 +34432,8 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "dlmzb", OPTION_MASK_DLMZB, false, true },
{ "efficient-unaligned-vsx", OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
false, true },
- { "float128", OPTION_MASK_FLOAT128, false, true },
- { "float128-hardware", OPTION_MASK_FLOAT128_HW, false, true },
+ { "float128", OPTION_MASK_FLOAT128, false, false },
+ { "float128-hardware", OPTION_MASK_FLOAT128_HW, false, false },
{ "fprnd", OPTION_MASK_FPRND, false, true },
{ "hard-dfp", OPTION_MASK_DFP, false, true },
{ "htm", OPTION_MASK_HTM, false, true },
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index ef1dea82c84..849b19a7b0b 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -7261,7 +7261,7 @@
(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
- (use (match_operand:V16QI 2 "register_operand" "=v"))]
+ (use (match_operand:V16QI 2 "register_operand" "v"))]
"TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlxor %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
@@ -7290,7 +7290,7 @@
(define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
- (use (match_operand:V16QI 2 "register_operand" "=v"))]
+ (use (match_operand:V16QI 2 "register_operand" "v"))]
"TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlandc %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
@@ -7306,7 +7306,7 @@
"#"
"&& 1"
[(parallel [(set (match_dup 0)
- (abs:IEEE128 (match_dup 1)))
+ (neg:IEEE128 (abs:IEEE128 (match_dup 1))))
(use (match_dup 2))])]
{
if (GET_CODE (operands[2]) == SCRATCH)
@@ -7323,7 +7323,7 @@
(neg:IEEE128
(abs:IEEE128
(match_operand:IEEE128 1 "register_operand" "wa"))))
- (use (match_operand:V16QI 2 "register_operand" "=v"))]
+ (use (match_operand:V16QI 2 "register_operand" "v"))]
"TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
"xxlor %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 080be617a5a..082af3cc9b1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -4917,13 +4917,18 @@ sparc_compute_frame_size (HOST_WIDE_INT size, int leaf_function)
/* Calculate space needed for global registers. */
if (TARGET_ARCH64)
- for (i = 0; i < 8; i++)
- if (save_global_or_fp_reg_p (i, 0))
- n_global_fp_regs += 2;
+ {
+ for (i = 0; i < 8; i++)
+ if (save_global_or_fp_reg_p (i, 0))
+ n_global_fp_regs += 2;
+ }
else
- for (i = 0; i < 8; i += 2)
- if (save_global_or_fp_reg_p (i, 0) || save_global_or_fp_reg_p (i + 1, 0))
- n_global_fp_regs += 2;
+ {
+ for (i = 0; i < 8; i += 2)
+ if (save_global_or_fp_reg_p (i, 0)
+ || save_global_or_fp_reg_p (i + 1, 0))
+ n_global_fp_regs += 2;
+ }
/* In the flat window model, find out which local and in registers need to
be saved. We don't reserve space in the current frame for them as they
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1a690a9bc5b..d89b73b4e76 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,171 @@
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/70436
+ * parser.c (cp_parser_pragma): Add IF_P argument, pass it down
+ where needed.
+ (cp_parser_declaration_seq_opt, cp_parser_member_specification_opt,
+ cp_parser_objc_interstitial_code, cp_parser_omp_declare_simd,
+ cp_parser_oacc_routine): Adjust cp_parser_pragma callers.
+ (cp_parser_statement): Likewise. Adjust cp_parser_cilk_for caller.
+ (cp_parser_omp_structured_block): Add IF_P argument, pass it down to
+ cp_parser_statement.
+ (cp_parser_oacc_data, cp_parser_oacc_host_data, cp_parser_oacc_loop,
+ cp_parser_oacc_kernels_parallel, cp_parser_omp_critical,
+ cp_parser_omp_simd, cp_parser_omp_for, cp_parser_omp_master,
+ cp_parser_omp_ordered, cp_parser_omp_parallel, cp_parser_omp_single,
+ cp_parser_omp_task, cp_parser_omp_taskgroup, cp_parser_omp_distribute,
+ cp_parser_omp_teams, cp_parser_omp_target_data, cp_parser_omp_target,
+ cp_parser_omp_taskloop, cp_parser_omp_construct,
+ cp_parser_cilk_grainsize, cp_parser_cilk_simd, cp_parser_cilk_for):
+ Add IF_P argument, pass it down where needed.
+ (cp_parser_omp_for_loop): Likewise. Clear IF_P if nbraces.
+ (cp_parser_omp_sections_scope): Adjust cp_parser_omp_structured_block
+ calls.
+
+2016-04-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/70494
+ * decl.c (cxx_maybe_build_cleanup): Handle non-decls.
+ * typeck2.c (split_nonconstant_init_1): Use it.
+
+ PR c++/70528
+ * class.c (type_has_constexpr_default_constructor): Return true
+ for an implicitly declared constructor.
+
+ PR c++/70622
+ * parser.c (cp_parser_init_declarator): Add auto_result parm.
+ (cp_parser_simple_declaration): Pass it.
+ (strip_declarator_types): New.
+
+ PR c++/70543
+ * pt.c (value_dependent_expression_p) [VAR_DECL]: A type-dependent
+ initializer also makes the variable value-dependent.
+
+ PR c++/70648
+ * constexpr.c (cxx_eval_store_expression): Also copy
+ CONSTRUCTOR_NO_IMPLICIT_ZERO.
+
+2016-04-14 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * cp-tree.h, decl.c, init.c, typeck2.c: Revert.
+
+2016-04-14 Jason Merrill <jason@redhat.com>
+
+ * call.c, decl.c, error.c, cp-tree.h, decl.c: Revert empty
+ parameter ABI change.
+
+2016-04-13 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * cp-tree.h (throw_bad_array_length, build_vla_check): Declare new
+ functions.
+ * decl.c (check_initializer, cp_finish_decl): Call them.
+ (reshape_init_r): Reject incompletely braced intializer-lists
+ for VLAs.
+ * init.c (throw_bad_array_length, build_vla_check)
+ (build_vla_size_check, build_vla_init_check): Define new functions.
+ * typeck2.c (split_nonconstant_init_1): Use variably_modified_type_p()
+ to detect a VLA.
+ (store_init_value): Same.
+
+2016-04-13 Jason Merrill <jason@redhat.com>
+
+ Warn about empty parameter ABI with -Wabi=9.
+ * call.c (empty_class_msg, mark_for_abi_warning)
+ (warn_empty_class_abi): New.
+ (build_call_a): Use them.
+ * decl.c (store_parm_decls): Use mark_for_abi_warning.
+ * error.c (pp_format_to_string): New.
+
+ Pass empty class parameters like C.
+ * call.c (pass_as_empty_struct, empty_class_arg): New.
+ (type_passed_as, build_x_va_arg): Use pass_as_empty_struct.
+ (build_call_a): Use empty_class_arg.
+ * cp-tree.h (CPTI_EMPTY_STRUCT, empty_struct_type): New.
+ * decl.c (cxx_init_decl_processing): Create empty_struct_type.
+
+2016-04-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/70627
+ * decl.c (start_enum): Don't change an existing ENUM_UNDERLYING_TYPE.
+
+2016-04-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/70635
+ * pt.c (resolve_typename_type): Fix typos in infinite recursion
+ avoidance mechanism.
+
+2016-04-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/70634
+ * pt.c (instantiation_dependent_uneval_expression_p): Split out
+ from instantiation_dependent_expression_p.
+ (value_dependent_expression_p): Use it for unevaluated operands.
+ (instantiation_dependent_r): Don't check value-dependence.
+ (instantiation_dependent_expression_p): Check
+ value-dependence of the expression as a whole.
+ * cp-tree.h: Declare instantiation_dependent_uneval_expression_p.
+ * semantics.c (finish_decltype_type): Use it.
+
+ * constexpr.c (potential_nondependent_constant_expression): New.
+ (potential_nondependent_static_init_expression): New.
+ (maybe_constant_value_1, fold_non_dependent_expr)
+ (maybe_constant_init): Use them.
+ * pt.c (instantiate_non_dependent_expr_sfinae)
+ (instantiate_non_dependent_or_null, convert_nontype_argument): Use
+ them.
+ * cp-tree.h: Declare them.
+
+2016-04-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70594
+ * decl.c (pop_labels_1): Removed.
+ (note_label, sort_labels): New functions.
+ (pop_labels): During named_labels traversal, just push the slot
+ pointers into a vector, then qsort it by DECL_UID and only then
+ call pop_label and chain it into BLOCK_VARS.
+
+2016-04-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/70615
+ * cp-gimplify.c (cp_genericize_r): Expand PTRMEM_CST here.
+ (cp_gimplify_expr): Not here.
+
+2016-04-12 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/70610
+ * tree.c (lvalue_kind) [NON_DEPENDENT_EXPR]: Unconditionally
+ recurse into it.
+ * typeck.c (build_x_conditional_expr): Unconditionally remember
+ that the result is an lvalue or xvalue.
+
+2016-04-12 Jason Merrill <jason@redhat.com>
+
+ * class.c (is_really_empty_class): A zero-length array is empty.
+ An unnamed bit-field doesn't make a class non-empty.
+
+2016-04-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/68722
+ * parser.c (cp_parser_cache_defarg): When file ends in default
+ argument simply return error_mark_node.
+
+2016-04-12 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70501
+ * constexpr.c (cxx_eval_bare_aggregate): Handle VECTOR_TYPE
+ similarly to PMF.
+
+2016-04-11 Jason Merrill <jason@redhat.com>
+
+ * mangle.c (decl_is_template_id): The template itself counts as a
+ template-id.
+
2016-04-08 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/70590
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e66f0b9c51e..e6d5bb0fe9c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3346,7 +3346,6 @@ add_implicitly_declared_members (tree t, tree* access_decls,
CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
if (cxx_dialect >= cxx11)
TYPE_HAS_CONSTEXPR_CTOR (t)
- /* This might force the declaration. */
= type_has_constexpr_default_constructor (t);
}
@@ -5349,8 +5348,11 @@ type_has_constexpr_default_constructor (tree t)
{
if (!TYPE_HAS_COMPLEX_DFLT (t))
return trivial_default_constructor_is_constexpr (t);
- /* Non-trivial, we need to check subobject constructors. */
- lazily_declare_fn (sfk_constructor, t);
+ /* Assume it's constexpr to avoid unnecessary instantiation; if the
+ definition would have made the class non-literal, it will still be
+ non-literal because of the base or member in question, and that
+ gives a better diagnostic. */
+ return true;
}
fns = locate_ctor (t);
return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
@@ -8406,12 +8408,15 @@ is_really_empty_class (tree type)
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
&& !DECL_ARTIFICIAL (field)
+ /* An unnamed bit-field is not a data member. */
+ && (DECL_NAME (field) || !DECL_C_BIT_FIELD (field))
&& !is_really_empty_class (TREE_TYPE (field)))
return false;
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
- return is_really_empty_class (TREE_TYPE (type));
+ return (integer_zerop (array_type_nelts_top (type))
+ || is_really_empty_class (TREE_TYPE (type)));
return false;
}
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index e6e2cf6ca5f..d9b9a2888f9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -915,7 +915,7 @@ struct constexpr_ctx {
/* A table of all constexpr calls that have been evaluated by the
compiler in this translation unit. */
-static GTY ((deletable)) hash_table<constexpr_call_hasher> *constexpr_call_table;
+static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table;
static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,
bool, bool *, bool *, tree * = NULL);
@@ -965,17 +965,6 @@ maybe_initialize_constexpr_call_table (void)
constexpr_call_table = hash_table<constexpr_call_hasher>::create_ggc (101);
}
-/* The representation of a single node in the per-function freelist maintained
- by FUNDEF_COPIES_TABLE. */
-
-struct fundef_copy
-{
- tree body;
- tree parms;
- tree res;
- fundef_copy *prev;
-};
-
/* During constexpr CALL_EXPR evaluation, to avoid issues with sharing when
a function happens to get called recursively, we unshare the callee
function's body and evaluate this unshared copy instead of evaluating the
@@ -983,45 +972,42 @@ struct fundef_copy
FUNDEF_COPIES_TABLE is a per-function freelist of these unshared function
copies. The underlying data structure of FUNDEF_COPIES_TABLE is a hash_map
- that's keyed off of the original FUNCTION_DECL and whose value is the chain
- of this function's unused copies awaiting reuse. */
+ that's keyed off of the original FUNCTION_DECL and whose value is a
+ TREE_LIST of this function's unused copies awaiting reuse.
-struct fundef_copies_table_t
-{
- hash_map<tree, fundef_copy *> *map;
-};
+ This is not GC-deletable to avoid GC affecting UID generation. */
-static GTY((deletable)) fundef_copies_table_t fundef_copies_table;
+static GTY(()) hash_map<tree, tree> *fundef_copies_table;
/* Initialize FUNDEF_COPIES_TABLE if it's not initialized. */
static void
maybe_initialize_fundef_copies_table ()
{
- if (fundef_copies_table.map == NULL)
- fundef_copies_table.map = hash_map<tree, fundef_copy *>::create_ggc (101);
+ if (fundef_copies_table == NULL)
+ fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
}
/* Reuse a copy or create a new unshared copy of the function FUN.
Return this copy. */
-static fundef_copy *
+static tree
get_fundef_copy (tree fun)
{
maybe_initialize_fundef_copies_table ();
- fundef_copy *copy;
- fundef_copy **slot = &fundef_copies_table.map->get_or_insert (fun, NULL);
- if (*slot == NULL)
+ tree copy;
+ tree *slot = fundef_copies_table->get (fun);
+ if (slot == NULL)
{
- copy = ggc_alloc<fundef_copy> ();
- copy->body = copy_fn (fun, copy->parms, copy->res);
- copy->prev = NULL;
+ copy = build_tree_list (NULL, NULL);
+ /* PURPOSE is body, VALUE is parms, TYPE is result. */
+ TREE_PURPOSE (copy) = copy_fn (fun, TREE_VALUE (copy), TREE_TYPE (copy));
}
else
{
copy = *slot;
- *slot = (*slot)->prev;
+ *slot = TREE_CHAIN (copy);
}
return copy;
@@ -1030,10 +1016,10 @@ get_fundef_copy (tree fun)
/* Save the copy COPY of function FUN for later reuse by get_fundef_copy(). */
static void
-save_fundef_copy (tree fun, fundef_copy *copy)
+save_fundef_copy (tree fun, tree copy)
{
- fundef_copy **slot = &fundef_copies_table.map->get_or_insert (fun, NULL);
- copy->prev = *slot;
+ tree *slot = &fundef_copies_table->get_or_insert (fun, NULL);
+ TREE_CHAIN (copy) = *slot;
*slot = copy;
}
@@ -1464,10 +1450,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
tree body, parms, res;
/* Reuse or create a new unshared copy of this function's body. */
- fundef_copy *copy = get_fundef_copy (fun);
- body = copy->body;
- parms = copy->parms;
- res = copy->res;
+ tree copy = get_fundef_copy (fun);
+ body = TREE_PURPOSE (copy);
+ parms = TREE_VALUE (copy);
+ res = TREE_TYPE (copy);
/* Associate the bindings with the remapped parms. */
tree bound = new_call.bindings;
@@ -2394,10 +2380,10 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
tree type = TREE_TYPE (t);
constexpr_ctx new_ctx;
- if (TYPE_PTRMEMFUNC_P (type))
+ if (TYPE_PTRMEMFUNC_P (type) || VECTOR_TYPE_P (type))
{
- /* We don't really need the ctx->ctor business for a PMF, but it's
- simpler to use the same code. */
+ /* We don't really need the ctx->ctor business for a PMF or
+ vector, but it's simpler to use the same code. */
new_ctx = *ctx;
new_ctx.ctor = build_constructor (type, NULL);
new_ctx.object = NULL_TREE;
@@ -3149,6 +3135,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
+ CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp)
+ = CONSTRUCTOR_NO_IMPLICIT_ZERO (init);
}
else
*valp = init;
@@ -4315,10 +4303,7 @@ maybe_constant_value_1 (tree t, tree decl)
{
tree r;
- if (instantiation_dependent_expression_p (t)
- || type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t)
- || !potential_constant_expression (t))
+ if (!potential_nondependent_constant_expression (t))
{
if (TREE_OVERFLOW_P (t))
{
@@ -4397,8 +4382,7 @@ fold_non_dependent_expr (tree t)
as two declarations of the same function, for example. */
if (processing_template_decl)
{
- if (!instantiation_dependent_expression_p (t)
- && potential_constant_expression (t))
+ if (potential_nondependent_constant_expression (t))
{
processing_template_decl_sentinel s;
t = instantiate_non_dependent_expr_internal (t, tf_none);
@@ -4449,10 +4433,7 @@ maybe_constant_init (tree t, tree decl)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == INIT_EXPR)
t = TREE_OPERAND (t, 1);
- if (instantiation_dependent_expression_p (t)
- || type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t)
- || !potential_static_init_expression (t))
+ if (!potential_nondependent_static_init_expression (t))
/* Don't try to evaluate it. */;
else
t = cxx_eval_outermost_constant_expr (t, true, false, decl);
@@ -5203,4 +5184,39 @@ require_potential_rvalue_constant_expression (tree t)
return potential_constant_expression_1 (t, true, true, tf_warning_or_error);
}
+/* Returns true if T is a potential constant expression that is not
+ instantiation-dependent, and therefore a candidate for constant folding even
+ in a template. */
+
+bool
+potential_nondependent_constant_expression (tree t)
+{
+ return (!type_unknown_p (t)
+ && !BRACE_ENCLOSED_INITIALIZER_P (t)
+ && potential_constant_expression (t)
+ && !instantiation_dependent_expression_p (t));
+}
+
+/* Returns true if T is a potential static initializer expression that is not
+ instantiation-dependent. */
+
+bool
+potential_nondependent_static_init_expression (tree t)
+{
+ return (!type_unknown_p (t)
+ && !BRACE_ENCLOSED_INITIALIZER_P (t)
+ && potential_static_init_expression (t)
+ && !instantiation_dependent_expression_p (t));
+}
+
+/* Finalize constexpr processing after parsing. */
+
+void
+fini_constexpr (void)
+{
+ /* The contexpr call and fundef copies tables are no longer needed. */
+ constexpr_call_table = NULL;
+ fundef_copies_table = NULL;
+}
+
#include "gt-cp-constexpr.h"
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 13f7b7ccbd7..30ac660906d 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -576,11 +576,6 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
switch (code)
{
- case PTRMEM_CST:
- *expr_p = cplus_expand_constant (*expr_p);
- ret = GS_OK;
- break;
-
case AGGR_INIT_EXPR:
simplify_aggr_init_expr (expr_p);
ret = GS_OK;
@@ -1388,6 +1383,13 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
|| TREE_CODE (stmt) == OMP_SIMD
|| TREE_CODE (stmt) == OMP_DISTRIBUTE)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
+ else if (TREE_CODE (stmt) == PTRMEM_CST)
+ {
+ /* By the time we get here we're handing off to the back end, so we don't
+ need or want to preserve PTRMEM_CST anymore. */
+ *stmt_p = cplus_expand_constant (stmt);
+ *walk_subtrees = 0;
+ }
else if ((flag_sanitize
& (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
&& !wtd->no_sanitize_p)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0f7e08ffe73..0df84707f88 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6127,6 +6127,7 @@ extern bool any_type_dependent_elements_p (const_tree);
extern bool type_dependent_expression_p_push (tree);
extern bool value_dependent_expression_p (tree);
extern bool instantiation_dependent_expression_p (tree);
+extern bool instantiation_dependent_uneval_expression_p (tree);
extern bool any_value_dependent_elements_p (const_tree);
extern bool dependent_omp_for_p (tree, tree, tree, tree);
extern tree resolve_typename_type (tree, bool);
@@ -6879,11 +6880,14 @@ bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree,
tree);
/* In constexpr.c */
+extern void fini_constexpr (void);
extern bool literal_type_p (tree);
extern tree register_constexpr_fundef (tree, tree);
extern bool check_constexpr_ctor_body (tree, tree, bool);
extern tree ensure_literal_type_for_constexpr_object (tree);
extern bool potential_constant_expression (tree);
+extern bool potential_nondependent_constant_expression (tree);
+extern bool potential_nondependent_static_init_expression (tree);
extern bool potential_static_init_expression (tree);
extern bool potential_rvalue_constant_expression (tree);
extern bool require_potential_constant_expression (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9260f4c4254..38e6bd83a2a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -368,33 +368,61 @@ pop_label (tree label, tree old_value)
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
}
-/* At the end of a function, all labels declared within the function
- go out of scope. BLOCK is the top-level block for the
- function. */
+/* Push all named labels into a vector, so that we can sort it on DECL_UID
+ to avoid code generation differences. */
int
-pop_labels_1 (named_label_entry **slot, tree block)
+note_label (named_label_entry **slot, vec<named_label_entry **> &labels)
{
- struct named_label_entry *ent = *slot;
-
- pop_label (ent->label_decl, NULL_TREE);
+ labels.quick_push (slot);
+ return 1;
+}
- /* Put the labels into the "variables" of the top-level block,
- so debugger can see them. */
- DECL_CHAIN (ent->label_decl) = BLOCK_VARS (block);
- BLOCK_VARS (block) = ent->label_decl;
+/* Helper function to sort named label entries in a vector by DECL_UID. */
- named_labels->clear_slot (slot);
-
- return 1;
+static int
+sort_labels (const void *a, const void *b)
+{
+ named_label_entry **slot1 = *(named_label_entry **const *) a;
+ named_label_entry **slot2 = *(named_label_entry **const *) b;
+ if (DECL_UID ((*slot1)->label_decl) < DECL_UID ((*slot2)->label_decl))
+ return -1;
+ if (DECL_UID ((*slot1)->label_decl) > DECL_UID ((*slot2)->label_decl))
+ return 1;
+ return 0;
}
+/* At the end of a function, all labels declared within the function
+ go out of scope. BLOCK is the top-level block for the
+ function. */
+
static void
pop_labels (tree block)
{
if (named_labels)
{
- named_labels->traverse<tree, pop_labels_1> (block);
+ auto_vec<named_label_entry **, 32> labels;
+ named_label_entry **slot;
+ unsigned int i;
+
+ /* Push all the labels into a vector and sort them by DECL_UID,
+ so that gaps between DECL_UIDs don't affect code generation. */
+ labels.reserve_exact (named_labels->elements ());
+ named_labels->traverse<vec<named_label_entry **> &, note_label> (labels);
+ labels.qsort (sort_labels);
+ FOR_EACH_VEC_ELT (labels, i, slot)
+ {
+ struct named_label_entry *ent = *slot;
+
+ pop_label (ent->label_decl, NULL_TREE);
+
+ /* Put the labels into the "variables" of the top-level block,
+ so debugger can see them. */
+ DECL_CHAIN (ent->label_decl) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = ent->label_decl;
+
+ named_labels->clear_slot (slot);
+ }
named_labels = NULL;
}
}
@@ -13225,7 +13253,10 @@ start_enum (tree name, tree enumtype, tree underlying_type,
if (underlying_type)
{
- if (CP_INTEGRAL_TYPE_P (underlying_type))
+ if (ENUM_UNDERLYING_TYPE (enumtype))
+ /* We already checked that it matches, don't change it to a different
+ typedef variant. */;
+ else if (CP_INTEGRAL_TYPE_P (underlying_type))
{
copy_type_enum (enumtype, underlying_type);
ENUM_UNDERLYING_TYPE (enumtype) = underlying_type;
@@ -14990,7 +15021,8 @@ complete_vars (tree type)
/* If DECL is of a type which needs a cleanup, build and return an
expression to perform that cleanup here. Return NULL_TREE if no
- cleanup need be done. */
+ cleanup need be done. DECL can also be a _REF when called from
+ split_nonconstant_init_1. */
tree
cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
@@ -15008,7 +15040,10 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
/* Handle "__attribute__((cleanup))". We run the cleanup function
before the destructor since the destructor is what actually
terminates the lifetime of the object. */
- attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+ if (DECL_P (decl))
+ attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+ else
+ attr = NULL_TREE;
if (attr)
{
tree id;
@@ -15067,6 +15102,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
if (cleanup
+ && DECL_P (decl)
&& !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (TREE_TYPE (decl)))
/* Treat objects with destructors as used; the destructor may do
something substantive. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index b3cc99a7dc1..0ea326d7699 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4904,6 +4904,8 @@ c_parse_final_cleanups (void)
finish_repo ();
+ fini_constexpr ();
+
/* The entire file is now complete. If requested, dump everything
to a file. */
dump_tu ();
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 5d38373765b..0e444097c19 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -264,9 +264,9 @@ static void write_java_integer_type_codes (const tree);
#define write_unsigned_number(NUMBER) \
write_number ((NUMBER), /*unsigned_p=*/1, 10)
-/* If DECL is a template instance, return nonzero and, if
- TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
- Otherwise return zero. */
+/* If DECL is a template instance (including the uninstantiated template
+ itself), return nonzero and, if TEMPLATE_INFO is non-NULL, set
+ *TEMPLATE_INFO to its template info. Otherwise return zero. */
static int
decl_is_template_id (const tree decl, tree* const template_info)
@@ -290,7 +290,8 @@ decl_is_template_id (const tree decl, tree* const template_info)
{
/* Check if this is a primary template. */
if (DECL_LANG_SPECIFIC (decl) != NULL
- && DECL_USE_TEMPLATE (decl)
+ && VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
&& TREE_CODE (decl) != TEMPLATE_DECL)
{
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 28e01afc572..54861298c84 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -249,9 +249,9 @@ static tree cp_literal_operator_id
(const char *);
static void cp_parser_cilk_simd
- (cp_parser *, cp_token *);
+ (cp_parser *, cp_token *, bool *);
static tree cp_parser_cilk_for
- (cp_parser *, tree);
+ (cp_parser *, tree, bool *);
static bool cp_parser_omp_declare_reduction_exprs
(tree, cp_parser *);
static tree cp_parser_cilk_simd_vectorlength
@@ -2193,7 +2193,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 *, location_t *, tree *);
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 +2434,7 @@ enum pragma_context {
pragma_compound
};
static bool cp_parser_pragma
- (cp_parser *, enum pragma_context);
+ (cp_parser *, enum pragma_context, bool *);
/* Objective-C++ Productions */
@@ -10404,7 +10404,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
statement = error_mark_node;
}
else
- statement = cp_parser_cilk_for (parser, integer_zero_node);
+ statement = cp_parser_cilk_for (parser, integer_zero_node, if_p);
break;
case RID_BREAK:
@@ -10496,8 +10496,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
return so that we can check for a close brace. Otherwise we
require a real statement and must go back and read one. */
if (in_compound)
- cp_parser_pragma (parser, pragma_compound);
- else if (!cp_parser_pragma (parser, pragma_stmt))
+ cp_parser_pragma (parser, pragma_compound, if_p);
+ else if (!cp_parser_pragma (parser, pragma_stmt, if_p))
goto restart;
return;
}
@@ -12016,7 +12016,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
A nested declaration cannot, so this is done here and not
in cp_parser_declaration. (A #pragma at block scope is
handled in cp_parser_statement.) */
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_external, NULL);
continue;
}
@@ -12337,10 +12337,9 @@ cp_parser_simple_declaration (cp_parser* parser,
&& !cp_parser_error_occurred (parser))
cp_parser_commit_to_tentative_parse (parser);
- tree last_type, auto_node;
+ tree last_type;
last_type = NULL_TREE;
- auto_node = type_uses_auto (decl_specifiers.type);
/* Keep going until we hit the `;' at the end of the simple
declaration. */
@@ -12351,6 +12350,7 @@ cp_parser_simple_declaration (cp_parser* parser,
cp_token *token;
bool function_definition_p;
tree decl;
+ tree auto_result = NULL_TREE;
if (saw_declarator)
{
@@ -12376,7 +12376,8 @@ cp_parser_simple_declaration (cp_parser* parser,
declares_class_or_enum,
&function_definition_p,
maybe_range_for_decl,
- &init_loc);
+ &init_loc,
+ &auto_result);
/* 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
@@ -12384,10 +12385,10 @@ cp_parser_simple_declaration (cp_parser* parser,
if (cp_parser_error_occurred (parser))
goto done;
- if (auto_node)
+ if (auto_result)
{
- tree type = TREE_TYPE (decl);
- if (last_type && !same_type_p (type, last_type))
+ if (last_type && last_type != error_mark_node
+ && !same_type_p (auto_result, last_type))
{
/* If the list of declarators contains more than one declarator,
the type of each declared variable is determined as described
@@ -12395,10 +12396,11 @@ cp_parser_simple_declaration (cp_parser* parser,
the same in each deduction, the program is ill-formed. */
error_at (decl_specifiers.locations[ds_type_spec],
"inconsistent deduction for %qT: %qT and then %qT",
- decl_specifiers.type, last_type, type);
- auto_node = NULL_TREE;
+ decl_specifiers.type, last_type, auto_result);
+ last_type = error_mark_node;
}
- last_type = type;
+ else
+ last_type = auto_result;
}
/* Handle function definitions specially. */
@@ -18221,6 +18223,31 @@ cp_parser_asm_definition (cp_parser* parser)
}
}
+/* Given the type TYPE of a declaration with declarator DECLARATOR, return the
+ type that comes from the decl-specifier-seq. */
+
+static tree
+strip_declarator_types (tree type, cp_declarator *declarator)
+{
+ for (cp_declarator *d = declarator; d;)
+ switch (d->kind)
+ {
+ case cdk_id:
+ case cdk_error:
+ d = NULL;
+ break;
+
+ default:
+ if (TYPE_PTRMEMFUNC_P (type))
+ type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ type = TREE_TYPE (type);
+ d = d->declarator;
+ break;
+ }
+
+ return type;
+}
+
/* Declarators [gram.dcl.decl] */
/* Parse an init-declarator.
@@ -18286,7 +18313,8 @@ cp_parser_init_declarator (cp_parser* parser,
int declares_class_or_enum,
bool* function_definition_p,
tree* maybe_range_for_decl,
- location_t* init_loc)
+ location_t* init_loc,
+ tree* auto_result)
{
cp_token *token = NULL, *asm_spec_start_token = NULL,
*attributes_start_token = NULL;
@@ -18677,6 +18705,10 @@ cp_parser_init_declarator (cp_parser* parser,
finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
}
+ if (auto_result && is_initialized && decl_specifiers->type
+ && type_uses_auto (decl_specifiers->type))
+ *auto_result = strip_declarator_types (TREE_TYPE (decl), declarator);
+
return decl;
}
@@ -22113,7 +22145,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
/* Accept #pragmas at class scope. */
if (token->type == CPP_PRAGMA)
{
- cp_parser_pragma (parser, pragma_member);
+ cp_parser_pragma (parser, pragma_member, NULL);
break;
}
@@ -25808,7 +25840,7 @@ cp_parser_single_declaration (cp_parser* parser,
member_p,
declares_class_or_enum,
&function_definition_p,
- NULL, NULL);
+ NULL, NULL, NULL);
/* 7.1.1-1 [dcl.stc]
@@ -27472,8 +27504,7 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
case CPP_EOF:
case CPP_PRAGMA_EOL:
error_at (token->location, "file ends in default argument");
- done = true;
- break;
+ return error_mark_node;
case CPP_NAME:
case CPP_SCOPE:
@@ -28450,7 +28481,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
cp_parser_linkage_specification (parser);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
- cp_parser_pragma (parser, pragma_objc_icode);
+ cp_parser_pragma (parser, pragma_objc_icode, NULL);
/* Allow stray semicolons. */
else if (token->type == CPP_SEMICOLON)
cp_lexer_consume_token (parser->lexer);
@@ -32578,12 +32609,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
}
static tree
-cp_parser_omp_structured_block (cp_parser *parser)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
{
tree stmt = begin_omp_structured_block ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_structured_block (stmt);
@@ -33043,7 +33074,7 @@ cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
static tree
-cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, name = NULL_TREE, clauses = NULL_TREE;
@@ -33068,7 +33099,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
else
cp_parser_require_pragma_eol (parser, pragma_tok);
- stmt = cp_parser_omp_structured_block (parser);
+ stmt = cp_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (input_location, stmt, name, clauses);
}
@@ -33444,7 +33475,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
static tree
cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
- tree *cclauses)
+ tree *cclauses, bool *if_p)
{
tree init, orig_init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
tree real_decl, initv, condv, incrv, declv;
@@ -33703,6 +33734,9 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
}
}
+ if (nbraces)
+ if_p = NULL;
+
/* Note that we saved the original contents of this flag when we entered
the structured block, and so we don't need to re-save it here. */
if (code == CILK_SIMD || code == CILK_FOR)
@@ -33713,7 +33747,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
/* Note that the grammar doesn't call for a structured block here,
though the loop as a whole is a structured block. */
body = push_stmt_list ();
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
body = pop_stmt_list (body);
if (declv == NULL_TREE)
@@ -33782,7 +33816,8 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
static tree
cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -33811,7 +33846,7 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -33840,7 +33875,8 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -33868,11 +33904,11 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -33907,7 +33943,7 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -33920,11 +33956,11 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
structured-block */
static tree
-cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
return c_finish_omp_master (input_location,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser, if_p));
}
/* OpenMP 2.5:
@@ -33944,7 +33980,7 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
static bool
cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
- enum pragma_context context)
+ enum pragma_context context, bool *if_p)
{
location_t loc = pragma_tok->location;
@@ -33983,7 +34019,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
= cp_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
"#pragma omp ordered", pragma_tok);
c_finish_omp_ordered (loc, clauses,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser, if_p));
return true;
}
@@ -34011,7 +34047,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))
!= PRAGMA_OMP_SECTION)
{
- substmt = cp_parser_omp_structured_block (parser);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -34036,7 +34072,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
error_suppress = true;
}
- substmt = cp_parser_omp_structured_block (parser);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -34115,7 +34151,8 @@ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -34136,10 +34173,12 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
- return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses,
+ if_p);
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses,
+ if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
block);
@@ -34193,7 +34232,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (clauses, block);
return stmt;
@@ -34210,7 +34249,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt = make_node (OMP_SINGLE);
TREE_TYPE (stmt) = void_type_node;
@@ -34218,7 +34257,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
OMP_SINGLE_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
"#pragma omp single", pragma_tok);
- OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -34240,7 +34279,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
static tree
-cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree clauses, block;
unsigned int save;
@@ -34249,7 +34288,7 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
"#pragma omp task", pragma_tok);
block = begin_omp_task ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_task (clauses, block);
}
@@ -34279,11 +34318,12 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
structured-block */
static tree
-cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
return c_finish_omp_taskgroup (input_location,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser,
+ if_p));
}
@@ -34372,7 +34412,8 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok)
static tree
cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -34402,19 +34443,19 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
{
if (simd)
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
else
return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
}
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
if (simd)
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
else
ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -34445,7 +34486,7 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -34468,7 +34509,8 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -34490,11 +34532,11 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -34525,7 +34567,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
OMP_TEAMS_CLAUSES (stmt) = clauses;
- OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -34541,7 +34583,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR))
static tree
-cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -34591,7 +34633,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok)
OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
keep_next_level (true);
- OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
SET_EXPR_LOCATION (stmt, pragma_tok->location);
return add_stmt (stmt);
@@ -34836,7 +34878,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
static bool
cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
- enum pragma_context context)
+ enum pragma_context context, bool *if_p)
{
tree *pc = NULL, stmt;
@@ -34875,17 +34917,17 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
case OMP_TEAMS:
stmt = cp_parser_omp_teams (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_PARALLEL:
stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_SIMD:
stmt = cp_parser_omp_simd (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
default:
gcc_unreachable ();
@@ -34899,15 +34941,18 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
{
case OMP_TEAMS:
ret = cp_parser_omp_teams (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_PARALLEL:
ret = cp_parser_omp_parallel (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_SIMD:
ret = cp_parser_omp_simd (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -34960,7 +35005,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
else if (strcmp (p, "data") == 0)
{
cp_lexer_consume_token (parser->lexer);
- cp_parser_omp_target_data (parser, pragma_tok);
+ cp_parser_omp_target_data (parser, pragma_tok, if_p);
return true;
}
else if (strcmp (p, "enter") == 0)
@@ -34990,7 +35035,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
"#pragma omp target", pragma_tok);
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level (true);
- OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
SET_EXPR_LOCATION (stmt, pragma_tok->location);
add_stmt (stmt);
@@ -35066,7 +35111,7 @@ cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE))
static tree
-cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -35076,7 +35121,7 @@ cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_oacc_data (clauses, block);
return stmt;
@@ -35090,7 +35135,7 @@ cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
static tree
-cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -35100,7 +35145,7 @@ cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok)
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_oacc_host_data (clauses, block);
return stmt;
@@ -35349,7 +35394,7 @@ cp_parser_oacc_enter_exit_data (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
- omp_clause_mask mask, tree *cclauses)
+ omp_clause_mask mask, tree *cclauses, bool *if_p)
{
strcat (p_name, " loop");
mask |= OACC_LOOP_CLAUSE_MASK;
@@ -35367,7 +35412,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
tree block = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
- tree stmt = cp_parser_omp_for_loop (parser, OACC_LOOP, clauses, NULL);
+ tree stmt = cp_parser_omp_for_loop (parser, OACC_LOOP, clauses, NULL, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (block));
@@ -35424,7 +35469,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
static tree
cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
- char *p_name)
+ char *p_name, bool *if_p)
{
omp_clause_mask mask;
enum tree_code code;
@@ -35455,7 +35500,8 @@ cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
tree block = begin_omp_parallel ();
tree clauses;
- cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, &clauses);
+ cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, &clauses,
+ if_p);
return finish_omp_construct (code, block, clauses);
}
}
@@ -35464,7 +35510,7 @@ cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
tree block = begin_omp_parallel ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_construct (code, block, clauses);
}
@@ -35568,7 +35614,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
if (first_p)
{
while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
- cp_parser_pragma (parser, context);
+ cp_parser_pragma (parser, context, NULL);
switch (context)
{
case pragma_external:
@@ -36291,7 +36337,8 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -36314,11 +36361,11 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -36349,7 +36396,8 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_TASKLOOP, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_TASKLOOP, clauses, cclauses,
+ if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -36512,7 +36560,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
parser->oacc_routine->clauses = c_head;
while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
- cp_parser_pragma (parser, context);
+ cp_parser_pragma (parser, context, NULL);
if (first_p)
{
@@ -36639,7 +36687,7 @@ cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn)
/* Main entry point to OpenMP statement pragmas. */
static void
-cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt;
char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
@@ -36654,7 +36702,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
stmt = cp_parser_oacc_cache (parser, pragma_tok);
break;
case PRAGMA_OACC_DATA:
- stmt = cp_parser_oacc_data (parser, pragma_tok);
+ stmt = cp_parser_oacc_data (parser, pragma_tok, if_p);
break;
case PRAGMA_OACC_ENTER_DATA:
stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, true);
@@ -36663,16 +36711,18 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, false);
break;
case PRAGMA_OACC_HOST_DATA:
- stmt = cp_parser_oacc_host_data (parser, pragma_tok);
+ stmt = cp_parser_oacc_host_data (parser, pragma_tok, if_p);
break;
case PRAGMA_OACC_KERNELS:
case PRAGMA_OACC_PARALLEL:
strcpy (p_name, "#pragma acc");
- stmt = cp_parser_oacc_kernels_parallel (parser, pragma_tok, p_name);
+ stmt = cp_parser_oacc_kernels_parallel (parser, pragma_tok, p_name,
+ if_p);
break;
case PRAGMA_OACC_LOOP:
strcpy (p_name, "#pragma acc");
- stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OACC_UPDATE:
stmt = cp_parser_oacc_update (parser, pragma_tok);
@@ -36684,22 +36734,25 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
cp_parser_omp_atomic (parser, pragma_tok);
return;
case PRAGMA_OMP_CRITICAL:
- stmt = cp_parser_omp_critical (parser, pragma_tok);
+ stmt = cp_parser_omp_critical (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_DISTRIBUTE:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_FOR:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_MASTER:
- stmt = cp_parser_omp_master (parser, pragma_tok);
+ stmt = cp_parser_omp_master (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_SECTIONS:
strcpy (p_name, "#pragma omp");
@@ -36707,24 +36760,27 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
break;
case PRAGMA_OMP_SIMD:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_SINGLE:
- stmt = cp_parser_omp_single (parser, pragma_tok);
+ stmt = cp_parser_omp_single (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASK:
- stmt = cp_parser_omp_task (parser, pragma_tok);
+ stmt = cp_parser_omp_task (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASKGROUP:
- stmt = cp_parser_omp_taskgroup (parser, pragma_tok);
+ stmt = cp_parser_omp_taskgroup (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASKLOOP:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_TEAMS:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -37079,7 +37135,7 @@ cp_parser_initial_pragma (cp_token *first_token)
#pragma cilk grainsize = <VALUE>. */
static void
-cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
if (cp_parser_require (parser, CPP_EQ, RT_EQ))
{
@@ -37094,7 +37150,7 @@ cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
/* Make sure the next token is _Cilk_for, it is invalid otherwise. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR))
- cp_parser_cilk_for (parser, exp);
+ cp_parser_cilk_for (parser, exp, if_p);
else
warning_at (cp_lexer_peek_token (parser->lexer)->location, 0,
"%<#pragma cilk grainsize%> is not followed by "
@@ -37108,7 +37164,7 @@ cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
regular lexer. */
static bool
-cp_parser_pragma (cp_parser *parser, enum pragma_context context)
+cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
{
cp_token *pragma_tok;
unsigned int id;
@@ -37266,19 +37322,19 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
if (context != pragma_stmt && context != pragma_compound)
goto bad_stmt;
stmt = push_omp_privatization_clauses (false);
- cp_parser_omp_construct (parser, pragma_tok);
+ cp_parser_omp_construct (parser, pragma_tok, if_p);
pop_omp_privatization_clauses (stmt);
return true;
case PRAGMA_OMP_ORDERED:
stmt = push_omp_privatization_clauses (false);
- ret = cp_parser_omp_ordered (parser, pragma_tok, context);
+ ret = cp_parser_omp_ordered (parser, pragma_tok, context, if_p);
pop_omp_privatization_clauses (stmt);
return ret;
case PRAGMA_OMP_TARGET:
stmt = push_omp_privatization_clauses (false);
- ret = cp_parser_omp_target (parser, pragma_tok, context);
+ ret = cp_parser_omp_target (parser, pragma_tok, context, if_p);
pop_omp_privatization_clauses (stmt);
return ret;
@@ -37310,7 +37366,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
cp_parser_error (parser, "for, while or do statement expected");
return false;
}
- cp_parser_iteration_statement (parser, NULL, true);
+ cp_parser_iteration_statement (parser, if_p, true);
return true;
}
@@ -37322,7 +37378,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
break;
}
stmt = push_omp_privatization_clauses (false);
- cp_parser_cilk_simd (parser, pragma_tok);
+ cp_parser_cilk_simd (parser, pragma_tok, if_p);
pop_omp_privatization_clauses (stmt);
return true;
@@ -37337,7 +37393,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
/* Ignore the pragma if Cilk Plus is not enabled. */
if (flag_cilkplus)
{
- cp_parser_cilk_grainsize (parser, pragma_tok);
+ cp_parser_cilk_grainsize (parser, pragma_tok, if_p);
return true;
}
else
@@ -37664,7 +37720,7 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops. */
static void
-cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
+cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token, bool *if_p)
{
tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
@@ -37680,7 +37736,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
tree sb = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
- tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL);
+ tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL, if_p);
if (ret)
cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret));
cp_parser_end_omp_structured_block (parser, save);
@@ -37692,7 +37748,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
when errors happen and CILK_FOR tree on success. */
static tree
-cp_parser_cilk_for (cp_parser *parser, tree grain)
+cp_parser_cilk_for (cp_parser *parser, tree grain, bool *if_p)
{
if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_CILK_FOR))
gcc_unreachable ();
@@ -37705,7 +37761,7 @@ cp_parser_cilk_for (cp_parser *parser, tree grain)
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
clauses = finish_omp_clauses (clauses, false);
- tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL);
+ tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL, if_p);
if (ret)
cpp_validate_cilk_plus_loop (ret);
else
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2d93a5c9169..4a00530b312 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5655,8 +5655,7 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
as two declarations of the same function, for example. */
if (processing_template_decl
- && !instantiation_dependent_expression_p (expr)
- && potential_constant_expression (expr))
+ && potential_nondependent_constant_expression (expr))
{
processing_template_decl_sentinel s;
expr = instantiate_non_dependent_expr_internal (expr, complain);
@@ -5680,8 +5679,7 @@ instantiate_non_dependent_or_null (tree expr)
return NULL_TREE;
if (processing_template_decl)
{
- if (instantiation_dependent_expression_p (expr)
- || !potential_constant_expression (expr))
+ if (!potential_nondependent_constant_expression (expr))
expr = NULL_TREE;
else
{
@@ -6240,10 +6238,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
if (TYPE_REF_OBJ_P (type)
&& has_value_dependent_address (expr))
/* If we want the address and it's value-dependent, don't fold. */;
- else if (!type_unknown_p (expr)
- && processing_template_decl
- && !instantiation_dependent_expression_p (expr)
- && potential_constant_expression (expr))
+ else if (processing_template_decl
+ && potential_nondependent_constant_expression (expr))
non_dep = true;
if (error_operand_p (expr))
return error_mark_node;
@@ -22674,6 +22670,7 @@ value_dependent_expression_p (tree expression)
&& (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
/* cp_finish_decl doesn't fold reference initializers. */
|| TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
+ || type_dependent_expression_p (DECL_INITIAL (expression))
|| value_dependent_expression_p (DECL_INITIAL (expression))))
return true;
return false;
@@ -22724,7 +22721,7 @@ value_dependent_expression_p (tree expression)
return true;
else if (TYPE_P (expression))
return dependent_type_p (expression);
- return instantiation_dependent_expression_p (expression);
+ return instantiation_dependent_uneval_expression_p (expression);
case AT_ENCODE_EXPR:
/* An 'encode' expression is value-dependent if the operand is
@@ -22734,7 +22731,7 @@ value_dependent_expression_p (tree expression)
case NOEXCEPT_EXPR:
expression = TREE_OPERAND (expression, 0);
- return instantiation_dependent_expression_p (expression);
+ return instantiation_dependent_uneval_expression_p (expression);
case SCOPE_REF:
/* All instantiation-dependent expressions should also be considered
@@ -23105,13 +23102,6 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
case TREE_VEC:
return NULL_TREE;
- case VAR_DECL:
- case CONST_DECL:
- /* A constant with a dependent initializer is dependent. */
- if (value_dependent_expression_p (*tp))
- return *tp;
- break;
-
case TEMPLATE_PARM_INDEX:
return *tp;
@@ -23137,12 +23127,6 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
break;
}
- case TRAIT_EXPR:
- if (value_dependent_expression_p (*tp))
- return *tp;
- *walk_subtrees = false;
- return NULL_TREE;
-
case COMPONENT_REF:
if (identifier_p (TREE_OPERAND (*tp, 1)))
/* In a template, finish_class_member_access_expr creates a
@@ -23193,10 +23177,15 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
"An expression is instantiation-dependent if it is type-dependent
or value-dependent, or it has a subexpression that is type-dependent
- or value-dependent." */
+ or value-dependent."
+
+ Except don't actually check value-dependence for unevaluated expressions,
+ because in sizeof(i) we don't care about the value of i. Checking
+ type-dependence will in turn check value-dependence of array bounds/template
+ arguments as needed. */
bool
-instantiation_dependent_expression_p (tree expression)
+instantiation_dependent_uneval_expression_p (tree expression)
{
tree result;
@@ -23211,6 +23200,15 @@ instantiation_dependent_expression_p (tree expression)
return result != NULL_TREE;
}
+/* As above, but also check value-dependence of the expression as a whole. */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+ return (instantiation_dependent_uneval_expression_p (expression)
+ || value_dependent_expression_p (expression));
+}
+
/* Like type_dependent_expression_p, but it also works while not processing
a template definition, i.e. during substitution or mangling. */
@@ -23598,9 +23596,9 @@ resolve_typename_type (tree type, bool only_current_p)
{
/* Ill-formed programs can cause infinite recursion here, so we
must catch that. */
- TYPENAME_IS_RESOLVING_P (type) = 1;
+ TYPENAME_IS_RESOLVING_P (result) = 1;
result = resolve_typename_type (result, only_current_p);
- TYPENAME_IS_RESOLVING_P (type) = 0;
+ TYPENAME_IS_RESOLVING_P (result) = 0;
}
/* Qualify the resulting type. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1574e60199e..0487adf6018 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8740,7 +8740,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
/* Depending on the resolution of DR 1172, we may later need to distinguish
instantiation-dependent but not type-dependent expressions so that, say,
A<decltype(sizeof(T))>::U doesn't require 'typename'. */
- if (instantiation_dependent_expression_p (expr))
+ if (instantiation_dependent_uneval_expression_p (expr))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e180fa11848..d6f7ff2adcb 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -224,13 +224,7 @@ lvalue_kind (const_tree ref)
return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
case NON_DEPENDENT_EXPR:
- /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but
- in C++11 lvalues don't bind to rvalue references, so we need to
- work harder to avoid bogus errors (c++/44870). */
- if (cxx_dialect < cxx11)
- return clk_ordinary;
- else
- return lvalue_kind (TREE_OPERAND (ref, 0));
+ return lvalue_kind (TREE_OPERAND (ref, 0));
default:
if (!TREE_TYPE (ref))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9e61090f57b..cef5604bd0b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6275,10 +6275,8 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2,
{
tree min = build_min_non_dep (COND_EXPR, expr,
orig_ifexp, orig_op1, orig_op2);
- /* In C++11, remember that the result is an lvalue or xvalue.
- In C++98, lvalue_kind can just assume lvalue in a template. */
- if (cxx_dialect >= cxx11
- && lvalue_or_rvalue_with_address_p (expr)
+ /* Remember that the result is an lvalue or xvalue. */
+ if (lvalue_or_rvalue_with_address_p (expr)
&& !lvalue_or_rvalue_with_address_p (min))
TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min),
!real_lvalue_p (expr));
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index b921689808a..e59ad51c3bd 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -688,14 +688,9 @@ split_nonconstant_init_1 (tree dest, tree init)
code = build_stmt (input_location, EXPR_STMT, code);
code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
- if (type_build_dtor_call (inner_type))
- {
- code = (build_special_member_call
- (sub, complete_dtor_identifier, NULL, inner_type,
- LOOKUP_NORMAL, tf_warning_or_error));
- if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
- finish_eh_cleanup (code);
- }
+ if (tree cleanup
+ = cxx_maybe_build_cleanup (sub, tf_warning_or_error))
+ finish_eh_cleanup (cleanup);
}
num_split_elts++;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 6e2702992c6..a5a8b23df27 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -954,9 +954,13 @@ typedef _Complex float __attribute__((mode(TC))) _Complex128;
typedef _Complex float __attribute__((mode(XC))) _Complex80;
@end smallexample
-On PowerPC 64-bit Linux systems there are currently problems in using
-the complex @code{__float128} type. When these problems are fixed,
-you would use:
+In order to use @code{__float128} and @code{__ibm128} on PowerPC Linux
+systems, you must use the @option{-mfloat128}. It is expected in
+future versions of GCC that @code{__float128} will be enabled
+automatically. In addition, there are currently problems in using the
+complex @code{__float128} type. When these problems are fixed, you
+would use the following syntax to declare @code{_Complex128} to be a
+complex @code{__float128} type:
@smallexample
typedef _Complex float __attribute__((mode(KC))) _Complex128;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index fccd1d125d4..c0588f77e19 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14042,6 +14042,8 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv7ve}, @samp{armv8-a}, @samp{armv8-a+crc}, @samp{armv8.1-a},
@samp{armv8.1-a+crc}, @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
+Architecture revisions older than @option{armv4t} are deprecated.
+
@option{-march=armv7ve} is the armv7-a architecture with virtualization
extensions.
diff --git a/gcc/explow.c b/gcc/explow.c
index 66783cb934a..cfc5cc581c9 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -259,12 +259,14 @@ break_out_memory_refs (rtx x)
which way). We take advantage of the fact that pointers are not allowed to
overflow by commuting arithmetic operations over conversions so that address
arithmetic insns can be used. IN_CONST is true if this conversion is inside
- a CONST. */
+ a CONST. NO_EMIT is true if no insns should be emitted, and instead
+ it should return NULL if it can't be simplified without emitting insns. */
-static rtx
+rtx
convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
rtx x, addr_space_t as ATTRIBUTE_UNUSED,
- bool in_const ATTRIBUTE_UNUSED)
+ bool in_const ATTRIBUTE_UNUSED,
+ bool no_emit ATTRIBUTE_UNUSED)
{
#ifndef POINTERS_EXTEND_UNSIGNED
gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
@@ -310,19 +312,16 @@ convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
temp = gen_rtx_LABEL_REF (to_mode, LABEL_REF_LABEL (x));
LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
return temp;
- break;
case SYMBOL_REF:
temp = shallow_copy_rtx (x);
PUT_MODE (temp, to_mode);
return temp;
- break;
case CONST:
- return gen_rtx_CONST (to_mode,
- convert_memory_address_addr_space_1
- (to_mode, XEXP (x, 0), as, true));
- break;
+ temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0), as,
+ true, no_emit);
+ return temp ? gen_rtx_CONST (to_mode, temp) : temp;
case PLUS:
case MULT:
@@ -338,18 +337,25 @@ convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
&& CONST_INT_P (XEXP (x, 1))
&& ((in_const && POINTERS_EXTEND_UNSIGNED != 0)
|| XEXP (x, 1) == convert_memory_address_addr_space_1
- (to_mode, XEXP (x, 1), as, in_const)
+ (to_mode, XEXP (x, 1), as, in_const,
+ no_emit)
|| POINTERS_EXTEND_UNSIGNED < 0)))
- return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
- convert_memory_address_addr_space_1
- (to_mode, XEXP (x, 0), as, in_const),
- XEXP (x, 1));
+ {
+ temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0),
+ as, in_const, no_emit);
+ return (temp ? gen_rtx_fmt_ee (GET_CODE (x), to_mode,
+ temp, XEXP (x, 1))
+ : temp);
+ }
break;
default:
break;
}
+ if (no_emit)
+ return NULL_RTX;
+
return convert_modes (to_mode, from_mode,
x, POINTERS_EXTEND_UNSIGNED);
#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
@@ -364,7 +370,7 @@ convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
rtx
convert_memory_address_addr_space (machine_mode to_mode, rtx x, addr_space_t as)
{
- return convert_memory_address_addr_space_1 (to_mode, x, as, false);
+ return convert_memory_address_addr_space_1 (to_mode, x, as, false, false);
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 961167b0129..e2f216d2bc6 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,15 @@
+2016-04-13 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/67039
+ * intrinsic.texi: Correct the documentation of pseudorandom
+ number intrinsics.
+
+2016-04-13 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/58000
+ * gfortran.texi: Document OPEN( ... NAME=) as not implemented
+ in GNU Fortran
+
2016-04-09 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/68566
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 257ee7c4e80..2704bc54978 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2148,6 +2148,7 @@ code that uses them running with the GNU Fortran compiler.
@c * Omitted arguments in procedure call::
* Alternate complex function syntax::
* Volatile COMMON blocks::
+* OPEN( ... NAME=)::
@end menu
@@ -2355,6 +2356,19 @@ invalid standard Fortran syntax and is not supported by
+@node OPEN( ... NAME=)
+@subsection @code{OPEN( ... NAME=)}
+@cindex @code{NAM}
+
+Some Fortran compilers, including @command{g77}, let the user declare
+@code{OPEN( ... NAME=)}. This is
+invalid standard Fortran syntax and is not supported by
+@command{gfortran}. @code{OPEN( ... NAME=)} should be replaced
+with @code{OPEN( ... FILE=)}.
+
+
+
+@c ---------------------------------------------------------------------
@c ---------------------------------------------------------------------
@c Mixed-Language Programming
@c ---------------------------------------------------------------------
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index f9760f6a3ab..88406301d9f 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -12628,10 +12628,12 @@ Does not return anything.
See @code{RAND} and @code{IRAND} for examples.
@item @emph{Notes}:
-The Fortran 2003 standard specifies the intrinsic @code{RANDOM_SEED} to
-initialize the pseudo-random numbers generator and @code{RANDOM_NUMBER}
-to generate pseudo-random numbers. Please note that in
-GNU Fortran, these two sets of intrinsics (@code{RAND},
+The Fortran standard specifies the intrinsic subroutines
+@code{RANDOM_SEED} to initialize the pseudo-random number
+generator and @code{RANDOM_NUMBER} to generate pseudo-random numbers.
+These subroutines should be used in new codes.
+
+Please note that in GNU Fortran, these two sets of intrinsics (@code{RAND},
@code{IRAND} and @code{SRAND} on the one hand, @code{RANDOM_NUMBER} and
@code{RANDOM_SEED} on the other hand) access two independent
pseudo-random number generators.
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4d80f96978d..04bd0b208fe 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4164,7 +4164,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
/* Vector types use CONSTRUCTOR all the way through gimple
- compilation as a general initializer. */
+ compilation as a general initializer. */
FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
{
enum gimplify_status tret;
@@ -4172,6 +4172,10 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
fb_rvalue);
if (tret == GS_ERROR)
ret = GS_ERROR;
+ else if (TREE_STATIC (ctor)
+ && !initializer_constant_valid_p (ce->value,
+ TREE_TYPE (ce->value)))
+ TREE_STATIC (ctor) = 0;
}
if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index d7f1dbc734d..ce20dad142f 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-8edf085a94579bd819a10f50328233812ceeb950
+ff29ea8e4e69eb94958aef4388da09a61b2b52b6
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c
index 8dd5dc8bb84..88609c08de9 100644
--- a/gcc/graphite-isl-ast-to-gimple.c
+++ b/gcc/graphite-isl-ast-to-gimple.c
@@ -2439,7 +2439,7 @@ copy_cond_phi_args (gphi *phi, gphi *new_phi, vec<tree> iv_map, bool postpone)
fprintf (dump_file, "\n");
}
gsi_insert_earliest (stmts);
- new_phi_args [i] = new_name;
+ new_phi_args[i] = new_expr;
continue;
}
diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c
index 0ebbd4ae66d..56f334471de 100644
--- a/gcc/ipa-polymorphic-call.c
+++ b/gcc/ipa-polymorphic-call.c
@@ -479,16 +479,12 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset,
}
-/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
+/* Return a FUNCTION_DECL if FN represent a constructor or destructor.
If CHECK_CLONES is true, also check for clones of ctor/dtors. */
tree
-inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
+polymorphic_ctor_dtor_p (tree fn, bool check_clones)
{
- tree fn = block_ultimate_origin (block);
- if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
- return NULL_TREE;
-
if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
|| (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
{
@@ -510,6 +506,19 @@ inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
return fn;
}
+/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
+ If CHECK_CLONES is true, also check for clones of ctor/dtors. */
+
+tree
+inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
+{
+ tree fn = block_ultimate_origin (block);
+ if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+
+ return polymorphic_ctor_dtor_p (fn, check_clones);
+}
+
/* We know that the instance is stored in variable or parameter
(not dynamically allocated) and we want to disprove the fact
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 892bf46d53c..3b3a419a3e3 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1956,10 +1956,25 @@ pass_nothrow::execute (function *)
}
node->set_nothrow_flag (true);
+
+ bool cfg_changed = false;
+ if (self_recursive_p (node))
+ FOR_EACH_BB_FN (this_block, cfun)
+ if (gimple *g = last_stmt (this_block))
+ if (is_gimple_call (g))
+ {
+ tree callee_t = gimple_call_fndecl (g);
+ if (callee_t
+ && recursive_call_p (current_function_decl, callee_t)
+ && maybe_clean_eh_stmt (g)
+ && gimple_purge_dead_eh_edges (this_block))
+ cfg_changed = true;
+ }
+
if (dump_file)
fprintf (dump_file, "Function found to be nothrow: %s\n",
current_function_name ());
- return 0;
+ return cfg_changed ? TODO_cleanup_cfg : 0;
}
} // anon namespace
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 839c6c51444..58d2de7e3c5 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -70,6 +70,7 @@ void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &,
struct cgraph_node *);
+tree polymorphic_ctor_dtor_p (tree, bool);
tree inlined_polymorphic_ctor_dtor_block_p (tree, bool);
bool decl_maybe_in_construction_p (tree, tree, gimple *, tree);
tree vtable_pointer_value_to_binfo (const_tree);
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index 5709ef13e8d..7e5f63785a0 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -528,11 +528,12 @@ spill_pseudos (void)
if (removed_pseudo_p)
{
lra_assert (DEBUG_INSN_P (insn));
- lra_set_insn_deleted (insn);
+ lra_invalidate_insn_data (insn);
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- "Debug insn #%u is deleted as containing removed pseudo\n",
- INSN_UID (insn));
+ "Debug insn #%u is reset because it referenced "
+ "removed pseudo\n", INSN_UID (insn));
}
bitmap_and_compl_into (df_get_live_in (bb), &spilled_pseudos);
bitmap_and_compl_into (df_get_live_out (bb), &spilled_pseudos);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index d25c51f5bc9..7282cc8a382 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5691,7 +5691,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
v3 = build_simple_mem_ref (v3);
outgoing = build_simple_mem_ref (outgoing);
- if (TREE_CODE (incoming) != INTEGER_CST)
+ if (!TREE_CONSTANT (incoming))
incoming = build_simple_mem_ref (incoming);
}
else
@@ -15730,7 +15730,6 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
location_t loc = gimple_location (stmt);
bool offloaded, data_region;
unsigned int map_cnt = 0;
- bool has_depend = false;
offloaded = is_gimple_omp_offloaded (stmt);
switch (gimple_omp_target_kind (stmt))
@@ -15765,7 +15764,6 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
&dep_ilist, &dep_olist);
- has_depend = true;
}
tgt_bind = NULL;
@@ -16280,44 +16278,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
type = TREE_TYPE (ovar);
if (is_reference (ovar))
type = TREE_TYPE (type);
- bool use_firstprivate_int, force_addr;
- use_firstprivate_int = false;
- force_addr = false;
if ((INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) <= POINTER_SIZE)
|| TREE_CODE (type) == POINTER_TYPE)
- use_firstprivate_int = true;
- if (has_depend)
- {
- if (is_reference (var))
- use_firstprivate_int = false;
- else if (is_gimple_reg (var))
- {
- if (DECL_HAS_VALUE_EXPR_P (var))
- {
- tree v = get_base_address (var);
- if (DECL_P (v) && TREE_ADDRESSABLE (v))
- {
- use_firstprivate_int = false;
- force_addr = true;
- }
- else
- switch (TREE_CODE (v))
- {
- case INDIRECT_REF:
- case MEM_REF:
- use_firstprivate_int = false;
- force_addr = true;
- break;
- default:
- break;
- }
- }
- }
- else
- use_firstprivate_int = false;
- }
- if (use_firstprivate_int)
{
tkind = GOMP_MAP_FIRSTPRIVATE_INT;
tree t = var;
@@ -16332,7 +16295,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
else if (is_reference (var))
gimplify_assign (x, var, &ilist);
- else if (!force_addr && is_gimple_reg (var))
+ else if (is_gimple_reg (var))
{
tree avar = create_tmp_var (TREE_TYPE (var));
mark_addressable (avar);
@@ -16470,40 +16433,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
type = TREE_TYPE (var);
if (is_reference (var))
type = TREE_TYPE (type);
- bool use_firstprivate_int;
- use_firstprivate_int = false;
if ((INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) <= POINTER_SIZE)
|| TREE_CODE (type) == POINTER_TYPE)
- use_firstprivate_int = true;
- if (has_depend)
- {
- tree v = lookup_decl_in_outer_ctx (var, ctx);
- if (is_reference (v))
- use_firstprivate_int = false;
- else if (is_gimple_reg (v))
- {
- if (DECL_HAS_VALUE_EXPR_P (v))
- {
- v = get_base_address (v);
- if (DECL_P (v) && TREE_ADDRESSABLE (v))
- use_firstprivate_int = false;
- else
- switch (TREE_CODE (v))
- {
- case INDIRECT_REF:
- case MEM_REF:
- use_firstprivate_int = false;
- break;
- default:
- break;
- }
- }
- }
- else
- use_firstprivate_int = false;
- }
- if (use_firstprivate_int)
{
x = build_receiver_ref (var, false, ctx);
if (TREE_CODE (type) != POINTER_TYPE)
@@ -18477,1612 +18409,6 @@ make_pass_diagnose_omp_blocks (gcc::context *ctxt)
return new pass_diagnose_omp_blocks (ctxt);
}
-/* SIMD clone supporting code. */
-
-/* Allocate a fresh `simd_clone' and return it. NARGS is the number
- of arguments to reserve space for. */
-
-static struct cgraph_simd_clone *
-simd_clone_struct_alloc (int nargs)
-{
- struct cgraph_simd_clone *clone_info;
- size_t len = (sizeof (struct cgraph_simd_clone)
- + nargs * sizeof (struct cgraph_simd_clone_arg));
- clone_info = (struct cgraph_simd_clone *)
- ggc_internal_cleared_alloc (len);
- return clone_info;
-}
-
-/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
-
-static inline void
-simd_clone_struct_copy (struct cgraph_simd_clone *to,
- struct cgraph_simd_clone *from)
-{
- memcpy (to, from, (sizeof (struct cgraph_simd_clone)
- + ((from->nargs - from->inbranch)
- * sizeof (struct cgraph_simd_clone_arg))));
-}
-
-/* Return vector of parameter types of function FNDECL. This uses
- TYPE_ARG_TYPES if available, otherwise falls back to types of
- DECL_ARGUMENTS types. */
-
-vec<tree>
-simd_clone_vector_of_formal_parm_types (tree fndecl)
-{
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
- return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
- vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
- unsigned int i;
- tree arg;
- FOR_EACH_VEC_ELT (args, i, arg)
- args[i] = TREE_TYPE (args[i]);
- return args;
-}
-
-/* Given a simd function in NODE, extract the simd specific
- information from the OMP clauses passed in CLAUSES, and return
- the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
- is set to TRUE if the `inbranch' or `notinbranch' clause specified,
- otherwise set to FALSE. */
-
-static struct cgraph_simd_clone *
-simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
- bool *inbranch_specified)
-{
- vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
- tree t;
- int n;
- *inbranch_specified = false;
-
- n = args.length ();
- if (n > 0 && args.last () == void_type_node)
- n--;
-
- /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
- be cloned have a distinctive artificial label in addition to "omp
- declare simd". */
- bool cilk_clone
- = (flag_cilkplus
- && lookup_attribute ("cilk simd function",
- DECL_ATTRIBUTES (node->decl)));
-
- /* Allocate one more than needed just in case this is an in-branch
- clone which will require a mask argument. */
- struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
- clone_info->nargs = n;
- clone_info->cilk_elemental = cilk_clone;
-
- if (!clauses)
- {
- args.release ();
- return clone_info;
- }
- clauses = TREE_VALUE (clauses);
- if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
- return clone_info;
-
- for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
- {
- switch (OMP_CLAUSE_CODE (t))
- {
- case OMP_CLAUSE_INBRANCH:
- clone_info->inbranch = 1;
- *inbranch_specified = true;
- break;
- case OMP_CLAUSE_NOTINBRANCH:
- clone_info->inbranch = 0;
- *inbranch_specified = true;
- break;
- case OMP_CLAUSE_SIMDLEN:
- clone_info->simdlen
- = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
- break;
- case OMP_CLAUSE_LINEAR:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- tree step = OMP_CLAUSE_LINEAR_STEP (t);
- int argno = TREE_INT_CST_LOW (decl);
- if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
- {
- enum cgraph_simd_clone_arg_type arg_type;
- if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
- switch (OMP_CLAUSE_LINEAR_KIND (t))
- {
- case OMP_CLAUSE_LINEAR_REF:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
- break;
- case OMP_CLAUSE_LINEAR_UVAL:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
- break;
- case OMP_CLAUSE_LINEAR_VAL:
- case OMP_CLAUSE_LINEAR_DEFAULT:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
- break;
- default:
- gcc_unreachable ();
- }
- else
- arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
- clone_info->args[argno].arg_type = arg_type;
- clone_info->args[argno].linear_step = tree_to_shwi (step);
- gcc_assert (clone_info->args[argno].linear_step >= 0
- && clone_info->args[argno].linear_step < n);
- }
- else
- {
- if (POINTER_TYPE_P (args[argno]))
- step = fold_convert (ssizetype, step);
- if (!tree_fits_shwi_p (step))
- {
- warning_at (OMP_CLAUSE_LOCATION (t), 0,
- "ignoring large linear step");
- args.release ();
- return NULL;
- }
- else if (integer_zerop (step))
- {
- warning_at (OMP_CLAUSE_LOCATION (t), 0,
- "ignoring zero linear step");
- args.release ();
- return NULL;
- }
- else
- {
- enum cgraph_simd_clone_arg_type arg_type;
- if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
- switch (OMP_CLAUSE_LINEAR_KIND (t))
- {
- case OMP_CLAUSE_LINEAR_REF:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
- break;
- case OMP_CLAUSE_LINEAR_UVAL:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
- break;
- case OMP_CLAUSE_LINEAR_VAL:
- case OMP_CLAUSE_LINEAR_DEFAULT:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
- break;
- default:
- gcc_unreachable ();
- }
- else
- arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
- clone_info->args[argno].arg_type = arg_type;
- clone_info->args[argno].linear_step = tree_to_shwi (step);
- }
- }
- break;
- }
- case OMP_CLAUSE_UNIFORM:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- int argno = tree_to_uhwi (decl);
- clone_info->args[argno].arg_type
- = SIMD_CLONE_ARG_TYPE_UNIFORM;
- break;
- }
- case OMP_CLAUSE_ALIGNED:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- int argno = tree_to_uhwi (decl);
- clone_info->args[argno].alignment
- = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
- break;
- }
- default:
- break;
- }
- }
- args.release ();
- return clone_info;
-}
-
-/* Given a SIMD clone in NODE, calculate the characteristic data
- type and return the coresponding type. The characteristic data
- type is computed as described in the Intel Vector ABI. */
-
-static tree
-simd_clone_compute_base_data_type (struct cgraph_node *node,
- struct cgraph_simd_clone *clone_info)
-{
- tree type = integer_type_node;
- tree fndecl = node->decl;
-
- /* a) For non-void function, the characteristic data type is the
- return type. */
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
- type = TREE_TYPE (TREE_TYPE (fndecl));
-
- /* b) If the function has any non-uniform, non-linear parameters,
- then the characteristic data type is the type of the first
- such parameter. */
- else
- {
- vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
- for (unsigned int i = 0; i < clone_info->nargs; ++i)
- if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
- {
- type = map[i];
- break;
- }
- map.release ();
- }
-
- /* c) If the characteristic data type determined by a) or b) above
- is struct, union, or class type which is pass-by-value (except
- for the type that maps to the built-in complex data type), the
- characteristic data type is int. */
- if (RECORD_OR_UNION_TYPE_P (type)
- && !aggregate_value_p (type, NULL)
- && TREE_CODE (type) != COMPLEX_TYPE)
- return integer_type_node;
-
- /* d) If none of the above three classes is applicable, the
- characteristic data type is int. */
-
- return type;
-
- /* e) For Intel Xeon Phi native and offload compilation, if the
- resulting characteristic data type is 8-bit or 16-bit integer
- data type, the characteristic data type is int. */
- /* Well, we don't handle Xeon Phi yet. */
-}
-
-static tree
-simd_clone_mangle (struct cgraph_node *node,
- struct cgraph_simd_clone *clone_info)
-{
- char vecsize_mangle = clone_info->vecsize_mangle;
- char mask = clone_info->inbranch ? 'M' : 'N';
- unsigned int simdlen = clone_info->simdlen;
- unsigned int n;
- pretty_printer pp;
-
- gcc_assert (vecsize_mangle && simdlen);
-
- pp_string (&pp, "_ZGV");
- pp_character (&pp, vecsize_mangle);
- pp_character (&pp, mask);
- pp_decimal_int (&pp, simdlen);
-
- for (n = 0; n < clone_info->nargs; ++n)
- {
- struct cgraph_simd_clone_arg arg = clone_info->args[n];
-
- switch (arg.arg_type)
- {
- case SIMD_CLONE_ARG_TYPE_UNIFORM:
- pp_character (&pp, 'u');
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
- pp_character (&pp, 'l');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
- pp_character (&pp, 'R');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- pp_character (&pp, 'L');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- pp_character (&pp, 'U');
- goto mangle_linear;
- mangle_linear:
- gcc_assert (arg.linear_step != 0);
- if (arg.linear_step > 1)
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- else if (arg.linear_step < 0)
- {
- pp_character (&pp, 'n');
- pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
- arg.linear_step));
- }
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
- pp_string (&pp, "ls");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
- pp_string (&pp, "Rs");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- pp_string (&pp, "Ls");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- pp_string (&pp, "Us");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- default:
- pp_character (&pp, 'v');
- }
- if (arg.alignment)
- {
- pp_character (&pp, 'a');
- pp_decimal_int (&pp, arg.alignment);
- }
- }
-
- pp_underscore (&pp);
- const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
- if (*str == '*')
- ++str;
- pp_string (&pp, str);
- str = pp_formatted_text (&pp);
-
- /* If there already is a SIMD clone with the same mangled name, don't
- add another one. This can happen e.g. for
- #pragma omp declare simd
- #pragma omp declare simd simdlen(8)
- int foo (int, int);
- if the simdlen is assumed to be 8 for the first one, etc. */
- for (struct cgraph_node *clone = node->simd_clones; clone;
- clone = clone->simdclone->next_clone)
- if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
- str) == 0)
- return NULL_TREE;
-
- return get_identifier (str);
-}
-
-/* Create a simd clone of OLD_NODE and return it. */
-
-static struct cgraph_node *
-simd_clone_create (struct cgraph_node *old_node)
-{
- struct cgraph_node *new_node;
- if (old_node->definition)
- {
- if (!old_node->has_gimple_body_p ())
- return NULL;
- old_node->get_body ();
- new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
- false, NULL, NULL,
- "simdclone");
- }
- else
- {
- tree old_decl = old_node->decl;
- tree new_decl = copy_node (old_node->decl);
- DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
- SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
- SET_DECL_RTL (new_decl, NULL);
- DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
- DECL_STATIC_DESTRUCTOR (new_decl) = 0;
- new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
- if (old_node->in_other_partition)
- new_node->in_other_partition = 1;
- }
- if (new_node == NULL)
- return new_node;
-
- TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
-
- /* The function cgraph_function_versioning () will force the new
- symbol local. Undo this, and inherit external visability from
- the old node. */
- new_node->local.local = old_node->local.local;
- new_node->externally_visible = old_node->externally_visible;
-
- return new_node;
-}
-
-/* Adjust the return type of the given function to its appropriate
- vector counterpart. Returns a simd array to be used throughout the
- function as a return value. */
-
-static tree
-simd_clone_adjust_return_type (struct cgraph_node *node)
-{
- tree fndecl = node->decl;
- tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
- unsigned int veclen;
- tree t;
-
- /* Adjust the function return type. */
- if (orig_rettype == void_type_node)
- return NULL_TREE;
- TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
- t = TREE_TYPE (TREE_TYPE (fndecl));
- if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
- veclen = node->simdclone->vecsize_int;
- else
- veclen = node->simdclone->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
- if (veclen > node->simdclone->simdlen)
- veclen = node->simdclone->simdlen;
- if (POINTER_TYPE_P (t))
- t = pointer_sized_int_node;
- if (veclen == node->simdclone->simdlen)
- t = build_vector_type (t, node->simdclone->simdlen);
- else
- {
- t = build_vector_type (t, veclen);
- t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
- }
- TREE_TYPE (TREE_TYPE (fndecl)) = t;
- if (!node->definition)
- return NULL_TREE;
-
- t = DECL_RESULT (fndecl);
- /* Adjust the DECL_RESULT. */
- gcc_assert (TREE_TYPE (t) != void_type_node);
- TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
- relayout_decl (t);
-
- tree atype = build_array_type_nelts (orig_rettype,
- node->simdclone->simdlen);
- if (veclen != node->simdclone->simdlen)
- return build1 (VIEW_CONVERT_EXPR, atype, t);
-
- /* Set up a SIMD array to use as the return value. */
- tree retval = create_tmp_var_raw (atype, "retval");
- gimple_add_tmp_var (retval);
- return retval;
-}
-
-/* Each vector argument has a corresponding array to be used locally
- as part of the eventual loop. Create such temporary array and
- return it.
-
- PREFIX is the prefix to be used for the temporary.
-
- TYPE is the inner element type.
-
- SIMDLEN is the number of elements. */
-
-static tree
-create_tmp_simd_array (const char *prefix, tree type, int simdlen)
-{
- tree atype = build_array_type_nelts (type, simdlen);
- tree avar = create_tmp_var_raw (atype, prefix);
- gimple_add_tmp_var (avar);
- return avar;
-}
-
-/* Modify the function argument types to their corresponding vector
- counterparts if appropriate. Also, create one array for each simd
- argument to be used locally when using the function arguments as
- part of the loop.
-
- NODE is the function whose arguments are to be adjusted.
-
- Returns an adjustment vector that will be filled describing how the
- argument types will be adjusted. */
-
-static ipa_parm_adjustment_vec
-simd_clone_adjust_argument_types (struct cgraph_node *node)
-{
- vec<tree> args;
- ipa_parm_adjustment_vec adjustments;
-
- if (node->definition)
- args = ipa_get_vector_of_formal_parms (node->decl);
- else
- args = simd_clone_vector_of_formal_parm_types (node->decl);
- adjustments.create (args.length ());
- unsigned i, j, veclen;
- struct ipa_parm_adjustment adj;
- struct cgraph_simd_clone *sc = node->simdclone;
-
- for (i = 0; i < sc->nargs; ++i)
- {
- memset (&adj, 0, sizeof (adj));
- tree parm = args[i];
- tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
- adj.base_index = i;
- adj.base = parm;
-
- sc->args[i].orig_arg = node->definition ? parm : NULL_TREE;
- sc->args[i].orig_type = parm_type;
-
- switch (sc->args[i].arg_type)
- {
- default:
- /* No adjustment necessary for scalar arguments. */
- adj.op = IPA_PARM_OP_COPY;
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- if (node->definition)
- sc->args[i].simd_array
- = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
- TREE_TYPE (parm_type),
- sc->simdlen);
- adj.op = IPA_PARM_OP_COPY;
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_VECTOR:
- if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
- veclen = sc->vecsize_int;
- else
- veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
- if (veclen > sc->simdlen)
- veclen = sc->simdlen;
- adj.arg_prefix = "simd";
- if (POINTER_TYPE_P (parm_type))
- adj.type = build_vector_type (pointer_sized_int_node, veclen);
- else
- adj.type = build_vector_type (parm_type, veclen);
- sc->args[i].vector_type = adj.type;
- for (j = veclen; j < sc->simdlen; j += veclen)
- {
- adjustments.safe_push (adj);
- if (j == veclen)
- {
- memset (&adj, 0, sizeof (adj));
- adj.op = IPA_PARM_OP_NEW;
- adj.arg_prefix = "simd";
- adj.base_index = i;
- adj.type = sc->args[i].vector_type;
- }
- }
-
- if (node->definition)
- sc->args[i].simd_array
- = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
- parm_type, sc->simdlen);
- }
- adjustments.safe_push (adj);
- }
-
- if (sc->inbranch)
- {
- tree base_type = simd_clone_compute_base_data_type (sc->origin, sc);
-
- memset (&adj, 0, sizeof (adj));
- adj.op = IPA_PARM_OP_NEW;
- adj.arg_prefix = "mask";
-
- adj.base_index = i;
- if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
- veclen = sc->vecsize_int;
- else
- veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
- if (veclen > sc->simdlen)
- veclen = sc->simdlen;
- if (sc->mask_mode != VOIDmode)
- adj.type
- = lang_hooks.types.type_for_mode (sc->mask_mode, 1);
- else if (POINTER_TYPE_P (base_type))
- adj.type = build_vector_type (pointer_sized_int_node, veclen);
- else
- adj.type = build_vector_type (base_type, veclen);
- adjustments.safe_push (adj);
-
- for (j = veclen; j < sc->simdlen; j += veclen)
- adjustments.safe_push (adj);
-
- /* We have previously allocated one extra entry for the mask. Use
- it and fill it. */
- sc->nargs++;
- if (sc->mask_mode != VOIDmode)
- base_type = boolean_type_node;
- if (node->definition)
- {
- sc->args[i].orig_arg
- = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
- if (sc->mask_mode == VOIDmode)
- sc->args[i].simd_array
- = create_tmp_simd_array ("mask", base_type, sc->simdlen);
- else if (veclen < sc->simdlen)
- sc->args[i].simd_array
- = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
- else
- sc->args[i].simd_array = NULL_TREE;
- }
- sc->args[i].orig_type = base_type;
- sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
- }
-
- if (node->definition)
- ipa_modify_formal_parameters (node->decl, adjustments);
- else
- {
- tree new_arg_types = NULL_TREE, new_reversed;
- bool last_parm_void = false;
- if (args.length () > 0 && args.last () == void_type_node)
- last_parm_void = true;
-
- gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
- j = adjustments.length ();
- for (i = 0; i < j; i++)
- {
- struct ipa_parm_adjustment *adj = &adjustments[i];
- tree ptype;
- if (adj->op == IPA_PARM_OP_COPY)
- ptype = args[adj->base_index];
- else
- ptype = adj->type;
- new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
- }
- new_reversed = nreverse (new_arg_types);
- if (last_parm_void)
- {
- if (new_reversed)
- TREE_CHAIN (new_arg_types) = void_list_node;
- else
- new_reversed = void_list_node;
- }
-
- tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
- TYPE_ARG_TYPES (new_type) = new_reversed;
- TREE_TYPE (node->decl) = new_type;
-
- adjustments.release ();
- }
- args.release ();
- return adjustments;
-}
-
-/* Initialize and copy the function arguments in NODE to their
- corresponding local simd arrays. Returns a fresh gimple_seq with
- the instruction sequence generated. */
-
-static gimple_seq
-simd_clone_init_simd_arrays (struct cgraph_node *node,
- ipa_parm_adjustment_vec adjustments)
-{
- gimple_seq seq = NULL;
- unsigned i = 0, j = 0, k;
-
- for (tree arg = DECL_ARGUMENTS (node->decl);
- arg;
- arg = DECL_CHAIN (arg), i++, j++)
- {
- if (adjustments[j].op == IPA_PARM_OP_COPY
- || POINTER_TYPE_P (TREE_TYPE (arg)))
- continue;
-
- node->simdclone->args[i].vector_arg = arg;
-
- tree array = node->simdclone->args[i].simd_array;
- if (node->simdclone->mask_mode != VOIDmode
- && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_MASK)
- {
- if (array == NULL_TREE)
- continue;
- unsigned int l
- = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array))));
- for (k = 0; k <= l; k++)
- {
- if (k)
- {
- arg = DECL_CHAIN (arg);
- j++;
- }
- tree t = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
- array, size_int (k), NULL, NULL);
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- continue;
- }
- if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
- {
- tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
- tree ptr = build_fold_addr_expr (array);
- tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
- build_int_cst (ptype, 0));
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- else
- {
- unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
- tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
- for (k = 0; k < node->simdclone->simdlen; k += simdlen)
- {
- tree ptr = build_fold_addr_expr (array);
- int elemsize;
- if (k)
- {
- arg = DECL_CHAIN (arg);
- j++;
- }
- elemsize
- = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
- tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
- build_int_cst (ptype, k * elemsize));
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- }
- }
- return seq;
-}
-
-/* Callback info for ipa_simd_modify_stmt_ops below. */
-
-struct modify_stmt_info {
- ipa_parm_adjustment_vec adjustments;
- gimple *stmt;
- /* True if the parent statement was modified by
- ipa_simd_modify_stmt_ops. */
- bool modified;
-};
-
-/* Callback for walk_gimple_op.
-
- Adjust operands from a given statement as specified in the
- adjustments vector in the callback data. */
-
-static tree
-ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
-{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
- struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
- tree *orig_tp = tp;
- if (TREE_CODE (*tp) == ADDR_EXPR)
- tp = &TREE_OPERAND (*tp, 0);
- struct ipa_parm_adjustment *cand = NULL;
- if (TREE_CODE (*tp) == PARM_DECL)
- cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
- else
- {
- if (TYPE_P (*tp))
- *walk_subtrees = 0;
- }
-
- tree repl = NULL_TREE;
- if (cand)
- repl = unshare_expr (cand->new_decl);
- else
- {
- if (tp != orig_tp)
- {
- *walk_subtrees = 0;
- bool modified = info->modified;
- info->modified = false;
- walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
- if (!info->modified)
- {
- info->modified = modified;
- return NULL_TREE;
- }
- info->modified = modified;
- repl = *tp;
- }
- else
- return NULL_TREE;
- }
-
- if (tp != orig_tp)
- {
- repl = build_fold_addr_expr (repl);
- gimple *stmt;
- if (is_gimple_debug (info->stmt))
- {
- tree vexpr = make_node (DEBUG_EXPR_DECL);
- stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
- DECL_ARTIFICIAL (vexpr) = 1;
- TREE_TYPE (vexpr) = TREE_TYPE (repl);
- DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
- repl = vexpr;
- }
- else
- {
- stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
- repl = gimple_assign_lhs (stmt);
- }
- gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
- gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- *orig_tp = repl;
- }
- else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
- {
- tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
- *tp = vce;
- }
- else
- *tp = repl;
-
- info->modified = true;
- return NULL_TREE;
-}
-
-/* Traverse the function body and perform all modifications as
- described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
- modified such that the replacement/reduction value will now be an
- offset into the corresponding simd_array.
-
- This function will replace all function argument uses with their
- corresponding simd array elements, and ajust the return values
- accordingly. */
-
-static void
-ipa_simd_modify_function_body (struct cgraph_node *node,
- ipa_parm_adjustment_vec adjustments,
- tree retval_array, tree iter)
-{
- basic_block bb;
- unsigned int i, j, l;
-
- /* Re-use the adjustments array, but this time use it to replace
- every function argument use to an offset into the corresponding
- simd_array. */
- for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
- {
- if (!node->simdclone->args[i].vector_arg)
- continue;
-
- tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
- tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
- adjustments[j].new_decl
- = build4 (ARRAY_REF,
- basetype,
- node->simdclone->args[i].simd_array,
- iter,
- NULL_TREE, NULL_TREE);
- if (adjustments[j].op == IPA_PARM_OP_NONE
- && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
- j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
- }
-
- l = adjustments.length ();
- for (i = 1; i < num_ssa_names; i++)
- {
- tree name = ssa_name (i);
- if (name
- && SSA_NAME_VAR (name)
- && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
- {
- for (j = 0; j < l; j++)
- if (SSA_NAME_VAR (name) == adjustments[j].base
- && adjustments[j].new_decl)
- {
- tree base_var;
- if (adjustments[j].new_ssa_base == NULL_TREE)
- {
- base_var
- = copy_var_decl (adjustments[j].base,
- DECL_NAME (adjustments[j].base),
- TREE_TYPE (adjustments[j].base));
- adjustments[j].new_ssa_base = base_var;
- }
- else
- base_var = adjustments[j].new_ssa_base;
- if (SSA_NAME_IS_DEFAULT_DEF (name))
- {
- bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- gimple_stmt_iterator gsi = gsi_after_labels (bb);
- tree new_decl = unshare_expr (adjustments[j].new_decl);
- set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
- SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
- SSA_NAME_IS_DEFAULT_DEF (name) = 0;
- gimple *stmt = gimple_build_assign (name, new_decl);
- gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- }
- else
- SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
- }
- }
- }
-
- struct modify_stmt_info info;
- info.adjustments = adjustments;
-
- FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
- {
- gimple_stmt_iterator gsi;
-
- gsi = gsi_start_bb (bb);
- while (!gsi_end_p (gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- info.stmt = stmt;
- struct walk_stmt_info wi;
-
- memset (&wi, 0, sizeof (wi));
- info.modified = false;
- wi.info = &info;
- walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
-
- if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
- {
- tree retval = gimple_return_retval (return_stmt);
- if (!retval)
- {
- gsi_remove (&gsi, true);
- continue;
- }
-
- /* Replace `return foo' with `retval_array[iter] = foo'. */
- tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
- retval_array, iter, NULL, NULL);
- stmt = gimple_build_assign (ref, retval);
- gsi_replace (&gsi, stmt, true);
- info.modified = true;
- }
-
- if (info.modified)
- {
- update_stmt (stmt);
- if (maybe_clean_eh_stmt (stmt))
- gimple_purge_dead_eh_edges (gimple_bb (stmt));
- }
- gsi_next (&gsi);
- }
- }
-}
-
-/* Helper function of simd_clone_adjust, return linear step addend
- of Ith argument. */
-
-static tree
-simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
- tree addtype, basic_block entry_bb)
-{
- tree ptype = NULL_TREE;
- switch (node->simdclone->args[i].arg_type)
- {
- case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- return build_int_cst (addtype, node->simdclone->args[i].linear_step);
- case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
- ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
- break;
- default:
- gcc_unreachable ();
- }
-
- unsigned int idx = node->simdclone->args[i].linear_step;
- tree arg = node->simdclone->args[idx].orig_arg;
- gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
- gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
- gimple *g;
- tree ret;
- if (is_gimple_reg (arg))
- ret = get_or_create_ssa_default_def (cfun, arg);
- else
- {
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
- {
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
- build_simple_mem_ref (ret));
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
- {
- g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (POINTER_TYPE_P (ptype))
- {
- tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
- if (size && TREE_CODE (size) == INTEGER_CST)
- {
- g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
- ret, fold_convert (addtype, size));
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- }
- return ret;
-}
-
-/* Adjust the argument types in NODE to their appropriate vector
- counterparts. */
-
-static void
-simd_clone_adjust (struct cgraph_node *node)
-{
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
-
- targetm.simd_clone.adjust (node);
-
- tree retval = simd_clone_adjust_return_type (node);
- ipa_parm_adjustment_vec adjustments
- = simd_clone_adjust_argument_types (node);
-
- push_gimplify_context ();
-
- gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
-
- /* Adjust all uses of vector arguments accordingly. Adjust all
- return values accordingly. */
- tree iter = create_tmp_var (unsigned_type_node, "iter");
- tree iter1 = make_ssa_name (iter);
- tree iter2 = make_ssa_name (iter);
- ipa_simd_modify_function_body (node, adjustments, retval, iter1);
-
- /* Initialize the iteration variable. */
- basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- basic_block body_bb = split_block_after_labels (entry_bb)->dest;
- gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
- /* Insert the SIMD array and iv initialization at function
- entry. */
- gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
-
- pop_gimplify_context (NULL);
-
- /* Create a new BB right before the original exit BB, to hold the
- iteration increment and the condition/branch. */
- basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
- basic_block incr_bb = create_empty_bb (orig_exit);
- add_bb_to_loop (incr_bb, body_bb->loop_father);
- /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
- flag. Set it now to be a FALLTHRU_EDGE. */
- gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
- EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
- for (unsigned i = 0;
- i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
- {
- edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
- redirect_edge_succ (e, incr_bb);
- }
- edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- gsi = gsi_last_bb (incr_bb);
- gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
- build_int_cst (unsigned_type_node, 1));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-
- /* Mostly annotate the loop for the vectorizer (the rest is done below). */
- struct loop *loop = alloc_loop ();
- cfun->has_force_vectorize_loops = true;
- loop->safelen = node->simdclone->simdlen;
- loop->force_vectorize = true;
- loop->header = body_bb;
-
- /* Branch around the body if the mask applies. */
- if (node->simdclone->inbranch)
- {
- gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
- tree mask_array
- = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
- tree mask;
- if (node->simdclone->mask_mode != VOIDmode)
- {
- tree shift_cnt;
- if (mask_array == NULL_TREE)
- {
- tree arg = node->simdclone->args[node->simdclone->nargs
- - 1].vector_arg;
- mask = get_or_create_ssa_default_def (cfun, arg);
- shift_cnt = iter1;
- }
- else
- {
- tree maskt = TREE_TYPE (mask_array);
- int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
- c = node->simdclone->simdlen / (c + 1);
- int s = exact_log2 (c);
- gcc_assert (s > 0);
- c--;
- tree idx = make_ssa_name (TREE_TYPE (iter1));
- g = gimple_build_assign (idx, RSHIFT_EXPR, iter1,
- build_int_cst (NULL_TREE, s));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
- tree aref = build4 (ARRAY_REF,
- TREE_TYPE (TREE_TYPE (mask_array)),
- mask_array, idx, NULL, NULL);
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- shift_cnt = make_ssa_name (TREE_TYPE (iter1));
- g = gimple_build_assign (shift_cnt, BIT_AND_EXPR, iter1,
- build_int_cst (TREE_TYPE (iter1), c));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- }
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
- RSHIFT_EXPR, mask, shift_cnt);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = gimple_assign_lhs (g);
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
- BIT_AND_EXPR, mask,
- build_int_cst (TREE_TYPE (mask), 1));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = gimple_assign_lhs (g);
- }
- else
- {
- mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
- tree aref = build4 (ARRAY_REF,
- TREE_TYPE (TREE_TYPE (mask_array)),
- mask_array, iter1, NULL, NULL);
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
- if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
- {
- aref = build1 (VIEW_CONVERT_EXPR,
- build_nonstandard_integer_type (bitsize, 0),
- mask);
- mask = make_ssa_name (TREE_TYPE (aref));
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- }
- }
-
- g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
- NULL, NULL);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
- FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
- }
-
- /* Generate the condition. */
- g = gimple_build_cond (LT_EXPR,
- iter2,
- build_int_cst (unsigned_type_node,
- node->simdclone->simdlen),
- NULL, NULL);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- e = split_block (incr_bb, gsi_stmt (gsi));
- basic_block latch_bb = e->dest;
- basic_block new_exit_bb;
- new_exit_bb = split_block_after_labels (latch_bb)->dest;
- loop->latch = latch_bb;
-
- redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
-
- make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
- /* The successor of incr_bb is already pointing to latch_bb; just
- change the flags.
- make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
- FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
-
- gphi *phi = create_phi_node (iter1, body_bb);
- edge preheader_edge = find_edge (entry_bb, body_bb);
- edge latch_edge = single_succ_edge (latch_bb);
- add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
- UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
-
- /* Generate the new return. */
- gsi = gsi_last_bb (new_exit_bb);
- if (retval
- && TREE_CODE (retval) == VIEW_CONVERT_EXPR
- && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
- retval = TREE_OPERAND (retval, 0);
- else if (retval)
- {
- retval = build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (TREE_TYPE (node->decl)),
- retval);
- retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
- false, GSI_CONTINUE_LINKING);
- }
- g = gimple_build_return (retval);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-
- /* Handle aligned clauses by replacing default defs of the aligned
- uniform args with __builtin_assume_aligned (arg_N(D), alignment)
- lhs. Handle linear by adding PHIs. */
- for (unsigned i = 0; i < node->simdclone->nargs; i++)
- if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
- && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
- || !is_gimple_reg_type
- (TREE_TYPE (node->simdclone->args[i].orig_arg))))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
- iter1 = make_ssa_name (TREE_TYPE (orig_arg));
- else
- {
- iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
- gimple_add_tmp_var (iter1);
- }
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (iter1, orig_arg);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (orig_arg, iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
- && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
- && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
- == REFERENCE_TYPE
- && TREE_ADDRESSABLE
- (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- if (def && !has_zero_uses (def))
- {
- iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
- gimple_add_tmp_var (iter1);
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (iter1, build_simple_mem_ref (def));
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (build_simple_mem_ref (def), iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- }
- else if (node->simdclone->args[i].alignment
- && node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_UNIFORM
- && (node->simdclone->args[i].alignment
- & (node->simdclone->args[i].alignment - 1)) == 0
- && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
- == POINTER_TYPE)
- {
- unsigned int alignment = node->simdclone->args[i].alignment;
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- if (def && !has_zero_uses (def))
- {
- tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
- gimple_seq seq = NULL;
- bool need_cvt = false;
- gcall *call
- = gimple_build_call (fn, 2, def, size_int (alignment));
- g = call;
- if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
- ptr_type_node))
- need_cvt = true;
- tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
- gimple_call_set_lhs (g, t);
- gimple_seq_add_stmt_without_update (&seq, g);
- if (need_cvt)
- {
- t = make_ssa_name (orig_arg);
- g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
- gimple_seq_add_stmt_without_update (&seq, g);
- }
- gsi_insert_seq_on_edge_immediate
- (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
-
- entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- int freq = compute_call_stmt_bb_frequency (current_function_decl,
- entry_bb);
- node->create_edge (cgraph_node::get_create (fn),
- call, entry_bb->count, freq);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- tree repl = gimple_get_lhs (g);
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (is_gimple_debug (use_stmt) || use_stmt == call)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, repl);
- }
- }
- else if ((node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
- tree def = NULL_TREE;
- if (TREE_ADDRESSABLE (orig_arg))
- {
- def = make_ssa_name (TREE_TYPE (orig_arg));
- iter1 = make_ssa_name (TREE_TYPE (orig_arg));
- iter2 = make_ssa_name (TREE_TYPE (orig_arg));
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (def, orig_arg);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else
- {
- def = ssa_default_def (cfun, orig_arg);
- if (!def || has_zero_uses (def))
- def = NULL_TREE;
- else
- {
- iter1 = make_ssa_name (orig_arg);
- iter2 = make_ssa_name (orig_arg);
- }
- }
- if (def)
- {
- phi = create_phi_node (iter1, body_bb);
- add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
- enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- ? PLUS_EXPR : POINTER_PLUS_EXPR;
- tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- ? TREE_TYPE (orig_arg) : sizetype;
- tree addcst = simd_clone_linear_addend (node, i, addtype,
- entry_bb);
- gsi = gsi_last_bb (incr_bb);
- g = gimple_build_assign (iter2, code, iter1, addcst);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- if (TREE_ADDRESSABLE (orig_arg))
- {
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (orig_arg, iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (use_stmt == phi)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, iter1);
- }
- }
- else if (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- gcc_assert (!TREE_ADDRESSABLE (orig_arg)
- && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
- if (def && !has_zero_uses (def))
- {
- tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
- iter1 = make_ssa_name (orig_arg);
- iter2 = make_ssa_name (orig_arg);
- tree iter3 = make_ssa_name (rtype);
- tree iter4 = make_ssa_name (rtype);
- tree iter5 = make_ssa_name (rtype);
- gsi = gsi_after_labels (entry_bb);
- gimple *load
- = gimple_build_assign (iter3, build_simple_mem_ref (def));
- gsi_insert_before (&gsi, load, GSI_NEW_STMT);
-
- tree array = node->simdclone->args[i].simd_array;
- TREE_ADDRESSABLE (array) = 1;
- tree ptr = build_fold_addr_expr (array);
- phi = create_phi_node (iter1, body_bb);
- add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
- g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
- TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
- gsi = gsi_last_bb (incr_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- phi = create_phi_node (iter4, body_bb);
- add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
- enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
- ? PLUS_EXPR : POINTER_PLUS_EXPR;
- tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
- ? TREE_TYPE (iter3) : sizetype;
- tree addcst = simd_clone_linear_addend (node, i, addtype,
- entry_bb);
- g = gimple_build_assign (iter5, code, iter4, addcst);
- gsi = gsi_last_bb (incr_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
- gsi = gsi_after_labels (body_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (use_stmt == load)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, iter1);
-
- if (!TYPE_READONLY (rtype))
- {
- tree v = make_ssa_name (rtype);
- tree aref = build4 (ARRAY_REF, rtype, array,
- size_zero_node, NULL_TREE,
- NULL_TREE);
- gsi = gsi_after_labels (new_exit_bb);
- g = gimple_build_assign (v, aref);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- g = gimple_build_assign (build_simple_mem_ref (def), v);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- }
- }
- }
-
- calculate_dominance_info (CDI_DOMINATORS);
- add_loop (loop, loop->header->loop_father);
- update_ssa (TODO_update_ssa);
-
- pop_cfun ();
-}
-
-/* If the function in NODE is tagged as an elemental SIMD function,
- create the appropriate SIMD clones. */
-
-static void
-expand_simd_clones (struct cgraph_node *node)
-{
- tree attr = lookup_attribute ("omp declare simd",
- DECL_ATTRIBUTES (node->decl));
- if (attr == NULL_TREE
- || node->global.inlined_to
- || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
- return;
-
- /* Ignore
- #pragma omp declare simd
- extern int foo ();
- in C, there we don't know the argument types at all. */
- if (!node->definition
- && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
- return;
-
- /* Call this before creating clone_info, as it might ggc_collect. */
- if (node->definition && node->has_gimple_body_p ())
- node->get_body ();
-
- do
- {
- /* Start with parsing the "omp declare simd" attribute(s). */
- bool inbranch_clause_specified;
- struct cgraph_simd_clone *clone_info
- = simd_clone_clauses_extract (node, TREE_VALUE (attr),
- &inbranch_clause_specified);
- if (clone_info == NULL)
- continue;
-
- int orig_simdlen = clone_info->simdlen;
- tree base_type = simd_clone_compute_base_data_type (node, clone_info);
- /* The target can return 0 (no simd clones should be created),
- 1 (just one ISA of simd clones should be created) or higher
- count of ISA variants. In that case, clone_info is initialized
- for the first ISA variant. */
- int count
- = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
- base_type, 0);
- if (count == 0)
- continue;
-
- /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
- also create one inbranch and one !inbranch clone of it. */
- for (int i = 0; i < count * 2; i++)
- {
- struct cgraph_simd_clone *clone = clone_info;
- if (inbranch_clause_specified && (i & 1) != 0)
- continue;
-
- if (i != 0)
- {
- clone = simd_clone_struct_alloc (clone_info->nargs
- + ((i & 1) != 0));
- simd_clone_struct_copy (clone, clone_info);
- /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
- and simd_clone_adjust_argument_types did to the first
- clone's info. */
- clone->nargs -= clone_info->inbranch;
- clone->simdlen = orig_simdlen;
- /* And call the target hook again to get the right ISA. */
- targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
- base_type,
- i / 2);
- if ((i & 1) != 0)
- clone->inbranch = 1;
- }
-
- /* simd_clone_mangle might fail if such a clone has been created
- already. */
- tree id = simd_clone_mangle (node, clone);
- if (id == NULL_TREE)
- continue;
-
- /* Only when we are sure we want to create the clone actually
- clone the function (or definitions) or create another
- extern FUNCTION_DECL (for prototypes without definitions). */
- struct cgraph_node *n = simd_clone_create (node);
- if (n == NULL)
- continue;
-
- n->simdclone = clone;
- clone->origin = node;
- clone->next_clone = NULL;
- if (node->simd_clones == NULL)
- {
- clone->prev_clone = n;
- node->simd_clones = n;
- }
- else
- {
- clone->prev_clone = node->simd_clones->simdclone->prev_clone;
- clone->prev_clone->simdclone->next_clone = n;
- node->simd_clones->simdclone->prev_clone = n;
- }
- symtab->change_decl_assembler_name (n->decl, id);
- /* And finally adjust the return type, parameters and for
- definitions also function body. */
- if (node->definition)
- simd_clone_adjust (n);
- else
- {
- simd_clone_adjust_return_type (n);
- simd_clone_adjust_argument_types (n);
- }
- }
- }
- while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
-}
-
-/* Entry point for IPA simd clone creation pass. */
-
-static unsigned int
-ipa_omp_simd_clone (void)
-{
- struct cgraph_node *node;
- FOR_EACH_FUNCTION (node)
- expand_simd_clones (node);
- return 0;
-}
-
-namespace {
-
-const pass_data pass_data_omp_simd_clone =
-{
- SIMPLE_IPA_PASS, /* type */
- "simdclone", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_NONE, /* tv_id */
- ( PROP_ssa | PROP_cfg ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_omp_simd_clone : public simple_ipa_opt_pass
-{
-public:
- pass_omp_simd_clone(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *);
- virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
-};
-
-bool
-pass_omp_simd_clone::gate (function *)
-{
- return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
-}
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_omp_simd_clone (gcc::context *ctxt)
-{
- return new pass_omp_simd_clone (ctxt);
-}
-
/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
adds their addresses and sizes to constructor-vector V_CTOR. */
static void
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
new file mode 100644
index 00000000000..fa6ffecb4c2
--- /dev/null
+++ b/gcc/omp-simd-clone.c
@@ -0,0 +1,1654 @@
+/* OMP constructs' SIMD clone supporting code.
+
+Copyright (C) 2005-2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "cgraph.h"
+#include "pretty-print.h"
+#include "diagnostic-core.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "cfganal.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimplify-me.h"
+#include "gimple-walk.h"
+#include "langhooks.h"
+#include "tree-cfg.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
+#include "cfgloop.h"
+#include "symbol-summary.h"
+#include "ipa-prop.h"
+#include "tree-eh.h"
+
+
+/* Allocate a fresh `simd_clone' and return it. NARGS is the number
+ of arguments to reserve space for. */
+
+static struct cgraph_simd_clone *
+simd_clone_struct_alloc (int nargs)
+{
+ struct cgraph_simd_clone *clone_info;
+ size_t len = (sizeof (struct cgraph_simd_clone)
+ + nargs * sizeof (struct cgraph_simd_clone_arg));
+ clone_info = (struct cgraph_simd_clone *)
+ ggc_internal_cleared_alloc (len);
+ return clone_info;
+}
+
+/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
+
+static inline void
+simd_clone_struct_copy (struct cgraph_simd_clone *to,
+ struct cgraph_simd_clone *from)
+{
+ memcpy (to, from, (sizeof (struct cgraph_simd_clone)
+ + ((from->nargs - from->inbranch)
+ * sizeof (struct cgraph_simd_clone_arg))));
+}
+
+/* Return vector of parameter types of function FNDECL. This uses
+ TYPE_ARG_TYPES if available, otherwise falls back to types of
+ DECL_ARGUMENTS types. */
+
+static vec<tree>
+simd_clone_vector_of_formal_parm_types (tree fndecl)
+{
+ if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
+ vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
+ unsigned int i;
+ tree arg;
+ FOR_EACH_VEC_ELT (args, i, arg)
+ args[i] = TREE_TYPE (args[i]);
+ return args;
+}
+
+/* Given a simd function in NODE, extract the simd specific
+ information from the OMP clauses passed in CLAUSES, and return
+ the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
+ is set to TRUE if the `inbranch' or `notinbranch' clause specified,
+ otherwise set to FALSE. */
+
+static struct cgraph_simd_clone *
+simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
+ bool *inbranch_specified)
+{
+ vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
+ tree t;
+ int n;
+ *inbranch_specified = false;
+
+ n = args.length ();
+ if (n > 0 && args.last () == void_type_node)
+ n--;
+
+ /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
+ be cloned have a distinctive artificial label in addition to "omp
+ declare simd". */
+ bool cilk_clone
+ = (flag_cilkplus
+ && lookup_attribute ("cilk simd function",
+ DECL_ATTRIBUTES (node->decl)));
+
+ /* Allocate one more than needed just in case this is an in-branch
+ clone which will require a mask argument. */
+ struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
+ clone_info->nargs = n;
+ clone_info->cilk_elemental = cilk_clone;
+
+ if (!clauses)
+ {
+ args.release ();
+ return clone_info;
+ }
+ clauses = TREE_VALUE (clauses);
+ if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
+ return clone_info;
+
+ for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
+ {
+ switch (OMP_CLAUSE_CODE (t))
+ {
+ case OMP_CLAUSE_INBRANCH:
+ clone_info->inbranch = 1;
+ *inbranch_specified = true;
+ break;
+ case OMP_CLAUSE_NOTINBRANCH:
+ clone_info->inbranch = 0;
+ *inbranch_specified = true;
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ clone_info->simdlen
+ = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
+ break;
+ case OMP_CLAUSE_LINEAR:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ tree step = OMP_CLAUSE_LINEAR_STEP (t);
+ int argno = TREE_INT_CST_LOW (decl);
+ if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
+ {
+ enum cgraph_simd_clone_arg_type arg_type;
+ if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
+ switch (OMP_CLAUSE_LINEAR_KIND (t))
+ {
+ case OMP_CLAUSE_LINEAR_REF:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_UVAL:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_VAL:
+ case OMP_CLAUSE_LINEAR_DEFAULT:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ else
+ arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
+ clone_info->args[argno].arg_type = arg_type;
+ clone_info->args[argno].linear_step = tree_to_shwi (step);
+ gcc_assert (clone_info->args[argno].linear_step >= 0
+ && clone_info->args[argno].linear_step < n);
+ }
+ else
+ {
+ if (POINTER_TYPE_P (args[argno]))
+ step = fold_convert (ssizetype, step);
+ if (!tree_fits_shwi_p (step))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (t), 0,
+ "ignoring large linear step");
+ args.release ();
+ return NULL;
+ }
+ else if (integer_zerop (step))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (t), 0,
+ "ignoring zero linear step");
+ args.release ();
+ return NULL;
+ }
+ else
+ {
+ enum cgraph_simd_clone_arg_type arg_type;
+ if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
+ switch (OMP_CLAUSE_LINEAR_KIND (t))
+ {
+ case OMP_CLAUSE_LINEAR_REF:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_UVAL:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_VAL:
+ case OMP_CLAUSE_LINEAR_DEFAULT:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ else
+ arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
+ clone_info->args[argno].arg_type = arg_type;
+ clone_info->args[argno].linear_step = tree_to_shwi (step);
+ }
+ }
+ break;
+ }
+ case OMP_CLAUSE_UNIFORM:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ int argno = tree_to_uhwi (decl);
+ clone_info->args[argno].arg_type
+ = SIMD_CLONE_ARG_TYPE_UNIFORM;
+ break;
+ }
+ case OMP_CLAUSE_ALIGNED:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ int argno = tree_to_uhwi (decl);
+ clone_info->args[argno].alignment
+ = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ args.release ();
+ return clone_info;
+}
+
+/* Given a SIMD clone in NODE, calculate the characteristic data
+ type and return the coresponding type. The characteristic data
+ type is computed as described in the Intel Vector ABI. */
+
+static tree
+simd_clone_compute_base_data_type (struct cgraph_node *node,
+ struct cgraph_simd_clone *clone_info)
+{
+ tree type = integer_type_node;
+ tree fndecl = node->decl;
+
+ /* a) For non-void function, the characteristic data type is the
+ return type. */
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
+ type = TREE_TYPE (TREE_TYPE (fndecl));
+
+ /* b) If the function has any non-uniform, non-linear parameters,
+ then the characteristic data type is the type of the first
+ such parameter. */
+ else
+ {
+ vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
+ for (unsigned int i = 0; i < clone_info->nargs; ++i)
+ if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
+ {
+ type = map[i];
+ break;
+ }
+ map.release ();
+ }
+
+ /* c) If the characteristic data type determined by a) or b) above
+ is struct, union, or class type which is pass-by-value (except
+ for the type that maps to the built-in complex data type), the
+ characteristic data type is int. */
+ if (RECORD_OR_UNION_TYPE_P (type)
+ && !aggregate_value_p (type, NULL)
+ && TREE_CODE (type) != COMPLEX_TYPE)
+ return integer_type_node;
+
+ /* d) If none of the above three classes is applicable, the
+ characteristic data type is int. */
+
+ return type;
+
+ /* e) For Intel Xeon Phi native and offload compilation, if the
+ resulting characteristic data type is 8-bit or 16-bit integer
+ data type, the characteristic data type is int. */
+ /* Well, we don't handle Xeon Phi yet. */
+}
+
+static tree
+simd_clone_mangle (struct cgraph_node *node,
+ struct cgraph_simd_clone *clone_info)
+{
+ char vecsize_mangle = clone_info->vecsize_mangle;
+ char mask = clone_info->inbranch ? 'M' : 'N';
+ unsigned int simdlen = clone_info->simdlen;
+ unsigned int n;
+ pretty_printer pp;
+
+ gcc_assert (vecsize_mangle && simdlen);
+
+ pp_string (&pp, "_ZGV");
+ pp_character (&pp, vecsize_mangle);
+ pp_character (&pp, mask);
+ pp_decimal_int (&pp, simdlen);
+
+ for (n = 0; n < clone_info->nargs; ++n)
+ {
+ struct cgraph_simd_clone_arg arg = clone_info->args[n];
+
+ switch (arg.arg_type)
+ {
+ case SIMD_CLONE_ARG_TYPE_UNIFORM:
+ pp_character (&pp, 'u');
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
+ pp_character (&pp, 'l');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
+ pp_character (&pp, 'R');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ pp_character (&pp, 'L');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ pp_character (&pp, 'U');
+ goto mangle_linear;
+ mangle_linear:
+ gcc_assert (arg.linear_step != 0);
+ if (arg.linear_step > 1)
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ else if (arg.linear_step < 0)
+ {
+ pp_character (&pp, 'n');
+ pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
+ arg.linear_step));
+ }
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
+ pp_string (&pp, "ls");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
+ pp_string (&pp, "Rs");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ pp_string (&pp, "Ls");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ pp_string (&pp, "Us");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ default:
+ pp_character (&pp, 'v');
+ }
+ if (arg.alignment)
+ {
+ pp_character (&pp, 'a');
+ pp_decimal_int (&pp, arg.alignment);
+ }
+ }
+
+ pp_underscore (&pp);
+ const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
+ if (*str == '*')
+ ++str;
+ pp_string (&pp, str);
+ str = pp_formatted_text (&pp);
+
+ /* If there already is a SIMD clone with the same mangled name, don't
+ add another one. This can happen e.g. for
+ #pragma omp declare simd
+ #pragma omp declare simd simdlen(8)
+ int foo (int, int);
+ if the simdlen is assumed to be 8 for the first one, etc. */
+ for (struct cgraph_node *clone = node->simd_clones; clone;
+ clone = clone->simdclone->next_clone)
+ if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
+ str) == 0)
+ return NULL_TREE;
+
+ return get_identifier (str);
+}
+
+/* Create a simd clone of OLD_NODE and return it. */
+
+static struct cgraph_node *
+simd_clone_create (struct cgraph_node *old_node)
+{
+ struct cgraph_node *new_node;
+ if (old_node->definition)
+ {
+ if (!old_node->has_gimple_body_p ())
+ return NULL;
+ old_node->get_body ();
+ new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
+ false, NULL, NULL,
+ "simdclone");
+ }
+ else
+ {
+ tree old_decl = old_node->decl;
+ tree new_decl = copy_node (old_node->decl);
+ DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
+ SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
+ SET_DECL_RTL (new_decl, NULL);
+ DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
+ DECL_STATIC_DESTRUCTOR (new_decl) = 0;
+ new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
+ if (old_node->in_other_partition)
+ new_node->in_other_partition = 1;
+ }
+ if (new_node == NULL)
+ return new_node;
+
+ TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
+
+ /* The function cgraph_function_versioning () will force the new
+ symbol local. Undo this, and inherit external visability from
+ the old node. */
+ new_node->local.local = old_node->local.local;
+ new_node->externally_visible = old_node->externally_visible;
+
+ return new_node;
+}
+
+/* Adjust the return type of the given function to its appropriate
+ vector counterpart. Returns a simd array to be used throughout the
+ function as a return value. */
+
+static tree
+simd_clone_adjust_return_type (struct cgraph_node *node)
+{
+ tree fndecl = node->decl;
+ tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
+ unsigned int veclen;
+ tree t;
+
+ /* Adjust the function return type. */
+ if (orig_rettype == void_type_node)
+ return NULL_TREE;
+ TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
+ t = TREE_TYPE (TREE_TYPE (fndecl));
+ if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
+ veclen = node->simdclone->vecsize_int;
+ else
+ veclen = node->simdclone->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
+ if (veclen > node->simdclone->simdlen)
+ veclen = node->simdclone->simdlen;
+ if (POINTER_TYPE_P (t))
+ t = pointer_sized_int_node;
+ if (veclen == node->simdclone->simdlen)
+ t = build_vector_type (t, node->simdclone->simdlen);
+ else
+ {
+ t = build_vector_type (t, veclen);
+ t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
+ }
+ TREE_TYPE (TREE_TYPE (fndecl)) = t;
+ if (!node->definition)
+ return NULL_TREE;
+
+ t = DECL_RESULT (fndecl);
+ /* Adjust the DECL_RESULT. */
+ gcc_assert (TREE_TYPE (t) != void_type_node);
+ TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
+ relayout_decl (t);
+
+ tree atype = build_array_type_nelts (orig_rettype,
+ node->simdclone->simdlen);
+ if (veclen != node->simdclone->simdlen)
+ return build1 (VIEW_CONVERT_EXPR, atype, t);
+
+ /* Set up a SIMD array to use as the return value. */
+ tree retval = create_tmp_var_raw (atype, "retval");
+ gimple_add_tmp_var (retval);
+ return retval;
+}
+
+/* Each vector argument has a corresponding array to be used locally
+ as part of the eventual loop. Create such temporary array and
+ return it.
+
+ PREFIX is the prefix to be used for the temporary.
+
+ TYPE is the inner element type.
+
+ SIMDLEN is the number of elements. */
+
+static tree
+create_tmp_simd_array (const char *prefix, tree type, int simdlen)
+{
+ tree atype = build_array_type_nelts (type, simdlen);
+ tree avar = create_tmp_var_raw (atype, prefix);
+ gimple_add_tmp_var (avar);
+ return avar;
+}
+
+/* Modify the function argument types to their corresponding vector
+ counterparts if appropriate. Also, create one array for each simd
+ argument to be used locally when using the function arguments as
+ part of the loop.
+
+ NODE is the function whose arguments are to be adjusted.
+
+ Returns an adjustment vector that will be filled describing how the
+ argument types will be adjusted. */
+
+static ipa_parm_adjustment_vec
+simd_clone_adjust_argument_types (struct cgraph_node *node)
+{
+ vec<tree> args;
+ ipa_parm_adjustment_vec adjustments;
+
+ if (node->definition)
+ args = ipa_get_vector_of_formal_parms (node->decl);
+ else
+ args = simd_clone_vector_of_formal_parm_types (node->decl);
+ adjustments.create (args.length ());
+ unsigned i, j, veclen;
+ struct ipa_parm_adjustment adj;
+ struct cgraph_simd_clone *sc = node->simdclone;
+
+ for (i = 0; i < sc->nargs; ++i)
+ {
+ memset (&adj, 0, sizeof (adj));
+ tree parm = args[i];
+ tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
+ adj.base_index = i;
+ adj.base = parm;
+
+ sc->args[i].orig_arg = node->definition ? parm : NULL_TREE;
+ sc->args[i].orig_type = parm_type;
+
+ switch (sc->args[i].arg_type)
+ {
+ default:
+ /* No adjustment necessary for scalar arguments. */
+ adj.op = IPA_PARM_OP_COPY;
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ if (node->definition)
+ sc->args[i].simd_array
+ = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
+ TREE_TYPE (parm_type),
+ sc->simdlen);
+ adj.op = IPA_PARM_OP_COPY;
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_VECTOR:
+ if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
+ veclen = sc->vecsize_int;
+ else
+ veclen = sc->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
+ if (veclen > sc->simdlen)
+ veclen = sc->simdlen;
+ adj.arg_prefix = "simd";
+ if (POINTER_TYPE_P (parm_type))
+ adj.type = build_vector_type (pointer_sized_int_node, veclen);
+ else
+ adj.type = build_vector_type (parm_type, veclen);
+ sc->args[i].vector_type = adj.type;
+ for (j = veclen; j < sc->simdlen; j += veclen)
+ {
+ adjustments.safe_push (adj);
+ if (j == veclen)
+ {
+ memset (&adj, 0, sizeof (adj));
+ adj.op = IPA_PARM_OP_NEW;
+ adj.arg_prefix = "simd";
+ adj.base_index = i;
+ adj.type = sc->args[i].vector_type;
+ }
+ }
+
+ if (node->definition)
+ sc->args[i].simd_array
+ = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
+ parm_type, sc->simdlen);
+ }
+ adjustments.safe_push (adj);
+ }
+
+ if (sc->inbranch)
+ {
+ tree base_type = simd_clone_compute_base_data_type (sc->origin, sc);
+
+ memset (&adj, 0, sizeof (adj));
+ adj.op = IPA_PARM_OP_NEW;
+ adj.arg_prefix = "mask";
+
+ adj.base_index = i;
+ if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
+ veclen = sc->vecsize_int;
+ else
+ veclen = sc->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
+ if (veclen > sc->simdlen)
+ veclen = sc->simdlen;
+ if (sc->mask_mode != VOIDmode)
+ adj.type
+ = lang_hooks.types.type_for_mode (sc->mask_mode, 1);
+ else if (POINTER_TYPE_P (base_type))
+ adj.type = build_vector_type (pointer_sized_int_node, veclen);
+ else
+ adj.type = build_vector_type (base_type, veclen);
+ adjustments.safe_push (adj);
+
+ for (j = veclen; j < sc->simdlen; j += veclen)
+ adjustments.safe_push (adj);
+
+ /* We have previously allocated one extra entry for the mask. Use
+ it and fill it. */
+ sc->nargs++;
+ if (sc->mask_mode != VOIDmode)
+ base_type = boolean_type_node;
+ if (node->definition)
+ {
+ sc->args[i].orig_arg
+ = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
+ if (sc->mask_mode == VOIDmode)
+ sc->args[i].simd_array
+ = create_tmp_simd_array ("mask", base_type, sc->simdlen);
+ else if (veclen < sc->simdlen)
+ sc->args[i].simd_array
+ = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
+ else
+ sc->args[i].simd_array = NULL_TREE;
+ }
+ sc->args[i].orig_type = base_type;
+ sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
+ }
+
+ if (node->definition)
+ ipa_modify_formal_parameters (node->decl, adjustments);
+ else
+ {
+ tree new_arg_types = NULL_TREE, new_reversed;
+ bool last_parm_void = false;
+ if (args.length () > 0 && args.last () == void_type_node)
+ last_parm_void = true;
+
+ gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
+ j = adjustments.length ();
+ for (i = 0; i < j; i++)
+ {
+ struct ipa_parm_adjustment *adj = &adjustments[i];
+ tree ptype;
+ if (adj->op == IPA_PARM_OP_COPY)
+ ptype = args[adj->base_index];
+ else
+ ptype = adj->type;
+ new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
+ }
+ new_reversed = nreverse (new_arg_types);
+ if (last_parm_void)
+ {
+ if (new_reversed)
+ TREE_CHAIN (new_arg_types) = void_list_node;
+ else
+ new_reversed = void_list_node;
+ }
+
+ tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
+ TYPE_ARG_TYPES (new_type) = new_reversed;
+ TREE_TYPE (node->decl) = new_type;
+
+ adjustments.release ();
+ }
+ args.release ();
+ return adjustments;
+}
+
+/* Initialize and copy the function arguments in NODE to their
+ corresponding local simd arrays. Returns a fresh gimple_seq with
+ the instruction sequence generated. */
+
+static gimple_seq
+simd_clone_init_simd_arrays (struct cgraph_node *node,
+ ipa_parm_adjustment_vec adjustments)
+{
+ gimple_seq seq = NULL;
+ unsigned i = 0, j = 0, k;
+
+ for (tree arg = DECL_ARGUMENTS (node->decl);
+ arg;
+ arg = DECL_CHAIN (arg), i++, j++)
+ {
+ if (adjustments[j].op == IPA_PARM_OP_COPY
+ || POINTER_TYPE_P (TREE_TYPE (arg)))
+ continue;
+
+ node->simdclone->args[i].vector_arg = arg;
+
+ tree array = node->simdclone->args[i].simd_array;
+ if (node->simdclone->mask_mode != VOIDmode
+ && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_MASK)
+ {
+ if (array == NULL_TREE)
+ continue;
+ unsigned int l
+ = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array))));
+ for (k = 0; k <= l; k++)
+ {
+ if (k)
+ {
+ arg = DECL_CHAIN (arg);
+ j++;
+ }
+ tree t = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
+ array, size_int (k), NULL, NULL);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ continue;
+ }
+ if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
+ {
+ tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
+ tree ptr = build_fold_addr_expr (array);
+ tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
+ build_int_cst (ptype, 0));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ else
+ {
+ unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
+ tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
+ for (k = 0; k < node->simdclone->simdlen; k += simdlen)
+ {
+ tree ptr = build_fold_addr_expr (array);
+ int elemsize;
+ if (k)
+ {
+ arg = DECL_CHAIN (arg);
+ j++;
+ }
+ elemsize
+ = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
+ tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
+ build_int_cst (ptype, k * elemsize));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ }
+ }
+ return seq;
+}
+
+/* Callback info for ipa_simd_modify_stmt_ops below. */
+
+struct modify_stmt_info {
+ ipa_parm_adjustment_vec adjustments;
+ gimple *stmt;
+ /* True if the parent statement was modified by
+ ipa_simd_modify_stmt_ops. */
+ bool modified;
+};
+
+/* Callback for walk_gimple_op.
+
+ Adjust operands from a given statement as specified in the
+ adjustments vector in the callback data. */
+
+static tree
+ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+ struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
+ tree *orig_tp = tp;
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ tp = &TREE_OPERAND (*tp, 0);
+ struct ipa_parm_adjustment *cand = NULL;
+ if (TREE_CODE (*tp) == PARM_DECL)
+ cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
+ else
+ {
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ }
+
+ tree repl = NULL_TREE;
+ if (cand)
+ repl = unshare_expr (cand->new_decl);
+ else
+ {
+ if (tp != orig_tp)
+ {
+ *walk_subtrees = 0;
+ bool modified = info->modified;
+ info->modified = false;
+ walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
+ if (!info->modified)
+ {
+ info->modified = modified;
+ return NULL_TREE;
+ }
+ info->modified = modified;
+ repl = *tp;
+ }
+ else
+ return NULL_TREE;
+ }
+
+ if (tp != orig_tp)
+ {
+ repl = build_fold_addr_expr (repl);
+ gimple *stmt;
+ if (is_gimple_debug (info->stmt))
+ {
+ tree vexpr = make_node (DEBUG_EXPR_DECL);
+ stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
+ DECL_ARTIFICIAL (vexpr) = 1;
+ TREE_TYPE (vexpr) = TREE_TYPE (repl);
+ DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
+ repl = vexpr;
+ }
+ else
+ {
+ stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
+ repl = gimple_assign_lhs (stmt);
+ }
+ gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ *orig_tp = repl;
+ }
+ else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
+ {
+ tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
+ *tp = vce;
+ }
+ else
+ *tp = repl;
+
+ info->modified = true;
+ return NULL_TREE;
+}
+
+/* Traverse the function body and perform all modifications as
+ described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
+ modified such that the replacement/reduction value will now be an
+ offset into the corresponding simd_array.
+
+ This function will replace all function argument uses with their
+ corresponding simd array elements, and ajust the return values
+ accordingly. */
+
+static void
+ipa_simd_modify_function_body (struct cgraph_node *node,
+ ipa_parm_adjustment_vec adjustments,
+ tree retval_array, tree iter)
+{
+ basic_block bb;
+ unsigned int i, j, l;
+
+ /* Re-use the adjustments array, but this time use it to replace
+ every function argument use to an offset into the corresponding
+ simd_array. */
+ for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
+ {
+ if (!node->simdclone->args[i].vector_arg)
+ continue;
+
+ tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
+ tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
+ adjustments[j].new_decl
+ = build4 (ARRAY_REF,
+ basetype,
+ node->simdclone->args[i].simd_array,
+ iter,
+ NULL_TREE, NULL_TREE);
+ if (adjustments[j].op == IPA_PARM_OP_NONE
+ && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
+ j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
+ }
+
+ l = adjustments.length ();
+ for (i = 1; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+ if (name
+ && SSA_NAME_VAR (name)
+ && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
+ {
+ for (j = 0; j < l; j++)
+ if (SSA_NAME_VAR (name) == adjustments[j].base
+ && adjustments[j].new_decl)
+ {
+ tree base_var;
+ if (adjustments[j].new_ssa_base == NULL_TREE)
+ {
+ base_var
+ = copy_var_decl (adjustments[j].base,
+ DECL_NAME (adjustments[j].base),
+ TREE_TYPE (adjustments[j].base));
+ adjustments[j].new_ssa_base = base_var;
+ }
+ else
+ base_var = adjustments[j].new_ssa_base;
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ {
+ bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ gimple_stmt_iterator gsi = gsi_after_labels (bb);
+ tree new_decl = unshare_expr (adjustments[j].new_decl);
+ set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
+ SSA_NAME_IS_DEFAULT_DEF (name) = 0;
+ gimple *stmt = gimple_build_assign (name, new_decl);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ }
+ else
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
+ }
+ }
+ }
+
+ struct modify_stmt_info info;
+ info.adjustments = adjustments;
+
+ FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
+ {
+ gimple_stmt_iterator gsi;
+
+ gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ info.stmt = stmt;
+ struct walk_stmt_info wi;
+
+ memset (&wi, 0, sizeof (wi));
+ info.modified = false;
+ wi.info = &info;
+ walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
+
+ if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
+ {
+ tree retval = gimple_return_retval (return_stmt);
+ if (!retval)
+ {
+ gsi_remove (&gsi, true);
+ continue;
+ }
+
+ /* Replace `return foo' with `retval_array[iter] = foo'. */
+ tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
+ retval_array, iter, NULL, NULL);
+ stmt = gimple_build_assign (ref, retval);
+ gsi_replace (&gsi, stmt, true);
+ info.modified = true;
+ }
+
+ if (info.modified)
+ {
+ update_stmt (stmt);
+ if (maybe_clean_eh_stmt (stmt))
+ gimple_purge_dead_eh_edges (gimple_bb (stmt));
+ }
+ gsi_next (&gsi);
+ }
+ }
+}
+
+/* Helper function of simd_clone_adjust, return linear step addend
+ of Ith argument. */
+
+static tree
+simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
+ tree addtype, basic_block entry_bb)
+{
+ tree ptype = NULL_TREE;
+ switch (node->simdclone->args[i].arg_type)
+ {
+ case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ return build_int_cst (addtype, node->simdclone->args[i].linear_step);
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
+ ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ unsigned int idx = node->simdclone->args[i].linear_step;
+ tree arg = node->simdclone->args[idx].orig_arg;
+ gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
+ gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
+ gimple *g;
+ tree ret;
+ if (is_gimple_reg (arg))
+ ret = get_or_create_ssa_default_def (cfun, arg);
+ else
+ {
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
+ {
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
+ build_simple_mem_ref (ret));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
+ {
+ g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (POINTER_TYPE_P (ptype))
+ {
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
+ if (size && TREE_CODE (size) == INTEGER_CST)
+ {
+ g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
+ ret, fold_convert (addtype, size));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ }
+ return ret;
+}
+
+/* Adjust the argument types in NODE to their appropriate vector
+ counterparts. */
+
+static void
+simd_clone_adjust (struct cgraph_node *node)
+{
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+
+ targetm.simd_clone.adjust (node);
+
+ tree retval = simd_clone_adjust_return_type (node);
+ ipa_parm_adjustment_vec adjustments
+ = simd_clone_adjust_argument_types (node);
+
+ push_gimplify_context ();
+
+ gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
+
+ /* Adjust all uses of vector arguments accordingly. Adjust all
+ return values accordingly. */
+ tree iter = create_tmp_var (unsigned_type_node, "iter");
+ tree iter1 = make_ssa_name (iter);
+ tree iter2 = make_ssa_name (iter);
+ ipa_simd_modify_function_body (node, adjustments, retval, iter1);
+
+ /* Initialize the iteration variable. */
+ basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ basic_block body_bb = split_block_after_labels (entry_bb)->dest;
+ gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
+ /* Insert the SIMD array and iv initialization at function
+ entry. */
+ gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
+
+ pop_gimplify_context (NULL);
+
+ /* Create a new BB right before the original exit BB, to hold the
+ iteration increment and the condition/branch. */
+ basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
+ basic_block incr_bb = create_empty_bb (orig_exit);
+ add_bb_to_loop (incr_bb, body_bb->loop_father);
+ /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
+ flag. Set it now to be a FALLTHRU_EDGE. */
+ gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
+ EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
+ for (unsigned i = 0;
+ i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
+ {
+ edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
+ redirect_edge_succ (e, incr_bb);
+ }
+ edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ e->probability = REG_BR_PROB_BASE;
+ gsi = gsi_last_bb (incr_bb);
+ gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
+ build_int_cst (unsigned_type_node, 1));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+
+ /* Mostly annotate the loop for the vectorizer (the rest is done below). */
+ struct loop *loop = alloc_loop ();
+ cfun->has_force_vectorize_loops = true;
+ loop->safelen = node->simdclone->simdlen;
+ loop->force_vectorize = true;
+ loop->header = body_bb;
+
+ /* Branch around the body if the mask applies. */
+ if (node->simdclone->inbranch)
+ {
+ gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
+ tree mask_array
+ = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
+ tree mask;
+ if (node->simdclone->mask_mode != VOIDmode)
+ {
+ tree shift_cnt;
+ if (mask_array == NULL_TREE)
+ {
+ tree arg = node->simdclone->args[node->simdclone->nargs
+ - 1].vector_arg;
+ mask = get_or_create_ssa_default_def (cfun, arg);
+ shift_cnt = iter1;
+ }
+ else
+ {
+ tree maskt = TREE_TYPE (mask_array);
+ int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
+ c = node->simdclone->simdlen / (c + 1);
+ int s = exact_log2 (c);
+ gcc_assert (s > 0);
+ c--;
+ tree idx = make_ssa_name (TREE_TYPE (iter1));
+ g = gimple_build_assign (idx, RSHIFT_EXPR, iter1,
+ build_int_cst (NULL_TREE, s));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
+ tree aref = build4 (ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (mask_array)),
+ mask_array, idx, NULL, NULL);
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ shift_cnt = make_ssa_name (TREE_TYPE (iter1));
+ g = gimple_build_assign (shift_cnt, BIT_AND_EXPR, iter1,
+ build_int_cst (TREE_TYPE (iter1), c));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ }
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
+ RSHIFT_EXPR, mask, shift_cnt);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = gimple_assign_lhs (g);
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
+ BIT_AND_EXPR, mask,
+ build_int_cst (TREE_TYPE (mask), 1));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = gimple_assign_lhs (g);
+ }
+ else
+ {
+ mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
+ tree aref = build4 (ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (mask_array)),
+ mask_array, iter1, NULL, NULL);
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
+ {
+ aref = build1 (VIEW_CONVERT_EXPR,
+ build_nonstandard_integer_type (bitsize, 0),
+ mask);
+ mask = make_ssa_name (TREE_TYPE (aref));
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ }
+ }
+
+ g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
+ NULL, NULL);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
+ FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
+ }
+
+ /* Generate the condition. */
+ g = gimple_build_cond (LT_EXPR,
+ iter2,
+ build_int_cst (unsigned_type_node,
+ node->simdclone->simdlen),
+ NULL, NULL);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ e = split_block (incr_bb, gsi_stmt (gsi));
+ basic_block latch_bb = e->dest;
+ basic_block new_exit_bb;
+ new_exit_bb = split_block_after_labels (latch_bb)->dest;
+ loop->latch = latch_bb;
+
+ redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
+
+ make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+ /* The successor of incr_bb is already pointing to latch_bb; just
+ change the flags.
+ make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
+ FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
+
+ gphi *phi = create_phi_node (iter1, body_bb);
+ edge preheader_edge = find_edge (entry_bb, body_bb);
+ edge latch_edge = single_succ_edge (latch_bb);
+ add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
+ UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+
+ /* Generate the new return. */
+ gsi = gsi_last_bb (new_exit_bb);
+ if (retval
+ && TREE_CODE (retval) == VIEW_CONVERT_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
+ retval = TREE_OPERAND (retval, 0);
+ else if (retval)
+ {
+ retval = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (TREE_TYPE (node->decl)),
+ retval);
+ retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
+ false, GSI_CONTINUE_LINKING);
+ }
+ g = gimple_build_return (retval);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+
+ /* Handle aligned clauses by replacing default defs of the aligned
+ uniform args with __builtin_assume_aligned (arg_N(D), alignment)
+ lhs. Handle linear by adding PHIs. */
+ for (unsigned i = 0; i < node->simdclone->nargs; i++)
+ if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
+ || !is_gimple_reg_type
+ (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ else
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
+ gimple_add_tmp_var (iter1);
+ }
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == REFERENCE_TYPE
+ && TREE_ADDRESSABLE
+ (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ if (def && !has_zero_uses (def))
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
+ gimple_add_tmp_var (iter1);
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, build_simple_mem_ref (def));
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (build_simple_mem_ref (def), iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ }
+ else if (node->simdclone->args[i].alignment
+ && node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (node->simdclone->args[i].alignment
+ & (node->simdclone->args[i].alignment - 1)) == 0
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == POINTER_TYPE)
+ {
+ unsigned int alignment = node->simdclone->args[i].alignment;
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ if (def && !has_zero_uses (def))
+ {
+ tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
+ gimple_seq seq = NULL;
+ bool need_cvt = false;
+ gcall *call
+ = gimple_build_call (fn, 2, def, size_int (alignment));
+ g = call;
+ if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
+ ptr_type_node))
+ need_cvt = true;
+ tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
+ gimple_call_set_lhs (g, t);
+ gimple_seq_add_stmt_without_update (&seq, g);
+ if (need_cvt)
+ {
+ t = make_ssa_name (orig_arg);
+ g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
+ gimple_seq_add_stmt_without_update (&seq, g);
+ }
+ gsi_insert_seq_on_edge_immediate
+ (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
+
+ entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ int freq = compute_call_stmt_bb_frequency (current_function_decl,
+ entry_bb);
+ node->create_edge (cgraph_node::get_create (fn),
+ call, entry_bb->count, freq);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ tree repl = gimple_get_lhs (g);
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (is_gimple_debug (use_stmt) || use_stmt == call)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, repl);
+ }
+ }
+ else if ((node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
+ tree def = NULL_TREE;
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ def = make_ssa_name (TREE_TYPE (orig_arg));
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ iter2 = make_ssa_name (TREE_TYPE (orig_arg));
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (def, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ {
+ def = ssa_default_def (cfun, orig_arg);
+ if (!def || has_zero_uses (def))
+ def = NULL_TREE;
+ else
+ {
+ iter1 = make_ssa_name (orig_arg);
+ iter2 = make_ssa_name (orig_arg);
+ }
+ }
+ if (def)
+ {
+ phi = create_phi_node (iter1, body_bb);
+ add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+ enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ ? PLUS_EXPR : POINTER_PLUS_EXPR;
+ tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ ? TREE_TYPE (orig_arg) : sizetype;
+ tree addcst = simd_clone_linear_addend (node, i, addtype,
+ entry_bb);
+ gsi = gsi_last_bb (incr_bb);
+ g = gimple_build_assign (iter2, code, iter1, addcst);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (use_stmt == phi)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, iter1);
+ }
+ }
+ else if (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ gcc_assert (!TREE_ADDRESSABLE (orig_arg)
+ && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
+ if (def && !has_zero_uses (def))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
+ iter1 = make_ssa_name (orig_arg);
+ iter2 = make_ssa_name (orig_arg);
+ tree iter3 = make_ssa_name (rtype);
+ tree iter4 = make_ssa_name (rtype);
+ tree iter5 = make_ssa_name (rtype);
+ gsi = gsi_after_labels (entry_bb);
+ gimple *load
+ = gimple_build_assign (iter3, build_simple_mem_ref (def));
+ gsi_insert_before (&gsi, load, GSI_NEW_STMT);
+
+ tree array = node->simdclone->args[i].simd_array;
+ TREE_ADDRESSABLE (array) = 1;
+ tree ptr = build_fold_addr_expr (array);
+ phi = create_phi_node (iter1, body_bb);
+ add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+ g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
+ TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
+ gsi = gsi_last_bb (incr_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ phi = create_phi_node (iter4, body_bb);
+ add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
+ enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+ ? PLUS_EXPR : POINTER_PLUS_EXPR;
+ tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+ ? TREE_TYPE (iter3) : sizetype;
+ tree addcst = simd_clone_linear_addend (node, i, addtype,
+ entry_bb);
+ g = gimple_build_assign (iter5, code, iter4, addcst);
+ gsi = gsi_last_bb (incr_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
+ gsi = gsi_after_labels (body_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (use_stmt == load)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, iter1);
+
+ if (!TYPE_READONLY (rtype))
+ {
+ tree v = make_ssa_name (rtype);
+ tree aref = build4 (ARRAY_REF, rtype, array,
+ size_zero_node, NULL_TREE,
+ NULL_TREE);
+ gsi = gsi_after_labels (new_exit_bb);
+ g = gimple_build_assign (v, aref);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (build_simple_mem_ref (def), v);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ }
+ }
+
+ calculate_dominance_info (CDI_DOMINATORS);
+ add_loop (loop, loop->header->loop_father);
+ update_ssa (TODO_update_ssa);
+
+ pop_cfun ();
+}
+
+/* If the function in NODE is tagged as an elemental SIMD function,
+ create the appropriate SIMD clones. */
+
+static void
+expand_simd_clones (struct cgraph_node *node)
+{
+ tree attr = lookup_attribute ("omp declare simd",
+ DECL_ATTRIBUTES (node->decl));
+ if (attr == NULL_TREE
+ || node->global.inlined_to
+ || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
+ return;
+
+ /* Ignore
+ #pragma omp declare simd
+ extern int foo ();
+ in C, there we don't know the argument types at all. */
+ if (!node->definition
+ && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
+ return;
+
+ /* Call this before creating clone_info, as it might ggc_collect. */
+ if (node->definition && node->has_gimple_body_p ())
+ node->get_body ();
+
+ do
+ {
+ /* Start with parsing the "omp declare simd" attribute(s). */
+ bool inbranch_clause_specified;
+ struct cgraph_simd_clone *clone_info
+ = simd_clone_clauses_extract (node, TREE_VALUE (attr),
+ &inbranch_clause_specified);
+ if (clone_info == NULL)
+ continue;
+
+ int orig_simdlen = clone_info->simdlen;
+ tree base_type = simd_clone_compute_base_data_type (node, clone_info);
+ /* The target can return 0 (no simd clones should be created),
+ 1 (just one ISA of simd clones should be created) or higher
+ count of ISA variants. In that case, clone_info is initialized
+ for the first ISA variant. */
+ int count
+ = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
+ base_type, 0);
+ if (count == 0)
+ continue;
+
+ /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
+ also create one inbranch and one !inbranch clone of it. */
+ for (int i = 0; i < count * 2; i++)
+ {
+ struct cgraph_simd_clone *clone = clone_info;
+ if (inbranch_clause_specified && (i & 1) != 0)
+ continue;
+
+ if (i != 0)
+ {
+ clone = simd_clone_struct_alloc (clone_info->nargs
+ + ((i & 1) != 0));
+ simd_clone_struct_copy (clone, clone_info);
+ /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
+ and simd_clone_adjust_argument_types did to the first
+ clone's info. */
+ clone->nargs -= clone_info->inbranch;
+ clone->simdlen = orig_simdlen;
+ /* And call the target hook again to get the right ISA. */
+ targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
+ base_type,
+ i / 2);
+ if ((i & 1) != 0)
+ clone->inbranch = 1;
+ }
+
+ /* simd_clone_mangle might fail if such a clone has been created
+ already. */
+ tree id = simd_clone_mangle (node, clone);
+ if (id == NULL_TREE)
+ continue;
+
+ /* Only when we are sure we want to create the clone actually
+ clone the function (or definitions) or create another
+ extern FUNCTION_DECL (for prototypes without definitions). */
+ struct cgraph_node *n = simd_clone_create (node);
+ if (n == NULL)
+ continue;
+
+ n->simdclone = clone;
+ clone->origin = node;
+ clone->next_clone = NULL;
+ if (node->simd_clones == NULL)
+ {
+ clone->prev_clone = n;
+ node->simd_clones = n;
+ }
+ else
+ {
+ clone->prev_clone = node->simd_clones->simdclone->prev_clone;
+ clone->prev_clone->simdclone->next_clone = n;
+ node->simd_clones->simdclone->prev_clone = n;
+ }
+ symtab->change_decl_assembler_name (n->decl, id);
+ /* And finally adjust the return type, parameters and for
+ definitions also function body. */
+ if (node->definition)
+ simd_clone_adjust (n);
+ else
+ {
+ simd_clone_adjust_return_type (n);
+ simd_clone_adjust_argument_types (n);
+ }
+ }
+ }
+ while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
+}
+
+/* Entry point for IPA simd clone creation pass. */
+
+static unsigned int
+ipa_omp_simd_clone (void)
+{
+ struct cgraph_node *node;
+ FOR_EACH_FUNCTION (node)
+ expand_simd_clones (node);
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_omp_simd_clone =
+{
+ SIMPLE_IPA_PASS, /* type */
+ "simdclone", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ ( PROP_ssa | PROP_cfg ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_omp_simd_clone : public simple_ipa_opt_pass
+{
+public:
+ pass_omp_simd_clone(gcc::context *ctxt)
+ : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
+};
+
+bool
+pass_omp_simd_clone::gate (function *)
+{
+ return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
+}
+
+} // anon namespace
+
+simple_ipa_opt_pass *
+make_pass_omp_simd_clone (gcc::context *ctxt)
+{
+ return new pass_omp_simd_clone (ctxt);
+}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 79916ad844a..8267252b196 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2747,6 +2747,8 @@ extern unsigned int subreg_highpart_offset (machine_mode,
machine_mode);
extern int byte_lowpart_offset (machine_mode, machine_mode);
extern rtx make_safe_from (rtx, rtx);
+extern rtx convert_memory_address_addr_space_1 (machine_mode, rtx,
+ addr_space_t, bool, bool);
extern rtx convert_memory_address_addr_space (machine_mode, rtx,
addr_space_t);
#define convert_memory_address(to_mode,x) \
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index b1b993663f1..fdc4b366c74 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1482,7 +1482,14 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
&& REG_POINTER (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == Pmode))
&& !targetm.have_ptr_extend ())
- return convert_memory_address (Pmode, op);
+ {
+ temp
+ = convert_memory_address_addr_space_1 (Pmode, op,
+ ADDR_SPACE_GENERIC, false,
+ true);
+ if (temp)
+ return temp;
+ }
#endif
break;
@@ -1604,7 +1611,14 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
&& REG_POINTER (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == Pmode))
&& !targetm.have_ptr_extend ())
- return convert_memory_address (Pmode, op);
+ {
+ temp
+ = convert_memory_address_addr_space_1 (Pmode, op,
+ ADDR_SPACE_GENERIC, false,
+ true);
+ if (temp)
+ return temp;
+ }
#endif
break;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 77b614b2db7..0f2e861c5b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,218 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70671
+ * gcc.dg/bitfld-22.c: New test.
+
+2016-04-15 Bernd Schmidt <bschmidt@redhat.com>
+
+ * gcc.target/i386/pr46470.c: Add -mno-red-zone to dg-options for
+ x86_64.
+
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70651
+ * c-c++-common/pr70651.c: New test.
+
+2016-04-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR rtl-optimization/70681
+ * gcc.dg/ira-shrinkwrap-prep-2.c: XFAIL shrinkwrapping
+ dump scan on arm and powerpc.
+ * gcc.dg/pr10474.c: Likewise.
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * g++.dg/cpp1y/vla11.C: Revert for real.
+
+ PR c/70436
+ * c-c++-common/Wparentheses-1.c: New test.
+ * c-c++-common/gomp/Wparentheses-1.c: New test.
+ * c-c++-common/gomp/Wparentheses-2.c: New test.
+ * c-c++-common/gomp/Wparentheses-3.c: New test.
+ * c-c++-common/gomp/Wparentheses-4.c: New test.
+ * c-c++-common/cilk-plus/PS/Wparentheses-1.c: New test.
+ * c-c++-common/cilk-plus/CK/Wparentheses-1.c: New test.
+ * c-c++-common/goacc/Wparentheses-1.c: New test.
+
+2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/70662
+ * gcc.target/i386/pr70662.c: New test.
+
+2016-04-15 Richard Biener <rguenther@suse.de>
+ Alan Modra <amodra@gmail.com>
+
+ PR tree-optimization/70130
+ * gcc.dg/vect/O3-pr70130.c: New testcase.
+
+2016-04-14 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70669
+ * gcc.target/powerpc/pr70669.c: New test.
+
+ PR target/70640
+ * gcc.target/powerpc/pr70640.c: Fix test so it correctly works on
+ a power7 system that does not have an assembler that supports
+ power8.
+
+2016-04-14 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * c-c++-common/ubsan/vla-1.c: Revert.
+ * g++.dg/cpp1y/vla11.C: Same.
+ * g++.dg/cpp1y/vla12.C: Same.
+ * g++.dg/cpp1y/vla13.C: Same.
+ * g++.dg/cpp1y/vla14.C: Same.
+ * g++.dg/cpp1y/vla3.C: Same.
+ * gcc/testsuite/g++.dg/init/array24.C: Same.
+ * g++.dg/ubsan/vla-1.C: Same.
+
+2016-04-14 Marek Polacek <polacek@redhat.com>
+ Jan Hubicka <hubicka@ucw.cz>
+
+ PR c++/70029
+ * g++.dg/torture/pr70029.C: New test.
+
+2016-04-14 Martin Sebor <msebor@redhat.com>
+
+ * g++.dg/cpp1y/vla11.C: Avoid using attribute aligned to increase
+ type size to prevent failures on targets with very low maximum
+ alignment.
+
+2016-04-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/70623
+ * gcc.dg/torture/pr70623.c: New testcase.
+ * gcc.dg/torture/pr70623-2.c: Likewise.
+
+2016-04-13 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * c-c++-common/ubsan/vla-1.c (main): Catch exceptions.
+ * g++.dg/cpp1y/vla11.C: New test.
+ * g++.dg/cpp1y/vla12.C: New test.
+ * g++.dg/cpp1y/vla13.C: New test.
+ * g++.dg/cpp1y/vla14.C: New test.
+ * g++.dg/cpp1y/vla3.C: Restore deleted test.
+ * gcc/testsuite/g++.dg/init/array24.C: Fully brace VLA initializer.
+ * g++.dg/ubsan/vla-1.C: Disable exceptions.
+
+2016-04-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70641
+ * g++.dg/opt/pr70641.C: New test.
+
+2016-04-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR rtl-optimization/68749
+ * gcc.dg/ifcvt-4.c: Use "word_mode" rather than "int" to limit the
+ effects of argument promotions.
+ Remove default args to dg-skip-if.
+
+2016-04-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/70635
+ * g++.dg/parse/pr70635.C: New.
+
+2016-04-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/70639
+ * c-c++-common/Wmisleading-indentation-4.c: New test.
+
+2016-04-13 Marek Polacek <polacek@redhat.com>
+
+ PR c/70436
+ * testsuite/gcc.dg/Wparentheses-12.c: New test.
+ * testsuite/gcc.dg/Wparentheses-13.c: New test.
+
+2016-04-13 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * gcc.target/i386/avx512bw-kunpckdq-2.c: New test.
+ * gcc.target/i386/avx512bw-kunpckwd-2.c: New test.
+ * gcc.target/i386/avx512f-kunpckbw-2.c: New test.
+
+2016-04-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/70633
+ * gcc.c-torture/compile/pr70633.c: New test.
+
+ PR debug/70628
+ * gcc.dg/torture/pr70628.c: New test.
+
+2016-04-12 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/70610
+ * g++.dg/template/pr70610.C: New test.
+ * g++.dg/template/pr70610-2.C: New test.
+ * g++.dg/template/pr70610-3.C: New test.
+ * g++.dg/template/pr70610-4.C: New test.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/cilk-plus/SE/ef_error2.c (func2): Use vectorlength
+ 128 instead of 32.
+
+ PR c++/70571
+ * g++.dg/ext/pr70571.C: New test.
+
+2016-04-12 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70640
+ * gcc.target/powerpc/pr70640.c: New test.
+
+2016-04-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/68722
+ * g++.dg/parse/pr68722.C: New.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/70596
+ * gcc.target/i386/pr70596.c: New test.
+
+2016-04-12 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70501
+ * g++.dg/init/pr70501.C: New.
+
+2016-04-12 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * gcc.target/i386/asm-flag-6.c: New test.
+
+2016-04-12 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/68756
+ * gcc.dg/graphite/pr68756.c: New test.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/70602
+ * gcc.c-torture/execute/pr70602.c: New test.
+
+2016-04-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70381
+ * gcc.target/powerpc/float128-1.c: New tests to make sure the
+ __float128 emulator is built and runs.
+ * gcc.target/powerpc/float128-1.c: Likewise.
+
+ * lib/target-supports.exp (check_ppc_float128_sw_available):
+ Rework tests for __float128 software and hardware
+ availability. Fix exit condition to return 0 on success.
+
+2016-04-11 James Greenhalgh <james.greenhalgh@arm.com>
+
+ PR target/70133
+ * gcc.target/aarch64/mgeneral-regs_4.c: Fix expected output.
+ * gcc.target/aarch64/target_attr_15.c: Likewise.
+
2016-04-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/69066
diff --git a/gcc/testsuite/c-c++-common/Wmisleading-indentation-4.c b/gcc/testsuite/c-c++-common/Wmisleading-indentation-4.c
new file mode 100644
index 00000000000..d15a4793da4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmisleading-indentation-4.c
@@ -0,0 +1,11 @@
+/* PR c++/70639 */
+/* { dg-do compile } */
+/* { dg-options "-Wmisleading-indentation" } */
+
+void bar (int);
+void
+foo (int x)
+{
+ switch (x);
+ bar (x);
+}
diff --git a/gcc/testsuite/c-c++-common/Wparentheses-1.c b/gcc/testsuite/c-c++-common/Wparentheses-1.c
new file mode 100644
index 00000000000..ed506083829
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wparentheses-1.c
@@ -0,0 +1,39 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-Wparentheses" } */
+
+int a, b, c[101], d[101], e[101], f[101];
+
+void
+f1 (void)
+{
+ int i;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ if (b)
+ c[i] = d[i] + e[i];
+ else
+ f[i] = d[i] * e[i];
+
+ if (a)
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ {
+ if (b)
+ c[i] = d[i] + e[i];
+ else
+ f[i] = d[i] * e[i];
+ }
+
+ if (a)
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ {
+ if (b)
+ c[i] = d[i] + e[i];
+ }
+ else
+ f[i] = d[i] * e[i];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c
new file mode 100644
index 00000000000..f07b49a2775
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c
@@ -0,0 +1,69 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wparentheses" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ _Cilk_for (int i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c
new file mode 100644
index 00000000000..d391d7b1eed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c
@@ -0,0 +1,41 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c
index 518d6407eeb..89e0c39b02c 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c
@@ -1,8 +1,8 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-fcilkplus -Wall" } */
-__attribute__((vector (vectorlength(32))))
-//#pragma omp simd simdlen (32)
+__attribute__((vector (vectorlength(128))))
+//#pragma omp simd simdlen (128)
int func2 (int x, int y) /* { dg-warning "unsupported simdlen" } */
{
return (x+y);
diff --git a/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c b/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c
new file mode 100644
index 00000000000..08265b65e0b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c
@@ -0,0 +1,174 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+#pragma acc routine
+void bar2 (void);
+#pragma acc routine
+void baz2 (void);
+
+void
+f1 (void)
+{
+ int i, d[10] = { 0 };
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc data copyin (d[0:10])
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ #pragma acc data copyin (d[0:10])
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc host_data use_device (d)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc kernels
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc kernels
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc parallel
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ (void) d[0];
+
+ if (a)
+ #pragma acc data copyin (d[0:10])
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma acc data copyin (d[0:10])
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ #pragma acc data copyin (d[0:10])
+ if (a)
+ #pragma acc host_data use_device (d)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ #pragma acc data copyin (d[0:10])
+ if (a)
+ #pragma acc host_data use_device (d)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma acc kernels
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc kernels
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc parallel
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ {
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+}
+
+#pragma acc routine vector
+void
+f2 (int *a, int b, int c)
+{
+ int i;
+
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma acc loop vector
+ for (i = 0; i < 10; i++)
+ if (c)
+ a[i] = a[i] + 1;
+ else
+ a[i] = a[i] + 2;
+
+ if (b)
+ #pragma acc loop vector
+ for (i = 0; i < 10; i++)
+ {
+ if (c)
+ a[i] = a[i] + 1;
+ else
+ a[i] = a[i] + 2;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c
new file mode 100644
index 00000000000..4420d670bde
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c
@@ -0,0 +1,338 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop
+ for (i = 0; i < 10; i++)
+ if (b)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp critical
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for simd schedule(runtime)
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp master
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp single
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp task
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskgroup
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp taskloop
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp critical
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for simd schedule(dynamic, 5)
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp master
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp single
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp task
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp taskgroup
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f2 (int d, int e, int f)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (d) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered threads
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (e)
+ #pragma omp ordered
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (f)
+ #pragma omp ordered threads
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c
new file mode 100644
index 00000000000..4341b223236
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c
@@ -0,0 +1,452 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+void f1 (void);
+#pragma omp declare target to (bar, baz, f1, a, b, c)
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target parallel
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ } }
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ }
+ }
+ else
+ baz ();
+}
+
+void
+f3 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f4 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target data map (tofrom: b)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target data map (tofrom: b)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c
new file mode 100644
index 00000000000..1688d1062d4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c
@@ -0,0 +1,338 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses -fno-openmp" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop
+ for (i = 0; i < 10; i++)
+ if (b)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp critical
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for simd schedule(runtime)
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp master
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp single
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp task
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskgroup
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp taskloop
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp critical
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for simd schedule(dynamic, 5)
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp master
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp single
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp task
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp taskgroup
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f2 (int d, int e, int f)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (d) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered threads
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (e)
+ #pragma omp ordered
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (f)
+ #pragma omp ordered threads
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c
new file mode 100644
index 00000000000..d44cdcd5756
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c
@@ -0,0 +1,452 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses -fno-openmp" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+void f1 (void);
+#pragma omp declare target to (bar, baz, f1, a, b, c)
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target parallel
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ } }
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ }
+ }
+ else
+ baz ();
+}
+
+void
+f3 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f4 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target data map (tofrom: b)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target data map (tofrom: b)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/pr70651.c b/gcc/testsuite/c-c++-common/pr70651.c
new file mode 100644
index 00000000000..a91a2d8fc88
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr70651.c
@@ -0,0 +1,9 @@
+/* PR c/70651 */
+/* { dg-do compile } */
+/* { dg-prune-output "\[^\n\r\]*first argument to .va_arg. not of type .va_list.\[^\n\r\]*" } */
+
+void fn1 ()
+{
+ char **a = 0;
+ __builtin_va_arg (a, char **);
+}
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag20.C b/gcc/testsuite/g++.dg/abi/abi-tag20.C
new file mode 100644
index 00000000000..229c1709be5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag20.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_ZN1B1gIcEEN7__cxx111XEv" } }
+
+inline namespace __cxx11 __attribute__((__abi_tag__ ("ABI_TAG"))) {
+ class X {};
+}
+struct B {
+ X f();
+ template <class U> X g();
+};
+int main() {
+ B b;
+ b.g<char>();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto47.C b/gcc/testsuite/g++.dg/cpp0x/auto47.C
new file mode 100644
index 00000000000..0d80be6d72f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto47.C
@@ -0,0 +1,7 @@
+// PR c++/70622
+// { dg-do compile { target c++11 } }
+
+int main()
+{
+ auto x = 0, *y = &x;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
index 45e1ed27fae..42ca30a38ce 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor12.C
@@ -3,6 +3,7 @@
template <typename Tp>
struct C {
+ C() = default;
constexpr C(const Tp& r) { }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
index a67505d749b..8d352d0bb99 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
@@ -7,6 +7,6 @@ struct A {
struct B: A { };
constexpr int f(B b) { return b.i; }
-struct C { C(); }; // { dg-message "calls non-constexpr" }
-struct D: C { }; // { dg-message "no constexpr constructor" }
+struct C { C(); }; // { dg-message "" }
+struct D: C { }; // { dg-message "" }
constexpr int g(D d) { return 42; } // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
index 30e0a643bcb..bf95b2443c7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
@@ -6,6 +6,6 @@ struct A
A(int);
};
-struct B : A {}; // { dg-error "no matching" }
+struct B : A {}; // { dg-message "" }
constexpr int foo(B) { return 0; } // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist10.C
new file mode 100644
index 00000000000..c12347dcc80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist10.C
@@ -0,0 +1,11 @@
+// PR c++/70648
+// { dg-do compile { target c++11 } }
+
+struct C
+{
+ template <class... U>
+ constexpr C (...) : c { static_cast<U &&>(0)... } {}
+ int c[1];
+};
+
+static constexpr int b = C{}.c[0];
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template9.C
new file mode 100644
index 00000000000..2ca641d77e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template9.C
@@ -0,0 +1,17 @@
+// PR c++/70543
+// { dg-do compile { target c++11 } }
+
+template <typename>
+struct X
+{
+ template <unsigned int = 0>
+ static constexpr int
+ calc (void)
+ {
+ return 0;
+ }
+
+ static constexpr unsigned int value = calc ();
+
+ char foo[value];
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base3.C b/gcc/testsuite/g++.dg/cpp0x/enum_base3.C
new file mode 100644
index 00000000000..3cb2d6d8186
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum_base3.C
@@ -0,0 +1,29 @@
+// PR c++/70627
+// { dg-do compile { target c++11 } }
+
+struct D;
+struct A
+{
+ D *operator->();
+};
+struct B
+{
+ template <typename... T> void foo (T &&...) {}
+};
+typedef unsigned char G;
+enum class H : G;
+struct C
+{
+};
+struct D : C
+{
+ B foo () const { B a; a.foo (d); }
+ H d;
+};
+struct F : C
+{
+ void foo ();
+ A f;
+};
+enum class H : unsigned char;
+void F::foo () { B b = f->foo (); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
index 7a22f8830ec..7e2d58b422e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
@@ -8,7 +8,7 @@ struct A
struct B : A
{
- using A::A; // { dg-error "inherited" }
+ using A::A;
};
constexpr B b; // { dg-error "literal" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-array2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-array2.C
new file mode 100644
index 00000000000..d0063e11cbf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-array2.C
@@ -0,0 +1,10 @@
+// PR c++/70494
+// { dg-do compile { target c++11 } }
+
+struct A { ~A(); };
+
+int main()
+{
+ A v[] = { A(), A() };
+ auto lambda = [v]{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr70528.C b/gcc/testsuite/g++.dg/cpp0x/pr70528.C
new file mode 100644
index 00000000000..af1c84e1e94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr70528.C
@@ -0,0 +1,16 @@
+// PR c++/70258
+// { dg-do compile { target c++11 } }
+
+template <class T>
+struct H
+{
+ template <typename A = T, typename = decltype (A())>
+ H ();
+};
+
+struct J {
+ struct K {
+ int First = 0;
+ };
+ H<K> FunctionMDInfo;
+};
diff --git a/gcc/testsuite/g++.dg/ext/pr70571.C b/gcc/testsuite/g++.dg/ext/pr70571.C
new file mode 100644
index 00000000000..2381bfe589c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr70571.C
@@ -0,0 +1,10 @@
+// PR c++/70571
+// { dg-do compile }
+
+typedef int V __attribute__ ((vector_size (sizeof (int))));
+
+void
+foo (V *x, V *y, int z)
+{
+ *x = (z == *y);
+}
diff --git a/gcc/testsuite/g++.dg/init/pr70501.C b/gcc/testsuite/g++.dg/init/pr70501.C
new file mode 100644
index 00000000000..901b3c1b5a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr70501.C
@@ -0,0 +1,11 @@
+/* { dg-options "" } Not pedantic */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+struct S { v4si v; };
+
+void
+fn2 (int i, int j)
+{
+ struct S s = { .v = i <= j + (v4si){(1, 2)} };
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr70641.C b/gcc/testsuite/g++.dg/opt/pr70641.C
new file mode 100644
index 00000000000..99af74248f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr70641.C
@@ -0,0 +1,10 @@
+// PR c++/70641
+// { dg-do compile }
+// { dg-options "-O2" }
+
+void
+foo ()
+{
+ try { foo (); }
+ catch (...) { __builtin_abort (); }
+}
diff --git a/gcc/testsuite/g++.dg/opt/ptrmem7.C b/gcc/testsuite/g++.dg/opt/ptrmem7.C
new file mode 100644
index 00000000000..7d9e9b17d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/ptrmem7.C
@@ -0,0 +1,31 @@
+// PR c++/70615
+// { dg-options -O }
+
+struct C
+{
+ virtual void f () {}
+};
+
+struct B
+{
+ virtual ~B () {}
+};
+
+class D : public B, public C
+{
+public:
+ D () {}
+};
+
+typedef void (C::*FP) ();
+typedef void (D::*D_f) ();
+
+int
+main ()
+{
+ D *d = new D ();
+ C *c = d;
+ const FP fptr = (FP) & D::f;
+ (d->*(D_f) fptr) ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr68722.C b/gcc/testsuite/g++.dg/parse/pr68722.C
new file mode 100644
index 00000000000..44a6213a0a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr68722.C
@@ -0,0 +1,9 @@
+// PR c++/68722
+
+class A {
+ &__loc // { dg-error "" }
+} class ios_base { // { dg-error "" }
+ A _M_ios_locale ios_base(ios_base &) template <_Traits> class basic_ios { // { dg-error "" }
+basic_ios basic_ios = operator= // { dg-error "" }
+
+// { dg-prune-output "file ends in default argument" }
diff --git a/gcc/testsuite/g++.dg/parse/pr70635.C b/gcc/testsuite/g++.dg/parse/pr70635.C
new file mode 100644
index 00000000000..0873840daf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr70635.C
@@ -0,0 +1,25 @@
+// PR c++/70635
+// { dg-options "-fpermissive -w" }
+
+template < typename T >
+struct A
+{
+ struct B;
+ typedef typename B::type type;
+};
+
+template < typename T >
+struct A < T >::B
+{
+ typedef typename A < type >::type type; // { dg-error "type" }
+ type Foo ();
+};
+
+template < typename T >
+typename A < T >::B::type
+A < T >::B::Foo ()
+{
+ return 0;
+}
+
+template class A<int>;
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr10.C b/gcc/testsuite/g++.dg/template/dependent-expr10.C
new file mode 100644
index 00000000000..94d66fc92b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-expr10.C
@@ -0,0 +1,8 @@
+// PR c++/70634
+
+template < typename T >
+bool foo ()
+{
+ const int i = sizeof (i) > 1 ? sizeof (T) : 0;
+ return i > 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610-2.C b/gcc/testsuite/g++.dg/template/pr70610-2.C
new file mode 100644
index 00000000000..3368a5e5d89
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-2.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { };
+
+void operator+ (const A &, A &);
+void operator+ (A &, const A &);
+void operator+ (const A &, const A &) { }
+
+template <typename T>
+void
+foo ()
+{
+ A () + A ();
+}
+
+int
+main ()
+{
+ foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610-3.C b/gcc/testsuite/g++.dg/template/pr70610-3.C
new file mode 100644
index 00000000000..4be458cca59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-3.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+void bar (const int &, int &);
+void bar (int &, const int &);
+void bar (const int &, const int &) { }
+
+int a, b;
+
+template <typename T>
+void
+foo ()
+{
+ bar (a + 1, b + 2);
+}
+
+int
+main ()
+{
+ foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610-4.C b/gcc/testsuite/g++.dg/template/pr70610-4.C
new file mode 100644
index 00000000000..127abdc44e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610-4.C
@@ -0,0 +1,19 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { void operator+ (const A &) { }; };
+
+void operator+ (const A &, A &);
+
+template <typename T>
+void
+foo ()
+{
+ A () + A ();
+}
+
+int
+main ()
+{
+ foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr70610.C b/gcc/testsuite/g++.dg/template/pr70610.C
new file mode 100644
index 00000000000..c7dde1c5cec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr70610.C
@@ -0,0 +1,21 @@
+// PR c++/70610
+// { dg-do link }
+
+struct A { };
+
+void operator+ (A &);
+void operator+ (const A &) { }
+
+
+template <typename T>
+void
+foo ()
+{
+ +A ();
+}
+
+int
+main ()
+{
+ foo<int> ();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr70029.C b/gcc/testsuite/g++.dg/torture/pr70029.C
new file mode 100644
index 00000000000..9592f0cc987
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr70029.C
@@ -0,0 +1,12 @@
+// PR c++/70029
+// { dg-do compile }
+// { dg-options "-std=c++11 -g -flto" }
+// { dg-require-effective-target lto }
+
+struct A
+{
+ A();
+ int foo() && __attribute__ ((__warn_unused_result__)) { return 0; }
+};
+
+A a;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70633.c b/gcc/testsuite/gcc.c-torture/compile/pr70633.c
new file mode 100644
index 00000000000..6d783cb3166
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr70633.c
@@ -0,0 +1,12 @@
+/* PR middle-end/70633 */
+
+typedef long V __attribute__((vector_size (4 * sizeof (long))));
+
+void foo (V *);
+
+void
+bar (void)
+{
+ V b = { (long) bar, 0, 0, 0 };
+ foo (&b);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr70602.c b/gcc/testsuite/gcc.c-torture/execute/pr70602.c
new file mode 100644
index 00000000000..c6628b037b2
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr70602.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/70602 */
+
+struct __attribute__((packed)) S
+{
+ int s : 1;
+ int t : 20;
+};
+
+int a, b, c;
+
+int
+main ()
+{
+ for (; a < 1; a++)
+ {
+ struct S e[] = { {0, 9}, {0, 9}, {0, 9}, {0, 0}, {0, 9}, {0, 9}, {0, 9},
+ {0, 0}, {0, 9}, {0, 9}, {0, 9}, {0, 0}, {0, 9}, {0, 9},
+ {0, 9}, {0, 0}, {0, 9}, {0, 9}, {0, 9}, {0, 0}, {0, 9} };
+ b = b || e[0].s;
+ c = e[0].t;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wparentheses-12.c b/gcc/testsuite/gcc.dg/Wparentheses-12.c
new file mode 100644
index 00000000000..7832415f1ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wparentheses-12.c
@@ -0,0 +1,135 @@
+/* PR c/70436 */
+/* { dg-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+foo (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ while (1)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ if (b)
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ while (1)
+ if (a)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ while (1)
+ {
+ if (a) { bar (); } else { baz (); }
+ }
+ else
+ bar ();
+
+ if (a)
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+ else bar ();
+
+ if (a)
+ while (1)
+ if (b)
+ bar ();
+ else
+ baz ();
+ else bar ();
+
+ if (a)
+ for (;;)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ for (;;)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ do
+ if (b) bar (); else baz ();
+ while (b);
+
+ if (a)
+ do
+ if (b) bar ();
+ while (b);
+ else baz ();
+}
diff --git a/gcc/testsuite/gcc.dg/Wparentheses-13.c b/gcc/testsuite/gcc.dg/Wparentheses-13.c
new file mode 100644
index 00000000000..9837ba566d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wparentheses-13.c
@@ -0,0 +1,67 @@
+/* PR c/70436 */
+/* { dg-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (int);
+
+void
+foo (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ if (b)
+ {
+ if (c)
+ bar (0);
+ }
+ else
+ bar (1);
+
+ if (a > 0)
+ if (a > 1)
+ if (a > 2)
+ if (a > 3)
+ if (a > 4)
+ if (a > 5) /* { dg-warning "ambiguous" } */
+ if (a > 6)
+ while (1)
+ bar (0);
+ else
+ bar (1);
+
+ if (a) /* { dg-warning "ambiguous" } */
+ if (b)
+ switch (c);
+ else
+ bar (1);
+
+ switch (a)
+ {
+ default:
+ if (b) /* { dg-warning "ambiguous" } */
+ if (c)
+ for (;;)
+ bar (0);
+ else
+ bar (1);
+ }
+
+ if (a) /* { dg-warning "ambiguous" } */
+ if (a)
+ {
+ bar (2);
+ }
+ else
+ bar (3);
+
+ if (a)
+ do if (b) bar (4); while (1);
+ else bar (5);
+
+ do
+ {
+ if (a)
+ if (b) /* { dg-warning "ambiguous" } */
+ if (c) for (;;) bar (6);
+ else bar (7);
+ } while (0);
+}
diff --git a/gcc/testsuite/gcc.dg/bitfld-22.c b/gcc/testsuite/gcc.dg/bitfld-22.c
new file mode 100644
index 00000000000..2fb904bce24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitfld-22.c
@@ -0,0 +1,18 @@
+/* PR c/70671 */
+/* { dg-do compile } */
+
+extern void bar (int *);
+
+struct S
+{
+ int x:2;
+} s, *r;
+
+void
+foo (void)
+{
+ int *p1 = &s.x; /* { dg-error "13:cannot take address of bit-field 'x'" } */
+ int *p2;
+ p2 = &s.x; /* { dg-error "8:cannot take address of bit-field 'x'" } */
+ bar (&s.x); /* { dg-error "8:cannot take address of bit-field 'x'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/pr68756.c b/gcc/testsuite/gcc.dg/graphite/pr68756.c
new file mode 100644
index 00000000000..ddb9789f133
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/graphite/pr68756.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -floop-nest-optimize" } */
+
+unsigned int z4, pz;
+int nn[2];
+
+static unsigned int
+xq (unsigned int dj)
+{
+ return dj > 1 ? z4 : z4 + dj;
+}
+
+void
+la (void)
+{
+ int hd, dl;
+ unsigned int hn = 0;
+
+ for (hd = 0; hd < 2; ++hd)
+ {
+ for (dl = 0; dl < 2; ++dl)
+ nn[dl] = 0;
+ --hn;
+ pz = xq (hn);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/ifcvt-4.c b/gcc/testsuite/gcc.dg/ifcvt-4.c
index d0d131b9ad8..319b583e4e2 100644
--- a/gcc/testsuite/gcc.dg/ifcvt-4.c
+++ b/gcc/testsuite/gcc.dg/ifcvt-4.c
@@ -1,12 +1,14 @@
/* { dg-options "-fdump-rtl-ce1 -O2 --param max-rtl-if-conversion-insns=3" } */
/* { dg-additional-options "-misel" { target { powerpc*-*-* } } } */
-/* { dg-skip-if "Multiple set if-conversion not guaranteed on all subtargets" { "arm*-*-* hppa*64*-*-* visium-*-*" } {"*"} { "" } } */
+/* { dg-skip-if "Multiple set if-conversion not guaranteed on all subtargets" { "arm*-*-* hppa*64*-*-* visium-*-*" } } */
-int
-foo (int x, int y, int a)
+typedef int word __attribute__((mode(word)));
+
+word
+foo (word x, word y, word a)
{
- int i = x;
- int j = y;
+ word i = x;
+ word j = y;
/* Try to make taking the branch likely. */
__builtin_expect (x > y, 1);
if (x > y)
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
index a7f846a1dcd..a23ac4efb1c 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
@@ -31,4 +31,5 @@ bar (long a)
/* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } */
/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" } } */
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* XFAIL due to PR70681. */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail arm*-*-* powerpc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/pr10474.c b/gcc/testsuite/gcc.dg/pr10474.c
index ee9edd442c9..a4af536ec28 100644
--- a/gcc/testsuite/gcc.dg/pr10474.c
+++ b/gcc/testsuite/gcc.dg/pr10474.c
@@ -12,4 +12,5 @@ void f(int *i)
}
}
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* XFAIL due to PR70681. */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail arm*-*-* powerpc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr70623-2.c b/gcc/testsuite/gcc.dg/torture/pr70623-2.c
new file mode 100644
index 00000000000..8e8dc96df0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr70623-2.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+int b8, il, rc, nm;
+
+void
+h9(void)
+{
+ int *av = &b8;
+
+is:
+ for (;;) {
+ int vj, wk;
+ int *m9 = &b8;
+
+ if (*m9 == *av) {
+ if (il == 0)
+ goto is;
+
+di:
+ continue;
+ for (vj = 0; vj < 1; ++vj) {
+ goto di;
+kz:
+ ;
+ }
+ }
+
+ for (rc = 0; rc < 2; ++rc) {
+ int bc = rc ? rc : nm;
+ int ud = bc ? (*av ? 0 : rc) : 1;
+
+ if (ud != 0)
+ if (*av != 0)
+ goto kz;
+ }
+
+ for (wk = 0; wk < 3; ++wk)
+ ++(*av);
+ av = 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr70623.c b/gcc/testsuite/gcc.dg/torture/pr70623.c
new file mode 100644
index 00000000000..37f2712d87d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr70623.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-w" } */
+
+int nm;
+int *av;
+
+void
+h9(void)
+{
+ for (;;) {
+ int wk, rc;
+ int **ptr_10 = &av;
+ if (*av != 0) {
+ }
+u4:
+ wk = 0;
+ for (rc = 0; rc < 3; ++rc) {
+ int bc = (rc ? rc : nm);
+ int ud = bc ? (*av ? 0 : rc) : 1;
+ if (ud != 0) {
+ if (*av != 0)
+ goto u4;
+ for (;;) {
+ }
+ }
+ }
+ while (wk < 3) {
+ av = **ptr_10;
+ ++wk;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr70628.c b/gcc/testsuite/gcc.dg/torture/pr70628.c
new file mode 100644
index 00000000000..00acae74b4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr70628.c
@@ -0,0 +1,46 @@
+/* PR debug/70628 */
+/* { dg-do compile } */
+/* { dg-options "-g -w" } */
+
+struct S { char s[64]; int *t; } *a;
+char b[64];
+int *foo (void);
+struct S *bar (int *);
+int baz (void);
+
+void
+test (const char *p, long q)
+{
+ int *c;
+ c = foo ();
+ while (a = bar (c))
+ {
+ if (__builtin_strstr (p, "ABCD")
+ || __builtin_strstr (p, "EFGHI")
+ || __builtin_strstr (p, "JKL")
+ || __builtin_strstr (p, "MNOPQR")
+ || __builtin_strstr (p, "STUV")
+ || __builtin_strstr (p, "WXYZabcd")
+ || __builtin_strstr (p, "efghij")
+ || __builtin_strstr (p, "klmno")
+ || __builtin_strstr (p, "pqrstuvw")
+ || __builtin_strstr (b, "MNOPQR") != "EFGHI"
+ || __builtin_strstr (b, "JKL"))
+ if (__builtin_strstr (a->s, "xyz12"))
+ continue;
+ __builtin_printf ("%p\n", a->t);
+ }
+ bar (c);
+ while (a)
+ if (__builtin_strstr (p, "ABCD")
+ || __builtin_strstr (p, "EFGHI")
+ || __builtin_strstr (p, "JKL")
+ || __builtin_strstr (p, "MNOPQR")
+ || __builtin_strstr (p, "STUV")
+ || __builtin_strstr (p, "WXYZabcd")
+ || __builtin_strstr (p, "efghij")
+ || __builtin_strstr (p, "klmno")
+ || __builtin_strstr (p, "pqrstuvw")
+ || __builtin_strstr ((const char *) q, "MNOPQR"))
+ baz ();
+}
diff --git a/gcc/testsuite/gcc.dg/vect/O3-pr70130.c b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
new file mode 100644
index 00000000000..e9938c21f41
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
@@ -0,0 +1,94 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw { target powerpc*-*-* } } */
+/* { dg-additional-options "-mcpu=power7" { target powerpc*-*-* } } */
+
+struct foo
+{
+ short a[3][16][16];
+ short pad;
+} images[8];
+
+void __attribute__ ((noinline, noclone))
+Loop_err (struct foo *img, const int s[16][2], int s0)
+{
+ int i, j;
+
+ for (j = 0; j < 16; j++)
+ {
+ for (i=0; i < 16; i++)
+ {
+ img->a[0][j][i] = s[i][0];
+ img->a[1][j][i] = s[j][1];
+ img->a[2][j][i] = s0;
+ }
+ }
+}
+
+const int s[16][2] = { { 1, 16 }, { 2, 15 }, { 3, 14 }, { 4, 13 },
+ { 5, 12 }, { 6, 11 }, { 7, 10 }, { 8, 9 },
+ { 9, 8 }, { 10, 7 }, { 11, 6 }, { 12, 5 },
+ { 13, 4 }, { 14, 3 }, { 15, 2 }, { 16, 1 } };
+const struct foo expected
+= { { { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } },
+ { { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 },
+ { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 },
+ { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 },
+ { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 },
+ { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 },
+ { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 },
+ { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
+ { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 },
+ { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
+ { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
+ { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+ { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
+ { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } },
+ { { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } },
+ 0 };
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ Loop_err (images + i, s, -1);
+
+ for (i = 0; i < 8; i++)
+ if (__builtin_memcmp (&expected, images + i, sizeof (expected)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c b/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
index 8eb50aafa2b..49b74d9e265 100644
--- a/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/mgeneral-regs_4.c
@@ -6,4 +6,4 @@ test (void)
return 1;
}
-/* { dg-final { scan-assembler "\.arch.*fp.*simd" } } */
+/* { dg-final { scan-assembler-times "\\.arch armv8-a\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
index f72bec878bf..2d8c7b955ce 100644
--- a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
+++ b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
@@ -10,4 +10,4 @@ foo (int a)
return a + 1;
}
-/* { dg-final { scan-assembler-times "\\.arch armv8-a\n" 1 } } */
+/* { dg-final { scan-assembler-times "\\.arch armv8-a\\+nofp\\+nosimd\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-6.c b/gcc/testsuite/gcc.target/i386/asm-flag-6.c
new file mode 100644
index 00000000000..458587ec9dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-6.c
@@ -0,0 +1,276 @@
+/* Executable testcase for 'output flags.' */
+/* { dg-do run } */
+
+char TestC ()
+{
+ char r;
+
+ __asm__ ("stc" : "=@ccc"(r));
+ if (r)
+ {
+ __asm__ ("clc" : "=@ccnc"(r));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+char TestE ()
+{
+ char r;
+
+ /* 1 equals 1. */
+ __asm__ ("cmp $1, %1" : "=@cce"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 not equals 2. */
+ __asm__ ("cmp $2, %1" : "=@ccne"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+char TestZ ()
+{
+ char r;
+
+ /* 1 equals 1. */
+ __asm__ ("cmp $1, %1" : "=@ccz"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 not equals 2. */
+ __asm__ ("cmp $2, %1" : "=@ccnz"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+char TestA ()
+{
+ char r;
+
+ /* 1 a 0. */
+ __asm__ ("cmp $0, %1" : "=@cca"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 na 2. */
+ __asm__ ("cmp $2, %1" : "=@ccna"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 na 1. */
+ __asm__ ("cmp $1, %1" : "=@ccna"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestAE ()
+{
+ char r;
+
+ /* 1 ae 0. */
+ __asm__ ("cmp $0, %1" : "=@ccae"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nae 2. */
+ __asm__ ("cmp $2, %1" : "=@ccnae"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 ae 1. */
+ __asm__ ("cmp $1, %1" : "=@ccae"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestB ()
+{
+ char r;
+
+ /* 1 b 2. */
+ __asm__ ("cmp $2, %1" : "=@ccb"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nb 0. */
+ __asm__ ("cmp $0, %1" : "=@ccnb"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nb 1. */
+ __asm__ ("cmp $1, %1" : "=@ccnb"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestBE ()
+{
+ char r;
+
+ /* 1 be 2. */
+ __asm__ ("cmp $2, %1" : "=@ccbe"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nbe 0. */
+ __asm__ ("cmp $0, %1" : "=@ccnbe"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 be 1. */
+ __asm__ ("cmp $1, %1" : "=@ccbe"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestG ()
+{
+ char r;
+
+ /* 1 g 0. */
+ __asm__ ("cmp $0, %1" : "=@ccg"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 ng 2. */
+ __asm__ ("cmp $2, %1" : "=@ccng"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 ng 1. */
+ __asm__ ("cmp $1, %1" : "=@ccng"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestGE ()
+{
+ char r;
+
+ /* 1 ge 0. */
+ __asm__ ("cmp $0, %1" : "=@ccge"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nge 2. */
+ __asm__ ("cmp $2, %1" : "=@ccnge"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 ge 1. */
+ __asm__ ("cmp $1, %1" : "=@ccge"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestL ()
+{
+ char r;
+
+ /* 1 l 2. */
+ __asm__ ("cmp $2, %1" : "=@ccl"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nl 0. */
+ __asm__ ("cmp $0, %1" : "=@ccnl"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nl 1. */
+ __asm__ ("cmp $1, %1" : "=@ccnl"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestLE ()
+{
+ char r;
+
+ /* 1 le 2. */
+ __asm__ ("cmp $2, %1" : "=@ccle"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 nle 0. */
+ __asm__ ("cmp $0, %1" : "=@ccnle"(r) : "r" (1));
+ if (r)
+ {
+ /* 1 le 1. */
+ __asm__ ("cmp $1, %1" : "=@ccle"(r) : "r" (1));
+ if (r)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+char TestO ()
+{
+ char r;
+ unsigned char res = 128;
+
+ /* overflow. */
+ __asm__ ("addb $128, %1" : "=@cco"(r), "+r"(res));
+ if (r)
+ {
+ /* not overflow. */
+ __asm__ ("addb $1, %1" : "=@ccno"(r), "+r"(res));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+char TestP ()
+{
+ char r, res = 1;
+
+ /* even # bits. */
+ __asm__ ("addb $2, %1" : "=@ccp"(r), "+r"(res));
+ if (r)
+ {
+ /* odd # bits. */
+ __asm__ ("addb $1, %1" : "=@ccnp"(r), "+r"(res));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+char TestS ()
+{
+ char r, res = 1;
+
+ /* sign bit set. */
+ __asm__ ("addb $128, %1" : "=@ccs"(r), "+r"(res));
+ if (r)
+ {
+ /* sign bit not set. */
+ __asm__ ("subb $128, %1" : "=@ccns"(r), "+r"(res));
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
+/* dg-do treats exit code of 0 as success. */
+int main ()
+{
+ if (TestC () && TestE () && TestZ () && TestA ()
+ && TestAE () && TestB () && TestBE () && TestG ()
+ && TestGE () && TestL () && TestLE () && TestO ()
+ && TestP () && TestS ())
+ return 0;
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-kunpckdq-2.c b/gcc/testsuite/gcc.target/i386/avx512bw-kunpckdq-2.c
new file mode 100644
index 00000000000..4fe503e42ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-kunpckdq-2.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512bw" } */
+/* { dg-require-effective-target avx512bw } */
+
+#define AVX512BW
+
+#include "avx512f-helper.h"
+
+static __mmask64 __attribute__((noinline,noclone))
+unpack (__mmask64 arg1, __mmask64 arg2)
+{
+ __mmask64 res;
+
+ res = _mm512_kunpackd (arg1, arg2);
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ if (unpack (0x07UL, 0x70UL) != 0x0700000070UL)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-kunpckwd-2.c b/gcc/testsuite/gcc.target/i386/avx512bw-kunpckwd-2.c
new file mode 100644
index 00000000000..5d7f8955975
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-kunpckwd-2.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512bw" } */
+/* { dg-require-effective-target avx512bw } */
+
+#define AVX512BW
+
+#include "avx512f-helper.h"
+
+static __mmask32 __attribute__((noinline,noclone))
+unpack (__mmask32 arg1, __mmask32 arg2)
+{
+ __mmask32 res;
+
+ res = _mm512_kunpackw (arg1, arg2);
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ if (unpack (0x07, 0x70) != 0x070070)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-kunpckbw-2.c b/gcc/testsuite/gcc.target/i386/avx512f-kunpckbw-2.c
new file mode 100644
index 00000000000..86580f289aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-kunpckbw-2.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-require-effective-target avx512f } */
+
+#define AVX512F
+
+#include "avx512f-helper.h"
+
+static __mmask16 __attribute__((noinline,noclone))
+unpack (__mmask16 arg1, __mmask16 arg2)
+{
+ __mmask16 res;
+
+ res = _mm512_kunpackb (arg1, arg2);
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ if (unpack (0x07, 0x70) != 0x0770)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr46470.c b/gcc/testsuite/gcc.target/i386/pr46470.c
index 11eb51a0394..8d6b5ca5d5e 100644
--- a/gcc/testsuite/gcc.target/i386/pr46470.c
+++ b/gcc/testsuite/gcc.target/i386/pr46470.c
@@ -4,7 +4,7 @@
/* These options are selected to ensure 1 word needs to be allocated
on the stack to maintain alignment for the call. This should be
transformed to push+pop. We also want to force unwind info updates. */
-/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables" } */
+/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables -mno-red-zone" } */
/* { dg-options "-Os -fomit-frame-pointer -mpreferred-stack-boundary=3 -fasynchronous-unwind-tables" { target ia32 } } */
/* ms_abi has reserved stack-region. */
/* { dg-skip-if "" { x86_64-*-mingw* } { "*" } { "" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70596.c b/gcc/testsuite/gcc.target/i386/pr70596.c
new file mode 100644
index 00000000000..0c73e838be1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr70596.c
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/70596 */
+/* { dg-do compile { target avx512f } } */
+/* { dg-options "-O2 -fno-dce -fschedule-insns -fno-tree-coalesce-vars -fno-tree-dce -fno-tree-fre -fno-tree-pre -fcompare-debug -mavx512f" } */
+
+typedef char V __attribute__((vector_size (64)));
+
+int
+foo (V u, V v)
+{
+ v /= u | 1;
+ v[18] = 1 | v[8];
+ return v[1] + v[6] + v[0] + v[1] + v[18] + v[2] + v[7];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr70662.c b/gcc/testsuite/gcc.target/i386/pr70662.c
new file mode 100644
index 00000000000..109e224d7b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr70662.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target avx512vbmi } */
+/* { dg-require-effective-target masm_intel } */
+/* { dg-options "-Og -fschedule-insns -fno-tree-fre -mavx512vbmi --param=max-sched-ready-insns=1 -masm=intel" } */
+
+typedef char v64u8 __attribute__((vector_size(64)));
+typedef int v64u32 __attribute__((vector_size(64)));
+typedef long v64u64 __attribute__((vector_size(64)));
+typedef __int128 v64u128 __attribute__((vector_size(64)));
+
+v64u128
+foo(int u8_0, unsigned u128_0, v64u32 v64u32_1, v64u32 v64u32_0, v64u64 v64u64_0, v64u128 v64u128_0)
+{
+ v64u8 v64u8_0 = v64u8_0;
+ v64u32_0 = v64u32_0 >> (v64u32){0, 0, 0, 1, 0, ((v64u64)v64u64_0)[u8_0], ((v64u32)v64u128_0)[15], 0, 0, 0, 0, 4, ((v64u64)v64u64_0)[v64u32_0[0]] - 1};
+ v64u8_0 = v64u8_0 << ((v64u8)v64u32_1 & 1);
+ v64u64_0[0] >>= 0;
+ return u128_0 + (v64u128)v64u8_0 + (v64u128)v64u32_0 + (v64u128)v64u64_0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-1.c b/gcc/testsuite/gcc.target/powerpc/float128-1.c
new file mode 100644
index 00000000000..b8e71ceaaae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-1.c
@@ -0,0 +1,147 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+
+#if !defined(__FLOAT128__) || !defined(_ARCH_PPC)
+static __float128
+pass_through (__float128 x)
+{
+ return x;
+}
+
+__float128 (*no_optimize) (__float128) = pass_through;
+#endif
+
+#ifdef DEBUG
+__attribute__((__noinline__))
+static void
+print_f128 (__float128 x)
+{
+ unsigned sign;
+ unsigned exponent;
+ uint64_t mantissa1;
+ uint64_t mantissa2;
+ uint64_t upper;
+ uint64_t lower;
+
+#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__)
+ struct ieee128 {
+ uint64_t upper;
+ uint64_t lower;
+ };
+
+#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__)
+ struct ieee128 {
+ uint64_t lower;
+ uint64_t upper;
+ };
+
+#else
+#error "Unknown system"
+#endif
+
+ union {
+ __float128 f128;
+ struct ieee128 s128;
+ } u;
+
+ u.f128 = x;
+ upper = u.s128.upper;
+ lower = u.s128.lower;
+
+ sign = (unsigned)((upper >> 63) & 1);
+ exponent = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1));
+ mantissa1 = (upper & ((((uint64_t)1) << 48) - 1));
+ mantissa2 = lower;
+
+ printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64,
+ sign ? '-' : '+',
+ exponent,
+ mantissa1,
+ mantissa2);
+}
+#endif
+
+__attribute__((__noinline__))
+static void
+do_test (__float128 expected, __float128 got, const char *name)
+{
+ int equal_p = (expected == got);
+
+#ifdef DEBUG
+ printf ("Test %s, expected: ", name);
+ print_f128 (expected);
+ printf (" %5g, got: ", (double) expected);
+ print_f128 (got);
+ printf (" %5g, result %s\n",
+ (double) got,
+ (equal_p) ? "equal" : "not equal");
+#endif
+
+ if (!equal_p)
+ __builtin_abort ();
+}
+
+
+int
+main (void)
+{
+ __float128 one = 1.0q;
+ __float128 two = 2.0q;
+ __float128 three = 3.0q;
+ __float128 four = 4.0q;
+ __float128 five = 5.0q;
+ __float128 add_result = (1.0q + 2.0q);
+ __float128 mul_result = ((1.0q + 2.0q) * 3.0q);
+ __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q);
+ __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q);
+ __float128 neg_result = - sub_result;
+ __float128 add_xresult;
+ __float128 mul_xresult;
+ __float128 div_xresult;
+ __float128 sub_xresult;
+ __float128 neg_xresult;
+
+#if defined(__FLOAT128__) && defined(_ARCH_PPC)
+ __asm__ (" #prevent constant folding, %x0" : "+wa" (one));
+ __asm__ (" #prevent constant folding, %x0" : "+wa" (two));
+ __asm__ (" #prevent constant folding, %x0" : "+wa" (three));
+ __asm__ (" #prevent constant folding, %x0" : "+wa" (four));
+ __asm__ (" #prevent constant folding, %x0" : "+wa" (five));
+
+#else
+ one = no_optimize (one);
+ two = no_optimize (two);
+ three = no_optimize (three);
+ four = no_optimize (four);
+ five = no_optimize (five);
+#endif
+
+ add_xresult = (one + two);
+ do_test (add_result, add_xresult, "add");
+
+ mul_xresult = add_xresult * three;
+ do_test (mul_result, mul_xresult, "mul");
+
+ div_xresult = mul_xresult / four;
+ do_test (div_result, div_xresult, "div");
+
+ sub_xresult = div_xresult - five;
+ do_test (sub_result, sub_xresult, "sub");
+
+ neg_xresult = - sub_xresult;
+ do_test (neg_result, neg_xresult, "neg");
+
+#ifdef DEBUG
+ printf ("Passed\n");
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-2.c b/gcc/testsuite/gcc.target/powerpc/float128-2.c
new file mode 100644
index 00000000000..f517686bd25
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-2.c
@@ -0,0 +1,226 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+/*
+ * Test program to make sure we are getting more precision than the 53 bits we
+ * get with IEEE double.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+#ifndef NO_INLINE
+#define NO_INLINE __attribute__((__noinline__))
+#endif
+
+static TYPE power_of_two (ssize_t) NO_INLINE;
+static TYPE calc1 (TYPE) NO_INLINE;
+static TYPE calc2 (TYPE) NO_INLINE;
+static TYPE calc3 (TYPE) NO_INLINE;
+
+#ifndef POWER2
+#define POWER2 60
+#endif
+
+
+/*
+ * Print TYPE in hex.
+ */
+
+
+#if defined(DEBUG) || defined(DEBUG2)
+static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
+
+#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__)
+#define ENDIAN_REVERSE(N, MAX) ((MAX) - 1 - (N))
+
+#else
+#define ENDIAN_REVERSE(N, MAX) (N)
+#endif
+
+static void
+print_hex (const char *prefix, TYPE value, const char *suffix)
+{
+ union {
+ TYPE f128;
+ unsigned char uc[sizeof (TYPE)];
+ } u;
+
+ size_t i;
+
+ u.f128 = value;
+ printf ("%s0x", prefix);
+ for (i = 0; i < sizeof (TYPE); i++)
+ printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
+
+ printf (", %24.2Lf%s", (long double)value, suffix);
+}
+#endif
+
+
+/*
+ * Return a power of two.
+ */
+
+static TYPE
+power_of_two (ssize_t num)
+{
+ TYPE ret = (TYPE) 1.0;
+ ssize_t i;
+
+ if (num >= 0)
+ {
+ for (i = 0; i < num; i++)
+ ret *= (TYPE) 2.0;
+ }
+ else
+ {
+ ssize_t num2 = -num;
+ for (i = 0; i < num2; i++)
+ ret /= (TYPE) 2.0;
+ }
+
+#ifdef DEBUG
+ printf ("power_of_two (%2ld) = ", (long) num);
+ print_hex ("", ret, "\n");
+#endif
+
+ return ret;
+}
+
+
+#ifdef ADDSUB
+static TYPE add (TYPE a, TYPE b) NO_INLINE;
+static TYPE sub (TYPE a, TYPE b) NO_INLINE;
+
+static TYPE
+add (TYPE a, TYPE b)
+{
+ TYPE c;
+#ifdef DEBUG
+ print_hex ("add, arg1 = ", a, "\n");
+ print_hex ("add, arg2 = ", b, "\n");
+#endif
+ c = a + b;
+#ifdef DEBUG
+ print_hex ("add, result = ", c, "\n");
+#endif
+ return c;
+}
+
+static TYPE
+sub (TYPE a, TYPE b)
+{
+ TYPE c;
+#ifdef DEBUG
+ print_hex ("sub, arg1 = ", a, "\n");
+ print_hex ("sub, arg2 = ", b, "\n");
+#endif
+ c = a - b;
+#ifdef DEBUG
+ print_hex ("sub, result = ", c, "\n");
+#endif
+ return c;
+}
+
+#else
+#define add(x, y) ((x) + (y))
+#define sub(x, y) ((x) - (y))
+#endif
+
+/*
+ * Various calculations. Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+ TYPE num2 = add (power_of_two (POWER2), num);
+ TYPE ret;
+
+#ifdef DEBUG
+ print_hex ("calc1 (before call) = ", num2, "\n");
+#endif
+
+ ret = calc2 (num2);
+
+#ifdef DEBUG
+ print_hex ("calc1 (after call) = ", ret, "\n");
+#endif
+
+ return ret;
+}
+
+static TYPE
+calc2 (TYPE num)
+{
+ TYPE num2 = sub (num, power_of_two (POWER2-1));
+ TYPE ret;
+
+#ifdef DEBUG
+ print_hex ("calc2 (before call) = ", num2, "\n");
+#endif
+
+ ret = calc3 (num2);
+
+#ifdef DEBUG
+ print_hex ("calc2 (after call) = ", ret, "\n");
+#endif
+
+ return ret;
+}
+
+static TYPE
+calc3 (TYPE num)
+{
+ TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
+
+#ifdef DEBUG
+ print_hex ("calc3 = ", ret, "\n");
+#endif
+
+ return ret;
+}
+
+
+int
+main (void)
+{
+ TYPE input, output;
+
+#ifdef DEBUG
+ printf ("Testing, %ld bytes\n", (long) sizeof (TYPE));
+#endif
+
+ input = power_of_two (-1);
+ if ((double)input != 0.5)
+ {
+#if defined(DEBUG) || defined(DEBUG2)
+ print_hex ("Input should be 0.5: ", output, "\n");
+ return 1;
+#else
+ __builtin_abort ();
+#endif
+ }
+
+ output = calc1 (input);
+ if ((double)output != 0.5)
+ {
+#if defined(DEBUG) || defined(DEBUG2)
+ print_hex ("Output should be 0.5: ", output, "\n");
+ return 1;
+#else
+ __builtin_abort ();
+#endif
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr70640.c b/gcc/testsuite/gcc.target/powerpc/pr70640.c
new file mode 100644
index 00000000000..5d49c6331f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr70640.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target powerpc_float128_sw_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power8 -mfloat128" } */
+
+__float128 foo (__float128 a) { return -a; }
+
+/* { dg-final { scan-assembler "xxlorc\|vspltisw" } } */
+/* { dg-final { scan-assembler "xxlxor" } } */
+/* { dg-final { scan-assembler "vslb" } } */
+/* { dg-final { scan-assembler "vsldoi" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr70669.c b/gcc/testsuite/gcc.target/powerpc/pr70669.c
new file mode 100644
index 00000000000..8054102ee50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr70669.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power8 -mfloat128" } */
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+void foo (TYPE *p, TYPE *q)
+{
+ TYPE r = *q;
+#ifndef NO_ASM
+ __asm__ (" # %0" : "+r" (r));
+#endif
+ *p = r;
+}
+
+/* { dg-final { scan-assembler "mfvsrd" } } */
+/* { dg-final { scan-assembler "mtvsrd" } } */
+/* { dg-final { scan-assembler-times "stxvd2x" 1 } } */
+/* { dg-final { scan-assembler-times "lxvd2x" 1 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index bdbee07ad11..df226b0f8a1 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1749,7 +1749,7 @@ proc check_ppc_float128_sw_available { } {
int main()
{
__float128 z = x + y;
- return (z == 3.0q);
+ return (z != 3.0q);
}
} $options
}
@@ -1768,7 +1768,7 @@ proc check_ppc_float128_hw_available { } {
|| [istarget *-*-darwin*]} {
expr 0
} else {
- set options "-mfloat128-hardware"
+ set options "-mfloat128 -mvsx -mfloat128-hardware -mpower9-vector"
check_runtime_nocache ppc_float128_hw_available {
volatile __float128 x = 1.0q;
volatile __float128 y = 2.0q;
@@ -1778,7 +1778,7 @@ proc check_ppc_float128_hw_available { } {
__float128 w = -1.0q;
__asm__ ("xsaddqp %0,%1,%2" : "+v" (w) : "v" (x), "v" (y));
- return ((z == 3.0q) && (z == w);
+ return ((z != 3.0q) || (z != w);
}
} $options
}
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 2894cbc869a..d3832841232 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -40,19 +40,19 @@ static void pretty_print_string (pretty_printer *, const char*);
static void newline_and_indent (pretty_printer *, int);
static void maybe_init_pretty_print (FILE *);
static void print_struct_decl (pretty_printer *, const_tree, int, int);
-static void do_niy (pretty_printer *, const_tree);
+static void do_niy (pretty_printer *, const_tree, int);
#define INDENT(SPACE) do { \
int i; for (i = 0; i<SPACE; i++) pp_space (pp); } while (0)
-#define NIY do_niy (pp, node)
+#define NIY do_niy (pp, node, flags)
static pretty_printer *tree_pp;
/* Try to print something for an unknown tree code. */
static void
-do_niy (pretty_printer *pp, const_tree node)
+do_niy (pretty_printer *pp, const_tree node, int flags)
{
int i, len;
@@ -65,7 +65,7 @@ do_niy (pretty_printer *pp, const_tree node)
for (i = 0; i < len; ++i)
{
newline_and_indent (pp, 2);
- dump_generic_node (pp, TREE_OPERAND (node, i), 2, 0, false);
+ dump_generic_node (pp, TREE_OPERAND (node, i), 2, flags, false);
}
}
@@ -161,6 +161,85 @@ print_generic_expr (FILE *file, tree t, int flags)
pp_flush (tree_pp);
}
+/* Dump NAME, an IDENTIFIER_POINTER, sanitized so that D<num> sequences
+ in it are replaced with Dxxxx, as long as they are at the start or
+ preceded by $ and at the end or followed by $. See make_fancy_name
+ in tree-sra.c. */
+
+static void
+dump_fancy_name (pretty_printer *pp, tree name)
+{
+ int cnt = 0;
+ int length = IDENTIFIER_LENGTH (name);
+ const char *n = IDENTIFIER_POINTER (name);
+ do
+ {
+ n = strchr (n, 'D');
+ if (n == NULL)
+ break;
+ if (ISDIGIT (n[1])
+ && (n == IDENTIFIER_POINTER (name) || n[-1] == '$'))
+ {
+ int l = 2;
+ while (ISDIGIT (n[l]))
+ l++;
+ if (n[l] == '\0' || n[l] == '$')
+ {
+ cnt++;
+ length += 5 - l;
+ }
+ n += l;
+ }
+ else
+ n++;
+ }
+ while (1);
+ if (cnt == 0)
+ {
+ pp_tree_identifier (pp, name);
+ return;
+ }
+
+ char *str = XNEWVEC (char, length + 1);
+ char *p = str;
+ const char *q;
+ q = n = IDENTIFIER_POINTER (name);
+ do
+ {
+ q = strchr (q, 'D');
+ if (q == NULL)
+ break;
+ if (ISDIGIT (q[1])
+ && (q == IDENTIFIER_POINTER (name) || q[-1] == '$'))
+ {
+ int l = 2;
+ while (ISDIGIT (q[l]))
+ l++;
+ if (q[l] == '\0' || q[l] == '$')
+ {
+ memcpy (p, n, q - n);
+ memcpy (p + (q - n), "Dxxxx", 5);
+ p += (q - n) + 5;
+ n = q + l;
+ }
+ q += l;
+ }
+ else
+ q++;
+ }
+ while (1);
+ memcpy (p, n, IDENTIFIER_LENGTH (name) - (n - IDENTIFIER_POINTER (name)));
+ str[length] = '\0';
+ if (pp_translate_identifiers (pp))
+ {
+ const char *text = identifier_to_locale (str);
+ pp_append_text (pp, text, text + strlen (text));
+ }
+ else
+ pp_append_text (pp, str, str + length);
+ XDELETEVEC (str);
+}
+
/* Dump the name of a _DECL node and its DECL_UID if TDF_UID is set
in FLAGS. */
@@ -171,6 +250,10 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
{
if ((flags & TDF_ASMNAME) && DECL_ASSEMBLER_NAME_SET_P (node))
pp_tree_identifier (pp, DECL_ASSEMBLER_NAME (node));
+ /* For DECL_NAMELESS names look for embedded uids in the
+ names and sanitize them for TDF_NOUID. */
+ else if ((flags & TDF_NOUID) && DECL_NAMELESS (node))
+ dump_fancy_name (pp, DECL_NAME (node));
else
pp_tree_identifier (pp, DECL_NAME (node));
}
@@ -2631,8 +2714,15 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, int flags,
case SSA_NAME:
if (SSA_NAME_IDENTIFIER (node))
- dump_generic_node (pp, SSA_NAME_IDENTIFIER (node),
- spc, flags, false);
+ {
+ if ((flags & TDF_NOUID)
+ && SSA_NAME_VAR (node)
+ && DECL_NAMELESS (SSA_NAME_VAR (node)))
+ dump_fancy_name (pp, SSA_NAME_IDENTIFIER (node));
+ else
+ dump_generic_node (pp, SSA_NAME_IDENTIFIER (node),
+ spc, flags, false);
+ }
pp_underscore (pp);
pp_decimal_int (pp, SSA_NAME_VERSION (node));
if (SSA_NAME_IS_DEFAULT_DEF (node))
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index fdd5da0589a..88a0eaaa82d 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1510,6 +1510,9 @@ analyze_evolution_in_loop (gphi *loop_phi_node,
/* When there are multiple back edges of the loop (which in fact never
happens currently, but nevertheless), merge their evolutions. */
evolution_function = chrec_merge (evolution_function, ev_fn);
+
+ if (evolution_function == chrec_dont_know)
+ break;
}
if (dump_file && (dump_flags & TDF_SCEV))
@@ -1687,6 +1690,8 @@ interpret_condition_phi (struct loop *loop, gphi *condition_phi)
(loop, PHI_ARG_DEF (condition_phi, i));
res = chrec_merge (res, branch_chrec);
+ if (res == chrec_dont_know)
+ break;
}
return res;
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 696e7b1ac7b..2d95dc0e81d 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2132,6 +2132,7 @@ create_access_replacement (struct access *access)
bool fail = false;
DECL_NAME (repl) = get_identifier (pretty_name);
+ DECL_NAMELESS (repl) = 1;
obstack_free (&name_obstack, pretty_name);
/* Get rid of any SSA_NAMEs embedded in debug_expr,
@@ -2743,6 +2744,9 @@ generate_subtree_copies (struct access *access, tree agg,
gimple_stmt_iterator *gsi, bool write,
bool insert_after, location_t loc)
{
+ /* Never write anything into constant pool decls. See PR70602. */
+ if (!write && constant_decl_p (agg))
+ return;
do
{
if (chunk_size && access->offset >= start_offset + chunk_size)
@@ -4702,6 +4706,7 @@ get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
repl = create_tmp_reg (TREE_TYPE (adj->base), "ISR");
DECL_NAME (repl) = get_identifier (pretty_name);
+ DECL_NAMELESS (repl) = 1;
obstack_free (&name_obstack, pretty_name);
adj->new_ssa_base = repl;
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index c76051ac542..15fc43f8126 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -393,14 +393,16 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
in_ctor_dtor_block = true;
unused = false;
}
- /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN
+ /* 2) inside such blocks, the outermost block with block_ultimate_origin
being a FUNCTION_DECL. */
- else if (in_ctor_dtor_block
- && BLOCK_ABSTRACT_ORIGIN (scope)
- && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL)
+ else if (in_ctor_dtor_block)
{
- in_ctor_dtor_block = false;
- unused = false;
+ tree fn = block_ultimate_origin (scope);
+ if (fn && TREE_CODE (fn) == FUNCTION_DECL)
+ {
+ in_ctor_dtor_block = false;
+ unused = false;
+ }
}
for (t = &BLOCK_VARS (scope); *t; t = next)
@@ -855,7 +857,9 @@ remove_unused_locals (void)
cfun->local_decls->truncate (dstidx);
}
- remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), false);
+ remove_unused_scope_block_p (DECL_INITIAL (current_function_decl),
+ polymorphic_ctor_dtor_p (current_function_decl,
+ true) != NULL_TREE);
clear_unused_block_pointer ();
BITMAP_FREE (usedvars);
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 7be4f16fbac..a016e9f64c4 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -121,11 +121,7 @@ avg_loop_niter (struct loop *loop)
{
HOST_WIDE_INT niter = estimated_stmt_executions_int (loop);
if (niter == -1)
- {
- niter = max_stmt_executions_int (loop);
- if (niter == -1 || niter > AVG_LOOP_NITER (loop))
- return AVG_LOOP_NITER (loop);
- }
+ return AVG_LOOP_NITER (loop);
return niter;
}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index c93e563e51c..81689fc1aa4 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -3115,6 +3115,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
tree low, high, type, next;
bool sign, upper = true, at_end = false;
struct loop *loop = data->loop;
+ bool reliable = true;
if (TREE_CODE (base) != ARRAY_REF)
return true;
@@ -3186,14 +3187,14 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
&& tree_int_cst_compare (next, high) <= 0)
return true;
- /* If access is not executed on every iteration, we must ensure that overlow
- may not make the access valid later. */
+ /* If access is not executed on every iteration, we must ensure that overlow may
+ not make the access valid later. */
if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt))
&& scev_probably_wraps_p (initial_condition_in_loop_num (ev, loop->num),
step, data->stmt, loop, true))
- upper = false;
+ reliable = false;
- record_nonwrapping_iv (loop, init, step, data->stmt, low, high, false, upper);
+ record_nonwrapping_iv (loop, init, step, data->stmt, low, high, reliable, upper);
return true;
}
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index 77acd66e997..dd6fd01256a 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -223,8 +223,6 @@ tree_unswitch_single_loop (struct loop *loop, int num)
/* If the loop is not expected to iterate, there is no need
for unswitching. */
iterations = estimated_loop_iterations_int (loop);
- if (iterations < 0)
- iterations = max_loop_iterations_int (loop);
if (iterations >= 0 && iterations <= 1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -441,8 +439,6 @@ tree_unswitch_outer_loop (struct loop *loop)
/* If the loop is not expected to iterate, there is no need
for unswitching. */
iterations = estimated_loop_iterations_int (loop);
- if (iterations < 0)
- iterations = max_loop_iterations_int (loop);
if (iterations >= 0 && iterations <= 1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index b2d63acf930..f1a3130cb1c 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2062,11 +2062,6 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block)
static sbitmap has_abnormal_preds;
-/* List of blocks that may have changed during ANTIC computation and
- thus need to be iterated over. */
-
-static sbitmap changed_blocks;
-
/* Compute the ANTIC set for BLOCK.
If succs(BLOCK) > 1 then
@@ -2125,6 +2120,16 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
first = e->dest;
else if (BB_VISITED (e->dest))
worklist.quick_push (e->dest);
+ else
+ {
+ /* Unvisited successors get their ANTIC_IN replaced by the
+ maximal set to arrive at a maximum ANTIC_IN solution.
+ We can ignore them in the intersection operation and thus
+ need not explicitely represent that maximum solution. */
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "ANTIC_IN is MAX on %d->%d\n",
+ e->src->index, e->dest->index);
+ }
}
/* Of multiple successors we have to have visited one already
@@ -2167,14 +2172,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
clean (ANTIC_IN (block));
if (!bitmap_set_equal (old, ANTIC_IN (block)))
- {
- changed = true;
- bitmap_set_bit (changed_blocks, block->index);
- FOR_EACH_EDGE (e, ei, block->preds)
- bitmap_set_bit (changed_blocks, e->src->index);
- }
- else
- bitmap_clear_bit (changed_blocks, block->index);
+ changed = true;
maybe_dump_sets:
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2182,6 +2180,8 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
if (ANTIC_OUT)
print_bitmap_set (dump_file, ANTIC_OUT, "ANTIC_OUT", block->index);
+ if (changed)
+ fprintf (dump_file, "[changed] ");
print_bitmap_set (dump_file, ANTIC_IN (block), "ANTIC_IN",
block->index);
@@ -2313,14 +2313,7 @@ compute_partial_antic_aux (basic_block block,
dependent_clean (PA_IN (block), ANTIC_IN (block));
if (!bitmap_set_equal (old_PA_IN, PA_IN (block)))
- {
- changed = true;
- bitmap_set_bit (changed_blocks, block->index);
- FOR_EACH_EDGE (e, ei, block->preds)
- bitmap_set_bit (changed_blocks, e->src->index);
- }
- else
- bitmap_clear_bit (changed_blocks, block->index);
+ changed = true;
maybe_dump_sets:
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2346,6 +2339,8 @@ compute_antic (void)
int num_iterations = 0;
basic_block block;
int i;
+ edge_iterator ei;
+ edge e;
/* If any predecessor edges are abnormal, we punt, so antic_in is empty.
We pre-build the map of blocks with incoming abnormal edges here. */
@@ -2354,18 +2349,12 @@ compute_antic (void)
FOR_ALL_BB_FN (block, cfun)
{
- edge_iterator ei;
- edge e;
-
FOR_EACH_EDGE (e, ei, block->preds)
- {
- e->flags &= ~EDGE_DFS_BACK;
- if (e->flags & EDGE_ABNORMAL)
- {
- bitmap_set_bit (has_abnormal_preds, block->index);
- break;
- }
- }
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ bitmap_set_bit (has_abnormal_preds, block->index);
+ break;
+ }
BB_VISITED (block) = 0;
@@ -2377,8 +2366,8 @@ compute_antic (void)
/* At the exit block we anticipate nothing. */
BB_VISITED (EXIT_BLOCK_PTR_FOR_FN (cfun)) = 1;
- changed_blocks = sbitmap_alloc (last_basic_block_for_fn (cfun) + 1);
- bitmap_ones (changed_blocks);
+ sbitmap worklist = sbitmap_alloc (last_basic_block_for_fn (cfun) + 1);
+ bitmap_ones (worklist);
while (changed)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2391,12 +2380,18 @@ compute_antic (void)
changed = false;
for (i = postorder_num - 1; i >= 0; i--)
{
- if (bitmap_bit_p (changed_blocks, postorder[i]))
+ if (bitmap_bit_p (worklist, postorder[i]))
{
basic_block block = BASIC_BLOCK_FOR_FN (cfun, postorder[i]);
- changed |= compute_antic_aux (block,
- bitmap_bit_p (has_abnormal_preds,
- block->index));
+ bitmap_clear_bit (worklist, block->index);
+ if (compute_antic_aux (block,
+ bitmap_bit_p (has_abnormal_preds,
+ block->index)))
+ {
+ FOR_EACH_EDGE (e, ei, block->preds)
+ bitmap_set_bit (worklist, e->src->index);
+ changed = true;
+ }
}
}
/* Theoretically possible, but *highly* unlikely. */
@@ -2408,8 +2403,7 @@ compute_antic (void)
if (do_partial_partial)
{
- bitmap_ones (changed_blocks);
- mark_dfs_back_edges ();
+ bitmap_ones (worklist);
num_iterations = 0;
changed = true;
while (changed)
@@ -2420,13 +2414,18 @@ compute_antic (void)
changed = false;
for (i = postorder_num - 1 ; i >= 0; i--)
{
- if (bitmap_bit_p (changed_blocks, postorder[i]))
+ if (bitmap_bit_p (worklist, postorder[i]))
{
basic_block block = BASIC_BLOCK_FOR_FN (cfun, postorder[i]);
- changed
- |= compute_partial_antic_aux (block,
- bitmap_bit_p (has_abnormal_preds,
- block->index));
+ bitmap_clear_bit (worklist, block->index);
+ if (compute_partial_antic_aux (block,
+ bitmap_bit_p (has_abnormal_preds,
+ block->index)))
+ {
+ FOR_EACH_EDGE (e, ei, block->preds)
+ bitmap_set_bit (worklist, e->src->index);
+ changed = true;
+ }
}
}
/* Theoretically possible, but *highly* unlikely. */
@@ -2436,7 +2435,7 @@ compute_antic (void)
num_iterations);
}
sbitmap_free (has_abnormal_preds);
- sbitmap_free (changed_blocks);
+ sbitmap_free (worklist);
}
@@ -4695,12 +4694,14 @@ init_pre (void)
connect_infinite_loops_to_exit ();
memset (&pre_stats, 0, sizeof (pre_stats));
+ /* For ANTIC computation we need a postorder that also guarantees that
+ a block with a single successor is visited after its successor.
+ RPO on the inverted CFG has this property. */
postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
postorder_num = inverted_post_order_compute (postorder);
alloc_aux_for_blocks (sizeof (struct bb_bitmap_sets));
- calculate_dominance_info (CDI_POST_DOMINATORS);
calculate_dominance_info (CDI_DOMINATORS);
bitmap_obstack_initialize (&grand_bitmap_obstack);
@@ -4734,8 +4735,6 @@ fini_pre ()
name_to_id.release ();
free_aux_for_blocks ();
-
- free_dominance_info (CDI_POST_DOMINATORS);
}
namespace {
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index f8695b13d6d..7652e216eb6 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -5983,10 +5983,19 @@ vect_supportable_dr_alignment (struct data_reference *dr,
|| targetm.vectorize.builtin_mask_for_load ()))
{
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- if ((nested_in_vect_loop
- && (TREE_INT_CST_LOW (DR_STEP (dr))
- != GET_MODE_SIZE (TYPE_MODE (vectype))))
- || !loop_vinfo)
+
+ /* If we are doing SLP then the accesses need not have the
+ same alignment, instead it depends on the SLP group size. */
+ if (loop_vinfo
+ && STMT_SLP_TYPE (stmt_info)
+ && (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+ * GROUP_SIZE (vinfo_for_stmt (GROUP_FIRST_ELEMENT (stmt_info)))
+ % TYPE_VECTOR_SUBPARTS (vectype) != 0))
+ ;
+ else if (!loop_vinfo
+ || (nested_in_vect_loop
+ && (TREE_INT_CST_LOW (DR_STEP (dr))
+ != GET_MODE_SIZE (TYPE_MODE (vectype)))))
return dr_explicit_realign;
else
return dr_explicit_realign_optimized;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index f977ee9351b..d813b862592 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -2063,8 +2063,6 @@ start_over:
estimated_niter
= estimated_stmt_executions_int (LOOP_VINFO_LOOP (loop_vinfo));
- if (estimated_niter != -1)
- estimated_niter = max_niter;
if (estimated_niter != -1
&& ((unsigned HOST_WIDE_INT) estimated_niter
<= MAX (th, (unsigned)min_profitable_estimate)))
diff --git a/gcc/tree.c b/gcc/tree.c
index 3095db65f52..9aa2022ba4b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13685,7 +13685,9 @@ verify_type (const_tree t)
debug_tree (ct);
error_found = true;
}
- if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
+ /* FIXME: this is violated by the C++ FE as discussed in PR70029, when
+ FUNCTION_*_QUALIFIED flags are set. */
+ if (0 && TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
{
error ("TYPE_CANONICAL of main variant is not main variant");
debug_tree (ct);
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 583f9542eab..acb8d75dccf 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,10 @@
+2016-04-13 Bernd Schmidt <bschmidt@redhat.com>
+
+ Patch from Roger Orr <rogero@howzatt.demon.co.uk>
+ PR preprocessor/69650
+ * directives.c (do_linemarker): Reread map after calling
+ cpp_get_token.
+
2016-04-06 Richard Henderson <rth@redhat.com>
PR preprocessor/61817
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 6aa6bd1f86a..1617ff61c3c 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -1048,6 +1048,9 @@ do_linemarker (cpp_reader *pfile)
if (reason == LC_LEAVE)
{
+ /* Reread map since cpp_get_token can invalidate it with a
+ reallocation. */
+ map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
const line_map_ordinary *from;
if (MAIN_FILE_P (map)
|| (new_file
@@ -1055,7 +1058,8 @@ do_linemarker (cpp_reader *pfile)
&& filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0))
{
cpp_warning (pfile, CPP_W_NONE,
- "file \"%s\" linemarker ignored due to incorrect nesting", new_file);
+ "file \"%s\" linemarker ignored due to "
+ "incorrect nesting", new_file);
return;
}
}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 6011d2cccfb..2a138628326 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-04-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/70381
+ * configure.ac (powerpc*-*-linux*): Rework tests to build
+ __float128 emulation routines to not depend on using #pragma GCC
+ target to enable -mfloat128.
+ * configure: Regnerate.
+
2016-04-04 Eric Botcazou <ebotcazou@adacore.com>
PR target/67172
diff --git a/libgcc/configure b/libgcc/configure
index f3f360512c4..e7d6c75a6f7 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4767,16 +4767,20 @@ esac
esac
case ${host} in
+# At present, we cannot turn -mfloat128 on via #pragma GCC target,
+# so just check if we have VSX (ISA 2.06) support to build the
+# software libraries, and whether the assembler can handle xsaddqp
+# for hardware support.
powerpc*-*-linux*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5
-$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 2.06 to build __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 2.06 to build __float128 libraries... " >&6; }
if test "${libgcc_cv_powerpc_float128+set}" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#pragma GCC target ("vsx,float128")
- __float128 add (__float128 *a) { return *a + *(a+1); }
+#pragma GCC target ("vsx")
+ vector double dadd (vector double a, vector double b) { return a + b; }
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
libgcc_cv_powerpc_float128=yes
@@ -4788,21 +4792,21 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5
$as_echo "$libgcc_cv_powerpc_float128" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do hardware __float128" >&5
-$as_echo_n "checking whether the PowerPC compiler can do hardware __float128... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 3.0 to build hardware __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 3.0 to build hardware __float128 libraries... " >&6; }
if test "${libgcc_cv_powerpc_float128_hw+set}" = set; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#pragma GCC target ("cpu=power9,float128,float128-hardware")
+#pragma GCC target ("vsx,power9-vector")
#include <sys/auxv.h>
#ifndef AT_PLATFORM
#error "AT_PLATFORM is not defined"
#endif
- __float128 add (__float128 a, __float128 b)
+ vector unsigned char (vector unsigned char a, vector unsigned char b)
{
- __float128 ret;
+ vector unsigned char ret;
__asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
return ret;
}
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 897259e62bc..269997f23e2 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -374,26 +374,30 @@ esac
esac
case ${host} in
+# At present, we cannot turn -mfloat128 on via #pragma GCC target,
+# so just check if we have VSX (ISA 2.06) support to build the
+# software libraries, and whether the assembler can handle xsaddqp
+# for hardware support.
powerpc*-*-linux*)
- AC_CACHE_CHECK([whether the PowerPC compiler can do __float128],
+ AC_CACHE_CHECK([for PowerPC ISA 2.06 to build __float128 libraries],
[libgcc_cv_powerpc_float128],
[AC_COMPILE_IFELSE(
- [#pragma GCC target ("vsx,float128")
- __float128 add (__float128 *a) { return *a + *(a+1); }],
+ [#pragma GCC target ("vsx")
+ vector double dadd (vector double a, vector double b) { return a + b; }],
[libgcc_cv_powerpc_float128=yes],
[libgcc_cv_powerpc_float128=no])])
- AC_CACHE_CHECK([whether the PowerPC compiler can do hardware __float128],
+ AC_CACHE_CHECK([for PowerPC ISA 3.0 to build hardware __float128 libraries],
[libgcc_cv_powerpc_float128_hw],
[AC_COMPILE_IFELSE(
- [#pragma GCC target ("cpu=power9,float128,float128-hardware")
+ [#pragma GCC target ("vsx,power9-vector")
#include <sys/auxv.h>
#ifndef AT_PLATFORM
#error "AT_PLATFORM is not defined"
#endif
- __float128 add (__float128 a, __float128 b)
+ vector unsigned char (vector unsigned char a, vector unsigned char b)
{
- __float128 ret;
+ vector unsigned char ret;
__asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
return ret;
}
diff --git a/libgo/MERGE b/libgo/MERGE
index 3cb26c37c07..a40967cea24 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-7bc40ffb05d8813bf9b41a331b45d37216f9e747
+f5cf5673590a68c55b2330df9dfcdd6fac75b893
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index 0be00434da5..e1bf218d1df 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.6 \ No newline at end of file
+go1.6.1 \ No newline at end of file
diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go
index 28e981b9dde..9f414a470c7 100644
--- a/libgo/go/crypto/dsa/dsa.go
+++ b/libgo/go/crypto/dsa/dsa.go
@@ -249,6 +249,10 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
// FIPS 186-3, section 4.7
+ if pub.P.Sign() == 0 {
+ return false
+ }
+
if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
return false
}
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go
index 0731f2b6703..e54488c9cf6 100644
--- a/libgo/go/crypto/ecdsa/ecdsa.go
+++ b/libgo/go/crypto/ecdsa/ecdsa.go
@@ -23,6 +23,7 @@ import (
"crypto/elliptic"
"crypto/sha512"
"encoding/asn1"
+ "errors"
"io"
"math/big"
)
@@ -140,6 +141,8 @@ func fermatInverse(k, N *big.Int) *big.Int {
return new(big.Int).Exp(k, nMinus2, N)
}
+var errZeroParam = errors.New("zero parameter")
+
// Sign signs an arbitrary length hash (which should be the result of hashing a
// larger message) using the private key, priv. It returns the signature as a
// pair of integers. The security of the private key depends on the entropy of
@@ -180,7 +183,9 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
// See [NSA] 3.4.1
c := priv.PublicKey.Curve
N := c.Params().N
-
+ if N.Sign() == 0 {
+ return nil, nil, errZeroParam
+ }
var k, kInv *big.Int
for {
for {
@@ -193,7 +198,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
if in, ok := priv.Curve.(invertible); ok {
kInv = in.Inverse(k)
} else {
- kInv = fermatInverse(k, N)
+ kInv = fermatInverse(k, N) // N != 0
}
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
@@ -207,7 +212,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
s = new(big.Int).Mul(priv.D, r)
s.Add(s, e)
s.Mul(s, kInv)
- s.Mod(s, N)
+ s.Mod(s, N) // N != 0
if s.Sign() != 0 {
break
}
diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go
index ee022b803ae..0f487fe1524 100644
--- a/libgo/go/crypto/rsa/rsa.go
+++ b/libgo/go/crypto/rsa/rsa.go
@@ -465,6 +465,9 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
err = ErrDecryption
return
}
+ if priv.N.Sign() == 0 {
+ return nil, ErrDecryption
+ }
var ir *big.Int
if random != nil {
@@ -490,7 +493,7 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
}
}
bigE := big.NewInt(int64(priv.E))
- rpowe := new(big.Int).Exp(r, bigE, priv.N)
+ rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0
cCopy := new(big.Int).Set(c)
cCopy.Mul(cCopy, rpowe)
cCopy.Mod(cCopy, priv.N)
diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go
index bd8b343adbe..c7cd8804da7 100644
--- a/libgo/go/go/build/deps_test.go
+++ b/libgo/go/go/build/deps_test.go
@@ -132,10 +132,10 @@ var pkgDeps = map[string][]string{
// End of linear dependency definitions.
// Operating system access.
- "syscall": {"L0", "internal/race", "unicode/utf16"},
+ "syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "unicode/utf16"},
"internal/syscall/unix": {"L0", "syscall"},
- "internal/syscall/windows": {"L0", "syscall"},
- "internal/syscall/windows/registry": {"L0", "syscall", "unicode/utf16"},
+ "internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"},
+ "internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
"time": {"L0", "syscall", "internal/syscall/windows/registry"},
"os": {"L1", "os", "syscall", "time", "internal/syscall/windows"},
"path/filepath": {"L2", "os", "syscall"},
diff --git a/libgo/go/internal/syscall/windows/registry/syscall.go b/libgo/go/internal/syscall/windows/registry/syscall.go
index 5426cae9096..02d985cec90 100644
--- a/libgo/go/internal/syscall/windows/registry/syscall.go
+++ b/libgo/go/internal/syscall/windows/registry/syscall.go
@@ -8,7 +8,7 @@ package registry
import "syscall"
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go -systemdll syscall.go
const (
_REG_OPTION_NON_VOLATILE = 0
diff --git a/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go b/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
index 9c17675a249..7e473d4e1de 100644
--- a/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
+++ b/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
@@ -4,12 +4,13 @@ package registry
import "unsafe"
import "syscall"
+import "internal/syscall/windows/sysdll"
var _ unsafe.Pointer
var (
- modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
- modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
+ modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
diff --git a/libgo/go/internal/syscall/windows/syscall_windows.go b/libgo/go/internal/syscall/windows/syscall_windows.go
index 165e8945ec3..e6a3f238d88 100644
--- a/libgo/go/internal/syscall/windows/syscall_windows.go
+++ b/libgo/go/internal/syscall/windows/syscall_windows.go
@@ -6,7 +6,7 @@ package windows
import "syscall"
-//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
+//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go -systemdll syscall_windows.go
const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
diff --git a/libgo/go/internal/syscall/windows/sysdll/sysdll.go b/libgo/go/internal/syscall/windows/sysdll/sysdll.go
new file mode 100644
index 00000000000..4e0018f3877
--- /dev/null
+++ b/libgo/go/internal/syscall/windows/sysdll/sysdll.go
@@ -0,0 +1,28 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sysdll is an internal leaf package that records and reports
+// which Windows DLL names are used by Go itself. These DLLs are then
+// only loaded from the System32 directory. See Issue 14959.
+package sysdll
+
+// IsSystemDLL reports whether the named dll key (a base name, like
+// "foo.dll") is a system DLL which should only be loaded from the
+// Windows SYSTEM32 directory.
+//
+// Filenames are case sensitive, but that doesn't matter because
+// the case registered with Add is also the same case used with
+// LoadDLL later.
+//
+// It has no associated mutex and should only be mutated serially
+// (currently: during init), and not concurrent with DLL loading.
+var IsSystemDLL = map[string]bool{}
+
+// Add notes that dll is a system32 DLL which should only be loaded
+// from the Windows SYSTEM32 directory. It returns its argument back,
+// for ease of use in generated code.
+func Add(dll string) string {
+ IsSystemDLL[dll] = true
+ return dll
+}
diff --git a/libgo/go/internal/syscall/windows/zsyscall_windows.go b/libgo/go/internal/syscall/windows/zsyscall_windows.go
index de41786c76e..d599258976b 100644
--- a/libgo/go/internal/syscall/windows/zsyscall_windows.go
+++ b/libgo/go/internal/syscall/windows/zsyscall_windows.go
@@ -4,12 +4,13 @@ package windows
import "unsafe"
import "syscall"
+import "internal/syscall/windows/sysdll"
var _ unsafe.Pointer
var (
- modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
- modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
+ modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 595d6908f7d..b8e7cd883cb 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -1478,6 +1478,12 @@ func TestFunc(t *testing.T) {
if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
}
+
+ for i, v := range ret {
+ if v.CanAddr() {
+ t.Errorf("result %d is addressable", i)
+ }
+ }
}
type emptyStruct struct{}
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 0f0eb846fc2..75944a6e532 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -433,9 +433,11 @@ func (v Value) call(op string, in []Value) []Value {
ret := make([]Value, nout)
results := make([]unsafe.Pointer, nout)
for i := 0; i < nout; i++ {
- v := New(t.Out(i))
- results[i] = unsafe.Pointer(v.Pointer())
- ret[i] = Indirect(v)
+ tv := t.Out(i)
+ v := New(tv)
+ results[i] = v.pointer()
+ fl := flagIndir | flag(tv.Kind())
+ ret[i] = Value{tv.common(), v.pointer(), fl}
}
var pp *unsafe.Pointer
diff --git a/libgo/go/runtime/export_windows_test.go b/libgo/go/runtime/export_windows_test.go
index f712c6f6535..7b269ecccb4 100644
--- a/libgo/go/runtime/export_windows_test.go
+++ b/libgo/go/runtime/export_windows_test.go
@@ -15,3 +15,7 @@ func NumberOfProcessors() int32 {
stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
return int32(info.dwnumberofprocessors)
}
+
+func LoadLibraryExStatus() (useEx, haveEx, haveFlags bool) {
+ return useLoadLibraryEx, _LoadLibraryExW != nil, _AddDllDirectory != nil
+}
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 742f19052a4..1c82e5de1ef 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,72 @@
+2016-04-14 Cesar Philippidis <cesar@codesourcery.com>
+
+ * testsuite/libgomp.oacc-fortran/non-scalar-data.f90: Don't
+ pass parameter variables to subroutines.
+
+2016-04-14 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR middle-end/70643
+ * testsuite/libgomp.oacc-fortran/pr70643.f90: New test.
+
+2016-04-13 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR testsuite/68242
+ * testsuite/libgomp.oacc-c-c++-common/reduction-1.c: Adjust test.
+ * testsuite/libgomp.oacc-c-c++-common/reduction-2.c: Likewise.
+
+2016-04-12 Thomas Schwinge <thomas@codesourcery.com>
+
+ * libgomp_g.h: Rename GOACC_parallel_keyd prototype to
+ GOACC_parallel_keyed, restore GOACC_parallel prototype, new
+ GOACC_declare prototype.
+
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gang-np-1.c:
+ Merge this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gv-np-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gw-np-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-2.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-3.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-4.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-2.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-worker-p-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-1.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-2.c:
+ ... this file, and...
+ * testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-3.c:
+ ... this file into...
+ * testsuite/libgomp.oacc-c-c++-common/reduction-7.c: ... this
+ file.
+
+ * testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c:
+ Make failure observable.
+
+2016-04-12 Jakub Jelinek <jakub@redhat.com>
+
+ * libgomp.h (struct gomp_target_task): Remove firstprivate_copies
+ field.
+ * target.c (gomp_target_fallback_firstprivate,
+ gomp_target_unshare_firstprivate): Removed.
+ (GOMP_target_ext): Copy firstprivate vars into gomp_allocaed memory
+ before waiting for dependencies.
+ (gomp_target_task_fn): Don't copy firstprivate vars here.
+ * task.c (GOMP_PLUGIN_target_task_completion): Don't free
+ firstprivate_copies here.
+ (gomp_create_target_task): Don't initialize firstprivate_copies field.
+ * testsuite/libgomp.c/target-25.c (main): Use map (to:) instead of
+ explicit/implicit firstprivate.
+
2016-04-08 Cesar Philippidis <cesar@codesourcery.com>
PR lto/70289
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index 7108a6d0118..664e76b52d1 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -496,8 +496,6 @@ struct gomp_target_task
struct target_mem_desc *tgt;
struct gomp_task *task;
struct gomp_team *team;
- /* Copies of firstprivate mapped data for shared memory accelerators. */
- void *firstprivate_copies;
/* Device-specific target arguments. */
void **args;
void *hostaddrs[];
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 24eebb68e67..20454e63a17 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -295,17 +295,20 @@ extern void GOMP_teams (unsigned int, unsigned int);
/* oacc-parallel.c */
+extern void GOACC_parallel_keyed (int, void (*) (void *), size_t,
+ void **, size_t *, unsigned short *, ...);
+extern void GOACC_parallel (int, void (*) (void *), size_t, void **, size_t *,
+ unsigned short *, int, int, int, int, int, ...);
extern void GOACC_data_start (int, size_t, void **, size_t *,
unsigned short *);
extern void GOACC_data_end (void);
extern void GOACC_enter_exit_data (int, size_t, void **,
size_t *, unsigned short *, int, int, ...);
-extern void GOACC_parallel_keyd (int, void (*) (void *), size_t,
- void **, size_t *, unsigned short *, ...);
extern void GOACC_update (int, size_t, void **, size_t *,
unsigned short *, int, int, ...);
extern void GOACC_wait (int, int, ...);
extern int GOACC_get_num_threads (void);
extern int GOACC_get_thread_num (void);
+extern void GOACC_declare (int, size_t, void **, size_t *, unsigned short *);
#endif /* LIBGOMP_G_H */
diff --git a/libgomp/target.c b/libgomp/target.c
index 96fe3d5eb0d..e2dd0e08997 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -1372,47 +1372,6 @@ copy_firstprivate_data (char *tgt, size_t mapnum, void **hostaddrs,
}
}
-/* Host fallback with firstprivate map-type handling. */
-
-static void
-gomp_target_fallback_firstprivate (void (*fn) (void *), size_t mapnum,
- void **hostaddrs, size_t *sizes,
- unsigned short *kinds)
-{
- size_t tgt_align = 0, tgt_size = 0;
- calculate_firstprivate_requirements (mapnum, sizes, kinds, &tgt_align,
- &tgt_size);
- if (tgt_align)
- {
- char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
- copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds, tgt_align,
- tgt_size);
- }
- gomp_target_fallback (fn, hostaddrs);
-}
-
-/* Handle firstprivate map-type for shared memory devices and the host
- fallback. Return the pointer of firstprivate copies which has to be freed
- after use. */
-
-static void *
-gomp_target_unshare_firstprivate (size_t mapnum, void **hostaddrs,
- size_t *sizes, unsigned short *kinds)
-{
- size_t tgt_align = 0, tgt_size = 0;
- char *tgt = NULL;
-
- calculate_firstprivate_requirements (mapnum, sizes, kinds, &tgt_align,
- &tgt_size);
- if (tgt_align)
- {
- tgt = gomp_malloc (tgt_size + tgt_align - 1);
- copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds, tgt_align,
- tgt_size);
- }
- return tgt;
-}
-
/* Helper function of GOMP_target{,_ext} routines. */
static void *
@@ -1504,6 +1463,8 @@ GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
unsigned int flags, void **depend, void **args)
{
struct gomp_device_descr *devicep = resolve_device (device);
+ size_t tgt_align = 0, tgt_size = 0;
+ bool fpc_done = false;
if (flags & GOMP_TARGET_FLAG_NOWAIT)
{
@@ -1555,7 +1516,19 @@ GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
{
struct gomp_thread *thr = gomp_thread ();
if (thr->task && thr->task->depend_hash)
- gomp_task_maybe_wait_for_dependencies (depend);
+ {
+ /* If we might need to wait, copy firstprivate now. */
+ calculate_firstprivate_requirements (mapnum, sizes, kinds,
+ &tgt_align, &tgt_size);
+ if (tgt_align)
+ {
+ char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
+ copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
+ tgt_align, tgt_size);
+ }
+ fpc_done = true;
+ gomp_task_maybe_wait_for_dependencies (depend);
+ }
}
void *fn_addr;
@@ -1564,15 +1537,35 @@ GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
|| !(fn_addr = gomp_get_target_fn_addr (devicep, fn))
|| (devicep->can_run_func && !devicep->can_run_func (fn_addr)))
{
- gomp_target_fallback_firstprivate (fn, mapnum, hostaddrs, sizes, kinds);
+ if (!fpc_done)
+ {
+ calculate_firstprivate_requirements (mapnum, sizes, kinds,
+ &tgt_align, &tgt_size);
+ if (tgt_align)
+ {
+ char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
+ copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
+ tgt_align, tgt_size);
+ }
+ }
+ gomp_target_fallback (fn, hostaddrs);
return;
}
struct target_mem_desc *tgt_vars;
- void *fpc = NULL;
if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
{
- fpc = gomp_target_unshare_firstprivate (mapnum, hostaddrs, sizes, kinds);
+ if (!fpc_done)
+ {
+ calculate_firstprivate_requirements (mapnum, sizes, kinds,
+ &tgt_align, &tgt_size);
+ if (tgt_align)
+ {
+ char *tgt = gomp_alloca (tgt_size + tgt_align - 1);
+ copy_firstprivate_data (tgt, mapnum, hostaddrs, sizes, kinds,
+ tgt_align, tgt_size);
+ }
+ }
tgt_vars = NULL;
}
else
@@ -1583,8 +1576,6 @@ GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
args);
if (tgt_vars)
gomp_unmap_vars (tgt_vars, true);
- else
- free (fpc);
}
/* Host fallback for GOMP_target_data{,_ext} routines. */
@@ -1891,9 +1882,7 @@ gomp_target_task_fn (void *data)
|| (devicep->can_run_func && !devicep->can_run_func (fn_addr)))
{
ttask->state = GOMP_TARGET_TASK_FALLBACK;
- gomp_target_fallback_firstprivate (ttask->fn, ttask->mapnum,
- ttask->hostaddrs, ttask->sizes,
- ttask->kinds);
+ gomp_target_fallback (ttask->fn, ttask->hostaddrs);
return false;
}
@@ -1908,9 +1897,6 @@ gomp_target_task_fn (void *data)
if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
{
ttask->tgt = NULL;
- ttask->firstprivate_copies
- = gomp_target_unshare_firstprivate (ttask->mapnum, ttask->hostaddrs,
- ttask->sizes, ttask->kinds);
actual_arguments = ttask->hostaddrs;
}
else
diff --git a/libgomp/task.c b/libgomp/task.c
index 38d4e9b413b..023663f43d5 100644
--- a/libgomp/task.c
+++ b/libgomp/task.c
@@ -582,7 +582,6 @@ GOMP_PLUGIN_target_task_completion (void *data)
return;
}
ttask->state = GOMP_TARGET_TASK_FINISHED;
- free (ttask->firstprivate_copies);
gomp_target_task_completion (team, task);
gomp_mutex_unlock (&team->task_lock);
}
@@ -683,7 +682,6 @@ gomp_create_target_task (struct gomp_device_descr *devicep,
ttask->state = state;
ttask->task = task;
ttask->team = team;
- ttask->firstprivate_copies = NULL;
task->fn = NULL;
task->fn_data = ttask;
task->final_task = 0;
diff --git a/libgomp/testsuite/libgomp.c/target-25.c b/libgomp/testsuite/libgomp.c/target-25.c
index aeb19aee510..09b8d52184a 100644
--- a/libgomp/testsuite/libgomp.c/target-25.c
+++ b/libgomp/testsuite/libgomp.c/target-25.c
@@ -23,7 +23,7 @@ main ()
usleep (7000);
z = 3;
}
- #pragma omp target map(tofrom: x) map(from: err) firstprivate (y) depend(inout: x, z)
+ #pragma omp target map(tofrom: x) map(from: err) map (to: y, z) depend(inout: x, z)
err = (x != 1 || y != 2 || z != 3);
if (err)
abort ();
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gang-np-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gang-np-1.c
deleted file mode 100644
index 55ab3c96334..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gang-np-1.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* { dg-additional-options "-w" } */
-
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs, non-private reduction
- variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, arr[1024], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[i];
- }
-
- for (i = 0; i < 1024; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- res = hres = 1;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang reduction(*:res)
- for (i = 0; i < 12; i++)
- res *= arr[i];
- }
-
- for (i = 0; i < 12; i++)
- hres *= arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gv-np-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gv-np-1.c
deleted file mode 100644
index d4341e9c2cf..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gv-np-1.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* { dg-additional-options "-w" } */
-
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs and vectors, non-private
- reduction variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, arr[1024], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang vector reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[i];
- }
-
- for (i = 0; i < 1024; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gw-np-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gw-np-1.c
deleted file mode 100644
index 2e5668b134e..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gw-np-1.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* { dg-additional-options "-w" } */
-
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs and workers, non-private
- reduction variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, arr[1024], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang worker reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[i];
- }
-
- for (i = 0; i < 1024; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-1.c
deleted file mode 100644
index d6103738813..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-1.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs, workers and vectors, non-private
- reduction variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, arr[1024], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang worker vector reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[i];
- }
-
- for (i = 0; i < 1024; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-2.c
deleted file mode 100644
index ea5c151af3c..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-2.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs, workers and vectors, non-private
- reduction variable: separate gang and worker/vector loops). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, arr[32768], res = 0, hres = 0;
-
- for (i = 0; i < 32768; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res)
- {
- #pragma acc loop gang reduction(+:res)
- for (j = 0; j < 32; j++)
- {
- #pragma acc loop worker vector reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[j * 1024 + i];
- }
- /* "res" is non-private, and is not available until after the parallel
- region. */
- }
-
- for (i = 0; i < 32768; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-3.c
deleted file mode 100644
index 0056f3ce10e..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-3.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs, workers and vectors, non-private
- reduction variable: separate gang and worker/vector loops). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j;
- double arr[32768], res = 0, hres = 0;
-
- for (i = 0; i < 32768; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copyin(arr) copy(res)
- {
- #pragma acc loop gang reduction(+:res)
- for (j = 0; j < 32; j++)
- {
- #pragma acc loop worker vector reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[j * 1024 + i];
- }
- }
-
- for (i = 0; i < 32768; i++)
- hres += arr[i];
-
- assert (res == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-4.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-4.c
deleted file mode 100644
index e69d0ec04c7..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-gwv-np-4.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (gangs, workers and vectors, multiple
- non-private reduction variables, float type). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j;
- float arr[32768];
- float res = 0, mres = 0, hres = 0, hmres = 0;
-
- for (i = 0; i < 32768; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- copy(res, mres)
- {
- #pragma acc loop gang reduction(+:res) reduction(max:mres)
- for (j = 0; j < 32; j++)
- {
- #pragma acc loop worker vector reduction(+:res) reduction(max:mres)
- for (i = 0; i < 1024; i++)
- {
- res += arr[j * 1024 + i];
- if (arr[j * 1024 + i] > mres)
- mres = arr[j * 1024 + i];
- }
-
- #pragma acc loop worker vector reduction(+:res) reduction(max:mres)
- for (i = 0; i < 1024; i++)
- {
- res += arr[j * 1024 + (1023 - i)];
- if (arr[j * 1024 + (1023 - i)] > mres)
- mres = arr[j * 1024 + (1023 - i)];
- }
- }
- }
-
- for (j = 0; j < 32; j++)
- for (i = 0; i < 1024; i++)
- {
- hres += arr[j * 1024 + i];
- hres += arr[j * 1024 + (1023 - i)];
- if (arr[j * 1024 + i] > hmres)
- hmres = arr[j * 1024 + i];
- if (arr[j * 1024 + (1023 - i)] > hmres)
- hmres = arr[j * 1024 + (1023 - i)];
- }
-
- assert (res == hres);
- assert (mres == hmres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-1.c
deleted file mode 100644
index 31e4366f88b..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-1.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* { dg-additional-options "-w" } */
-
-#include <assert.h>
-
-/* Test of reduction on loop directive (vectors, private reduction
- variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, arr[1024], out[32], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(res) copyout(out)
- {
- #pragma acc loop gang
- for (j = 0; j < 32; j++)
- {
- res = 0;
-
- #pragma acc loop vector reduction(+:res)
- for (i = 0; i < 32; i++)
- res += arr[j * 32 + i];
-
- out[j] = res;
- }
- }
-
- for (j = 0; j < 32; j++)
- {
- hres = 0;
-
- for (i = 0; i < 32; i++)
- hres += arr[j * 32 + i];
-
- assert (out[j] == hres);
- }
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-2.c
deleted file mode 100644
index 15f0053e5bc..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-vector-p-2.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (vector reduction in
- gang-partitioned/worker-partitioned mode, private reduction variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, k;
- double ina[1024], inb[1024], out[1024], acc;
-
- for (j = 0; j < 32; j++)
- for (i = 0; i < 32; i++)
- {
- ina[j * 32 + i] = (i == j) ? 2.0 : 0.0;
- inb[j * 32 + i] = (double) (i + j);
- }
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(acc) copyin(ina, inb) copyout(out)
- {
- #pragma acc loop gang worker
- for (k = 0; k < 32; k++)
- for (j = 0; j < 32; j++)
- {
- acc = 0;
-
- #pragma acc loop vector reduction(+:acc)
- for (i = 0; i < 32; i++)
- acc += ina[k * 32 + i] * inb[i * 32 + j];
-
- out[k * 32 + j] = acc;
- }
- }
-
- for (j = 0; j < 32; j++)
- for (i = 0; i < 32; i++)
- assert (out[j * 32 + i] == (i + j) * 2);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-worker-p-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-worker-p-1.c
deleted file mode 100644
index 4a925036a5b..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-worker-p-1.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* { dg-additional-options "-w" } */
-
-#include <assert.h>
-
-/* Test of reduction on loop directive (workers, private reduction
- variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, arr[1024], out[32], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(res) copyout(out)
- {
- #pragma acc loop gang
- for (j = 0; j < 32; j++)
- {
- res = 0;
-
- #pragma acc loop worker reduction(+:res)
- for (i = 0; i < 32; i++)
- res += arr[j * 32 + i];
-
- out[j] = res;
- }
- }
-
- for (j = 0; j < 32; j++)
- {
- hres = 0;
-
- for (i = 0; i < 32; i++)
- hres += arr[j * 32 + i];
-
- assert (out[j] == hres);
- }
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-1.c
deleted file mode 100644
index 1bfb284cb3b..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-1.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (workers and vectors, private reduction
- variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, arr[1024], out[32], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(res) copyout(out)
- {
- #pragma acc loop gang
- for (j = 0; j < 32; j++)
- {
- res = 0;
-
- #pragma acc loop worker vector reduction(+:res)
- for (i = 0; i < 32; i++)
- res += arr[j * 32 + i];
-
- out[j] = res;
- }
- }
-
- for (j = 0; j < 32; j++)
- {
- hres = 0;
-
- for (i = 0; i < 32; i++)
- hres += arr[j * 32 + i];
-
- assert (out[j] == hres);
- }
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-2.c
deleted file mode 100644
index 93ab78f106a..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-2.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (workers and vectors, private reduction
- variable). */
-
-int
-main (int argc, char *argv[])
-{
- int i, j, arr[32768], out[32], res = 0, hres = 0;
-
- for (i = 0; i < 32768; i++)
- arr[i] = i;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(res) copyout(out)
- {
- #pragma acc loop gang
- for (j = 0; j < 32; j++)
- {
- res = j;
-
- #pragma acc loop worker reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[j * 1024 + i];
-
- #pragma acc loop vector reduction(+:res)
- for (i = 1023; i >= 0; i--)
- res += arr[j * 1024 + i];
-
- out[j] = res;
- }
- }
-
- for (j = 0; j < 32; j++)
- {
- hres = j;
-
- for (i = 0; i < 1024; i++)
- hres += arr[j * 1024 + i] * 2;
-
- assert (out[j] == hres);
- }
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-3.c
deleted file mode 100644
index 298e25c87d2..00000000000
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-reduction-wv-p-3.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <assert.h>
-
-/* Test of reduction on loop directive (workers and vectors, private reduction
- variable: gang-redundant mode). */
-
-int
-main (int argc, char *argv[])
-{
- int i, arr[1024], out[32], res = 0, hres = 0;
-
- for (i = 0; i < 1024; i++)
- arr[i] = i ^ 33;
-
- #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
- private(res) copyin(arr) copyout(out)
- {
- /* Private variables aren't initialized by default in openacc. */
- res = 0;
-
- /* "res" should be available at the end of the following loop (and should
- have the same value redundantly in each gang). */
- #pragma acc loop worker vector reduction(+:res)
- for (i = 0; i < 1024; i++)
- res += arr[i];
-
- #pragma acc loop gang (static: 1)
- for (i = 0; i < 32; i++)
- out[i] = res;
- }
-
- for (i = 0; i < 1024; i++)
- hres += arr[i];
-
- for (i = 0; i < 32; i++)
- assert (out[i] == hres);
-
- return 0;
-}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c
index a7a75a94104..a339f327956 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/par-loop-comb-reduction-2.c
@@ -19,7 +19,7 @@ main (int argc, char *argv[])
{
#pragma acc loop worker vector reduction(^:res)
for (i = 0; i < 1024; i++)
- res ^= arr[j * 1024 + i];
+ res ^= 3 * arr[j * 1024 + i];
#pragma acc loop worker vector reduction(^:res)
for (i = 0; i < 1024; i++)
@@ -30,7 +30,7 @@ main (int argc, char *argv[])
for (j = 0; j < 32; j++)
for (i = 0; i < 1024; i++)
{
- hres ^= arr[j * 1024 + i];
+ hres ^= 3 * arr[j * 1024 + i];
hres ^= arr[j * 1024 + (1023 - i)];
}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-1.c
index 10eb2788bd9..e8a8911faeb 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-1.c
@@ -15,7 +15,7 @@ const int vl = 32;
static void
test_reductions (void)
{
- const int n = 100;
+ const int n = 10;
int i;
int array[n];
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-2.c
index 7cb94971559..d19b1c825ca 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-2.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-2.c
@@ -15,7 +15,7 @@ const int vl = 32;
static void
test_reductions (void)
{
- const int n = 100;
+ const int n = 10;
int i;
float array[n];
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-7.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-7.c
index b23c75877f8..76c33e4470d 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-7.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/reduction-7.c
@@ -118,12 +118,363 @@ void gwv_np_1()
}
+/* Test of reduction on loop directive (gangs, workers and vectors, non-private
+ reduction variable: separate gang and worker/vector loops). */
+
+void gwv_np_2()
+{
+ int i, j, arr[32768], res = 0, hres = 0;
+
+ for (i = 0; i < 32768; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ copy(res)
+ {
+ #pragma acc loop gang reduction(+:res)
+ for (j = 0; j < 32; j++)
+ {
+ #pragma acc loop worker vector reduction(+:res)
+ for (i = 0; i < 1024; i++)
+ res += arr[j * 1024 + i];
+ }
+ /* "res" is non-private, and is not available until after the parallel
+ region. */
+ }
+
+ for (i = 0; i < 32768; i++)
+ hres += arr[i];
+
+ assert (res == hres);
+}
+
+
+/* Test of reduction on loop directive (gangs, workers and vectors, non-private
+ reduction variable: separate gang and worker/vector loops). */
+
+void gwv_np_3()
+{
+ int i, j;
+ double arr[32768], res = 0, hres = 0;
+
+ for (i = 0; i < 32768; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ copyin(arr) copy(res)
+ {
+ #pragma acc loop gang reduction(+:res)
+ for (j = 0; j < 32; j++)
+ {
+ #pragma acc loop worker vector reduction(+:res)
+ for (i = 0; i < 1024; i++)
+ res += arr[j * 1024 + i];
+ }
+ }
+
+ for (i = 0; i < 32768; i++)
+ hres += arr[i];
+
+ assert (res == hres);
+}
+
+
+/* Test of reduction on loop directive (gangs, workers and vectors, multiple
+ non-private reduction variables, float type). */
+
+void gwv_np_4()
+{
+ int i, j;
+ float arr[32768];
+ float res = 0, mres = 0, hres = 0, hmres = 0;
+
+ for (i = 0; i < 32768; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ copy(res, mres)
+ {
+ #pragma acc loop gang reduction(+:res) reduction(max:mres)
+ for (j = 0; j < 32; j++)
+ {
+ #pragma acc loop worker vector reduction(+:res) reduction(max:mres)
+ for (i = 0; i < 1024; i++)
+ {
+ res += arr[j * 1024 + i];
+ if (arr[j * 1024 + i] > mres)
+ mres = arr[j * 1024 + i];
+ }
+
+ #pragma acc loop worker vector reduction(+:res) reduction(max:mres)
+ for (i = 0; i < 1024; i++)
+ {
+ res += arr[j * 1024 + (1023 - i)];
+ if (arr[j * 1024 + (1023 - i)] > mres)
+ mres = arr[j * 1024 + (1023 - i)];
+ }
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ for (i = 0; i < 1024; i++)
+ {
+ hres += arr[j * 1024 + i];
+ hres += arr[j * 1024 + (1023 - i)];
+ if (arr[j * 1024 + i] > hmres)
+ hmres = arr[j * 1024 + i];
+ if (arr[j * 1024 + (1023 - i)] > hmres)
+ hmres = arr[j * 1024 + (1023 - i)];
+ }
+
+ assert (res == hres);
+ assert (mres == hmres);
+}
+
+
+/* Test of reduction on loop directive (vectors, private reduction
+ variable). */
+
+void v_p_1()
+{
+ int i, j, arr[1024], out[32], res = 0, hres = 0;
+
+ for (i = 0; i < 1024; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(res) copyout(out)
+ {
+ #pragma acc loop gang
+ for (j = 0; j < 32; j++)
+ {
+ res = 0;
+
+ #pragma acc loop vector reduction(+:res)
+ for (i = 0; i < 32; i++)
+ res += arr[j * 32 + i];
+
+ out[j] = res;
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ {
+ hres = 0;
+
+ for (i = 0; i < 32; i++)
+ hres += arr[j * 32 + i];
+
+ assert (out[j] == hres);
+ }
+}
+
+
+/* Test of reduction on loop directive (vector reduction in
+ gang-partitioned/worker-partitioned mode, private reduction variable). */
+
+void v_p_2()
+{
+ int i, j, k;
+ double ina[1024], inb[1024], out[1024], acc;
+
+ for (j = 0; j < 32; j++)
+ for (i = 0; i < 32; i++)
+ {
+ ina[j * 32 + i] = (i == j) ? 2.0 : 0.0;
+ inb[j * 32 + i] = (double) (i + j);
+ }
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(acc) copyin(ina, inb) copyout(out)
+ {
+ #pragma acc loop gang worker
+ for (k = 0; k < 32; k++)
+ for (j = 0; j < 32; j++)
+ {
+ acc = 0;
+
+ #pragma acc loop vector reduction(+:acc)
+ for (i = 0; i < 32; i++)
+ acc += ina[k * 32 + i] * inb[i * 32 + j];
+
+ out[k * 32 + j] = acc;
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ for (i = 0; i < 32; i++)
+ assert (out[j * 32 + i] == (i + j) * 2);
+}
+
+
+/* Test of reduction on loop directive (workers, private reduction
+ variable). */
+
+void w_p_1()
+{
+ int i, j, arr[1024], out[32], res = 0, hres = 0;
+
+ for (i = 0; i < 1024; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(res) copyout(out)
+ {
+ #pragma acc loop gang
+ for (j = 0; j < 32; j++)
+ {
+ res = 0;
+
+ #pragma acc loop worker reduction(+:res)
+ for (i = 0; i < 32; i++)
+ res += arr[j * 32 + i];
+
+ out[j] = res;
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ {
+ hres = 0;
+
+ for (i = 0; i < 32; i++)
+ hres += arr[j * 32 + i];
+
+ assert (out[j] == hres);
+ }
+}
+
+
+/* Test of reduction on loop directive (workers and vectors, private reduction
+ variable). */
+
+void wv_p_1()
+{
+ int i, j, arr[1024], out[32], res = 0, hres = 0;
+
+ for (i = 0; i < 1024; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(res) copyout(out)
+ {
+ #pragma acc loop gang
+ for (j = 0; j < 32; j++)
+ {
+ res = 0;
+
+ #pragma acc loop worker vector reduction(+:res)
+ for (i = 0; i < 32; i++)
+ res += arr[j * 32 + i];
+
+ out[j] = res;
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ {
+ hres = 0;
+
+ for (i = 0; i < 32; i++)
+ hres += arr[j * 32 + i];
+
+ assert (out[j] == hres);
+ }
+}
+
+
+/* Test of reduction on loop directive (workers and vectors, private reduction
+ variable). */
+
+void wv_p_2()
+{
+ int i, j, arr[32768], out[32], res = 0, hres = 0;
+
+ for (i = 0; i < 32768; i++)
+ arr[i] = i;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(res) copyout(out)
+ {
+ #pragma acc loop gang
+ for (j = 0; j < 32; j++)
+ {
+ res = j;
+
+ #pragma acc loop worker reduction(+:res)
+ for (i = 0; i < 1024; i++)
+ res += arr[j * 1024 + i];
+
+ #pragma acc loop vector reduction(+:res)
+ for (i = 1023; i >= 0; i--)
+ res += arr[j * 1024 + i];
+
+ out[j] = res;
+ }
+ }
+
+ for (j = 0; j < 32; j++)
+ {
+ hres = j;
+
+ for (i = 0; i < 1024; i++)
+ hres += arr[j * 1024 + i] * 2;
+
+ assert (out[j] == hres);
+ }
+}
+
+
+/* Test of reduction on loop directive (workers and vectors, private reduction
+ variable: gang-redundant mode). */
+
+void wv_p_3()
+{
+ int i, arr[1024], out[32], res = 0, hres = 0;
+
+ for (i = 0; i < 1024; i++)
+ arr[i] = i ^ 33;
+
+ #pragma acc parallel num_gangs(32) num_workers(32) vector_length(32) \
+ private(res) copyin(arr) copyout(out)
+ {
+ /* Private variables aren't initialized by default in openacc. */
+ res = 0;
+
+ /* "res" should be available at the end of the following loop (and should
+ have the same value redundantly in each gang). */
+ #pragma acc loop worker vector reduction(+:res)
+ for (i = 0; i < 1024; i++)
+ res += arr[i];
+
+ #pragma acc loop gang (static: 1)
+ for (i = 0; i < 32; i++)
+ out[i] = res;
+ }
+
+ for (i = 0; i < 1024; i++)
+ hres += arr[i];
+
+ for (i = 0; i < 32; i++)
+ assert (out[i] == hres);
+}
+
+
int main()
{
g_np_1();
gv_np_1();
gw_np_1();
gwv_np_1();
+ gwv_np_2();
+ gwv_np_3();
+ gwv_np_4();
+ v_p_1();
+ v_p_2();
+ w_p_1();
+ wv_p_1();
+ wv_p_2();
+ wv_p_3();
return 0;
}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/non-scalar-data.f90 b/libgomp/testsuite/libgomp.oacc-fortran/non-scalar-data.f90
index 4afb562e00c..94e4228e7a9 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/non-scalar-data.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/non-scalar-data.f90
@@ -6,9 +6,11 @@
program main
implicit none
- integer, parameter :: n = 100
- integer :: array(n), i
-
+ integer,parameter :: size = 100
+ integer :: array(size), i, n
+
+ n = size
+
!$acc data copy(array)
call kernels(array, n)
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr70643.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr70643.f90
new file mode 100644
index 00000000000..7c2e5eef904
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr70643.f90
@@ -0,0 +1,51 @@
+MODULE reduction_test
+
+CONTAINS
+
+SUBROUTINE reduction_kernel(x_min,x_max,y_min,y_max,arr,sum)
+
+ IMPLICIT NONE
+
+ INTEGER :: x_min,x_max,y_min,y_max
+ REAL(KIND=8), DIMENSION(x_min-2:x_max+2,y_min-2:y_max+2) :: arr
+ REAL(KIND=8) :: sum
+
+ INTEGER :: j,k
+
+!$ACC DATA PRESENT(arr) COPY(sum)
+!$ACC PARALLEL LOOP REDUCTION(+ : sum)
+ DO k=y_min,y_max
+ DO j=x_min,x_max
+ sum=sum+arr(j,k)
+ ENDDO
+ ENDDO
+!$ACC END PARALLEL LOOP
+!$ACC END DATA
+END SUBROUTINE reduction_kernel
+
+END MODULE reduction_test
+
+program main
+ use reduction_test
+
+ integer :: x_min,x_max,y_min,y_max
+ real(kind=8), dimension(1:10,1:10) :: arr
+ real(kind=8) :: sum
+
+ x_min = 1
+ x_max = 2
+ y_min = 1
+ y_max = 2
+
+ arr(:,:) = 1.0
+
+ sum = 0.0
+
+ !$acc data copy(arr)
+
+ call reduction_kernel(x_min,x_max,y_min,y_max,arr,sum)
+
+ !$acc end data
+
+ if (sum .ne. 4.0) call abort
+end program
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 48a13fa90a6..f63e09145ba 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,48 @@
+2016-04-14 Jason Merrill <jason@redhat.com>
+
+ Revert Jonathan's empty ABI change from yesterday.
+
+2016-04-13 Martin Sebor <msebor@redhat.com>
+
+ PR c++/69517
+ * testsuite/25_algorithms/rotate/moveable2.cc: Make sure VLA
+ upper bound is positive.
+
+2016-04-13 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/c++config (_GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES,
+ _GLIBCXX_END_NAMESPACE_EMPTY_TYPES, _GLIBCXX_ABI_TAG_EMPTY): Define.
+ * include/bits/hashtable.h (_Hashtable::_M_emplace): Change signatures
+ of functions taking empty structs by value. Add a template parameter
+ to overloads without hints. Rename overloads with hints to
+ _M_emplace_hint.
+ (_Hashtable::_M_erase(true_type, const_iterator),
+ _Hashtable::_M_erase(false_type, const_iterator)): Change signatures
+ by reordering parameters.
+ * include/bits/hashtable_policy.h (_Insert::insert): Adjust to call
+ _M_emplace_hint instead of _M_emplace.
+ * include/bits/shared_ptr.h (shared_ptr(_Tp1*, _Deleter, _Alloc),
+ shared_ptr(nullptr_t, _Deleter, _Alloc)): Use _GLIBCXX_ABI_TAG_EMPTY.
+ * include/bits/shared_ptr_base.h (_Sp_counted_deleter, __shared_count,
+ __shared_ptr): Likewise.
+ * include/bits/stl_algo.h (replace_if): Likewise.
+ * include/bits/stl_pair.h (piecewise_construct_t,
+ piecewise_construct): Use _GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES.
+ * include/bits/uses_allocator.h (allocator_arg_t, allocator_arg,
+ __uses_alloc0): Likewise.
+ * include/ext/pb_ds/assoc_container.hpp (basic_hash_table): Likewise.
+ * testsuite/20_util/scoped_allocator/69293_neg.cc: Adjust dg-error.
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Likewise.
+ * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
+ * testsuite/20_util/uses_allocator/69293_neg.cc: Likewise.
+ * testsuite/20_util/uses_allocator/cons_neg.cc: Likewise.
+ * testsuite/ext/profile/mutex_extensions_neg.cc: Likewise.
+
+2016-04-12 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Document C++17/TR29124 C++ Special Math Functions.
+ * include/bits/specfun.h: Add Doxygen markup.
+
2016-04-07 Jonathan Wakely <jwakely@redhat.com>
* testsuite/30_threads/thread/70503.cc: Adjust from xfail to pass.
diff --git a/libstdc++-v3/include/bits/specfun.h b/libstdc++-v3/include/bits/specfun.h
index 28c9d30e5be..77bbda36fd8 100644
--- a/libstdc++-v3/include/bits/specfun.h
+++ b/libstdc++-v3/include/bits/specfun.h
@@ -1,6 +1,6 @@
// Mathematical Special Functions for -*- C++ -*-
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -34,12 +34,14 @@
#include <bits/c++config.h>
+#define __STDCPP_MATH_SPEC_FUNCS__ 201003L
+
+#define __cpp_lib_math_special_functions 201603L
+
#if __STDCPP_WANT_MATH_SPEC_FUNCS__ == 0
# error include <cmath> and define __STDCPP_WANT_MATH_SPEC_FUNCS__
#endif
-#define __STDCPP_MATH_SPEC_FUNCS__ 201003L
-
#include <bits/stl_algobase.h>
#include <limits>
#include <type_traits>
@@ -69,16 +71,182 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @{
*/
+ /**
+ * @mainpage Mathematical Special Functions
+ *
+ * @section intro Introduction and History
+ * The first significant library upgrade on the road to C++2011,
+ * <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf">
+ * TR1</a>, included a set of 23 mathematical functions that significantly
+ * extended the standard transcendental functions inherited from C and declared
+ * in @<cmath@>.
+ *
+ * Although most components from TR1 were eventually adopted for C++11 these
+ * math functions were left behind out of concern for implementability.
+ * The math functions were published as a separate international standard
+ * <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2010/n3060.pdf">
+ * IS 29124 - Extensions to the C++ Library to Support Mathematical Special
+ * Functions</a>.
+ *
+ * For C++17 these functions were incorporated into the main standard.
+ *
+ * @section contents Contents
+ * The following functions are implemented in namespace @c std:
+ * - @ref assoc_laguerre "assoc_laguerre - Associated Laguerre functions"
+ * - @ref assoc_legendre "assoc_legendre - Associated Legendre functions"
+ * - @ref beta "beta - Beta functions"
+ * - @ref comp_ellint_1 "comp_ellint_1 - Complete elliptic functions of the first kind"
+ * - @ref comp_ellint_2 "comp_ellint_2 - Complete elliptic functions of the second kind"
+ * - @ref comp_ellint_3 "comp_ellint_3 - Complete elliptic functions of the third kind"
+ * - @ref cyl_bessel_i "cyl_bessel_i - Regular modified cylindrical Bessel functions"
+ * - @ref cyl_bessel_j "cyl_bessel_j - Cylindrical Bessel functions of the first kind"
+ * - @ref cyl_bessel_k "cyl_bessel_k - Irregular modified cylindrical Bessel functions"
+ * - @ref cyl_neumann "cyl_neumann - Cylindrical Neumann functions or Cylindrical Bessel functions of the second kind"
+ * - @ref ellint_1 "ellint_1 - Incomplete elliptic functions of the first kind"
+ * - @ref ellint_2 "ellint_2 - Incomplete elliptic functions of the second kind"
+ * - @ref ellint_3 "ellint_3 - Incomplete elliptic functions of the third kind"
+ * - @ref expint "expint - The exponential integral"
+ * - @ref hermite "hermite - Hermite polynomials"
+ * - @ref laguerre "laguerre - Laguerre functions"
+ * - @ref legendre "legendre - Legendre polynomials"
+ * - @ref riemann_zeta "riemann_zeta - The Riemann zeta function"
+ * - @ref sph_bessel "sph_bessel - Spherical Bessel functions"
+ * - @ref sph_legendre "sph_legendre - Spherical Legendre functions"
+ * - @ref sph_neumann "sph_neumann - Spherical Neumann functions"
+ *
+ * The hypergeometric functions were stricken from the TR29124 and C++17
+ * versions of this math library because of implementation concerns.
+ * However, since they were in the TR1 version and since they are popular
+ * we kept them as an extension in namespace @c __gnu_cxx:
+ * - @ref conf_hyperg "conf_hyperg - Confluent hypergeometric functions"
+ * - @ref hyperg "hyperg - Hypergeometric functions"
+ *
+ * @section general General Features
+ *
+ * @subsection promotion Argument Promotion
+ * The arguments suppled to the non-suffixed functions will be promoted
+ * according to the following rules:
+ * 1. If any argument intended to be floating opint is given an integral value
+ * That integral value is promoted to double.
+ * 2. All floating point arguments are promoted up to the largest floating
+ * point precision among them.
+ *
+ * @subsection NaN NaN Arguments
+ * If any of the floating point arguments supplied to these functions is
+ * invalid or NaN (std::numeric_limits<Tp>::quiet_NaN),
+ * the value NaN is returned.
+ *
+ * @section impl Implementation
+ *
+ * We strive to implement the underlying math with type generic algorithms
+ * to the greatest extent possible. In practice, the functions are thin
+ * wrappers that dispatch to function templates. Type dependence is
+ * controlled with std::numeric_limits and functions thereof.
+ *
+ * We don't promote @c float to @c double or @c double to <tt>long double</tt>
+ * reflexively. The goal is for @c float functions to operate more quickly,
+ * at the cost of @c float accuracy and possibly a smaller domain of validity.
+ * Similaryly, <tt>long double</tt> should give you more dynamic range
+ * and slightly more pecision than @c double on many systems.
+ *
+ * @section testing Testing
+ *
+ * These functions have been tested against equivalent implementations
+ * from the <a href="http://www.gnu.org/software/gsl">
+ * Gnu Scientific Library, GSL</a> and
+ * <a href="http://www.boost.org/doc/libs/1_60_0/libs/math/doc/html/index.html>Boost</a>
+ * and the ratio
+ * @f[
+ * \frac{|f - f_{test}|}{|f_{test}|}
+ * @f]
+ * is generally found to be within 10^-15 for 64-bit double on linux-x86_64 systems
+ * over most of the ranges of validity.
+ *
+ * @todo Provide accuracy comparisons on a per-function basis for a small
+ * number of targets.
+ *
+ * @section bibliography General Bibliography
+ *
+ * @see Abramowitz and Stegun: Handbook of Mathematical Functions,
+ * with Formulas, Graphs, and Mathematical Tables
+ * Edited by Milton Abramowitz and Irene A. Stegun,
+ * National Bureau of Standards Applied Mathematics Series - 55
+ * Issued June 1964, Tenth Printing, December 1972, with corrections
+ * Electronic versions of A&S abound including both pdf and navigable html.
+ * @see for example http://people.math.sfu.ca/~cbm/aands/
+ *
+ * @see The old A&S has been redone as the
+ * NIST Digital Library of Mathematical Functions: http://dlmf.nist.gov/
+ * This version is far more navigable and includes more recent work.
+ *
+ * @see An Atlas of Functions: with Equator, the Atlas Function Calculator
+ * 2nd Edition, by Oldham, Keith B., Myland, Jan, Spanier, Jerome
+ *
+ * @see Asymptotics and Special Functions by Frank W. J. Olver,
+ * Academic Press, 1974
+ *
+ * @see Numerical Recipes in C, The Art of Scientific Computing,
+ * by William H. Press, Second Ed., Saul A. Teukolsky,
+ * William T. Vetterling, and Brian P. Flannery,
+ * Cambridge University Press, 1992
+ *
+ * @see The Special Functions and Their Approximations: Volumes 1 and 2,
+ * by Yudell L. Luke, Academic Press, 1969
+ */
+
// Associated Laguerre polynomials
+ /**
+ * Return the associated Laguerre polynomial of order @c n,
+ * degree @c m: @f$ L_n^m(x) @f$ for @c float argument.
+ *
+ * @see assoc_laguerre for more details.
+ */
inline float
assoc_laguerref(unsigned int __n, unsigned int __m, float __x)
{ return __detail::__assoc_laguerre<float>(__n, __m, __x); }
+ /**
+ * Return the associated Laguerre polynomial of order @c n,
+ * degree @c m: @f$ L_n^m(x) @f$.
+ *
+ * @see assoc_laguerre for more details.
+ */
inline long double
assoc_laguerrel(unsigned int __n, unsigned int __m, long double __x)
{ return __detail::__assoc_laguerre<long double>(__n, __m, __x); }
+ /**
+ * Return the associated Laguerre polynomial of nonnegative order @c n,
+ * nonnegative degree @c m and real argument @c x: @f$ L_n^m(x) @f$.
+ *
+ * The associated Laguerre function of real degree @f$ \alpha @f$,
+ * @f$ L_n^\alpha(x) @f$, is defined by
+ * @f[
+ * L_n^\alpha(x) = \frac{(\alpha + 1)_n}{n!}
+ * {}_1F_1(-n; \alpha + 1; x)
+ * @f]
+ * where @f$ (\alpha)_n @f$ is the Pochhammer symbol and
+ * @f$ {}_1F_1(a; c; x) @f$ is the confluent hypergeometric function.
+ *
+ * The associated Laguerre polynomial is defined for integral
+ * degree @f$ \alpha = m @f$ by:
+ * @f[
+ * L_n^m(x) = (-1)^m \frac{d^m}{dx^m} L_{n + m}(x)
+ * @f]
+ * where the Laguerre polynomial is defined by:
+ * @f[
+ * L_n(x) = \frac{e^x}{n!} \frac{d^n}{dx^n} (x^ne^{-x})
+ * @f]
+ * and @f$ x >= 0 @f$.
+ * @see laguerre for details of the Laguerre function of degree @c n
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __n The order of the Laguerre function, <tt>__n >= 0</tt>.
+ * @param __m The degree of the Laguerre function, <tt>__m >= 0</tt>.
+ * @param __x The argument of the Laguerre function, <tt>__x >= 0</tt>.
+ * @throw std::domain_error if <tt>__x < 0</tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
assoc_laguerre(unsigned int __n, unsigned int __m, _Tp __x)
@@ -89,14 +257,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Associated Legendre functions
+ /**
+ * Return the associated Legendre function of degree @c l and order @c m
+ * for @c float argument.
+ *
+ * @see assoc_legendre for more details.
+ */
inline float
assoc_legendref(unsigned int __l, unsigned int __m, float __x)
{ return __detail::__assoc_legendre_p<float>(__l, __m, __x); }
+ /**
+ * Return the associated Legendre function of degree @c l and order @c m.
+ *
+ * @see assoc_legendre for more details.
+ */
inline long double
assoc_legendrel(unsigned int __l, unsigned int __m, long double __x)
{ return __detail::__assoc_legendre_p<long double>(__l, __m, __x); }
+
+ /**
+ * Return the associated Legendre function of degree @c l and order @c m.
+ *
+ * The associated Legendre function is derived from the Legendre function
+ * @f$ P_l(x) @f$ by the Rodrigues formula:
+ * @f[
+ * P_l^m(x) = (1 - x^2)^{m/2}\frac{d^m}{dx^m}P_l(x)
+ * @f]
+ * @see legendre for details of the Legendre function of degree @c l
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __l The degree <tt>__l >= 0</tt>.
+ * @param __m The order <tt>__m <= l</tt>.
+ * @param __x The argument, <tt>abs(__x) <= 1</tt>.
+ * @throw std::domain_error if <tt>abs(__x) > 1</tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
assoc_legendre(unsigned int __l, unsigned int __m, _Tp __x)
@@ -107,32 +303,89 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Beta functions
+ /**
+ * Return the beta function, @f$ B(a,b) @f$, for @c float parameters @c a, @c b.
+ *
+ * @see beta for more details.
+ */
inline float
- betaf(float __x, float __y)
- { return __detail::__beta<float>(__x, __y); }
+ betaf(float __a, float __b)
+ { return __detail::__beta<float>(__a, __b); }
+ /**
+ * Return the beta function, @f$B(a,b)@f$, for long double
+ * parameters @c a, @c b.
+ *
+ * @see beta for more details.
+ */
inline long double
- betal(long double __x, long double __y)
- { return __detail::__beta<long double>(__x, __y); }
+ betal(long double __a, long double __b)
+ { return __detail::__beta<long double>(__a, __b); }
- template<typename _Tpx, typename _Tpy>
- inline typename __gnu_cxx::__promote_2<_Tpx, _Tpy>::__type
- beta(_Tpx __x, _Tpy __y)
+ /**
+ * Return the beta function, @f$B(a,b)@f$, for real parameters @c a, @c b.
+ *
+ * The beta function is defined by
+ * @f[
+ * B(a,b) = \int_0^1 t^{a - 1} (1 - t)^{b - 1} dt
+ * = \frac{\Gamma(a)\Gamma(b)}{\Gamma(a+b)}
+ * @f]
+ * where @f$ a > 0 @f$ and @f$ b > 0 @f$
+ *
+ * @tparam _Tpa The floating-point type of the parameter @c __a.
+ * @tparam _Tpb The floating-point type of the parameter @c __b.
+ * @param __a The first argument of the beta function, <tt> __a > 0 </tt>.
+ * @param __b The second argument of the beta function, <tt> __b > 0 </tt>.
+ * @throw std::domain_error if <tt> __a < 0 </tt> or <tt> __b < 0 </tt>.
+ */
+ template<typename _Tpa, typename _Tpb>
+ inline typename __gnu_cxx::__promote_2<_Tpa, _Tpb>::__type
+ beta(_Tpa __a, _Tpb __b)
{
- typedef typename __gnu_cxx::__promote_2<_Tpx, _Tpy>::__type __type;
- return __detail::__beta<__type>(__x, __y);
+ typedef typename __gnu_cxx::__promote_2<_Tpa, _Tpb>::__type __type;
+ return __detail::__beta<__type>(__a, __b);
}
// Complete elliptic integrals of the first kind
+ /**
+ * Return the complete elliptic integral of the first kind @f$ E(k) @f$
+ * for @c float modulus @c k.
+ *
+ * @see comp_ellint_1 for details.
+ */
inline float
comp_ellint_1f(float __k)
{ return __detail::__comp_ellint_1<float>(__k); }
+ /**
+ * Return the complete elliptic integral of the first kind @f$ E(k) @f$
+ * for long double modulus @c k.
+ *
+ * @see comp_ellint_1 for details.
+ */
inline long double
comp_ellint_1l(long double __k)
{ return __detail::__comp_ellint_1<long double>(__k); }
+ /**
+ * Return the complete elliptic integral of the first kind
+ * @f$ K(k) @f$ for real modulus @c k.
+ *
+ * The complete elliptic integral of the first kind is defined as
+ * @f[
+ * K(k) = F(k,\pi/2) = \int_0^{\pi/2}\frac{d\theta}
+ * {\sqrt{1 - k^2 sin^2\theta}}
+ * @f]
+ * where @f$ F(k,\phi) @f$ is the incomplete elliptic integral of the
+ * first kind and the modulus @f$ |k| <= 1 @f$.
+ * @see ellint_1 for details of the incomplete elliptic function
+ * of the first kind.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @param __k The modulus, <tt> abs(__k) <= 1 </tt>
+ * @throw std::domain_error if <tt> abs(__k) > 1 </tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
comp_ellint_1(_Tp __k)
@@ -143,14 +396,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Complete elliptic integrals of the second kind
+ /**
+ * Return the complete elliptic integral of the second kind @f$ E(k) @f$
+ * for @c float modulus @c k.
+ *
+ * @see comp_ellint_2 for details.
+ */
inline float
comp_ellint_2f(float __k)
{ return __detail::__comp_ellint_2<float>(__k); }
+ /**
+ * Return the complete elliptic integral of the second kind @f$ E(k) @f$
+ * for long double modulus @c k.
+ *
+ * @see comp_ellint_2 for details.
+ */
inline long double
comp_ellint_2l(long double __k)
{ return __detail::__comp_ellint_2<long double>(__k); }
+ /**
+ * Return the complete elliptic integral of the second kind @f$ E(k) @f$
+ * for real modulus @c k.
+ *
+ * The complete elliptic integral of the second kind is defined as
+ * @f[
+ * E(k) = E(k,\pi/2) = \int_0^{\pi/2}\sqrt{1 - k^2 sin^2\theta}
+ * @f]
+ * where @f$ E(k,\phi) @f$ is the incomplete elliptic integral of the
+ * second kind and the modulus @f$ |k| <= 1 @f$.
+ * @see ellint_2 for details of the incomplete elliptic function
+ * of the second kind.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @param __k The modulus, @c abs(__k) <= 1
+ * @throw std::domain_error if @c abs(__k) > 1.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
comp_ellint_2(_Tp __k)
@@ -161,14 +443,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Complete elliptic integrals of the third kind
+ /**
+ * @brief Return the complete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu) @f$ for @c float modulus @c k.
+ *
+ * @see comp_ellint_3 for details.
+ */
inline float
comp_ellint_3f(float __k, float __nu)
{ return __detail::__comp_ellint_3<float>(__k, __nu); }
+ /**
+ * @brief Return the complete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu) @f$ for <tt>long double</tt> modulus @c k.
+ *
+ * @see comp_ellint_3 for details.
+ */
inline long double
comp_ellint_3l(long double __k, long double __nu)
{ return __detail::__comp_ellint_3<long double>(__k, __nu); }
+ /**
+ * Return the complete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu) = \Pi(k,\nu,\pi/2) @f$ for real modulus @c k.
+ *
+ * The complete elliptic integral of the third kind is defined as
+ * @f[
+ * \Pi(k,\nu) = \Pi(k,\nu,\pi/2) = \int_0^{\pi/2}
+ * \frac{d\theta}
+ * {(1 - \nu \sin^2\theta)\sqrt{1 - k^2 \sin^2\theta}}
+ * @f]
+ * where @f$ \Pi(k,\nu,\phi) @f$ is the incomplete elliptic integral of the
+ * second kind and the modulus @f$ |k| <= 1 @f$.
+ * @see ellint_3 for details of the incomplete elliptic function
+ * of the third kind.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @tparam _Tpn The floating-point type of the argument @c __nu.
+ * @param __k The modulus, @c abs(__k) <= 1
+ * @param __nu The argument
+ * @throw std::domain_error if @c abs(__k) > 1.
+ */
template<typename _Tp, typename _Tpn>
inline typename __gnu_cxx::__promote_2<_Tp, _Tpn>::__type
comp_ellint_3(_Tp __k, _Tpn __nu)
@@ -179,14 +494,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Regular modified cylindrical Bessel functions
+ /**
+ * Return the regular modified Bessel function @f$ I_{\nu}(x) @f$
+ * for @c float order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_i for setails.
+ */
inline float
cyl_bessel_if(float __nu, float __x)
{ return __detail::__cyl_bessel_i<float>(__nu, __x); }
+ /**
+ * Return the regular modified Bessel function @f$ I_{\nu}(x) @f$
+ * for <tt>long double</tt> order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_i for setails.
+ */
inline long double
cyl_bessel_il(long double __nu, long double __x)
{ return __detail::__cyl_bessel_i<long double>(__nu, __x); }
+ /**
+ * Return the regular modified Bessel function @f$ I_{\nu}(x) @f$
+ * for real order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * The regular modified cylindrical Bessel function is:
+ * @f[
+ * I_{\nu}(x) = i^{-\nu}J_\nu(ix) = \sum_{k=0}^{\infty}
+ * \frac{(x/2)^{\nu + 2k}}{k!\Gamma(\nu+k+1)}
+ * @f]
+ *
+ * @tparam _Tpnu The floating-point type of the order @c __nu.
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __nu The order
+ * @param __x The argument, <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tpnu, typename _Tp>
inline typename __gnu_cxx::__promote_2<_Tpnu, _Tp>::__type
cyl_bessel_i(_Tpnu __nu, _Tp __x)
@@ -197,14 +540,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Cylindrical Bessel functions (of the first kind)
+ /**
+ * Return the Bessel function of the first kind @f$ J_{\nu}(x) @f$
+ * for @c float order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_j for setails.
+ */
inline float
cyl_bessel_jf(float __nu, float __x)
{ return __detail::__cyl_bessel_j<float>(__nu, __x); }
+ /**
+ * Return the Bessel function of the first kind @f$ J_{\nu}(x) @f$
+ * for <tt>long double</tt> order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_j for setails.
+ */
inline long double
cyl_bessel_jl(long double __nu, long double __x)
{ return __detail::__cyl_bessel_j<long double>(__nu, __x); }
+ /**
+ * Return the Bessel function @f$ J_{\nu}(x) @f$ of real order @f$ \nu @f$
+ * and argument @f$ x >= 0 @f$.
+ *
+ * The cylindrical Bessel function is:
+ * @f[
+ * J_{\nu}(x) = \sum_{k=0}^{\infty}
+ * \frac{(-1)^k (x/2)^{\nu + 2k}}{k!\Gamma(\nu+k+1)}
+ * @f]
+ *
+ * @tparam _Tpnu The floating-point type of the order @c __nu.
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __nu The order
+ * @param __x The argument, <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tpnu, typename _Tp>
inline typename __gnu_cxx::__promote_2<_Tpnu, _Tp>::__type
cyl_bessel_j(_Tpnu __nu, _Tp __x)
@@ -215,14 +586,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Irregular modified cylindrical Bessel functions
+ /**
+ * Return the irregular modified Bessel function @f$ K_{\nu}(x) @f$
+ * for @c float order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_k for setails.
+ */
inline float
cyl_bessel_kf(float __nu, float __x)
{ return __detail::__cyl_bessel_k<float>(__nu, __x); }
+ /**
+ * Return the irregular modified Bessel function @f$ K_{\nu}(x) @f$
+ * for <tt>long double</tt> order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * @see cyl_bessel_k for setails.
+ */
inline long double
cyl_bessel_kl(long double __nu, long double __x)
{ return __detail::__cyl_bessel_k<long double>(__nu, __x); }
+ /**
+ * Return the irregular modified Bessel function @f$ K_{\nu}(x) @f$
+ * of real order @f$ \nu @f$ and argument @f$ x @f$.
+ *
+ * The irregular modified Bessel function is defined by:
+ * @f[
+ * K_{\nu}(x) = \frac{\pi}{2}
+ * \frac{I_{-\nu}(x) - I_{\nu}(x)}{\sin \nu\pi}
+ * @f]
+ * where for integral @f$ \nu = n @f$ a limit is taken:
+ * @f$ lim_{\nu \to n} @f$.
+ * For negative argument we have simply:
+ * @f[
+ * K_{-\nu}(x) = K_{\nu}(x)
+ * @f]
+ *
+ * @tparam _Tpnu The floating-point type of the order @c __nu.
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __nu The order
+ * @param __x The argument, <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tpnu, typename _Tp>
inline typename __gnu_cxx::__promote_2<_Tpnu, _Tp>::__type
cyl_bessel_k(_Tpnu __nu, _Tp __x)
@@ -233,14 +638,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Cylindrical Neumann functions
+ /**
+ * Return the Neumann function @f$ N_{\nu}(x) @f$
+ * of @c float order @f$ \nu @f$ and argument @f$ x @f$.
+ *
+ * @see cyl_neumann for setails.
+ */
inline float
cyl_neumannf(float __nu, float __x)
{ return __detail::__cyl_neumann_n<float>(__nu, __x); }
+ /**
+ * Return the Neumann function @f$ N_{\nu}(x) @f$
+ * of <tt>long double</tt> order @f$ \nu @f$ and argument @f$ x @f$.
+ *
+ * @see cyl_neumann for setails.
+ */
inline long double
cyl_neumannl(long double __nu, long double __x)
{ return __detail::__cyl_neumann_n<long double>(__nu, __x); }
+ /**
+ * Return the Neumann function @f$ N_{\nu}(x) @f$
+ * of real order @f$ \nu @f$ and argument @f$ x >= 0 @f$.
+ *
+ * The Neumann function is defined by:
+ * @f[
+ * N_{\nu}(x) = \frac{J_{\nu}(x) \cos \nu\pi - J_{-\nu}(x)}
+ * {\sin \nu\pi}
+ * @f]
+ * where @f$ x >= 0 @f$ and for integral order @f$ \nu = n @f$
+ * a limit is taken: @f$ lim_{\nu \to n} @f$.
+ *
+ * @tparam _Tpnu The floating-point type of the order @c __nu.
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __nu The order
+ * @param __x The argument, <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tpnu, typename _Tp>
inline typename __gnu_cxx::__promote_2<_Tpnu, _Tp>::__type
cyl_neumann(_Tpnu __nu, _Tp __x)
@@ -251,14 +686,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Incomplete elliptic integrals of the first kind
+ /**
+ * Return the incomplete elliptic integral of the first kind @f$ E(k,\phi) @f$
+ * for @c float modulus @f$ k @f$ and angle @f$ \phi @f$.
+ *
+ * @see ellint_1 for details.
+ */
inline float
ellint_1f(float __k, float __phi)
{ return __detail::__ellint_1<float>(__k, __phi); }
+ /**
+ * Return the incomplete elliptic integral of the first kind @f$ E(k,\phi) @f$
+ * for <tt>long double</tt> modulus @f$ k @f$ and angle @f$ \phi @f$.
+ *
+ * @see ellint_1 for details.
+ */
inline long double
ellint_1l(long double __k, long double __phi)
{ return __detail::__ellint_1<long double>(__k, __phi); }
+ /**
+ * Return the incomplete elliptic integral of the first kind @f$ F(k,\phi) @f$
+ * for @c real modulus @f$ k @f$ and angle @f$ \phi @f$.
+ *
+ * The incomplete elliptic integral of the first kind is defined as
+ * @f[
+ * F(k,\phi) = \int_0^{\phi}\frac{d\theta}
+ * {\sqrt{1 - k^2 sin^2\theta}}
+ * @f]
+ * For @f$ \phi= \pi/2 @f$ this becomes the complete elliptic integral of
+ * the first kind, @f$ K(k) @f$. @see comp_ellint_1.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @tparam _Tpp The floating-point type of the angle @c __phi.
+ * @param __k The modulus, <tt> abs(__k) <= 1 </tt>
+ * @param __phi The integral limit argument in radians
+ * @throw std::domain_error if <tt> abs(__k) > 1 </tt>.
+ */
template<typename _Tp, typename _Tpp>
inline typename __gnu_cxx::__promote_2<_Tp, _Tpp>::__type
ellint_1(_Tp __k, _Tpp __phi)
@@ -269,14 +734,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Incomplete elliptic integrals of the second kind
+ /**
+ * @brief Return the incomplete elliptic integral of the second kind
+ * @f$ E(k,\phi) @f$ for @c float argument.
+ *
+ * @see ellint_2 for details.
+ */
inline float
ellint_2f(float __k, float __phi)
{ return __detail::__ellint_2<float>(__k, __phi); }
+ /**
+ * @brief Return the incomplete elliptic integral of the second kind
+ * @f$ E(k,\phi) @f$.
+ *
+ * @see ellint_2 for details.
+ */
inline long double
ellint_2l(long double __k, long double __phi)
{ return __detail::__ellint_2<long double>(__k, __phi); }
+ /**
+ * Return the incomplete elliptic integral of the second kind
+ * @f$ E(k,\phi) @f$.
+ *
+ * The incomplete elliptic integral of the second kind is defined as
+ * @f[
+ * E(k,\phi) = \int_0^{\phi} \sqrt{1 - k^2 sin^2\theta}
+ * @f]
+ * For @f$ \phi= \pi/2 @f$ this becomes the complete elliptic integral of
+ * the second kind, @f$ E(k) @f$. @see comp_ellint_2.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @tparam _Tpp The floating-point type of the angle @c __phi.
+ * @param __k The modulus, <tt> abs(__k) <= 1 </tt>
+ * @param __phi The integral limit argument in radians
+ * @return The elliptic function of the second kind.
+ * @throw std::domain_error if <tt> abs(__k) > 1 </tt>.
+ */
template<typename _Tp, typename _Tpp>
inline typename __gnu_cxx::__promote_2<_Tp, _Tpp>::__type
ellint_2(_Tp __k, _Tpp __phi)
@@ -287,14 +782,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Incomplete elliptic integrals of the third kind
+ /**
+ * @brief Return the incomplete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu,\phi) @f$ for @c float argument.
+ *
+ * @see ellint_3 for details.
+ */
inline float
ellint_3f(float __k, float __nu, float __phi)
{ return __detail::__ellint_3<float>(__k, __nu, __phi); }
+ /**
+ * @brief Return the incomplete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu,\phi) @f$.
+ *
+ * @see ellint_3 for details.
+ */
inline long double
ellint_3l(long double __k, long double __nu, long double __phi)
{ return __detail::__ellint_3<long double>(__k, __nu, __phi); }
+ /**
+ * @brief Return the incomplete elliptic integral of the third kind
+ * @f$ \Pi(k,\nu,\phi) @f$.
+ *
+ * The incomplete elliptic integral of the third kind is defined by:
+ * @f[
+ * \Pi(k,\nu,\phi) = \int_0^{\phi}
+ * \frac{d\theta}
+ * {(1 - \nu \sin^2\theta)
+ * \sqrt{1 - k^2 \sin^2\theta}}
+ * @f]
+ * For @f$ \phi= \pi/2 @f$ this becomes the complete elliptic integral of
+ * the third kind, @f$ \Pi(k,\nu) @f$. @see comp_ellint_3.
+ *
+ * @tparam _Tp The floating-point type of the modulus @c __k.
+ * @tparam _Tpn The floating-point type of the argument @c __nu.
+ * @tparam _Tpp The floating-point type of the angle @c __phi.
+ * @param __k The modulus, <tt> abs(__k) <= 1 </tt>
+ * @param __nu The second argument
+ * @param __phi The integral limit argument in radians
+ * @return The elliptic function of the third kind.
+ * @throw std::domain_error if <tt> abs(__k) > 1 </tt>.
+ */
template<typename _Tp, typename _Tpn, typename _Tpp>
inline typename __gnu_cxx::__promote_3<_Tp, _Tpn, _Tpp>::__type
ellint_3(_Tp __k, _Tpn __nu, _Tpp __phi)
@@ -305,14 +835,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Exponential integrals
+ /**
+ * Return the exponential integral @f$ Ei(x) @f$ for @c float argument @c x.
+ *
+ * @see expint for details.
+ */
inline float
expintf(float __x)
{ return __detail::__expint<float>(__x); }
+ /**
+ * Return the exponential integral @f$ Ei(x) @f$
+ * for <tt>long double</tt> argument @c x.
+ *
+ * @see expint for details.
+ */
inline long double
expintl(long double __x)
{ return __detail::__expint<long double>(__x); }
+ /**
+ * Return the exponential integral @f$ Ei(x) @f$ for @c real argument @c x.
+ *
+ * The exponential integral is given by
+ * \f[
+ * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt
+ * \f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __x The argument of the exponential integral function.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
expint(_Tp __x)
@@ -323,14 +875,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Hermite polynomials
+ /**
+ * Return the Hermite polynomial @f$ H_n(x) @f$ of nonnegative order n
+ * and float argument @c x.
+ *
+ * @see hermite for details.
+ */
inline float
hermitef(unsigned int __n, float __x)
{ return __detail::__poly_hermite<float>(__n, __x); }
+ /**
+ * Return the Hermite polynomial @f$ H_n(x) @f$ of nonnegative order n
+ * and <tt>long double</tt> argument @c x.
+ *
+ * @see hermite for details.
+ */
inline long double
hermitel(unsigned int __n, long double __x)
{ return __detail::__poly_hermite<long double>(__n, __x); }
+ /**
+ * Return the Hermite polynomial @f$ H_n(x) @f$ of order n
+ * and @c real argument @c x.
+ *
+ * The Hermite polynomial is defined by:
+ * @f[
+ * H_n(x) = (-1)^n e^{x^2} \frac{d^n}{dx^n} e^{-x^2}
+ * @f]
+ *
+ * The Hermite polynomial obeys a reflection formula:
+ * @f[
+ * H_n(-x) = (-1)^n H_n(x)
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __n The order
+ * @param __x The argument
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
hermite(unsigned int __n, _Tp __x)
@@ -341,14 +923,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Laguerre polynomials
+ /**
+ * Returns the Laguerre polynomial @f$ L_n(x) @f$ of nonnegative degree @c n
+ * and @c float argument @f$ x >= 0 @f$.
+ *
+ * @see laguerre for more details.
+ */
inline float
laguerref(unsigned int __n, float __x)
{ return __detail::__laguerre<float>(__n, __x); }
+ /**
+ * Returns the Laguerre polynomial @f$ L_n(x) @f$ of nonnegative degree @c n
+ * and <tt>long double</tt> argument @f$ x >= 0 @f$.
+ *
+ * @see laguerre for more details.
+ */
inline long double
laguerrel(unsigned int __n, long double __x)
{ return __detail::__laguerre<long double>(__n, __x); }
+ /**
+ * Returns the Laguerre polynomial @f$ L_n(x) @f$
+ * of nonnegative degree @c n and real argument @f$ x >= 0 @f$.
+ *
+ * The Laguerre polynomial is defined by:
+ * @f[
+ * L_n(x) = \frac{e^x}{n!} \frac{d^n}{dx^n} (x^ne^{-x})
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __n The nonnegative order
+ * @param __x The argument <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
laguerre(unsigned int __n, _Tp __x)
@@ -359,32 +967,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Legendre polynomials
+ /**
+ * Return the Legendre polynomial @f$ P_l(x) @f$ of nonnegative
+ * degree @f$ l @f$ and @c float argument @f$ |x| <= 0 @f$.
+ *
+ * @see legendre for more details.
+ */
inline float
- legendref(unsigned int __n, float __x)
- { return __detail::__poly_legendre_p<float>(__n, __x); }
+ legendref(unsigned int __l, float __x)
+ { return __detail::__poly_legendre_p<float>(__l, __x); }
+ /**
+ * Return the Legendre polynomial @f$ P_l(x) @f$ of nonnegative
+ * degree @f$ l @f$ and <tt>long double</tt> argument @f$ |x| <= 0 @f$.
+ *
+ * @see legendre for more details.
+ */
inline long double
- legendrel(unsigned int __n, long double __x)
- { return __detail::__poly_legendre_p<long double>(__n, __x); }
+ legendrel(unsigned int __l, long double __x)
+ { return __detail::__poly_legendre_p<long double>(__l, __x); }
+ /**
+ * Return the Legendre polynomial @f$ P_l(x) @f$ of nonnegative
+ * degree @f$ l @f$ and real argument @f$ |x| <= 0 @f$.
+ *
+ * The Legendre function of order @f$ l @f$ and argument @f$ x @f$,
+ * @f$ P_l(x) @f$, is defined by:
+ * @f[
+ * P_l(x) = \frac{1}{2^l l!}\frac{d^l}{dx^l}(x^2 - 1)^{l}
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __l The degree @f$ l >= 0 @f$
+ * @param __x The argument @c abs(__x) <= 1
+ * @throw std::domain_error if @c abs(__x) > 1
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
- legendre(unsigned int __n, _Tp __x)
+ legendre(unsigned int __l, _Tp __x)
{
typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
- return __detail::__poly_legendre_p<__type>(__n, __x);
+ return __detail::__poly_legendre_p<__type>(__l, __x);
}
// Riemann zeta functions
+ /**
+ * Return the Riemann zeta function @f$ \zeta(s) @f$
+ * for @c float argument @f$ s @f$.
+ *
+ * @see riemann_zeta for more details.
+ */
inline float
riemann_zetaf(float __s)
{ return __detail::__riemann_zeta<float>(__s); }
+ /**
+ * Return the Riemann zeta function @f$ \zeta(s) @f$
+ * for <tt>long double</tt> argument @f$ s @f$.
+ *
+ * @see riemann_zeta for more details.
+ */
inline long double
riemann_zetal(long double __s)
{ return __detail::__riemann_zeta<long double>(__s); }
+ /**
+ * Return the Riemann zeta function @f$ \zeta(s) @f$
+ * for real argument @f$ s @f$.
+ *
+ * The Riemann zeta function is defined by:
+ * @f[
+ * \zeta(s) = \sum_{k=1}^{\infty} k^{-s} \hbox{ for } s > 1
+ * @f]
+ * and
+ * @f[
+ * \zeta(s) = \frac{1}{1-2^{1-s}}\sum_{k=1}^{\infty}(-1)^{k-1}k^{-s}
+ * \hbox{ for } 0 <= s <= 1
+ * @f]
+ * For s < 1 use the reflection formula:
+ * @f[
+ * \zeta(s) = 2^s \pi^{s-1} \sin(\frac{\pi s}{2}) \Gamma(1-s) \zeta(1-s)
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __s.
+ * @param __s The argument <tt> s != 1 </tt>
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
riemann_zeta(_Tp __s)
@@ -395,14 +1063,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Spherical Bessel functions
+ /**
+ * Return the spherical Bessel function @f$ j_n(x) @f$ of nonnegative order n
+ * and @c float argument @f$ x >= 0 @f$.
+ *
+ * @see sph_bessel for more details.
+ */
inline float
sph_besself(unsigned int __n, float __x)
{ return __detail::__sph_bessel<float>(__n, __x); }
+ /**
+ * Return the spherical Bessel function @f$ j_n(x) @f$ of nonnegative order n
+ * and <tt>long double</tt> argument @f$ x >= 0 @f$.
+ *
+ * @see sph_bessel for more details.
+ */
inline long double
sph_bessell(unsigned int __n, long double __x)
{ return __detail::__sph_bessel<long double>(__n, __x); }
+ /**
+ * Return the spherical Bessel function @f$ j_n(x) @f$ of nonnegative order n
+ * and real argument @f$ x >= 0 @f$.
+ *
+ * The spherical Bessel function is defined by:
+ * @f[
+ * j_n(x) = \left(\frac{\pi}{2x} \right) ^{1/2} J_{n+1/2}(x)
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __n The integral order <tt> n >= 0 </tt>
+ * @param __x The real argument <tt> x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
sph_bessel(unsigned int __n, _Tp __x)
@@ -413,14 +1107,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Spherical associated Legendre functions
+ /**
+ * Return the spherical Legendre function of nonnegative integral
+ * degree @c l and order @c m and float angle @f$ \theta @f$ in radians.
+ *
+ * @see sph_legendre for details.
+ */
inline float
sph_legendref(unsigned int __l, unsigned int __m, float __theta)
{ return __detail::__sph_legendre<float>(__l, __m, __theta); }
+ /**
+ * Return the spherical Legendre function of nonnegative integral
+ * degree @c l and order @c m and <tt>long double</tt> angle @f$ \theta @f$
+ * in radians.
+ *
+ * @see sph_legendre for details.
+ */
inline long double
sph_legendrel(unsigned int __l, unsigned int __m, long double __theta)
{ return __detail::__sph_legendre<long double>(__l, __m, __theta); }
+ /**
+ * Return the spherical Legendre function of nonnegative integral
+ * degree @c l and order @c m and real angle @f$ \theta @f$ in radians.
+ *
+ * The spherical Legendre function is defined by
+ * @f[
+ * Y_l^m(\theta,\phi) = (-1)^m[\frac{(2l+1)}{4\pi}
+ * \frac{(l-m)!}{(l+m)!}]
+ * P_l^m(\cos\theta) \exp^{im\phi}
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the angle @c __theta.
+ * @param __l The order <tt> __l >= 0 </tt>
+ * @param __m The degree <tt> __m >= 0 </tt> and <tt> __m <= __l </tt>
+ * @param __theta The radian polar angle argument
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
sph_legendre(unsigned int __l, unsigned int __m, _Tp __theta)
@@ -431,14 +1154,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Spherical Neumann functions
+ /**
+ * Return the spherical Neumann function of integral order @f$ n >= 0 @f$
+ * and @c float argument @f$ x >= 0 @f$.
+ *
+ * @see sph_neumann for details.
+ */
inline float
sph_neumannf(unsigned int __n, float __x)
{ return __detail::__sph_neumann<float>(__n, __x); }
+ /**
+ * Return the spherical Neumann function of integral order @f$ n >= 0 @f$
+ * and <tt>long double</tt> @f$ x >= 0 @f$.
+ *
+ * @see sph_neumann for details.
+ */
inline long double
sph_neumannl(unsigned int __n, long double __x)
{ return __detail::__sph_neumann<long double>(__n, __x); }
+ /**
+ * Return the spherical Neumann function of integral order @f$ n >= 0 @f$
+ * and real argument @f$ x >= 0 @f$.
+ *
+ * The spherical Neumann function is defined by
+ * @f[
+ * n_n(x) = \left(\frac{\pi}{2x} \right) ^{1/2} N_{n+1/2}(x)
+ * @f]
+ *
+ * @tparam _Tp The floating-point type of the argument @c __x.
+ * @param __n The integral order <tt> n >= 0 </tt>
+ * @param __x The real argument <tt> __x >= 0 </tt>
+ * @throw std::domain_error if <tt> __x < 0 </tt>.
+ */
template<typename _Tp>
inline typename __gnu_cxx::__promote<_Tp>::__type
sph_neumann(unsigned int __n, _Tp __x)
@@ -457,14 +1206,44 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
// Confluent hypergeometric functions
+ /**
+ * Return the confluent hypergeometric function @f$ {}_1F_1(a;c;x) @f$
+ * of @c float numeratorial parameter @c a, denominatorial parameter @c c,
+ * and argument @c x.
+ *
+ * @see conf_hyperg for details.
+ */
inline float
conf_hypergf(float __a, float __c, float __x)
{ return std::__detail::__conf_hyperg<float>(__a, __c, __x); }
+ /**
+ * Return the confluent hypergeometric function @f$ {}_1F_1(a;c;x) @f$
+ * of <tt>long double</tt> numeratorial parameter @c a,
+ * denominatorial parameter @c c, and argument @c x.
+ *
+ * @see conf_hyperg for details.
+ */
inline long double
conf_hypergl(long double __a, long double __c, long double __x)
{ return std::__detail::__conf_hyperg<long double>(__a, __c, __x); }
+ /**
+ * Return the confluent hypergeometric function @f$ {}_1F_1(a;c;x) @f$
+ * of real numeratorial parameter @c a, denominatorial parameter @c c,
+ * and argument @c x.
+ *
+ * The confluent hypergeometric function is defined by
+ * @f[
+ * {}_1F_1(a;c;x) = \sum_{n=0}^{\infty} \frac{(a)_n x^n}{(c)_n n!}
+ * @f]
+ * where the Pochhammer symbol is @f$ (x)_k = (x)(x+1)...(x+k-1) @f$,
+ * @f$ (x)_0 = 1 @f$
+ *
+ * @param __a The numeratorial parameter
+ * @param __c The denominatorial parameter
+ * @param __x The argument
+ */
template<typename _Tpa, typename _Tpc, typename _Tp>
inline typename __gnu_cxx::__promote_3<_Tpa, _Tpc, _Tp>::__type
conf_hyperg(_Tpa __a, _Tpc __c, _Tp __x)
@@ -475,14 +1254,45 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
// Hypergeometric functions
+ /**
+ * Return the hypergeometric function @f$ {}_2F_1(a,b;c;x) @f$
+ * of @ float numeratorial parameters @c a and @c b,
+ * denominatorial parameter @c c, and argument @c x.
+ *
+ * @see hyperg for details.
+ */
inline float
hypergf(float __a, float __b, float __c, float __x)
{ return std::__detail::__hyperg<float>(__a, __b, __c, __x); }
+ /**
+ * Return the hypergeometric function @f$ {}_2F_1(a,b;c;x) @f$
+ * of <tt>long double</tt> numeratorial parameters @c a and @c b,
+ * denominatorial parameter @c c, and argument @c x.
+ *
+ * @see hyperg for details.
+ */
inline long double
hypergl(long double __a, long double __b, long double __c, long double __x)
{ return std::__detail::__hyperg<long double>(__a, __b, __c, __x); }
+ /**
+ * Return the hypergeometric function @f$ {}_2F_1(a,b;c;x) @f$
+ * of real numeratorial parameters @c a and @c b,
+ * denominatorial parameter @c c, and argument @c x.
+ *
+ * The hypergeometric function is defined by
+ * @f[
+ * {}_2F_1(a;c;x) = \sum_{n=0}^{\infty} \frac{(a)_n (b)_n x^n}{(c)_n n!}
+ * @f]
+ * where the Pochhammer symbol is @f$ (x)_k = (x)(x+1)...(x+k-1) @f$,
+ * @f$ (x)_0 = 1 @f$
+ *
+ * @param __a The first numeratorial parameter
+ * @param __b The second numeratorial parameter
+ * @param __c The denominatorial parameter
+ * @param __x The argument
+ */
template<typename _Tpa, typename _Tpb, typename _Tpc, typename _Tp>
inline typename __gnu_cxx::__promote_4<_Tpa, _Tpb, _Tpc, _Tp>::__type
hyperg(_Tpa __a, _Tpb __b, _Tpc __c, _Tp __x)
diff --git a/libstdc++-v3/testsuite/25_algorithms/rotate/moveable2.cc b/libstdc++-v3/testsuite/25_algorithms/rotate/moveable2.cc
index d9d1f2a44ca..f944236f061 100644
--- a/libstdc++-v3/testsuite/25_algorithms/rotate/moveable2.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/rotate/moveable2.cc
@@ -44,7 +44,8 @@ template<typename Con>
{
bool test __attribute__((unused)) = true;
- rvalstruct array[length];
+ /* Make sure the VLA upper bound is positive. */
+ rvalstruct array[length + 1];
for(int i = 0; i < length; ++i)
array[i] = i;
Con con(array, array + length);