aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Kuvyrkov <maxim.kuvyrkov@linaro.org>2018-03-07 14:18:54 +0000
committerMaxim Kuvyrkov <maxim.kuvyrkov@linaro.org>2018-03-08 09:47:02 +0000
commitac919e63e9a661f0deeffcc8fe49517fd523e894 (patch)
tree7dc14af0c974f18c09a92813bf82169defe4b8dd
parent27f22a4f680559ced8fc96728c5453aee135596e (diff)
Merge branches/gcc-6-branch rev 258335 .
Change-Id: I03b5446106d0313b01799c902a8f52f92c908045
-rw-r--r--gcc/ChangeLog335
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/gcc-interface/trans.c2
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/config/aarch64/aarch64.c6
-rw-r--r--gcc/config/aarch64/aarch64.h6
-rw-r--r--gcc/config/aarch64/constraints.md4
-rw-r--r--gcc/config/nvptx/nvptx.c10
-rw-r--r--gcc/config/pa/pa.c8
-rw-r--r--gcc/config/pa/predicates.md3
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c91
-rw-r--r--gcc/config/rs6000/rs6000.md121
-rw-r--r--gcc/config/rs6000/vsx.md32
-rw-r--r--gcc/config/s390/s390-opts.h9
-rw-r--r--gcc/config/s390/s390-protos.h12
-rw-r--r--gcc/config/s390/s390.c713
-rw-r--r--gcc/config/s390/s390.h120
-rw-r--r--gcc/config/s390/s390.md568
-rw-r--r--gcc/config/s390/s390.opt59
-rw-r--r--gcc/config/sh/sh-protos.h10
-rw-r--r--gcc/config/sh/sh_optimize_sett_clrt.cc5
-rwxr-xr-xgcc/configure8
-rw-r--r--gcc/configure.ac8
-rw-r--r--gcc/cp/ChangeLog30
-rw-r--r--gcc/cp/call.c19
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/lambda.c5
-rw-r--r--gcc/cp/pt.c24
-rw-r--r--gcc/doc/gcov.texi4
-rw-r--r--gcc/doc/invoke.texi6
-rw-r--r--gcc/expmed.c12
-rw-r--r--gcc/final.c4
-rw-r--r--gcc/fortran/ChangeLog134
-rw-r--r--gcc/fortran/check.c2
-rw-r--r--gcc/fortran/decl.c65
-rw-r--r--gcc/fortran/expr.c5
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/interface.c32
-rw-r--r--gcc/fortran/match.c12
-rw-r--r--gcc/fortran/module.c4
-rw-r--r--gcc/fortran/primary.c18
-rw-r--r--gcc/fortran/resolve.c10
-rw-r--r--gcc/fortran/simplify.c21
-rw-r--r--gcc/fortran/trans-array.c14
-rw-r--r--gcc/fortran/trans-decl.c50
-rw-r--r--gcc/fortran/trans-expr.c46
-rw-r--r--gcc/fortran/trans-intrinsic.c22
-rw-r--r--gcc/fortran/trans-io.c16
-rw-r--r--gcc/ipa-cp.c18
-rw-r--r--gcc/ipa-utils.c2
-rw-r--r--gcc/loop-unroll.c2
-rw-r--r--gcc/lto-streamer-out.c55
-rw-r--r--gcc/lto/ChangeLog73
-rw-r--r--gcc/lto/lto-lang.c2
-rw-r--r--gcc/lto/lto-partition.c3
-rw-r--r--gcc/lto/lto-symtab.c47
-rw-r--r--gcc/lto/lto.c67
-rw-r--r--gcc/opts.c20
-rw-r--r--gcc/rtlanal.c2
-rw-r--r--gcc/symtab.c56
-rw-r--r--gcc/testsuite/ChangeLog287
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/elision3.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual18.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C8
-rw-r--r--gcc/testsuite/g++.dg/other/anon5.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/volatile1.C28
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/volatile2.C20
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr82096.c11
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c5
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr81440.h4
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr81440_0.c9
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr81440_1.c6
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr83954.h3
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr83954_0.c8
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr83954_1.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr83424.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr82726.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr83370.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/i386.exp12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84310-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84310.c8
-rw-r--r--gcc/testsuite/gcc.target/nvptx/indirect_call.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83399.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83862.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsxcopy.c4
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c59
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c42
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c42
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c40
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c49
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c48
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c44
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c44
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c78
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c78
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c77
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c78
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_charlen_parameter.f909
-rw-r--r--gcc/testsuite/gfortran.dg/automatic_module_variable.f904
-rw-r--r--gcc/testsuite/gfortran.dg/bad_automatic_objects_1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/class_67.f9055
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_8.f904
-rw-r--r--gcc/testsuite/gfortran.dg/data_substring.f906
-rw-r--r--gcc/testsuite/gfortran.dg/deallocate_error_3.f909
-rw-r--r--gcc/testsuite/gfortran.dg/deallocate_error_4.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/explicit_shape_1.f907
-rw-r--r--gcc/testsuite/gfortran.dg/implied_do_2.f907
-rw-r--r--gcc/testsuite/gfortran.dg/inquire_19.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_17.f909
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_18.f908
-rw-r--r--gcc/testsuite/gfortran.dg/num_images_1.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/pr70754.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/pr71085.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr83874.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/shape_9.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/statement_function_1.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/statement_function_2.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/statement_function_3.f15
-rw-r--r--gcc/testsuite/gnat.dg/array11.adb10
-rw-r--r--gcc/testsuite/gnat.dg/disp1.adb (renamed from gcc/testsuite/gnat.dg/dispatch1.adb)5
-rw-r--r--gcc/testsuite/gnat.dg/disp1_pkg.ads (renamed from gcc/testsuite/gnat.dg/dispatch1_p.ads)6
-rw-r--r--gcc/testsuite/gnat.dg/disp2.adb (renamed from gcc/testsuite/gnat.dg/dispatch2.adb)5
-rw-r--r--gcc/testsuite/gnat.dg/disp2_pkg.adb (renamed from gcc/testsuite/gnat.dg/dispatch2_p.adb)7
-rw-r--r--gcc/testsuite/gnat.dg/disp2_pkg.ads (renamed from gcc/testsuite/gnat.dg/dispatch2_p.ads)9
-rw-r--r--gcc/testsuite/gnat.dg/generic_disp.adb (renamed from gcc/testsuite/gnat.dg/generic_dispatch.adb)7
-rw-r--r--gcc/testsuite/gnat.dg/generic_disp_pkg.adb (renamed from gcc/testsuite/gnat.dg/generic_dispatch_p.adb)8
-rw-r--r--gcc/testsuite/gnat.dg/generic_disp_pkg.ads (renamed from gcc/testsuite/gnat.dg/generic_dispatch_p.ads)5
-rw-r--r--gcc/testsuite/gnat.dg/null_pointer_deref1.adb2
-rw-r--r--gcc/testsuite/gnat.dg/null_pointer_deref2.adb2
-rw-r--r--gcc/testsuite/gnat.dg/object_overflow1.adb4
-rw-r--r--gcc/testsuite/gnat.dg/object_overflow2.adb4
-rw-r--r--gcc/testsuite/gnat.dg/object_overflow3.adb4
-rw-r--r--gcc/testsuite/gnat.dg/object_overflow4.adb8
-rw-r--r--gcc/testsuite/gnat.dg/object_overflow5.adb8
-rw-r--r--gcc/testsuite/lib/prune.exp2
-rw-r--r--gcc/testsuite/lib/target-supports.exp11
-rw-r--r--gcc/tree-predcom.c138
-rw-r--r--gcc/tree-vect-stmts.c2
-rw-r--r--gcc/tree.c7
-rw-r--r--libgcc/ChangeLog19
-rw-r--r--libgcc/config/xtensa/ieee754-df.S55
-rw-r--r--libgcc/config/xtensa/ieee754-sf.S52
-rw-r--r--libstdc++-v3/ChangeLog43
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver2
-rwxr-xr-xlibstdc++-v3/configure36
-rw-r--r--libstdc++-v3/configure.ac6
-rw-r--r--libstdc++-v3/include/Makefile.am5
-rw-r--r--libstdc++-v3/include/Makefile.in3
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h7
-rw-r--r--libstdc++-v3/include/bits/random.h7
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/literals/84671.cc26
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/chi_squared_distribution/83833.cc40
170 files changed, 5341 insertions, 553 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b17b12ae7de..f1274bfd957 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,336 @@
+2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-02-08 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * config/s390/s390-opts.h (enum indirect_branch): Define.
+ * config/s390/s390-protos.h (s390_return_addr_from_memory)
+ (s390_indirect_branch_via_thunk)
+ (s390_indirect_branch_via_inline_thunk): Add function prototypes.
+ (enum s390_indirect_branch_type): Define.
+ * config/s390/s390.c (struct s390_frame_layout, struct
+ machine_function): Remove.
+ (indirect_branch_prez10thunk_mask, indirect_branch_z10thunk_mask)
+ (indirect_branch_table_label_no, indirect_branch_table_name):
+ Define variables.
+ (INDIRECT_BRANCH_NUM_OPTIONS): Define macro.
+ (enum s390_indirect_branch_option): Define.
+ (s390_return_addr_from_memory): New function.
+ (s390_handle_string_attribute): New function.
+ (s390_attribute_table): Add new attribute handler.
+ (s390_execute_label): Handle UNSPEC_EXECUTE_JUMP patterns.
+ (s390_indirect_branch_via_thunk): New function.
+ (s390_indirect_branch_via_inline_thunk): New function.
+ (s390_function_ok_for_sibcall): When jumping via thunk disallow
+ sibling call optimization for non z10 compiles.
+ (s390_emit_call): Force indirect branch target to be a single
+ register. Add r1 clobber for non-z10 compiles.
+ (s390_emit_epilogue): Emit return jump via return_use expander.
+ (s390_reorg): Handle JUMP_INSNs as execute targets.
+ (s390_option_override_internal): Perform validity checks for the
+ new command line options.
+ (s390_indirect_branch_attrvalue): New function.
+ (s390_indirect_branch_settings): New function.
+ (s390_set_current_function): Invoke s390_indirect_branch_settings.
+ (s390_output_indirect_thunk_function): New function.
+ (s390_code_end): Implement target hook.
+ (s390_case_values_threshold): Implement target hook.
+ (TARGET_ASM_CODE_END, TARGET_CASE_VALUES_THRESHOLD): Define target
+ macros.
+ * config/s390/s390.h (struct s390_frame_layout)
+ (struct machine_function): Move here from s390.c.
+ (TARGET_INDIRECT_BRANCH_NOBP_RET)
+ (TARGET_INDIRECT_BRANCH_NOBP_JUMP)
+ (TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK)
+ (TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK)
+ (TARGET_INDIRECT_BRANCH_NOBP_CALL)
+ (TARGET_DEFAULT_INDIRECT_BRANCH_TABLE)
+ (TARGET_INDIRECT_BRANCH_THUNK_NAME_EXRL)
+ (TARGET_INDIRECT_BRANCH_THUNK_NAME_EX)
+ (TARGET_INDIRECT_BRANCH_TABLE): Define macros.
+ * config/s390/s390.md (UNSPEC_EXECUTE_JUMP)
+ (INDIRECT_BRANCH_THUNK_REGNUM): Define constants.
+ (mnemonic attribute): Add values which aren't recognized
+ automatically.
+ ("*cjump_long", "*icjump_long", "*basr", "*basr_r"): Disable
+ pattern for branch conversion. Fix mnemonic attribute.
+ ("*c<code>", "*sibcall_br", "*sibcall_value_br", "*return"): Emit
+ indirect branch via thunk if requested.
+ ("indirect_jump", "<code>"): Expand patterns for branch conversion.
+ ("*indirect_jump"): Disable for branch conversion using out of
+ line thunks.
+ ("indirect_jump_via_thunk<mode>_z10")
+ ("indirect_jump_via_thunk<mode>")
+
+2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-02-09 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/PR84295
+ * config/s390/s390.c (s390_set_current_function): Invoke
+ s390_indirect_branch_settings also if fndecl didn't change.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-20 Martin Liska <mliska@suse.cz>
+
+ PR c/84310
+ PR target/79747
+ * final.c (shorten_branches): Build align_tab array with one
+ more element.
+ * opts.c (finish_options): Add alignment option limit check.
+ (MAX_CODE_ALIGN): Likewise.
+ (MAX_CODE_ALIGN_VALUE): Likewise.
+ * doc/invoke.texi: Document maximum allowed option value for
+ all -falign-* options.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-19 Martin Liska <mliska@suse.cz>
+
+ PR other/80589
+ * doc/invoke.texi: Fix typo.
+ * params.def (PARAM_MAX_LOOP_HEADER_INSNS): Likewise.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-05 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/84137
+ * doc/gcov.texi: Fix typo in documentation.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-05 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/83879
+ * doc/gcov.texi: Document necessity of --dynamic-list-data when
+ using dlopen functionality.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2017-12-19 Martin Liska <mliska@suse.cz>
+
+ PR rtl-optimization/82675
+ * loop-unroll.c (unroll_loop_constant_iterations): Allocate one
+ more element in sbitmap.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-03-05 Martin Liska <mliska@suse.cz>
+
+ * ipa-utils.c (ipa_merge_profiles): Do not merge alias or
+ a function without profile.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-21 Jan Hubicka <hubicka@ucw.cz>
+
+ PR c/84229
+ * ipa-cp.c (determine_versionability): Do not version functions caling
+ va_arg_pack.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-08 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/81360
+ * cgraph.h (symtab_node::output_to_lto_symbol_table_p): Declare
+ * symtab.c: Include builtins.h
+ (symtab_node::output_to_lto_symbol_table_p): Move here
+ from lto-streamer-out.c:output_symbol_p.
+ * lto-streamer-out.c (write_symbol): Turn early exit to assert.
+ (output_symbol_p): Move all logic to symtab.c
+ (produce_symtab): Update.
+
+2017-03-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ Backport from trunk r256891:
+ 2018-01-19 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR target/83790
+ * config/nvptx/nvptx.c (output_init_frag): Don't use generic address
+ spaces for function labels.
+
+2018-02-21 Sudakshina Das <sudi.das@arm.com>
+
+ Backport from trunk
+ 2018-01-10 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/82096
+ * expmed.c (emit_store_flag_force): Swap if const op0
+ and change VOIDmode to mode of op0.
+
+2018-02-15 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from trunk
+ 2018-02-06 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/84154
+ * config/rs6000/rs6000.md (su code attribute): Use "u" for
+ unsigned_fix, not "s".
+
+2018-02-15 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
+
+ Back port from mainline
+ 2018-01-30 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
+
+ PR target/83758
+ * config/rs6000/rs6000.c (rs6000_internal_arg_pointer): Only return
+ a reg rtx.
+
+2018-02-10 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.c (hppa_profile_hook): Mark SYMBOL_REF for _mcount as
+ function label.
+
+ Backport from mainline
+ 2018-02-01 Aldy Hernandez <aldyh@redhat.com>
+
+ PR target/84089
+ * config/pa/predicates.md (base14_operand): Handle VOIDmode.
+
+2018-02-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ Backport from mainline
+ 2018-01-30 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/84017
+ * configure.ac (gcc_cv_as_shf_merge): Disable on Solaris 10/x86.
+ * configure: Regenerate.
+
+2018-02-01 Renlin Li <renlin.li@arm.com>
+
+ Backport from mainline
+ 2018-02-01 Renlin Li <renlin.li@arm.com>
+
+ PR target/83370
+ * config/aarch64/aarch64.c (aarch64_class_max_nregs): Handle
+ TAILCALL_ADDR_REGS.
+ (aarch64_register_move_cost): Likewise.
+ * config/aarch64/aarch64.h (reg_class): Rename CALLER_SAVE_REGS to
+ TAILCALL_ADDR_REGS.
+ (REG_CLASS_NAMES): Likewise.
+ (REG_CLASS_CONTENTS): Rename CALLER_SAVE_REGS to
+ TAILCALL_ADDR_REGS. Remove IP registers.
+ * config/aarch64/aarch64.md (Ucs): Update register constraint.
+
+2018-02-01 Bin Cheng <bin.cheng@arm.com>
+
+ Backport from mainline
+ 2017-11-15 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/82726
+ PR tree-optimization/70754
+ * tree-predcom.c (order_drefs_by_pos): New function.
+ (combine_chains): Move code setting has_max_use_after to...
+ (try_combine_chains): ...here. New parameter. Sort combined chains
+ according to position information.
+ (tree_predictive_commoning_loop): Update call to above function.
+ (update_pos_for_combined_chains, pcom_stmt_dominates_stmt_p): New.
+
+2018-01-31 Richard Biener <rguenther@suse.de>
+ Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ Backport from mainline
+ 2018-01-29 Richard Biener <rguenther@suse.de>
+ Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ PR bootstrap/80867
+ * tree-vect-stmts.c (vectorizable_call): Don't call
+ targetm.vectorize_builtin_md_vectorized_function if callee is
+ NULL.
+
+2018-01-29 Alan Modra <amodra@gmail.com>
+
+ Backport from mainline
+ 2018-01-26 Alan Modra <amodra@gmail.com>
+ PR target/84033
+ * config/rs6000/rs6000.c (rtx_is_swappable_p): Exclude
+ UNSPEC_VBPERMQ.
+
+2018-01-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-01-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-p8swap.c (swap_feeds_both_load_and_store):
+ New function.
+ (rs6000_analyze_swaps): Mark a web unoptimizable if it contains a
+ swap associated with both a load and a store.
+
+2018-01-23 Peter Bergner <bergner@vnet.ibm.com>
+
+ Back port from mainline
+ 2018-01-10 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/83399
+ * config/rs6000/rs6000.c (print_operand) <'y'>: Use
+ VECTOR_MEM_ALTIVEC_OR_VSX_P.
+ * config/rs6000/vsx.md (*vsx_le_perm_load_<mode> for VSX_D): Use
+ indexed_or_indirect_operand predicate.
+ (*vsx_le_perm_load_<mode> for VSX_W): Likewise.
+ (*vsx_le_perm_load_v8hi): Likewise.
+ (*vsx_le_perm_load_v16qi): Likewise.
+ (*vsx_le_perm_store_<mode> for VSX_D): Likewise.
+ (*vsx_le_perm_store_<mode> for VSX_W): Likewise.
+ (*vsx_le_perm_store_v8hi): Likewise.
+ (*vsx_le_perm_store_v16qi): Likewise.
+ (eight unnamed splitters): Likewise.
+
+2018-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from trunk
+ 2018-01-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/83862
+ * config/rs6000/rs6000-protos.h (rs6000_split_signbit): Delete,
+ no longer used.
+ * config/rs6000/rs6000.c (rs6000_split_signbit): Likewise.
+ * config/rs6000/rs6000.md (signbit<mode>2): Change code for IEEE
+ 128-bit to produce an UNSPEC move to get the double word with the
+ signbit and then a shift directly to do signbit.
+ (signbit<mode>2_dm): Replace old IEEE 128-bit signbit
+ implementation with a new version that just does either a direct
+ move or a regular move. Move memory interface to separate insns.
+ Move insns so they are next to the expander.
+ (signbit<mode>2_dm_mem_be): New combiner insns to combine load
+ with signbit move. Split big and little endian case.
+ (signbit<mode>2_dm_mem_le): Likewise.
+ (signbit<mode>2_dm_<su>ext): Delete, no longer used.
+ (signbit<mode>2_dm2): Likewise.
+
+2018-01-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/81485
+ * config/sh/sh-protos.h (sh_find_set_of_reg): Remove assert.
+
+2018-01-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ Backport from mainline
+ 2018-01-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/80870
+ * config/sh/sh_optimize_sett_clrt.cc:
+ Use INCLUDE_ALGORITHM and INCLUDE_VECTOR instead of direct includes.
+
+2018-01-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ Backport from mainline
+ 2017-12-18 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/83424
+ * rtlanal.c (dead_or_set_regno_p): Handle CLOBBER just like SET.
+
2018-01-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Backport from mainline
@@ -100,7 +433,7 @@
* config/i386/i386.h: (host_detect_local_cpu): New define.
(TARGET_EMIT_VZEROUPPER): New.
* config/i386/x86-tune.def: Add X86_TUNE_EMIT_VZEROUPPER
-
+
2017-12-01 Segher Boessenkool <segher@kernel.crashing.org>
Backport from mainline
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index a384ad6e140..d326f67838d 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20180115
+20180307
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index aca3c23380f..67abd8fcf94 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,9 @@
+2018-03-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (convert_with_check): Fix typo in the condition
+ guarding the overflow check emitted for the upper bound of a floating-
+ point conversion.
+
2017-12-14 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_field): Do not set the alignment
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 8a4924c9f28..245994181f3 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -9215,7 +9215,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
? tree_int_cst_lt (gnu_out_ub, gnu_in_ub)
: (FLOAT_TYPE_P (gnu_base_type)
? real_less (&TREE_REAL_CST (gnu_out_ub),
- &TREE_REAL_CST (gnu_in_lb))
+ &TREE_REAL_CST (gnu_in_ub))
: 1))
gnu_cond
= build_binary_op (TRUTH_ORIF_EXPR, boolean_type_node, gnu_cond,
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 958cc4c5d21..5a81b48d300 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -315,6 +315,9 @@ public:
or abstract function kept for debug info purposes only. */
bool real_symbol_p (void);
+ /* Return true when the symbol needs to be output to the LTO symbol table. */
+ bool output_to_lto_symbol_table_p (void);
+
/* Determine if symbol declaration is needed. That is, visible to something
either outside this translation unit, something magic in the system
configury. This function is used just during symbol creation. */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 4170838b7dd..f3f55aa7ca9 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -5403,7 +5403,7 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode)
{
switch (regclass)
{
- case CALLER_SAVE_REGS:
+ case TAILCALL_ADDR_REGS:
case POINTER_REGS:
case GENERAL_REGS:
case ALL_REGS:
@@ -7481,10 +7481,10 @@ aarch64_register_move_cost (machine_mode mode,
= aarch64_tune_params.regmove_cost;
/* Caller save and pointer regs are equivalent to GENERAL_REGS. */
- if (to == CALLER_SAVE_REGS || to == POINTER_REGS)
+ if (to == TAILCALL_ADDR_REGS || to == POINTER_REGS)
to = GENERAL_REGS;
- if (from == CALLER_SAVE_REGS || from == POINTER_REGS)
+ if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS)
from = GENERAL_REGS;
/* Moving between GPR and stack cost is the same as GP2GP. */
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 5f268e2350f..42339b27def 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -439,7 +439,7 @@ extern unsigned aarch64_architecture_version;
enum reg_class
{
NO_REGS,
- CALLER_SAVE_REGS,
+ TAILCALL_ADDR_REGS,
GENERAL_REGS,
STACK_REG,
POINTER_REGS,
@@ -454,7 +454,7 @@ enum reg_class
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
- "CALLER_SAVE_REGS", \
+ "TAILCALL_ADDR_REGS", \
"GENERAL_REGS", \
"STACK_REG", \
"POINTER_REGS", \
@@ -466,7 +466,7 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x0007ffff, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \
+ { 0x0004ffff, 0x00000000, 0x00000000 }, /* TAILCALL_ADDR_REGS */\
{ 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \
{ 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index d64a7ebe36f..8c279cb62b3 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -21,8 +21,8 @@
(define_register_constraint "k" "STACK_REG"
"@internal The stack register.")
-(define_register_constraint "Ucs" "CALLER_SAVE_REGS"
- "@internal The caller save registers.")
+(define_register_constraint "Ucs" "TAILCALL_ADDR_REGS"
+ "@internal Registers suitable for an indirect tail call")
(define_register_constraint "w" "FP_REGS"
"Floating point and SIMD vector registers.")
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 2262005ae7a..16e80421f69 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1483,9 +1483,15 @@ output_init_frag (rtx sym)
if (sym)
{
- fprintf (asm_out_file, "generic(");
+ bool function = (SYMBOL_REF_DECL (sym)
+ && (TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL));
+ if (!function)
+ fprintf (asm_out_file, "generic(");
output_address (VOIDmode, sym);
- fprintf (asm_out_file, val ? ") + " : ")");
+ if (!function)
+ fprintf (asm_out_file, ")");
+ if (val)
+ fprintf (asm_out_file, " + ");
}
if (!sym || val)
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index b4f7a7113ff..2ac2025e89d 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -4565,13 +4565,17 @@ hppa_profile_hook (int label_no)
lcla2 and load_offset_label_address insn patterns. */
rtx reg = gen_reg_rtx (SImode);
rtx_code_label *label_rtx = gen_label_rtx ();
- rtx mcount = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "_mcount"));
int reg_parm_stack_space = REG_PARM_STACK_SPACE (NULL_TREE);
- rtx arg_bytes, begin_label_rtx;
+ rtx arg_bytes, begin_label_rtx, mcount, sym;
rtx_insn *call_insn;
char begin_label_name[16];
bool use_mcount_pcrel_call;
+ /* Set up call destination. */
+ sym = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
+ pa_encode_label (sym);
+ mcount = gen_rtx_MEM (Pmode, sym);
+
/* If we can reach _mcount with a pc-relative call, we can optimize
loading the address of the current function. This requires linker
long branch stub support. */
diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md
index 447a04c090b..225010cc52f 100644
--- a/gcc/config/pa/predicates.md
+++ b/gcc/config/pa/predicates.md
@@ -277,6 +277,9 @@
case HImode:
return true;
+ case VOIDmode:
+ return false;
+
default:
return (INTVAL (op) % GET_MODE_SIZE (mode)) == 0;
}
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index cbd197b9126..490000dcfe8 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -136,7 +136,6 @@ extern bool rs6000_emit_set_const (rtx, rtx);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
-extern void rs6000_split_signbit (rtx, rtx);
extern void rs6000_expand_atomic_compare_and_swap (rtx op[]);
extern void rs6000_expand_atomic_exchange (rtx op[]);
extern void rs6000_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 5ac2f832328..bfa1df042fe 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21343,7 +21343,7 @@ print_operand (FILE *file, rtx x, int code)
/* Fall through. Must be [reg+reg]. */
}
- if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x))
+ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (GET_MODE (x))
&& GET_CODE (tmp) == AND
&& GET_CODE (XEXP (tmp, 1)) == CONST_INT
&& INTVAL (XEXP (tmp, 1)) == -16)
@@ -23306,49 +23306,6 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target);
}
-/* Split a signbit operation on 64-bit machines with direct move. Also allow
- for the value to come from memory or if it is already loaded into a GPR. */
-
-void
-rs6000_split_signbit (rtx dest, rtx src)
-{
- machine_mode d_mode = GET_MODE (dest);
- machine_mode s_mode = GET_MODE (src);
- rtx dest_di = (d_mode == DImode) ? dest : gen_lowpart (DImode, dest);
- rtx shift_reg = dest_di;
-
- gcc_assert (FLOAT128_IEEE_P (s_mode) && TARGET_POWERPC64);
-
- if (MEM_P (src))
- {
- rtx mem = (WORDS_BIG_ENDIAN
- ? adjust_address (src, DImode, 0)
- : adjust_address (src, DImode, 8));
- emit_insn (gen_rtx_SET (dest_di, mem));
- }
-
- else
- {
- unsigned int r = reg_or_subregno (src);
-
- if (INT_REGNO_P (r))
- shift_reg = gen_rtx_REG (DImode, r + (BYTES_BIG_ENDIAN == 0));
-
- else
- {
- /* Generate the special mfvsrd instruction to get it in a GPR. */
- gcc_assert (VSX_REGNO_P (r));
- if (s_mode == KFmode)
- emit_insn (gen_signbitkf2_dm2 (dest_di, src));
- else
- emit_insn (gen_signbittf2_dm2 (dest_di, src));
- }
- }
-
- emit_insn (gen_lshrdi3 (dest_di, shift_reg, GEN_INT (63)));
- return;
-}
-
/* A subroutine of the atomic operation splitters. Jump to LABEL if
COND is true. Mark the jump as unlikely to be taken. */
@@ -29158,8 +29115,9 @@ rs6000_internal_arg_pointer (void)
emit_insn_after (pat, get_insns ());
pop_topmost_sequence ();
}
- return plus_constant (Pmode, cfun->machine->split_stack_arg_pointer,
- FIRST_PARM_OFFSET (current_function_decl));
+ rtx ret = plus_constant (Pmode, cfun->machine->split_stack_arg_pointer,
+ FIRST_PARM_OFFSET (current_function_decl));
+ return copy_to_reg (ret);
}
return virtual_incoming_args_rtx;
}
@@ -38508,6 +38466,38 @@ insn_is_swap_p (rtx insn)
return 1;
}
+/* Return 1 iff UID, known to reference a swap, is both fed by a load
+ and a feeder of a store. */
+static unsigned int
+swap_feeds_both_load_and_store (swap_web_entry *insn_entry)
+{
+ rtx insn = insn_entry->insn;
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref def, use;
+ struct df_link *link = 0;
+ rtx_insn *load = 0, *store = 0;
+ bool fed_by_load = 0;
+ bool feeds_store = 0;
+
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ link = DF_REF_CHAIN (use);
+ load = DF_REF_INSN (link->ref);
+ if (insn_is_load_p (load) && insn_is_swap_p (load))
+ fed_by_load = 1;
+ }
+
+ FOR_EACH_INSN_INFO_DEF (def, insn_info)
+ {
+ link = DF_REF_CHAIN (def);
+ store = DF_REF_INSN (link->ref);
+ if (insn_is_store_p (store) && insn_is_swap_p (store))
+ feeds_store = 1;
+ }
+
+ return fed_by_load && feeds_store;
+}
+
/* Return TRUE if insn is a swap fed by a load from the constant pool. */
static bool
const_load_sequence_p (swap_web_entry *insn_entry, rtx insn)
@@ -38706,6 +38696,7 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
{
default:
break;
+ case UNSPEC_VBPERMQ:
case UNSPEC_VMRGH_DIRECT:
case UNSPEC_VMRGL_DIRECT:
case UNSPEC_VPACK_SIGN_SIGN_SAT:
@@ -39664,6 +39655,14 @@ rs6000_analyze_swaps (function *fun)
&& !insn_entry[i].is_swap && !insn_entry[i].is_swappable)
root->web_not_optimizable = 1;
+ /* If we have a swap that is both fed by a permuting load
+ and a feeder of a permuting store, then the optimization
+ isn't appropriate. (Consider vec_xl followed by vec_xst_be.) */
+ else if (insn_entry[i].is_swap && !insn_entry[i].is_load
+ && !insn_entry[i].is_store
+ && swap_feeds_both_load_and_store (&insn_entry[i]))
+ root->web_not_optimizable = 1;
+
/* If we have permuting loads or stores that are not accompanied
by a register swap, the optimization isn't appropriate. */
else if (insn_entry[i].is_load && insn_entry[i].is_swap)
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 2ff61a23dd3..5cb37463cf6 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -535,7 +535,7 @@
(define_code_attr su [(sign_extend "s")
(zero_extend "u")
(fix "s")
- (unsigned_fix "s")
+ (unsigned_fix "u")
(float "s")
(unsigned_float "u")])
@@ -4556,12 +4556,19 @@
{
if (FLOAT128_IEEE_P (<MODE>mode))
{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx tmp = gen_reg_rtx (DImode);
+ rtx dest_di = gen_lowpart (DImode, dest);
+
if (<MODE>mode == KFmode)
- emit_insn (gen_signbitkf2_dm (operands[0], operands[1]));
+ emit_insn (gen_signbitkf2_dm (tmp, src));
else if (<MODE>mode == TFmode)
- emit_insn (gen_signbittf2_dm (operands[0], operands[1]));
+ emit_insn (gen_signbittf2_dm (tmp, src));
else
gcc_unreachable ();
+
+ emit_insn (gen_lshrdi3 (dest_di, tmp, GEN_INT (63)));
DONE;
}
operands[2] = gen_reg_rtx (DFmode);
@@ -4582,6 +4589,66 @@
}
})
+;; Optimize IEEE 128-bit signbit on 64-bit systems with direct move to avoid
+;; multiple direct moves. If we used a SUBREG:DI of the Floa128 type, the
+;; register allocator would typically move the entire _Float128 item to GPRs (2
+;; instructions on ISA 3.0, 3-4 instructions on ISA 2.07).
+;;
+;; After register allocation, if the _Float128 had originally been in GPRs, the
+;; split allows the post reload phases to eliminate the move, and do the shift
+;; directly with the register that contains the signbit.
+(define_insn_and_split "signbit<mode>2_dm"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa,r")]
+ UNSPEC_SIGNBIT))]
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "@
+ mfvsrd %0,%x1
+ #"
+ "&& reload_completed && int_reg_operand (operands[1], <MODE>mode)"
+ [(set (match_dup 0)
+ (match_dup 2))]
+{
+ operands[2] = gen_highpart (DImode, operands[1]);
+}
+ [(set_attr "type" "mftgpr,*")])
+
+;; Optimize IEEE 128-bit signbit on to avoid loading the value into a vector
+;; register and then doing a direct move if the value comes from memory. On
+;; little endian, we have to load the 2nd double-word to get the sign bit.
+(define_insn_and_split "*signbit<mode>2_dm_mem"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (unspec:DI [(match_operand:SIGNBIT 1 "memory_operand" "m")]
+ UNSPEC_SIGNBIT))]
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (match_dup 2))]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx addr = XEXP (src, 0);
+
+ if (WORDS_BIG_ENDIAN)
+ operands[2] = adjust_address (src, DImode, 0);
+
+ else if (REG_P (addr) || SUBREG_P (addr))
+ operands[2] = adjust_address (src, DImode, 8);
+
+ else if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0))
+ && CONST_INT_P (XEXP (addr, 1)) && mem_operand_gpr (src, DImode))
+ operands[2] = adjust_address (src, DImode, 8);
+
+ else
+ {
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx (DImode) : dest;
+ emit_insn (gen_rtx_SET (tmp, addr));
+ operands[2] = change_address (src, DImode,
+ gen_rtx_PLUS (DImode, tmp, GEN_INT (8)));
+ }
+})
+
(define_expand "copysign<mode>3"
[(set (match_dup 3)
(abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
@@ -4611,54 +4678,6 @@
operands[5] = CONST0_RTX (<MODE>mode);
})
-;; Optimize signbit on 64-bit systems with direct move to avoid doing the store
-;; and load.
-(define_insn_and_split "signbit<mode>2_dm"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
- (unspec:SI
- [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")]
- UNSPEC_SIGNBIT))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_signbit (operands[0], operands[1]);
- DONE;
-}
- [(set_attr "length" "8,8,4")
- (set_attr "type" "mftgpr,load,integer")])
-
-(define_insn_and_split "*signbit<mode>2_dm_<su>ext"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
- (any_extend:DI
- (unspec:SI
- [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")]
- UNSPEC_SIGNBIT)))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_signbit (operands[0], operands[1]);
- DONE;
-}
- [(set_attr "length" "8,8,4")
- (set_attr "type" "mftgpr,load,integer")])
-
-;; MODES_TIEABLE_P doesn't allow DImode to be tied with the various floating
-;; point types, which makes normal SUBREG's problematical. Instead use a
-;; special pattern to avoid using a normal movdi.
-(define_insn "signbit<mode>2_dm2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa")
- (const_int 0)]
- UNSPEC_SIGNBIT))]
- "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
- "mfvsrd %0,%x1"
- [(set_attr "type" "mftgpr")])
-
-
;; Use an unspec rather providing an if-then-else in RTL, to prevent the
;; compiler from optimizing -0.0
(define_insn "copysign<mode>3_fcpsgn"
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index d0715e951e6..ca8a702a7b9 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -298,7 +298,7 @@
;; VSX moves so they match first.
(define_insn_and_split "*vsx_le_perm_load_<mode>"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
- (match_operand:VSX_D 1 "memory_operand" "Z"))]
+ (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
@@ -321,7 +321,7 @@
(define_insn_and_split "*vsx_le_perm_load_<mode>"
[(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
- (match_operand:VSX_W 1 "memory_operand" "Z"))]
+ (match_operand:VSX_W 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
@@ -346,7 +346,7 @@
(define_insn_and_split "*vsx_le_perm_load_v8hi"
[(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
- (match_operand:V8HI 1 "memory_operand" "Z"))]
+ (match_operand:V8HI 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
@@ -375,7 +375,7 @@
(define_insn_and_split "*vsx_le_perm_load_v16qi"
[(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
- (match_operand:V16QI 1 "memory_operand" "Z"))]
+ (match_operand:V16QI 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
@@ -411,7 +411,7 @@
(set_attr "length" "8")])
(define_insn "*vsx_le_perm_store_<mode>"
- [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
+ [(set (match_operand:VSX_D 0 "indexed_or_indirect_operand" "=Z")
(match_operand:VSX_D 1 "vsx_register_operand" "+<VSa>"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -419,7 +419,7 @@
(set_attr "length" "12")])
(define_split
- [(set (match_operand:VSX_D 0 "memory_operand" "")
+ [(set (match_operand:VSX_D 0 "indexed_or_indirect_operand" "")
(match_operand:VSX_D 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
[(set (match_dup 2)
@@ -438,7 +438,7 @@
;; The post-reload split requires that we re-permute the source
;; register in case it is still live.
(define_split
- [(set (match_operand:VSX_D 0 "memory_operand" "")
+ [(set (match_operand:VSX_D 0 "indexed_or_indirect_operand" "")
(match_operand:VSX_D 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
[(set (match_dup 1)
@@ -456,7 +456,7 @@
"")
(define_insn "*vsx_le_perm_store_<mode>"
- [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+ [(set (match_operand:VSX_W 0 "indexed_or_indirect_operand" "=Z")
(match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -464,7 +464,7 @@
(set_attr "length" "12")])
(define_split
- [(set (match_operand:VSX_W 0 "memory_operand" "")
+ [(set (match_operand:VSX_W 0 "indexed_or_indirect_operand" "")
(match_operand:VSX_W 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
[(set (match_dup 2)
@@ -485,7 +485,7 @@
;; The post-reload split requires that we re-permute the source
;; register in case it is still live.
(define_split
- [(set (match_operand:VSX_W 0 "memory_operand" "")
+ [(set (match_operand:VSX_W 0 "indexed_or_indirect_operand" "")
(match_operand:VSX_W 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
[(set (match_dup 1)
@@ -506,7 +506,7 @@
"")
(define_insn "*vsx_le_perm_store_v8hi"
- [(set (match_operand:V8HI 0 "memory_operand" "=Z")
+ [(set (match_operand:V8HI 0 "indexed_or_indirect_operand" "=Z")
(match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -514,7 +514,7 @@
(set_attr "length" "12")])
(define_split
- [(set (match_operand:V8HI 0 "memory_operand" "")
+ [(set (match_operand:V8HI 0 "indexed_or_indirect_operand" "")
(match_operand:V8HI 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
[(set (match_dup 2)
@@ -539,7 +539,7 @@
;; The post-reload split requires that we re-permute the source
;; register in case it is still live.
(define_split
- [(set (match_operand:V8HI 0 "memory_operand" "")
+ [(set (match_operand:V8HI 0 "indexed_or_indirect_operand" "")
(match_operand:V8HI 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
[(set (match_dup 1)
@@ -566,7 +566,7 @@
"")
(define_insn "*vsx_le_perm_store_v16qi"
- [(set (match_operand:V16QI 0 "memory_operand" "=Z")
+ [(set (match_operand:V16QI 0 "indexed_or_indirect_operand" "=Z")
(match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -574,7 +574,7 @@
(set_attr "length" "12")])
(define_split
- [(set (match_operand:V16QI 0 "memory_operand" "")
+ [(set (match_operand:V16QI 0 "indexed_or_indirect_operand" "")
(match_operand:V16QI 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && !reload_completed"
[(set (match_dup 2)
@@ -607,7 +607,7 @@
;; The post-reload split requires that we re-permute the source
;; register in case it is still live.
(define_split
- [(set (match_operand:V16QI 0 "memory_operand" "")
+ [(set (match_operand:V16QI 0 "indexed_or_indirect_operand" "")
(match_operand:V16QI 1 "vsx_register_operand" ""))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR && reload_completed"
[(set (match_dup 1)
diff --git a/gcc/config/s390/s390-opts.h b/gcc/config/s390/s390-opts.h
index 0ad87a26985..063354d99a9 100644
--- a/gcc/config/s390/s390-opts.h
+++ b/gcc/config/s390/s390-opts.h
@@ -42,4 +42,13 @@ enum processor_type
PROCESSOR_max
};
+
+/* Values for -mindirect-branch and -mfunction-return options. */
+enum indirect_branch {
+ indirect_branch_unset = 0,
+ indirect_branch_keep,
+ indirect_branch_thunk,
+ indirect_branch_thunk_inline,
+ indirect_branch_thunk_extern
+};
#endif
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 2ccf0bbb0ab..236105cbd63 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -53,6 +53,7 @@ extern int s390_class_max_nregs (enum reg_class, machine_mode);
extern int s390_cannot_change_mode_class (machine_mode, machine_mode,
enum reg_class);
extern bool s390_function_arg_vector (machine_mode, const_tree);
+extern bool s390_return_addr_from_memory(void);
#if S390_USE_TARGET_ATTRIBUTE
extern tree s390_valid_target_attribute_tree (tree args,
struct gcc_options *opts,
@@ -146,6 +147,17 @@ extern int s390_compare_and_branch_condition_mask (rtx);
extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT);
extern void s390_asm_output_function_label (FILE *, const char *, tree);
+enum s390_indirect_branch_type
+ {
+ s390_indirect_branch_type_jump = 0,
+ s390_indirect_branch_type_call,
+ s390_indirect_branch_type_return
+ };
+extern void s390_indirect_branch_via_thunk (unsigned int regno,
+ unsigned int return_addr_regno,
+ rtx comparison_operator,
+ enum s390_indirect_branch_type type);
+extern void s390_indirect_branch_via_inline_thunk (rtx execute_target);
#endif /* RTX_CODE */
/* s390-c.c routines */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index ff566951d11..b061a680680 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -372,84 +372,6 @@ struct s390_address
bool literal_pool;
};
-/* The following structure is embedded in the machine
- specific part of struct function. */
-
-struct GTY (()) s390_frame_layout
-{
- /* Offset within stack frame. */
- HOST_WIDE_INT gprs_offset;
- HOST_WIDE_INT f0_offset;
- HOST_WIDE_INT f4_offset;
- HOST_WIDE_INT f8_offset;
- HOST_WIDE_INT backchain_offset;
-
- /* Number of first and last gpr where slots in the register
- save area are reserved for. */
- int first_save_gpr_slot;
- int last_save_gpr_slot;
-
- /* Location (FP register number) where GPRs (r0-r15) should
- be saved to.
- 0 - does not need to be saved at all
- -1 - stack slot */
-#define SAVE_SLOT_NONE 0
-#define SAVE_SLOT_STACK -1
- signed char gpr_save_slots[16];
-
- /* Number of first and last gpr to be saved, restored. */
- int first_save_gpr;
- int first_restore_gpr;
- int last_save_gpr;
- int last_restore_gpr;
-
- /* Bits standing for floating point registers. Set, if the
- respective register has to be saved. Starting with reg 16 (f0)
- at the rightmost bit.
- Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- fpr 15 13 11 9 14 12 10 8 7 5 3 1 6 4 2 0
- reg 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
- unsigned int fpr_bitmap;
-
- /* Number of floating point registers f8-f15 which must be saved. */
- int high_fprs;
-
- /* Set if return address needs to be saved.
- This flag is set by s390_return_addr_rtx if it could not use
- the initial value of r14 and therefore depends on r14 saved
- to the stack. */
- bool save_return_addr_p;
-
- /* Size of stack frame. */
- HOST_WIDE_INT frame_size;
-};
-
-/* Define the structure for the machine field in struct function. */
-
-struct GTY(()) machine_function
-{
- struct s390_frame_layout frame_layout;
-
- /* Literal pool base register. */
- rtx base_reg;
-
- /* True if we may need to perform branch splitting. */
- bool split_branches_pending_p;
-
- bool has_landing_pad_p;
-
- /* True if the current function may contain a tbegin clobbering
- FPRs. */
- bool tbegin_p;
-
- /* For -fsplit-stack support: A stack local which holds a pointer to
- the stack arguments for a function with a variable number of
- arguments. This is set at the start of the function and is used
- to initialize the overflow_arg_area field of the va_list
- structure. */
- rtx split_stack_varargs_pointer;
-};
-
/* Few accessor macros for struct cfun->machine->s390_frame_layout. */
#define cfun_frame_layout (cfun->machine->frame_layout)
@@ -490,6 +412,33 @@ struct GTY(()) machine_function
bytes on a z10 (or higher) CPU. */
#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
+/* Masks per jump target register indicating which thunk need to be
+ generated. */
+static GTY(()) int indirect_branch_prez10thunk_mask = 0;
+static GTY(()) int indirect_branch_z10thunk_mask = 0;
+
+#define INDIRECT_BRANCH_NUM_OPTIONS 4
+
+enum s390_indirect_branch_option
+ {
+ s390_opt_indirect_branch_jump = 0,
+ s390_opt_indirect_branch_call,
+ s390_opt_function_return_reg,
+ s390_opt_function_return_mem
+ };
+
+static GTY(()) int indirect_branch_table_label_no[INDIRECT_BRANCH_NUM_OPTIONS] = { 0 };
+const char *indirect_branch_table_label[INDIRECT_BRANCH_NUM_OPTIONS] = \
+ { "LJUMP", "LCALL", "LRETREG", "LRETMEM" };
+const char *indirect_branch_table_name[INDIRECT_BRANCH_NUM_OPTIONS] = \
+ { ".s390_indirect_jump", ".s390_indirect_call",
+ ".s390_return_reg", ".s390_return_mem" };
+
+bool
+s390_return_addr_from_memory ()
+{
+ return cfun_gpr_save_slot(RETURN_REGNUM) == SAVE_SLOT_STACK;
+}
/* Indicate which ABI has been used for passing vector args.
0 - no vector type arguments have been passed where the ABI is relevant
@@ -1124,9 +1073,83 @@ s390_handle_vectorbool_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
return NULL_TREE;
}
+/* Check syntax of function decl attributes having a string type value. */
+
+static tree
+s390_handle_string_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
+{
+ tree cst;
+
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+
+ cst = TREE_VALUE (args);
+
+ if (TREE_CODE (cst) != STRING_CST)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute requires a string constant argument",
+ name);
+ *no_add_attrs = true;
+ }
+
+ if (is_attribute_p ("indirect_branch", name)
+ || is_attribute_p ("indirect_branch_call", name)
+ || is_attribute_p ("function_return", name)
+ || is_attribute_p ("function_return_reg", name)
+ || is_attribute_p ("function_return_mem", name))
+ {
+ if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
+ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
+ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
+ {
+ warning (OPT_Wattributes,
+ "argument to %qE attribute is not "
+ "(keep|thunk|thunk-extern)", name);
+ *no_add_attrs = true;
+ }
+ }
+
+ if (is_attribute_p ("indirect_branch_jump", name)
+ && strcmp (TREE_STRING_POINTER (cst), "keep") != 0
+ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
+ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
+ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
+ {
+ warning (OPT_Wattributes,
+ "argument to %qE attribute is not "
+ "(keep|thunk|thunk-inline|thunk-extern)", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
static const struct attribute_spec s390_attribute_table[] = {
- { "hotpatch", 2, 2, true, false, false, s390_handle_hotpatch_attribute, false },
- { "s390_vector_bool", 0, 0, false, true, false, s390_handle_vectorbool_attribute, true },
+ { "hotpatch", 2, 2, true, false, false,
+ s390_handle_hotpatch_attribute, false },
+ { "s390_vector_bool", 0, 0, false, true, false,
+ s390_handle_vectorbool_attribute, true },
+ { "indirect_branch", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+ { "indirect_branch_jump", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+ { "indirect_branch_call", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+ { "function_return", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+ { "function_return_reg", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+ { "function_return_mem", 1, 1, true, false, false,
+ s390_handle_string_attribute, false },
+
/* End element. */
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -8266,11 +8289,25 @@ s390_find_constant (struct constant_pool *pool, rtx val,
static rtx
s390_execute_label (rtx insn)
{
- if (NONJUMP_INSN_P (insn)
+ if (INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == PARALLEL
&& GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
- && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
- return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
+ && (XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE
+ || XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE_JUMP))
+ {
+ if (XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
+ return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
+ else
+ {
+ gcc_assert (JUMP_P (insn));
+ /* For jump insns as execute target:
+ - There is one operand less in the parallel (the
+ modification register of the execute is always 0).
+ - The execute target label is wrapped into an
+ if_then_else in order to hide it from jump analysis. */
+ return XEXP (XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 0), 0);
+ }
+ }
return NULL_RTX;
}
@@ -10942,7 +10979,6 @@ s390_emit_epilogue (bool sibcall)
rtx frame_pointer, return_reg, cfa_restores = NULL_RTX;
int area_bottom, area_top, offset = 0;
int next_offset;
- rtvec p;
int i;
if (TARGET_TPF_PROFILING)
@@ -11096,10 +11132,15 @@ s390_emit_epilogue (bool sibcall)
if (cfun_gpr_save_slot (RETURN_REGNUM) == SAVE_SLOT_STACK)
{
int return_regnum = find_unused_clobbered_reg();
- if (!return_regnum)
- return_regnum = 4;
+ if (!return_regnum
+ || (TARGET_INDIRECT_BRANCH_NOBP_RET_OPTION
+ && !TARGET_CPU_Z10
+ && return_regnum == INDIRECT_BRANCH_THUNK_REGNUM))
+ {
+ gcc_assert (INDIRECT_BRANCH_THUNK_REGNUM != 4);
+ return_regnum = 4;
+ }
return_reg = gen_rtx_REG (Pmode, return_regnum);
-
addr = plus_constant (Pmode, frame_pointer,
offset + cfun_frame_layout.gprs_offset
+ (RETURN_REGNUM
@@ -11135,16 +11176,7 @@ s390_emit_epilogue (bool sibcall)
s390_restore_gprs_from_fprs ();
if (! sibcall)
- {
-
- /* Return to caller. */
-
- p = rtvec_alloc (2);
-
- RTVEC_ELT (p, 0) = ret_rtx;
- RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
- }
+ emit_jump_insn (gen_return_use (return_reg));
}
/* Implement TARGET_SET_UP_BY_PROLOGUE. */
@@ -12722,6 +12754,112 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
final_end_function ();
}
+/* Output either an indirect jump or a an indirect call
+ (RETURN_ADDR_REGNO != INVALID_REGNUM) with target register REGNO
+ using a branch trampoline disabling branch target prediction. */
+
+void
+s390_indirect_branch_via_thunk (unsigned int regno,
+ unsigned int return_addr_regno,
+ rtx comparison_operator,
+ enum s390_indirect_branch_type type)
+{
+ enum s390_indirect_branch_option option;
+
+ if (type == s390_indirect_branch_type_return)
+ {
+ if (s390_return_addr_from_memory ())
+ option = s390_opt_function_return_mem;
+ else
+ option = s390_opt_function_return_reg;
+ }
+ else if (type == s390_indirect_branch_type_jump)
+ option = s390_opt_indirect_branch_jump;
+ else if (type == s390_indirect_branch_type_call)
+ option = s390_opt_indirect_branch_call;
+ else
+ gcc_unreachable ();
+
+ if (TARGET_INDIRECT_BRANCH_TABLE)
+ {
+ char label[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (label,
+ indirect_branch_table_label[option],
+ indirect_branch_table_label_no[option]++);
+ ASM_OUTPUT_LABEL (asm_out_file, label);
+ }
+
+ if (return_addr_regno != INVALID_REGNUM)
+ {
+ gcc_assert (comparison_operator == NULL_RTX);
+ fprintf (asm_out_file, " \tbrasl\t%%r%d,", return_addr_regno);
+ }
+ else
+ {
+ fputs (" \tjg", asm_out_file);
+ if (comparison_operator != NULL_RTX)
+ print_operand (asm_out_file, comparison_operator, 'C');
+
+ fputs ("\t", asm_out_file);
+ }
+
+ if (TARGET_CPU_Z10)
+ fprintf (asm_out_file,
+ TARGET_INDIRECT_BRANCH_THUNK_NAME_EXRL "\n",
+ regno);
+ else
+ fprintf (asm_out_file,
+ TARGET_INDIRECT_BRANCH_THUNK_NAME_EX "\n",
+ INDIRECT_BRANCH_THUNK_REGNUM, regno);
+
+ if ((option == s390_opt_indirect_branch_jump
+ && cfun->machine->indirect_branch_jump == indirect_branch_thunk)
+ || (option == s390_opt_indirect_branch_call
+ && cfun->machine->indirect_branch_call == indirect_branch_thunk)
+ || (option == s390_opt_function_return_reg
+ && cfun->machine->function_return_reg == indirect_branch_thunk)
+ || (option == s390_opt_function_return_mem
+ && cfun->machine->function_return_mem == indirect_branch_thunk))
+ {
+ if (TARGET_CPU_Z10)
+ indirect_branch_z10thunk_mask |= (1 << regno);
+ else
+ indirect_branch_prez10thunk_mask |= (1 << regno);
+ }
+}
+
+/* Output an inline thunk for indirect jumps. EXECUTE_TARGET can
+ either be an address register or a label pointing to the location
+ of the jump instruction. */
+
+void
+s390_indirect_branch_via_inline_thunk (rtx execute_target)
+{
+ if (TARGET_INDIRECT_BRANCH_TABLE)
+ {
+ char label[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (label,
+ indirect_branch_table_label[s390_opt_indirect_branch_jump],
+ indirect_branch_table_label_no[s390_opt_indirect_branch_jump]++);
+ ASM_OUTPUT_LABEL (asm_out_file, label);
+ }
+
+ if (!TARGET_ZARCH)
+ fputs ("\t.machinemode zarch\n", asm_out_file);
+
+ if (REG_P (execute_target))
+ fprintf (asm_out_file, "\tex\t%%r0,0(%%r%d)\n", REGNO (execute_target));
+ else
+ output_asm_insn ("exrl\t%%r0,%0", &execute_target);
+
+ if (!TARGET_ZARCH)
+ fputs ("\t.machinemode esa\n", asm_out_file);
+
+ fputs ("0:\tj\t0b\n", asm_out_file);
+}
+
static bool
s390_valid_pointer_mode (machine_mode mode)
{
@@ -12827,6 +12965,14 @@ s390_function_ok_for_sibcall (tree decl, tree exp)
if (!TARGET_64BIT && flag_pic && decl && !targetm.binds_local_p (decl))
return false;
+ /* The thunks for indirect branches require r1 if no exrl is
+ available. r1 might not be available when doing a sibling
+ call. */
+ if (TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && !TARGET_CPU_Z10
+ && !decl)
+ return false;
+
/* Register 6 on s390 is available as an argument register but unfortunately
"caller saved". This makes functions needing this register for arguments
not suitable for sibcalls. */
@@ -12860,9 +13006,13 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
{
bool plt_call = false;
rtx_insn *insn;
- rtx call;
- rtx clobber;
- rtvec vec;
+ rtx vec[4] = { NULL_RTX };
+ int elts = 0;
+ rtx *call = &vec[0];
+ rtx *clobber_ret_reg = &vec[1];
+ rtx *use = &vec[2];
+ rtx *clobber_thunk_reg = &vec[3];
+ int i;
/* Direct function calls need special treatment. */
if (GET_CODE (addr_location) == SYMBOL_REF)
@@ -12914,26 +13064,58 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM);
}
+ if (TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && GET_CODE (addr_location) != SYMBOL_REF
+ && !plt_call)
+ {
+ /* Indirect branch thunks require the target to be a single GPR. */
+ addr_location = force_reg (Pmode, addr_location);
+
+ /* Without exrl the indirect branch thunks need an additional
+ register for larl;ex */
+ if (!TARGET_CPU_Z10)
+ {
+ *clobber_thunk_reg = gen_rtx_REG (Pmode, INDIRECT_BRANCH_THUNK_REGNUM);
+ *clobber_thunk_reg = gen_rtx_CLOBBER (VOIDmode, *clobber_thunk_reg);
+ }
+ }
+
addr_location = gen_rtx_MEM (QImode, addr_location);
- call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
+ *call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
if (result_reg != NULL_RTX)
- call = gen_rtx_SET (result_reg, call);
+ *call = gen_rtx_SET (result_reg, *call);
if (retaddr_reg != NULL_RTX)
{
- clobber = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
+ *clobber_ret_reg = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
if (tls_call != NULL_RTX)
- vec = gen_rtvec (3, call, clobber,
- gen_rtx_USE (VOIDmode, tls_call));
- else
- vec = gen_rtvec (2, call, clobber);
+ *use = gen_rtx_USE (VOIDmode, tls_call);
+ }
+
+
+ for (i = 0; i < 4; i++)
+ if (vec[i] != NULL_RTX)
+ elts++;
+
+ if (elts > 1)
+ {
+ rtvec v;
+ int e = 0;
+
+ v = rtvec_alloc (elts);
+ for (i = 0; i < 4; i++)
+ if (vec[i] != NULL_RTX)
+ {
+ RTVEC_ELT (v, e) = vec[i];
+ e++;
+ }
- call = gen_rtx_PARALLEL (VOIDmode, vec);
+ *call = gen_rtx_PARALLEL (VOIDmode, v);
}
- insn = emit_call_insn (call);
+ insn = emit_call_insn (*call);
/* 31-bit PLT stubs and tls calls use the GOT register implicitly. */
if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX)
@@ -13563,7 +13745,16 @@ s390_reorg (void)
target = emit_label (XEXP (label, 0));
INSN_ADDRESSES_NEW (target, -1);
- target = emit_insn (s390_execute_target (insn));
+ if (JUMP_P (insn))
+ {
+ target = emit_jump_insn (s390_execute_target (insn));
+ /* This is important in order to keep a table jump
+ pointing at the jump table label. Only this makes it
+ being recognized as table jump. */
+ JUMP_LABEL (target) = JUMP_LABEL (insn);
+ }
+ else
+ target = emit_insn (s390_execute_target (insn));
INSN_ADDRESSES_NEW (target, -1);
}
}
@@ -14213,6 +14404,42 @@ s390_option_override_internal (bool main_args_p,
if (TARGET_64BIT && !TARGET_ZARCH_P (opts->x_target_flags))
error ("64-bit ABI not supported in ESA/390 mode");
+ if (opts->x_s390_indirect_branch == indirect_branch_thunk_inline
+ || opts->x_s390_indirect_branch_call == indirect_branch_thunk_inline
+ || opts->x_s390_function_return == indirect_branch_thunk_inline
+ || opts->x_s390_function_return_reg == indirect_branch_thunk_inline
+ || opts->x_s390_function_return_mem == indirect_branch_thunk_inline)
+ error ("thunk-inline is only supported with -mindirect-branch-jump");
+
+ if (opts->x_s390_indirect_branch != indirect_branch_keep)
+ {
+ if (!opts_set->x_s390_indirect_branch_call)
+ opts->x_s390_indirect_branch_call = opts->x_s390_indirect_branch;
+
+ if (!opts_set->x_s390_indirect_branch_jump)
+ opts->x_s390_indirect_branch_jump = opts->x_s390_indirect_branch;
+ }
+
+ if (opts->x_s390_function_return != indirect_branch_keep)
+ {
+ if (!opts_set->x_s390_function_return_reg)
+ opts->x_s390_function_return_reg = opts->x_s390_function_return;
+
+ if (!opts_set->x_s390_function_return_mem)
+ opts->x_s390_function_return_mem = opts->x_s390_function_return;
+ }
+
+ if (!TARGET_CPU_ZARCH)
+ {
+ if (opts->x_s390_indirect_branch_call != indirect_branch_keep
+ || opts->x_s390_indirect_branch_jump != indirect_branch_keep)
+ error ("-mindirect-branch* options require -march=z900 or higher");
+ if (opts->x_s390_function_return_reg != indirect_branch_keep
+ || opts->x_s390_function_return_mem != indirect_branch_keep)
+ error ("-mfunction-return* options require -march=z900 or higher");
+ }
+
+
/* Enable hardware transactions if available and not explicitly
disabled by user. E.g. with -m31 -march=zEC12 -mzarch */
if (!TARGET_OPT_HTM_P (opts_set->x_target_flags))
@@ -14777,6 +15004,79 @@ s390_valid_target_attribute_p (tree fndecl,
return ret;
}
+/* Set VAL to correct enum value according to the indirect-branch or
+ function-return attribute in ATTR. */
+
+static inline void
+s390_indirect_branch_attrvalue (tree attr, enum indirect_branch *val)
+{
+ const char *str = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+ if (strcmp (str, "keep") == 0)
+ *val = indirect_branch_keep;
+ else if (strcmp (str, "thunk") == 0)
+ *val = indirect_branch_thunk;
+ else if (strcmp (str, "thunk-inline") == 0)
+ *val = indirect_branch_thunk_inline;
+ else if (strcmp (str, "thunk-extern") == 0)
+ *val = indirect_branch_thunk_extern;
+}
+
+/* Memorize the setting for -mindirect-branch* and -mfunction-return*
+ from either the cmdline or the function attributes in
+ cfun->machine. */
+
+static void
+s390_indirect_branch_settings (tree fndecl)
+{
+ tree attr;
+
+ if (!fndecl)
+ return;
+
+ /* Initialize with the cmdline options and let the attributes
+ override it. */
+ cfun->machine->indirect_branch_jump = s390_indirect_branch_jump;
+ cfun->machine->indirect_branch_call = s390_indirect_branch_call;
+
+ cfun->machine->function_return_reg = s390_function_return_reg;
+ cfun->machine->function_return_mem = s390_function_return_mem;
+
+ if ((attr = lookup_attribute ("indirect_branch",
+ DECL_ATTRIBUTES (fndecl))))
+ {
+ s390_indirect_branch_attrvalue (attr,
+ &cfun->machine->indirect_branch_jump);
+ s390_indirect_branch_attrvalue (attr,
+ &cfun->machine->indirect_branch_call);
+ }
+
+ if ((attr = lookup_attribute ("indirect_branch_jump",
+ DECL_ATTRIBUTES (fndecl))))
+ s390_indirect_branch_attrvalue (attr, &cfun->machine->indirect_branch_jump);
+
+ if ((attr = lookup_attribute ("indirect_branch_call",
+ DECL_ATTRIBUTES (fndecl))))
+ s390_indirect_branch_attrvalue (attr, &cfun->machine->indirect_branch_call);
+
+ if ((attr = lookup_attribute ("function_return",
+ DECL_ATTRIBUTES (fndecl))))
+ {
+ s390_indirect_branch_attrvalue (attr,
+ &cfun->machine->function_return_reg);
+ s390_indirect_branch_attrvalue (attr,
+ &cfun->machine->function_return_mem);
+ }
+
+ if ((attr = lookup_attribute ("function_return_reg",
+ DECL_ATTRIBUTES (fndecl))))
+ s390_indirect_branch_attrvalue (attr, &cfun->machine->function_return_reg);
+
+ if ((attr = lookup_attribute ("function_return_mem",
+ DECL_ATTRIBUTES (fndecl))))
+ s390_indirect_branch_attrvalue (attr, &cfun->machine->function_return_mem);
+}
+
+
/* Restore targets globals from NEW_TREE and invalidate s390_previous_fndecl
cache. */
@@ -14803,7 +15103,10 @@ s390_set_current_function (tree fndecl)
several times in the course of compiling a function, and we don't want to
slow things down too much or call target_reinit when it isn't safe. */
if (fndecl == s390_previous_fndecl)
- return;
+ {
+ s390_indirect_branch_settings (fndecl);
+ return;
+ }
tree old_tree;
if (s390_previous_fndecl == NULL_TREE)
@@ -14827,6 +15130,8 @@ s390_set_current_function (tree fndecl)
if (old_tree != new_tree)
s390_activate_target_options (new_tree);
s390_previous_fndecl = fndecl;
+
+ s390_indirect_branch_settings (fndecl);
}
#endif
@@ -15062,6 +15367,186 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
return NULL;
}
+#ifdef HAVE_GAS_HIDDEN
+# define USE_HIDDEN_LINKONCE 1
+#else
+# define USE_HIDDEN_LINKONCE 0
+#endif
+
+/* Output an indirect branch trampoline for target register REGNO. */
+
+static void
+s390_output_indirect_thunk_function (unsigned int regno, bool z10_p)
+{
+ tree decl;
+ char thunk_label[32];
+ int i;
+
+ if (z10_p)
+ sprintf (thunk_label, TARGET_INDIRECT_BRANCH_THUNK_NAME_EXRL, regno);
+ else
+ sprintf (thunk_label, TARGET_INDIRECT_BRANCH_THUNK_NAME_EX,
+ INDIRECT_BRANCH_THUNK_REGNUM, regno);
+
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (thunk_label),
+ build_function_type_list (void_type_node, NULL_TREE));
+ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
+ NULL_TREE, void_type_node);
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+
+ if (USE_HIDDEN_LINKONCE)
+ {
+ cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
+
+ targetm.asm_out.unique_section (decl, 0);
+ switch_to_section (get_named_section (decl, NULL, 0));
+
+ targetm.asm_out.globalize_label (asm_out_file, thunk_label);
+ fputs ("\t.hidden\t", asm_out_file);
+ assemble_name (asm_out_file, thunk_label);
+ putc ('\n', asm_out_file);
+ ASM_DECLARE_FUNCTION_NAME (asm_out_file, thunk_label, decl);
+ }
+ else
+ {
+ switch_to_section (text_section);
+ ASM_OUTPUT_LABEL (asm_out_file, thunk_label);
+ }
+
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ allocate_struct_function (decl, false);
+ init_function_start (decl);
+ cfun->is_thunk = true;
+ first_function_block_is_cold = false;
+ final_start_function (emit_barrier (), asm_out_file, 1);
+
+ /* This makes CFI at least usable for indirect jumps.
+
+ Stopping in the thunk: backtrace will point to the thunk target
+ is if it was interrupted by a signal. For a call this means that
+ the call chain will be: caller->callee->thunk */
+ if (flag_asynchronous_unwind_tables)
+ {
+ fputs ("\t.cfi_signal_frame\n", asm_out_file);
+ fprintf (asm_out_file, "\t.cfi_return_column %d\n", regno);
+ for (i = 0; i < FPR15_REGNUM; i++)
+ fprintf (asm_out_file, "\t.cfi_same_value %s\n", reg_names[i]);
+ }
+
+ if (z10_p)
+ {
+ /* exrl 0,1f */
+
+ /* We generate a thunk for z10 compiled code although z10 is
+ currently not enabled. Tell the assembler to accept the
+ instruction. */
+ if (!TARGET_CPU_Z10)
+ {
+ fputs ("\t.machine push\n", asm_out_file);
+ fputs ("\t.machine z10\n", asm_out_file);
+ }
+ /* We use exrl even if -mzarch hasn't been specified on the
+ command line so we have to tell the assembler to accept
+ it. */
+ if (!TARGET_ZARCH)
+ fputs ("\t.machinemode zarch\n", asm_out_file);
+
+ fputs ("\texrl\t0,1f\n", asm_out_file);
+
+ if (!TARGET_ZARCH)
+ fputs ("\t.machinemode esa\n", asm_out_file);
+
+ if (!TARGET_CPU_Z10)
+ fputs ("\t.machine pop\n", asm_out_file);
+ }
+ else if (TARGET_CPU_ZARCH)
+ {
+ /* larl %r1,1f */
+ fprintf (asm_out_file, "\tlarl\t%%r%d,1f\n",
+ INDIRECT_BRANCH_THUNK_REGNUM);
+
+ /* ex 0,0(%r1) */
+ fprintf (asm_out_file, "\tex\t0,0(%%r%d)\n",
+ INDIRECT_BRANCH_THUNK_REGNUM);
+ }
+ else
+ gcc_unreachable ();
+
+ /* 0: j 0b */
+ fputs ("0:\tj\t0b\n", asm_out_file);
+
+ /* 1: br <regno> */
+ fprintf (asm_out_file, "1:\tbr\t%%r%d\n", regno);
+
+ final_end_function ();
+ init_insn_lengths ();
+ free_after_compilation (cfun);
+ set_cfun (NULL);
+ current_function_decl = NULL;
+}
+
+/* Implement the asm.code_end target hook. */
+
+static void
+s390_code_end (void)
+{
+ int i;
+
+ for (i = 1; i < 16; i++)
+ {
+ if (indirect_branch_z10thunk_mask & (1 << i))
+ s390_output_indirect_thunk_function (i, true);
+
+ if (indirect_branch_prez10thunk_mask & (1 << i))
+ s390_output_indirect_thunk_function (i, false);
+ }
+
+ if (TARGET_INDIRECT_BRANCH_TABLE)
+ {
+ int o;
+ int i;
+
+ for (o = 0; o < INDIRECT_BRANCH_NUM_OPTIONS; o++)
+ {
+ if (indirect_branch_table_label_no[o] == 0)
+ continue;
+
+ switch_to_section (get_section (indirect_branch_table_name[o],
+ 0,
+ NULL_TREE));
+ for (i = 0; i < indirect_branch_table_label_no[o]; i++)
+ {
+ char label_start[32];
+
+ ASM_GENERATE_INTERNAL_LABEL (label_start,
+ indirect_branch_table_label[o], i);
+
+ fputs ("\t.long\t", asm_out_file);
+ assemble_name_raw (asm_out_file, label_start);
+ fputs ("-.\n", asm_out_file);
+ }
+ switch_to_section (current_function_section ());
+ }
+ }
+}
+
+/* Implement the TARGET_CASE_VALUES_THRESHOLD target hook. */
+
+unsigned int
+s390_case_values_threshold (void)
+{
+ /* Disabling branch prediction for indirect jumps makes jump tables
+ much more expensive. */
+ if (TARGET_INDIRECT_BRANCH_NOBP_JUMP)
+ return 20;
+
+ return default_case_values_threshold ();
+}
+
/* Initialize GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -15301,6 +15786,12 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE s390_function_specific_restore
+#undef TARGET_ASM_CODE_END
+#define TARGET_ASM_CODE_END s390_code_end
+
+#undef TARGET_CASE_VALUES_THRESHOLD
+#define TARGET_CASE_VALUES_THRESHOLD s390_case_values_threshold
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 3a7be1af779..9a49cdb2f00 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1094,4 +1094,124 @@ extern const int processor_flags_table[];
s390_register_target_pragmas (); \
} while (0)
+#ifndef USED_FOR_TARGET
+/* The following structure is embedded in the machine
+ specific part of struct function. */
+
+struct GTY (()) s390_frame_layout
+{
+ /* Offset within stack frame. */
+ HOST_WIDE_INT gprs_offset;
+ HOST_WIDE_INT f0_offset;
+ HOST_WIDE_INT f4_offset;
+ HOST_WIDE_INT f8_offset;
+ HOST_WIDE_INT backchain_offset;
+
+ /* Number of first and last gpr where slots in the register
+ save area are reserved for. */
+ int first_save_gpr_slot;
+ int last_save_gpr_slot;
+
+ /* Location (FP register number) where GPRs (r0-r15) should
+ be saved to.
+ 0 - does not need to be saved at all
+ -1 - stack slot */
+#define SAVE_SLOT_NONE 0
+#define SAVE_SLOT_STACK -1
+ signed char gpr_save_slots[16];
+
+ /* Number of first and last gpr to be saved, restored. */
+ int first_save_gpr;
+ int first_restore_gpr;
+ int last_save_gpr;
+ int last_restore_gpr;
+
+ /* Bits standing for floating point registers. Set, if the
+ respective register has to be saved. Starting with reg 16 (f0)
+ at the rightmost bit.
+ Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ fpr 15 13 11 9 14 12 10 8 7 5 3 1 6 4 2 0
+ reg 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
+ unsigned int fpr_bitmap;
+
+ /* Number of floating point registers f8-f15 which must be saved. */
+ int high_fprs;
+
+ /* Set if return address needs to be saved.
+ This flag is set by s390_return_addr_rtx if it could not use
+ the initial value of r14 and therefore depends on r14 saved
+ to the stack. */
+ bool save_return_addr_p;
+
+ /* Size of stack frame. */
+ HOST_WIDE_INT frame_size;
+};
+
+
+/* Define the structure for the machine field in struct function. */
+
+struct GTY(()) machine_function
+{
+ struct s390_frame_layout frame_layout;
+
+ /* Literal pool base register. */
+ rtx base_reg;
+
+ /* True if we may need to perform branch splitting. */
+ bool split_branches_pending_p;
+
+ bool has_landing_pad_p;
+
+ /* True if the current function may contain a tbegin clobbering
+ FPRs. */
+ bool tbegin_p;
+
+ /* For -fsplit-stack support: A stack local which holds a pointer to
+ the stack arguments for a function with a variable number of
+ arguments. This is set at the start of the function and is used
+ to initialize the overflow_arg_area field of the va_list
+ structure. */
+ rtx split_stack_varargs_pointer;
+
+ enum indirect_branch indirect_branch_jump;
+ enum indirect_branch indirect_branch_call;
+
+ enum indirect_branch function_return_mem;
+ enum indirect_branch function_return_reg;
+};
+#endif
+
+#define TARGET_INDIRECT_BRANCH_NOBP_RET_OPTION \
+ (cfun->machine->function_return_reg != indirect_branch_keep \
+ || cfun->machine->function_return_mem != indirect_branch_keep)
+
+#define TARGET_INDIRECT_BRANCH_NOBP_RET \
+ ((cfun->machine->function_return_reg != indirect_branch_keep \
+ && !s390_return_addr_from_memory ()) \
+ || (cfun->machine->function_return_mem != indirect_branch_keep \
+ && s390_return_addr_from_memory ()))
+
+#define TARGET_INDIRECT_BRANCH_NOBP_JUMP \
+ (cfun->machine->indirect_branch_jump != indirect_branch_keep)
+
+#define TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK \
+ (cfun->machine->indirect_branch_jump == indirect_branch_thunk \
+ || cfun->machine->indirect_branch_jump == indirect_branch_thunk_extern)
+
+#define TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK \
+ (cfun->machine->indirect_branch_jump == indirect_branch_thunk_inline)
+
+#define TARGET_INDIRECT_BRANCH_NOBP_CALL \
+ (cfun->machine->indirect_branch_call != indirect_branch_keep)
+
+#ifndef TARGET_DEFAULT_INDIRECT_BRANCH_TABLE
+#define TARGET_DEFAULT_INDIRECT_BRANCH_TABLE 0
+#endif
+
+#define TARGET_INDIRECT_BRANCH_THUNK_NAME_EXRL "__s390_indirect_jump_r%d"
+#define TARGET_INDIRECT_BRANCH_THUNK_NAME_EX "__s390_indirect_jump_r%duse_r%d"
+
+#define TARGET_INDIRECT_BRANCH_TABLE s390_indirect_branch_table
+
+
#endif /* S390_H */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index dfc8698ebfe..928dec64782 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -89,6 +89,7 @@
UNSPEC_LTREF
UNSPEC_INSN
UNSPEC_EXECUTE
+ UNSPEC_EXECUTE_JUMP
; Atomic Support
UNSPEC_MB
@@ -292,6 +293,8 @@
[
; Sibling call register.
(SIBCALL_REGNUM 1)
+ ; A call-clobbered reg which can be used in indirect branch thunks
+ (INDIRECT_BRANCH_THUNK_REGNUM 1)
; Literal pool base register.
(BASE_REGNUM 13)
; Return address register.
@@ -461,7 +464,10 @@
z196_cracked"
(const_string "none"))
-(define_attr "mnemonic" "bcr_flush,unknown" (const_string "unknown"))
+; mnemonics which only get defined through if_then_else currently
+; don't get added to the list values automatically and hence need to
+; be listed here.
+(define_attr "mnemonic" "b,br,bas,bc,bcr,bcr_flush,unknown" (const_string "unknown"))
;; Length in bytes.
@@ -8631,7 +8637,7 @@
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(match_operand 0 "address_operand" "ZQZR")
(pc)))]
- ""
+ "!TARGET_INDIRECT_BRANCH_NOBP_JUMP"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "b%C1r\t%0";
@@ -8641,6 +8647,9 @@
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "bcr") (const_string "bc")))
(set_attr "type" "branch")
(set_attr "atype" "agen")])
@@ -8652,8 +8661,26 @@
(ANY_RETURN)
(pc)))]
"s390_can_use_<code>_insn ()"
- "b%C0r\t%%r14"
- [(set_attr "op_type" "RR")
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_RET)
+ {
+ s390_indirect_branch_via_thunk (RETURN_REGNUM,
+ INVALID_REGNUM,
+ operands[0],
+ s390_indirect_branch_type_return);
+ return "";
+ }
+ else
+ return "b%C0r\t%%r14";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "brcl")
+ (const_string "bcr")))
(set_attr "type" "jsr")
(set_attr "atype" "agen")])
@@ -8706,7 +8733,7 @@
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(pc)
(match_operand 0 "address_operand" "ZQZR")))]
- ""
+ "!TARGET_INDIRECT_BRANCH_NOBP_JUMP"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "b%D1r\t%0";
@@ -8716,6 +8743,9 @@
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "bcr") (const_string "bc")))
(set_attr "type" "branch")
(set_attr "atype" "agen")])
@@ -9208,30 +9238,220 @@
; indirect-jump instruction pattern(s).
;
-(define_insn "indirect_jump"
+(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "address_operand" "ZQZR"))]
""
{
+ if (TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK)
+ {
+ operands[0] = force_reg (Pmode, operands[0]);
+ if (TARGET_CPU_Z10)
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_indirect_jump_via_thunkdi_z10 (operands[0]));
+ else
+ emit_jump_insn (gen_indirect_jump_via_thunksi_z10 (operands[0]));
+ }
+ else
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_indirect_jump_via_thunkdi (operands[0]));
+ else
+ emit_jump_insn (gen_indirect_jump_via_thunksi (operands[0]));
+ }
+ DONE;
+ }
+
+ if (TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK)
+ {
+ operands[0] = force_reg (Pmode, operands[0]);
+ rtx label_ref = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ if (TARGET_CPU_Z10)
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_indirect_jump_via_inlinethunkdi_z10 (operands[0],
+ label_ref));
+ else
+ emit_jump_insn (gen_indirect_jump_via_inlinethunksi_z10 (operands[0],
+ label_ref));
+ }
+ else
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_indirect_jump_via_inlinethunkdi (operands[0],
+ label_ref,
+ force_reg (Pmode, label_ref)));
+ else
+ emit_jump_insn (gen_indirect_jump_via_inlinethunksi (operands[0],
+ label_ref,
+ force_reg (Pmode, label_ref)));
+ }
+ DONE;
+ }
+})
+
+(define_insn "*indirect_jump"
+ [(set (pc)
+ (match_operand 0 "address_operand" "ZR"))]
+ "!TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK"
+{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "br\t%0";
else
return "b\t%a0";
}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "br") (const_string "b")))
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+(define_insn "indirect_jump_via_thunk<mode>_z10"
+ [(set (pc)
+ (match_operand:P 0 "register_operand" "a"))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK
+ && TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_jump);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "jg")
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+(define_insn "indirect_jump_via_thunk<mode>"
+ [(set (pc)
+ (match_operand:P 0 "register_operand" " a"))
+ (clobber (reg:P INDIRECT_BRANCH_THUNK_REGNUM))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK
+ && !TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_jump);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "jg")
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+
+; The label_ref is wrapped into an if_then_else in order to hide it
+; from mark_jump_label. Without this the label_ref would become the
+; ONLY jump target of that jump breaking the control flow graph.
+(define_insn "indirect_jump_via_inlinethunk<mode>_z10"
+ [(unspec [(if_then_else (match_operand:P 1 "larl_operand" "X")
+ (const_int 0)
+ (const_int 0))
+ (const_int 0)] UNSPEC_EXECUTE_JUMP)
+ (set (pc) (match_operand:P 0 "register_operand" "a"))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK
+ && TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_inline_thunk (operands[1]);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "branch")
+ (set_attr "length" "10")])
+
+(define_insn "indirect_jump_via_inlinethunk<mode>"
+ [(unspec [(if_then_else (match_operand:P 1 "larl_operand" "X")
+ (const_int 0)
+ (const_int 0))
+ (match_operand:P 2 "register_operand" "a")] UNSPEC_EXECUTE_JUMP)
+ (set (pc) (match_operand:P 0 "register_operand" "a"))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK
+ && !TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_inline_thunk (operands[2]);
+ return "";
+}
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "branch")
+ (set_attr "length" "8")])
;
; casesi instruction pattern(s).
;
-(define_insn "casesi_jump"
- [(set (pc) (match_operand 0 "address_operand" "ZQZR"))
- (use (label_ref (match_operand 1 "" "")))]
+(define_expand "casesi_jump"
+ [(parallel
+ [(set (pc) (match_operand 0 "address_operand"))
+ (use (label_ref (match_operand 1 "")))])]
""
{
+ if (TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK)
+ {
+ operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
+
+ if (TARGET_CPU_Z10)
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_casesi_jump_via_thunkdi_z10 (operands[0],
+ operands[1]));
+ else
+ emit_jump_insn (gen_casesi_jump_via_thunksi_z10 (operands[0],
+ operands[1]));
+ }
+ else
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_casesi_jump_via_thunkdi (operands[0],
+ operands[1]));
+ else
+ emit_jump_insn (gen_casesi_jump_via_thunksi (operands[0],
+ operands[1]));
+ }
+ DONE;
+ }
+
+ if (TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK)
+ {
+ operands[0] = force_reg (Pmode, operands[0]);
+ rtx label_ref = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ if (TARGET_CPU_Z10)
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_casesi_jump_via_inlinethunkdi_z10 (operands[0],
+ operands[1],
+ label_ref));
+ else
+ emit_jump_insn (gen_casesi_jump_via_inlinethunksi_z10 (operands[0],
+ operands[1],
+ label_ref));
+ }
+ else
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_casesi_jump_via_inlinethunkdi (operands[0],
+ operands[1],
+ label_ref,
+ force_reg (Pmode, label_ref)));
+ else
+ emit_jump_insn (gen_casesi_jump_via_inlinethunksi (operands[0],
+ operands[1],
+ label_ref,
+ force_reg (Pmode, label_ref)));
+ }
+ DONE;
+ }
+})
+
+(define_insn "*casesi_jump"
+ [(set (pc) (match_operand 0 "address_operand" "ZR"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "!TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK"
+{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "br\t%0";
else
@@ -9240,9 +9460,85 @@
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "br") (const_string "b")))
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+(define_insn "casesi_jump_via_thunk<mode>_z10"
+ [(set (pc) (match_operand:P 0 "register_operand" "a"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK
+ && TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_jump);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "jg")
(set_attr "type" "branch")
(set_attr "atype" "agen")])
+(define_insn "casesi_jump_via_thunk<mode>"
+ [(set (pc) (match_operand:P 0 "register_operand" "a"))
+ (use (label_ref (match_operand 1 "" "")))
+ (clobber (reg:P INDIRECT_BRANCH_THUNK_REGNUM))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK
+ && !TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_jump);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "jg")
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+
+; The label_ref is wrapped into an if_then_else in order to hide it
+; from mark_jump_label. Without this the label_ref would become the
+; ONLY jump target of that jump breaking the control flow graph.
+(define_insn "casesi_jump_via_inlinethunk<mode>_z10"
+ [(unspec [(if_then_else (match_operand:P 2 "larl_operand" "X")
+ (const_int 0)
+ (const_int 0))
+ (const_int 0)] UNSPEC_EXECUTE_JUMP)
+ (set (pc) (match_operand:P 0 "register_operand" "a"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK
+ && TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_inline_thunk (operands[2]);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "cs")
+ (set_attr "length" "10")])
+
+(define_insn "casesi_jump_via_inlinethunk<mode>"
+ [(unspec [(if_then_else (match_operand:P 2 "larl_operand" "X")
+ (const_int 0)
+ (const_int 0))
+ (match_operand:P 3 "register_operand" "a")] UNSPEC_EXECUTE_JUMP)
+ (set (pc) (match_operand:P 0 "register_operand" "a"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK
+ && !TARGET_CPU_Z10"
+{
+ s390_indirect_branch_via_inline_thunk (operands[3]);
+ return "";
+}
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "cs")
+ (set_attr "length" "8")])
+
(define_expand "casesi"
[(match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" "")
@@ -9347,8 +9643,27 @@
(match_operand 0 "const_int_operand" "n"))]
"SIBLING_CALL_P (insn)
&& GET_MODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == Pmode"
- "br\t%%r1"
- [(set_attr "op_type" "RR")
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_CALL)
+ {
+ gcc_assert (TARGET_CPU_Z10);
+ s390_indirect_branch_via_thunk (SIBCALL_REGNUM,
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+ }
+ else
+ return "br\t%%r1";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_CALL")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_CALL")
+ (const_string "jg")
+ (const_string "br")))
(set_attr "type" "branch")
(set_attr "atype" "agen")])
@@ -9388,8 +9703,27 @@
(match_operand 1 "const_int_operand" "n")))]
"SIBLING_CALL_P (insn)
&& GET_MODE (XEXP (XEXP (XEXP (PATTERN (insn), 1), 0), 0)) == Pmode"
- "br\t%%r1"
- [(set_attr "op_type" "RR")
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_CALL)
+ {
+ gcc_assert (TARGET_CPU_Z10);
+ s390_indirect_branch_via_thunk (SIBCALL_REGNUM,
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+ }
+ else
+ return "br\t%%r1";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_CALL")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_CALL")
+ (const_string "jg")
+ (const_string "br")))
(set_attr "type" "branch")
(set_attr "atype" "agen")])
@@ -9455,7 +9789,9 @@
[(call (mem:QI (match_operand 0 "address_operand" "ZQZR"))
(match_operand 1 "const_int_operand" "n"))
(clobber (match_operand 2 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
+ "!TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && !SIBLING_CALL_P (insn)
+ && GET_MODE (operands[2]) == Pmode"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "basr\t%2,%0";
@@ -9465,6 +9801,50 @@
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "basr") (const_string "bas")))
+ (set_attr "type" "jsr")
+ (set_attr "atype" "agen")
+ (set_attr "z196prop" "z196_cracked")])
+
+(define_insn "*basr_via_thunk<mode>_z10"
+ [(call (mem:QI (match_operand:P 0 "register_operand" "a"))
+ (match_operand 1 "const_int_operand" "n"))
+ (clobber (match_operand:P 2 "register_operand" "=&r"))]
+ "TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && TARGET_CPU_Z10
+ && !SIBLING_CALL_P (insn)"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ REGNO (operands[2]),
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "brasl")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "agen")
+ (set_attr "z196prop" "z196_cracked")])
+
+(define_insn "*basr_via_thunk<mode>"
+ [(call (mem:QI (match_operand:P 0 "register_operand" "a"))
+ (match_operand 1 "const_int_operand" "n"))
+ (clobber (match_operand:P 2 "register_operand" "=&r"))
+ (clobber (reg:P INDIRECT_BRANCH_THUNK_REGNUM))]
+ "TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && !TARGET_CPU_Z10
+ && !SIBLING_CALL_P (insn)"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ REGNO (operands[2]),
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "brasl")
(set_attr "type" "jsr")
(set_attr "atype" "agen")
(set_attr "z196prop" "z196_cracked")])
@@ -9516,7 +9896,9 @@
(call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
+ "!TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && !SIBLING_CALL_P (insn)
+ && GET_MODE (operands[3]) == Pmode"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "basr\t%3,%1";
@@ -9526,6 +9908,54 @@
[(set (attr "op_type")
(if_then_else (match_operand 1 "register_operand" "")
(const_string "RR") (const_string "RX")))
+ (set (attr "mnemonic")
+ (if_then_else (match_operand 1 "register_operand" "")
+ (const_string "basr") (const_string "bas")))
+ (set_attr "type" "jsr")
+ (set_attr "atype" "agen")
+ (set_attr "z196prop" "z196_cracked")])
+
+(define_insn "*basr_r_via_thunk_z10"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand 1 "register_operand" "a"))
+ (match_operand 2 "const_int_operand" "n")))
+ (clobber (match_operand 3 "register_operand" "=&r"))]
+ "TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && TARGET_CPU_Z10
+ && !SIBLING_CALL_P (insn)
+ && GET_MODE (operands[3]) == Pmode"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[1]),
+ REGNO (operands[3]),
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "brasl")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "agen")
+ (set_attr "z196prop" "z196_cracked")])
+
+(define_insn "*basr_r_via_thunk"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand 1 "register_operand" "a"))
+ (match_operand 2 "const_int_operand" "n")))
+ (clobber (match_operand 3 "register_operand" "=&r"))
+ (clobber (reg:P INDIRECT_BRANCH_THUNK_REGNUM))]
+ "TARGET_INDIRECT_BRANCH_NOBP_CALL
+ && !TARGET_CPU_Z10
+ && !SIBLING_CALL_P (insn)
+ && GET_MODE (operands[3]) == Pmode"
+{
+ s390_indirect_branch_via_thunk (REGNO (operands[1]),
+ REGNO (operands[3]),
+ NULL_RTX,
+ s390_indirect_branch_type_call);
+ return "";
+}
+ [(set_attr "op_type" "RIL")
+ (set_attr "mnemonic" "brasl")
(set_attr "type" "jsr")
(set_attr "atype" "agen")
(set_attr "z196prop" "z196_cracked")])
@@ -10282,17 +10712,101 @@
(define_insn "<code>"
[(ANY_RETURN)]
"s390_can_use_<code>_insn ()"
- "br\t%%r14"
- [(set_attr "op_type" "RR")
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_RET)
+ {
+ /* The target is always r14 so there is no clobber
+ of r1 needed for pre z10 targets. */
+ s390_indirect_branch_via_thunk (RETURN_REGNUM,
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_return);
+ return "";
+ }
+ else
+ return "br\t%%r14";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "jg")
+ (const_string "br")))
+ (set_attr "type" "jsr")
+ (set_attr "atype" "agen")])
+
+
+(define_expand "return_use"
+ [(parallel
+ [(return)
+ (use (match_operand 0 "register_operand" "a"))])]
+ ""
+{
+ if (!TARGET_CPU_Z10
+ && TARGET_INDIRECT_BRANCH_NOBP_RET_OPTION)
+ {
+ if (TARGET_64BIT)
+ emit_jump_insn (gen_returndi_prez10 (operands[0]));
+ else
+ emit_jump_insn (gen_returnsi_prez10 (operands[0]));
+ DONE;
+ }
+})
+
+(define_insn "*return<mode>"
+ [(return)
+ (use (match_operand:P 0 "register_operand" "a"))]
+ "TARGET_CPU_Z10 || !TARGET_INDIRECT_BRANCH_NOBP_RET_OPTION"
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_RET)
+ {
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_return);
+ return "";
+ }
+ else
+ return "br\t%0";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "jg")
+ (const_string "br")))
(set_attr "type" "jsr")
(set_attr "atype" "agen")])
-(define_insn "*return"
+(define_insn "return<mode>_prez10"
[(return)
- (use (match_operand 0 "register_operand" "a"))]
- "GET_MODE (operands[0]) == Pmode"
- "br\t%0"
- [(set_attr "op_type" "RR")
+ (use (match_operand:P 0 "register_operand" "a"))
+ (clobber (reg:P INDIRECT_BRANCH_THUNK_REGNUM))]
+ "!TARGET_CPU_Z10 && TARGET_INDIRECT_BRANCH_NOBP_RET_OPTION"
+{
+ if (TARGET_INDIRECT_BRANCH_NOBP_RET)
+ {
+ s390_indirect_branch_via_thunk (REGNO (operands[0]),
+ INVALID_REGNUM,
+ NULL_RTX,
+ s390_indirect_branch_type_return);
+ return "";
+ }
+ else
+ return "br\t%0";
+}
+ [(set (attr "op_type")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "RIL")
+ (const_string "RR")))
+ (set (attr "mnemonic")
+ (if_then_else (match_test "TARGET_INDIRECT_BRANCH_NOBP_RET")
+ (const_string "jg")
+ (const_string "br")))
(set_attr "type" "jsr")
(set_attr "atype" "agen")])
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index 1ae1396e9a5..fd7cfb0356e 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -199,3 +199,62 @@ values are small, non-negative integers. The default branch cost is
mlra
Target Report Var(s390_lra_flag) Init(1) Save
Use LRA instead of reload.
+
+mindirect-branch=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch) Init(indirect_branch_keep)
+Wrap all indirect branches into execute in order to disable branch
+prediction.
+
+mindirect-branch-jump=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_jump) Init(indirect_branch_keep)
+Wrap indirect table jumps and computed gotos into execute in order to
+disable branch prediction. Using thunk or thunk-extern with this
+option requires the thunks to be considered signal handlers to order to
+generate correct CFI. For environments where unwinding (e.g. for
+exceptions) is required please use thunk-inline instead.
+
+mindirect-branch-call=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_indirect_branch_call) Init(indirect_branch_keep)
+Wrap all indirect calls into execute in order to disable branch prediction.
+
+mfunction-return=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return) Init(indirect_branch_keep)
+Wrap all indirect return branches into execute in order to disable branch
+prediction.
+
+mfunction-return-mem=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_mem) Init(indirect_branch_keep)
+Wrap indirect return branches into execute in order to disable branch
+prediction. This affects only branches where the return address is
+going to be restored from memory.
+
+mfunction-return-reg=
+Target Report RejectNegative Joined Enum(indirect_branch) Var(s390_function_return_reg) Init(indirect_branch_keep)
+Wrap indirect return branches into execute in order to disable branch
+prediction. This affects only branches where the return address
+doesn't need to be restored from memory.
+
+Enum
+Name(indirect_branch) Type(enum indirect_branch)
+Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
+
+EnumValue
+Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
+
+EnumValue
+Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
+
+EnumValue
+Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+
+EnumValue
+Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+
+mindirect-branch-table
+Target Report Var(s390_indirect_branch_table) Init(TARGET_DEFAULT_INDIRECT_BRANCH_TABLE)
+Generate sections .s390_indirect_jump, .s390_indirect_call,
+.s390_return_reg, and .s390_return_mem to contain the indirect branch
+locations which have been patched as part of using one of the
+-mindirect-branch* or -mfunction-return* options. The sections
+consist of an array of 32 bit elements. Each entry holds the offset
+from the entry to the patched location.
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index b08120d3737..68fbfa7f63f 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -228,9 +228,13 @@ sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc,
}
}
- if (result.set_src != NULL)
- gcc_assert (result.insn != NULL && result.set_rtx != NULL);
-
+ /* If the searched reg is found inside a (mem (post_inc:SI (reg))), set_of
+ will return NULL and set_rtx will be NULL.
+ In this case report a 'not found'. result.insn will always be non-null
+ at this point, so no need to check it. */
+ if (result.set_src != NULL && result.set_rtx == NULL)
+ result.set_src = NULL;
+
return result;
}
diff --git a/gcc/config/sh/sh_optimize_sett_clrt.cc b/gcc/config/sh/sh_optimize_sett_clrt.cc
index 11285dc112d..43f2e30deb2 100644
--- a/gcc/config/sh/sh_optimize_sett_clrt.cc
+++ b/gcc/config/sh/sh_optimize_sett_clrt.cc
@@ -18,6 +18,8 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
+#define INCLUDE_ALGORITHM
+#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -27,9 +29,6 @@ along with GCC; see the file COPYING3. If not see
#include "cfgrtl.h"
#include "tree-pass.h"
-#include <vector>
-#include <algorithm>
-
/*
This pass tries to eliminate unnecessary sett or clrt instructions in cases
where the ccreg value is already known to be the same as the constant set
diff --git a/gcc/configure b/gcc/configure
index 00a2dc05792..beec8574cf3 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -23568,6 +23568,14 @@ fi
$as_echo "$gcc_cv_as_shf_merge" >&6; }
fi
+case "$target" in
+ i?86-*-solaris2.10* | x86_64-*-solaris2.10*)
+ # SHF_MERGE support in Solaris 10/x86 ld is broken.
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_as_shf_merge=no
+ fi
+ ;;
+esac
cat >>confdefs.h <<_ACEOF
#define HAVE_GAS_SHF_MERGE `if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 8025e912432..2c12bd2a9fe 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2933,6 +2933,14 @@ if test $gcc_cv_as_shf_merge = no; then
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", %progbits, 1])
fi
+case "$target" in
+ i?86-*-solaris2.10* | x86_64-*-solaris2.10*)
+ # SHF_MERGE support in Solaris 10/x86 ld is broken.
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_as_shf_merge=no
+ fi
+ ;;
+esac
AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_MERGE,
[`if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`],
[Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.])
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 807ed460482..763a6947ec2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,33 @@
+2018-03-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/84686 - missing volatile loads.
+ * cvt.c (convert_to_void): Call maybe_undo_parenthesized_ref.
+
+2018-03-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/84489 - dependent default template argument
+ * pt.c (type_unification_real): Handle early substitution failure.
+
+2018-02-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/71784 - ICE with ref-qualifier and explicit specialization.
+ * pt.c (determine_specialization): Check ref-qualifier.
+
+2018-02-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/84441 - ICE with base initialized from ?:
+ * call.c (unsafe_copy_elision_p): Handle COND_EXPR.
+
+ PR c++/84520 - ICE with generic lambda in NSDMI.
+ * lambda.c (lambda_expr_this_capture): Don't look for fake NSDMI
+ 'this' in a generic lambda instantiation.
+
+2018-02-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/84151 - unnecessary volatile load with static member.
+ * call.c (build_new_method_call_1): Avoid loading from a volatile
+ lvalue used as the object argument for a static member function.
+
2017-09-15 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8090dbf29e6..3bdd5fef3f3 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7189,6 +7189,15 @@ unsafe_copy_elision_p (tree target, tree exp)
/* build_compound_expr pushes COMPOUND_EXPR inside TARGET_EXPR. */
while (TREE_CODE (init) == COMPOUND_EXPR)
init = TREE_OPERAND (init, 1);
+ if (TREE_CODE (init) == COND_EXPR)
+ {
+ /* We'll end up copying from each of the arms of the COND_EXPR directly
+ into the target, so look at them. */
+ if (tree op = TREE_OPERAND (init, 1))
+ if (unsafe_copy_elision_p (target, op))
+ return true;
+ return unsafe_copy_elision_p (target, TREE_OPERAND (init, 2));
+ }
return (TREE_CODE (init) == AGGR_INIT_EXPR
&& !AGGR_INIT_VIA_CTOR_P (init));
}
@@ -8437,8 +8446,14 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
&& !is_dummy_object (instance)
&& TREE_SIDE_EFFECTS (instance))
- call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
- instance, call);
+ {
+ /* But avoid the implicit lvalue-rvalue conversion when 'a'
+ is volatile. */
+ tree a = instance;
+ if (TREE_THIS_VOLATILE (a))
+ a = build_this (a);
+ call = build2 (COMPOUND_EXPR, TREE_TYPE (call), a, call);
+ }
else if (call != error_mark_node
&& DECL_DESTRUCTOR_P (cand->fn)
&& !VOID_TYPE_P (TREE_TYPE (call)))
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 0d1048cd7fe..43fcff9854e 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -932,6 +932,8 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
|| TREE_TYPE (expr) == error_mark_node)
return error_mark_node;
+ expr = maybe_undo_parenthesized_ref (expr);
+
if (implicit == ICV_CAST)
mark_exp_read (expr);
else
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 91a5c1a0b08..ea15c26ae3e 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -665,11 +665,14 @@ lambda_expr_this_capture (tree lambda, bool add_capture_p)
lambda_stack);
if (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)
+ && !COMPLETE_TYPE_P (LAMBDA_EXPR_CLOSURE (tlambda))
&& TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)) == FIELD_DECL)
{
/* In an NSDMI, we don't have a function to look up the decl in,
but the fake 'this' pointer that we're using for parsing is
- in scope_chain. */
+ in scope_chain. But if the closure is already complete, we're
+ in an instantiation of a generic lambda, and the fake 'this'
+ is gone. */
init = scope_chain->x_current_class_ptr;
gcc_checking_assert
(init && (TREE_TYPE (TREE_TYPE (init))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 28bb7853198..27e4c84ac79 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2170,10 +2170,17 @@ determine_specialization (tree template_id,
that the const qualification is the same. Since
get_bindings does not try to merge the "this" parameter,
we must do the comparison explicitly. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !same_type_p (TREE_VALUE (fn_arg_types),
- TREE_VALUE (decl_arg_types)))
- continue;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ {
+ if (!same_type_p (TREE_VALUE (fn_arg_types),
+ TREE_VALUE (decl_arg_types)))
+ continue;
+
+ /* And the ref-qualification. */
+ if (type_memfn_rqual (TREE_TYPE (decl))
+ != type_memfn_rqual (TREE_TYPE (fn)))
+ continue;
+ }
/* Skip the "this" parameter and, for constructors of
classes with virtual bases, the VTT parameter. A
@@ -2279,6 +2286,11 @@ determine_specialization (tree template_id,
decl_arg_types))
continue;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && (type_memfn_rqual (TREE_TYPE (decl))
+ != type_memfn_rqual (TREE_TYPE (fn))))
+ continue;
+
// If the deduced arguments do not satisfy the constraints,
// this is not a candidate.
if (flag_concepts && !constraints_satisfied_p (fn))
@@ -18591,10 +18603,10 @@ type_unification_real (tree tparms,
if (DECL_P (parm))
input_location = DECL_SOURCE_LOCATION (parm);
arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
- if (!uses_template_parms (arg))
+ if (arg != error_mark_node && !uses_template_parms (arg))
arg = convert_template_argument (parm, arg, targs, complain,
i, NULL_TREE);
- else if (saw_undeduced < 2)
+ else if (saw_undeduced == 1)
arg = NULL_TREE;
else
arg = error_mark_node;
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index 8e1ef5cdba8..ff1eca714b1 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -321,7 +321,7 @@ program source code. The format is
Additional block information may succeed each line, when requested by
command line option. The @var{execution_count} is @samp{-} for lines
containing no code. Unexecuted lines are marked @samp{#####} or
-@samp{====}, depending on whether they are reachable by
+@samp{=====}, depending on whether they are reachable by
non-exceptional paths or only exceptional paths such as C++ exception
handlers, respectively. Given @samp{-a} option, unexecuted blocks are
marked @samp{$$$$$} or @samp{%%%%%}, depending on whether a basic block
@@ -604,6 +604,8 @@ facilities to restrict profile collection to the program region of
interest. Calling @code{_gcov_reset(void)} will clear all profile counters
to zero, and calling @code{_gcov_dump(void)} will cause the profile information
collected at that point to be dumped to @file{.gcda} output files.
+If an executable loads a dynamic shared object via dlopen functionality,
+@option{-Wl,--dynamic-list-data} is needed to dump all profile data.
@c man end
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 7638f848713..8b9fb2eb1ef 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -7281,7 +7281,7 @@ This flag is enabled by default at @option{-O2} and higher and depends on
@item -fisolate-erroneous-paths-attribute
@opindex fisolate-erroneous-paths-attribute
-Detect paths that trigger erroneous or undefined behavior due a null value
+Detect paths that trigger erroneous or undefined behavior due to a null value
being used in a way forbidden by a @code{returns_nonnull} or @code{nonnull}
attribute. Isolate those paths from the main control flow and turn the
statement with erroneous or undefined behavior into a trap. This is not
@@ -7825,6 +7825,7 @@ Some assemblers only support this flag when @var{n} is a power of two;
in that case, it is rounded up.
If @var{n} is not specified or is zero, use a machine-dependent default.
+The maximum allowed @var{n} option value is 65536.
Enabled at levels @option{-O2}, @option{-O3}.
@@ -7844,6 +7845,7 @@ are greater than this value, then their values are used instead.
If @var{n} is not specified or is zero, use a machine-dependent default
which is very likely to be @samp{1}, meaning no alignment.
+The maximum allowed @var{n} option value is 65536.
Enabled at levels @option{-O2}, @option{-O3}.
@@ -7857,6 +7859,7 @@ operations.
@option{-fno-align-loops} and @option{-falign-loops=1} are
equivalent and mean that loops are not aligned.
+The maximum allowed @var{n} option value is 65536.
If @var{n} is not specified or is zero, use a machine-dependent default.
@@ -7874,6 +7877,7 @@ need be executed.
equivalent and mean that loops are not aligned.
If @var{n} is not specified or is zero, use a machine-dependent default.
+The maximum allowed @var{n} option value is 65536.
Enabled at levels @option{-O2}, @option{-O3}.
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3f95a70817d..6bfbc5fd3b9 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -5909,6 +5909,18 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
if (tem != 0)
return tem;
+ /* If one operand is constant, make it the second one. Only do this
+ if the other operand is not constant as well. */
+
+ if (swap_commutative_operands_p (op0, op1))
+ {
+ std::swap (op0, op1);
+ code = swap_condition (code);
+ }
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op0);
+
if (!target)
target = gen_reg_rtx (word_mode);
diff --git a/gcc/final.c b/gcc/final.c
index 55cf509611f..c07764e02e2 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -901,7 +901,7 @@ shorten_branches (rtx_insn *first)
char *varying_length;
rtx body;
int uid;
- rtx align_tab[MAX_CODE_ALIGN];
+ rtx align_tab[MAX_CODE_ALIGN + 1];
/* Compute maximum UID and allocate label_align / uid_shuid. */
max_uid = get_max_uid ();
@@ -1010,7 +1010,7 @@ shorten_branches (rtx_insn *first)
alignment of n. */
uid_align = XCNEWVEC (rtx, max_uid);
- for (i = MAX_CODE_ALIGN; --i >= 0;)
+ for (i = MAX_CODE_ALIGN + 1; --i >= 0;)
align_tab[i] = NULL_RTX;
seq = get_last_insn ();
for (; seq; seq = PREV_INSN (seq))
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index ccad53b1b86..60159842746 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,137 @@
+2018-03-06 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/56667
+ * primary.c (match_sym_complex_part): Give the matcher for an implied
+ do-loop a chance to run.
+
+2018-03-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/71085
+ * trans-expr.c (gfc_apply_interface_mapping_to_expr): Do not
+ dereference NULL pointer.
+
+2018-03-03 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from trunk.
+ PR fortran/78990
+ * expr.c (gfc_is_class_array_function): Renamed from
+ 'gfc_is_alloc_class_array_function' and modified to return true
+ for pointers as well as allocatable results.
+ * gfortran.h : Change of name for prototype of above function.
+ * trans-array.c (gfc_add_loop_ss_code): Force finalization of
+ class array results.
+ (build_class_array_ref): Change assertion into a condition.
+ (build_class_array_ref): Set the se class_vptr for class array
+ function results.
+ (gfc_walk_function_expr): Reference gfc_is_class_array_function
+ as above.
+ * trans-decl.c (get_proc_result): Move it up before
+ gfc_trans_deferred_vars.
+ (gfc_trans_deferred_vars): Nullify explicit return class arrays
+ on entry.
+ * trans-expr.c (gfc_conv_class_to_class): Allow conversion of
+ class array functions that have an se class_vptr and use it
+ for the result vptr.
+ (gfc_conv_subref_array_arg): Rename reference to the above
+ function.
+ (gfc_conv_procedure_call): Ditto. Add the se pre block to the
+ loop pre block before the function is evaluated. Do not
+ finalize class pointer results.
+ (arrayfunc_assign_needs_temporary, gfc_trans_assignment_1) More
+ renamed references.
+ * trans-intrinsic.c (gfc_conv_intrinsic_size): Ditto.
+
+2018-02-25 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83633
+ * decl.c (variable_decl): Check that an explicit-shape-array with
+ nonconstant bounds is allowed.
+
+2018-02-24 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/30792
+ * decl.c (gfc_match_data): Check for invalid substring in
+ data-implied-do
+
+2018-02-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from trunk
+ PR fortran/84506
+ * trans-io.c (set_parameter_value_inquire): Adjust range check of
+ negative unit values for kind=8 units to the kind=4 negative limit.
+
+2018-02-23 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/84511
+ * trans-io.c (transfer_expr): Deal with C_LOC in transfer statement.
+
+2018-02-23 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/84346
+ * interface.c (compare_actual_formal): Issue error if keyword is
+ used in a statement function.
+
+2018-02-13 Alastair McKinstry <alastair.mckinstry@sceal.ie>
+ Janne Blomqvist <jb@gcc.gnu.org>
+
+ * module.c (dump_module): Use lbasename to ensure that module
+ files are reproducible.
+
+2018-02-12 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/68560
+ * gfortran.dg/shape_9.f90: New test.
+
+2018-02-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/35299
+ ChangeLog for r257566
+ * resolve.c (resolve_formal_arglist): Update error message.
+
+2018-02-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/54223
+ PR fortran/84276
+ * interface.c (compare_actual_formal): Add in_statement_function
+ bool parameter. Skip check of INTENT attribute for statement
+ functions. Arguments to a statement function cannot be optional,
+ issue error for missing argument.
+ (gfc_procedure_use, gfc_ppc_use, gfc_arglist_matches_symbol): Use
+ in_statement_function.
+
+2018-02-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/82994
+ * match.c (gfc_match_deallocate): Check for NULL pointer.
+
+2018-02-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/82049
+ * match.c (gfc_match_type_spec): If the charlen is non-NULL, then
+ try to resolve it. While here return early if possible.
+
+2018-01-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83900
+ * simplify.c (gfc_simplify_matmul): Set return type correctly.
+
+2018-01-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83900
+ * simplify.c (gfc_simplify_matmul): Delete bogus assertion.
+
+2018-01-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ Backport of r250734 from mainline
+ PR fortran/80768
+ * check.c (gfc_check_num_images): Fix typo.
+
+2018-01-17 Harald Anlauf <anlauf@gmx.de>
+
+ Back from mainline
+ PR fortran/83874
+ * decl.c (add_init_expr_to_sym): Do not dereference NULL pointer.
+
2018-01-13 Steven G. Kargl <kargl@gcc.gnu.org>
Backport from mainline
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index ee421d99cd9..f7829db7a7d 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -5028,7 +5028,7 @@ gfc_check_num_images (gfc_expr *distance, gfc_expr *failed)
return false;
if (!gfc_notify_std (GFC_STD_F2008_TS, "FAILED= argument to "
- "NUM_IMAGES at %L", &distance->where))
+ "NUM_IMAGES at %L", &failed->where))
return false;
}
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 080492b3f4f..64e0fee5c29 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -573,6 +573,20 @@ gfc_match_data (void)
if (m != MATCH_YES)
goto cleanup;
+ if (new_data->var->iter.var
+ && new_data->var->iter.var->ts.type == BT_INTEGER
+ && new_data->var->iter.var->symtree->n.sym->attr.implied_index == 1
+ && new_data->var->list
+ && new_data->var->list->expr
+ && new_data->var->list->expr->ts.type == BT_CHARACTER
+ && new_data->var->list->expr->ref
+ && new_data->var->list->expr->ref->type == REF_SUBSTRING)
+ {
+ gfc_error ("Invalid substring in data-implied-do at %L in DATA "
+ "statement", &new_data->var->list->expr->where);
+ goto cleanup;
+ }
+
m = top_val_list (new_data);
if (m != MATCH_YES)
goto cleanup;
@@ -1692,7 +1706,7 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
}
else if (init->expr_type == EXPR_ARRAY)
{
- if (init->ts.u.cl)
+ if (init->ts.u.cl && init->ts.u.cl->length)
clen = mpz_get_si (init->ts.u.cl->length->value.integer);
else if (init->value.constructor)
{
@@ -2206,7 +2220,10 @@ variable_decl (int elem)
/* At this point, we know for sure if the symbol is PARAMETER and can thus
determine (and check) whether it can be implied-shape. If it
was parsed as assumed-size, change it because PARAMETERs can not
- be assumed-size. */
+ be assumed-size.
+
+ An explicit-shape-array cannot appear under several conditions.
+ That check is done here as well. */
if (as)
{
if (as->type == AS_IMPLIED_SHAPE && current_attr.flavor != FL_PARAMETER)
@@ -2228,6 +2245,50 @@ variable_decl (int elem)
m = MATCH_ERROR;
goto cleanup;
}
+
+ /* F2018:C830 (R816) An explicit-shape-spec whose bounds are not
+ constant expressions shall appear only in a subprogram, derived
+ type definition, BLOCK construct, or interface body. */
+ if (as->type == AS_EXPLICIT
+ && gfc_current_state () != COMP_BLOCK
+ && gfc_current_state () != COMP_DERIVED
+ && gfc_current_state () != COMP_FUNCTION
+ && gfc_current_state () != COMP_INTERFACE
+ && gfc_current_state () != COMP_SUBROUTINE)
+ {
+ gfc_expr *e;
+ bool not_constant = false;
+
+ for (int i = 0; i < as->rank; i++)
+ {
+ e = gfc_copy_expr (as->lower[i]);
+ gfc_resolve_expr (e);
+ gfc_simplify_expr (e, 0);
+ if (e && (e->expr_type != EXPR_CONSTANT))
+ {
+ not_constant = true;
+ break;
+ }
+ gfc_free_expr (e);
+
+ e = gfc_copy_expr (as->upper[i]);
+ gfc_resolve_expr (e);
+ gfc_simplify_expr (e, 0);
+ if (e && (e->expr_type != EXPR_CONSTANT))
+ {
+ not_constant = true;
+ break;
+ }
+ gfc_free_expr (e);
+ }
+
+ if (not_constant)
+ {
+ gfc_error ("Explicit shaped array with nonconstant bounds at %C");
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+ }
}
char_len = NULL;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index a30ea2d3d54..aceefb6e110 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4348,14 +4348,15 @@ gfc_is_alloc_class_scalar_function (gfc_expr *expr)
/* Determine if an expression is a function with an allocatable class array
result. */
bool
-gfc_is_alloc_class_array_function (gfc_expr *expr)
+gfc_is_class_array_function (gfc_expr *expr)
{
if (expr->expr_type == EXPR_FUNCTION
&& expr->value.function.esym
&& expr->value.function.esym->result
&& expr->value.function.esym->result->ts.type == BT_CLASS
&& CLASS_DATA (expr->value.function.esym->result)->attr.dimension
- && CLASS_DATA (expr->value.function.esym->result)->attr.allocatable)
+ && (CLASS_DATA (expr->value.function.esym->result)->attr.allocatable
+ || CLASS_DATA (expr->value.function.esym->result)->attr.pointer))
return true;
return false;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 0bb71cb184d..4e08449d2a3 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3057,7 +3057,7 @@ bool gfc_expr_check_typed (gfc_expr*, gfc_namespace*, bool);
gfc_component * gfc_get_proc_ptr_comp (gfc_expr *);
bool gfc_is_proc_ptr_comp (gfc_expr *);
bool gfc_is_alloc_class_scalar_function (gfc_expr *);
-bool gfc_is_alloc_class_array_function (gfc_expr *);
+bool gfc_is_class_array_function (gfc_expr *);
bool gfc_ref_this_image (gfc_ref *ref);
bool gfc_is_coindexed (gfc_expr *);
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 6dac80195bd..04b92c994f1 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -2710,7 +2710,8 @@ is_procptr_result (gfc_expr *expr)
static int
compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
- int ranks_must_agree, int is_elemental, locus *where)
+ int ranks_must_agree, int is_elemental,
+ bool in_statement_function, locus *where)
{
gfc_actual_arglist **new_arg, *a, *actual;
gfc_formal_arglist *f;
@@ -2738,6 +2739,13 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
for (a = actual; a; a = a->next, f = f->next)
{
+ if (a->name != NULL && in_statement_function)
+ {
+ gfc_error ("Keyword argument %qs at %L is invalid in "
+ "a statement function", a->name, &a->expr->where);
+ return false;
+ }
+
/* Look for keywords but ignore g77 extensions like %VAL. */
if (a->name != NULL && a->name[0] != '%')
{
@@ -3058,8 +3066,9 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
}
/* Check intent = OUT/INOUT for definable actual argument. */
- if ((f->sym->attr.intent == INTENT_OUT
- || f->sym->attr.intent == INTENT_INOUT))
+ if (!in_statement_function
+ && (f->sym->attr.intent == INTENT_OUT
+ || f->sym->attr.intent == INTENT_INOUT))
{
const char* context = (where
? _("actual argument to INTENT = OUT/INOUT")
@@ -3157,7 +3166,8 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
"at %L", where);
return 0;
}
- if (!f->sym->attr.optional)
+ if (!f->sym->attr.optional
+ || (in_statement_function && f->sym->attr.optional))
{
if (where)
gfc_error ("Missing actual argument for argument %qs at %L",
@@ -3443,6 +3453,7 @@ check_intents (gfc_formal_arglist *f, gfc_actual_arglist *a)
bool
gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
{
+ gfc_actual_arglist *a;
gfc_formal_arglist *dummy_args;
/* Warn about calls with an implicit interface. Special case
@@ -3469,8 +3480,6 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
if (sym->attr.if_source == IFSRC_UNKNOWN)
{
- gfc_actual_arglist *a;
-
if (sym->attr.pointer)
{
gfc_error ("The pointer object %qs at %L must have an explicit "
@@ -3562,9 +3571,12 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
dummy_args = gfc_sym_get_dummy_args (sym);
- if (!compare_actual_formal (ap, dummy_args, 0, sym->attr.elemental, where))
+ /* For a statement function, check that types and type parameters of actual
+ arguments and dummy arguments match. */
+ if (!compare_actual_formal (ap, dummy_args, 0, sym->attr.elemental,
+ sym->attr.proc == PROC_ST_FUNCTION, where))
return false;
-
+
if (!check_intents (dummy_args, *ap))
return false;
@@ -3611,7 +3623,7 @@ gfc_ppc_use (gfc_component *comp, gfc_actual_arglist **ap, locus *where)
}
if (!compare_actual_formal (ap, comp->ts.interface->formal, 0,
- comp->attr.elemental, where))
+ comp->attr.elemental, false, where))
return;
check_intents (comp->ts.interface->formal, *ap);
@@ -3636,7 +3648,7 @@ gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym)
dummy_args = gfc_sym_get_dummy_args (sym);
r = !sym->attr.elemental;
- if (compare_actual_formal (args, dummy_args, r, !r, NULL))
+ if (compare_actual_formal (args, dummy_args, r, !r, false, NULL))
{
check_intents (dummy_args, *args);
if (warn_aliasing)
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index eed3f618005..516abc5ba80 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -1983,11 +1983,17 @@ gfc_match_type_spec (gfc_typespec *ts)
{
match m;
locus old_locus;
+ char c;
gfc_clear_ts (ts);
gfc_gobble_whitespace ();
old_locus = gfc_current_locus;
+ /* If c isn't in [a-z], then return immediately. */
+ c = gfc_peek_ascii_char ();
+ if (!ISALPHA(c))
+ return MATCH_NO;
+
if (match_derived_type_spec (ts) == MATCH_YES)
{
/* Enforce F03:C401. */
@@ -2033,6 +2039,8 @@ gfc_match_type_spec (gfc_typespec *ts)
ts->type = BT_CHARACTER;
m = gfc_match_char_spec (ts);
+ if (ts->u.cl && ts->u.cl->length)
+ gfc_resolve_expr (ts->u.cl->length);
if (m == MATCH_NO)
m = MATCH_YES;
@@ -4267,8 +4275,8 @@ gfc_match_deallocate (void)
&& (tail->expr->ref->type == REF_COMPONENT
|| tail->expr->ref->type == REF_ARRAY));
if (sym && sym->ts.type == BT_CLASS)
- b2 = !(CLASS_DATA (sym)->attr.allocatable
- || CLASS_DATA (sym)->attr.class_pointer);
+ b2 = !(CLASS_DATA (sym) && (CLASS_DATA (sym)->attr.allocatable
+ || CLASS_DATA (sym)->attr.class_pointer));
else
b2 = sym && !(sym->attr.allocatable || sym->attr.pointer
|| sym->attr.proc_pointer);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 29bcaf37bf9..a77337be668 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -6080,8 +6080,10 @@ dump_module (const char *name, int dump_flag)
gfc_fatal_error ("Can't open module file %qs for writing at %C: %s",
filename_tmp, xstrerror (errno));
+ /* Use lbasename to ensure module files are reproducible regardless
+ of the build path (see the reproducible builds project). */
gzprintf (module_fp, "GFORTRAN module version '%s' created from %s\n",
- MOD_VERSION, gfc_source_file);
+ MOD_VERSION, lbasename (gfc_source_file));
/* Write the module itself. */
iomode = IO_OUTPUT;
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 009ae99bbd4..a90beb17393 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1250,8 +1250,22 @@ match_sym_complex_part (gfc_expr **result)
if (sym->attr.flavor != FL_PARAMETER)
{
- gfc_error ("Expected PARAMETER symbol in complex constant at %C");
- return MATCH_ERROR;
+ /* Give the matcher for implied do-loops a chance to run. This yields
+ a much saner error message for "write(*,*) (i, i=1, 6" where the
+ right parenthesis is missing. */
+ char c;
+ gfc_gobble_whitespace ();
+ c = gfc_peek_ascii_char ();
+ if (c == '=' || c == ',')
+ {
+ m = MATCH_NO;
+ }
+ else
+ {
+ gfc_error ("Expected PARAMETER symbol in complex constant at %C");
+ m = MATCH_ERROR;
+ }
+ return m;
}
if (!sym->value)
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index ef938009f75..d2d1b583535 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -506,8 +506,11 @@ resolve_formal_arglist (gfc_symbol *proc)
{
if (sym->as != NULL)
{
- gfc_error ("Argument %qs of statement function at %L must "
- "be scalar", sym->name, &sym->declared_at);
+ /* F03:C1263 (R1238) The function-name and each dummy-arg-name
+ shall be specified, explicitly or implicitly, to be scalar. */
+ gfc_error ("Argument '%s' of statement function '%s' at %L "
+ "must be scalar", sym->name, proc->name,
+ &proc->declared_at);
continue;
}
@@ -8341,6 +8344,9 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
code->expr1->symtree->n.sym->ts = code->expr2->ts;
selector_type = CLASS_DATA (code->expr2)->ts.u.derived;
+ if (code->expr2->rank && CLASS_DATA (code->expr1)->as)
+ CLASS_DATA (code->expr1)->as->rank = code->expr2->rank;
+
/* F2008: C803 The selector expression must not be coindexed. */
if (gfc_is_coindexed (code->expr2))
{
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 75fedc0f598..ac443d81f50 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -4017,10 +4017,23 @@ gfc_simplify_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b)
|| !is_constant_array_expr (matrix_b))
return NULL;
- gcc_assert (gfc_compare_types (&matrix_a->ts, &matrix_b->ts));
- result = gfc_get_array_expr (matrix_a->ts.type,
- matrix_a->ts.kind,
- &matrix_a->where);
+ /* MATMUL should do mixed-mode arithmetic. Set the result type. */
+ if (matrix_a->ts.type != matrix_b->ts.type)
+ {
+ gfc_expr e;
+ e.expr_type = EXPR_OP;
+ gfc_clear_ts (&e.ts);
+ e.value.op.op = INTRINSIC_NONE;
+ e.value.op.op1 = matrix_a;
+ e.value.op.op2 = matrix_b;
+ gfc_type_convert_binary (&e, 1);
+ result = gfc_get_array_expr (e.ts.type, e.ts.kind, &matrix_a->where);
+ }
+ else
+ {
+ result = gfc_get_array_expr (matrix_a->ts.type, matrix_a->ts.kind,
+ &matrix_a->where);
+ }
if (matrix_a->rank == 1 && matrix_b->rank == 2)
{
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index b1a07f5defd..c9ed95bbd9f 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2615,6 +2615,8 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
gfc_init_se (&se, NULL);
se.loop = loop;
se.ss = ss;
+ if (gfc_is_class_array_function (expr))
+ expr->must_finalize = 1;
gfc_conv_expr (&se, expr);
gfc_add_block_to_block (&outer_loop->pre, &se.pre);
gfc_add_block_to_block (&outer_loop->post, &se.post);
@@ -3045,7 +3047,7 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
if (expr == NULL
|| (expr->ts.type != BT_CLASS
- && !gfc_is_alloc_class_array_function (expr)))
+ && !gfc_is_class_array_function (expr)))
return false;
if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
@@ -3074,12 +3076,12 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
return false;
if (class_ref == NULL && expr->symtree->n.sym->attr.function
- && expr->symtree->n.sym == expr->symtree->n.sym->result)
+ && expr->symtree->n.sym == expr->symtree->n.sym->result
+ && expr->symtree->n.sym->backend_decl == current_function_decl)
{
- gcc_assert (expr->symtree->n.sym->backend_decl == current_function_decl);
decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
}
- else if (gfc_is_alloc_class_array_function (expr))
+ else if (gfc_is_class_array_function (expr))
{
size = NULL_TREE;
decl = NULL_TREE;
@@ -3102,6 +3104,8 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
if (decl == NULL_TREE)
return false;
+
+ se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
}
else if (class_ref == NULL)
{
@@ -9537,7 +9541,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
if (!sym)
sym = expr->symtree->n.sym;
- if (gfc_is_alloc_class_array_function (expr))
+ if (gfc_is_class_array_function (expr))
return gfc_get_array_ss (ss, expr,
CLASS_DATA (expr->value.function.esym->result)->as->rank,
GFC_SS_FUNCTION);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 36f882029e2..7b30380f50a 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4007,6 +4007,24 @@ gfc_null_and_pass_deferred_len (gfc_symbol *sym, stmtblock_t *init,
return tmp;
}
+
+/* Get the result expression for a procedure. */
+
+static tree
+get_proc_result (gfc_symbol* sym)
+{
+ if (sym->attr.subroutine || sym == sym->result)
+ {
+ if (current_fake_result_decl != NULL)
+ return TREE_VALUE (current_fake_result_decl);
+
+ return NULL_TREE;
+ }
+
+ return sym->result->backend_decl;
+}
+
+
/* Generate function entry and exit code, and add it to the function body.
This includes:
Allocation and initialization of array variables.
@@ -4116,6 +4134,21 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
else
gcc_assert (flag_f2c && proc_sym->ts.type == BT_COMPLEX);
}
+ else if (proc_sym == proc_sym->result && IS_CLASS_ARRAY (proc_sym))
+ {
+ /* Nullify explicit return class arrays on entry. */
+ tree type;
+ tmp = get_proc_result (proc_sym);
+ if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
+ {
+ gfc_start_block (&init);
+ tmp = gfc_class_data_get (tmp);
+ type = TREE_TYPE (gfc_conv_descriptor_data_get (tmp));
+ gfc_conv_descriptor_data_set (&init, tmp, build_int_cst (type, 0));
+ gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
+ }
+ }
+
/* Initialize the INTENT(OUT) derived type dummy arguments. This
should be done here so that the offsets and lbounds of arrays
@@ -5830,23 +5863,6 @@ create_main_function (tree fndecl)
}
-/* Get the result expression for a procedure. */
-
-static tree
-get_proc_result (gfc_symbol* sym)
-{
- if (sym->attr.subroutine || sym == sym->result)
- {
- if (current_fake_result_decl != NULL)
- return TREE_VALUE (current_fake_result_decl);
-
- return NULL_TREE;
- }
-
- return sym->result->backend_decl;
-}
-
-
/* Generate an appropriate return-statement for a procedure. */
tree
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index f1b7bfd9d6b..32b7b7c055a 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -890,6 +890,7 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
}
if ((ref == NULL || class_ref == ref)
+ && !(gfc_is_class_array_function (e) && parmse->class_vptr != NULL_TREE)
&& (!class_ts.u.derived->components->as
|| class_ts.u.derived->components->as->rank != -1))
return;
@@ -960,8 +961,11 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
First we have to find the corresponding class reference. */
tmp = NULL_TREE;
- if (class_ref == NULL
- && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
+ if (gfc_is_class_array_function (e)
+ && parmse->class_vptr != NULL_TREE)
+ tmp = parmse->class_vptr;
+ else if (class_ref == NULL
+ && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
{
tmp = e->symtree->n.sym->backend_decl;
if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
@@ -988,7 +992,11 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
if (TREE_CODE (TREE_TYPE (tmp)) == REFERENCE_TYPE)
tmp = build_fold_indirect_ref_loc (input_location, tmp);
- vptr = gfc_class_vptr_get (tmp);
+ if (!(gfc_is_class_array_function (e) && parmse->class_vptr))
+ vptr = gfc_class_vptr_get (tmp);
+ else
+ vptr = tmp;
+
gfc_add_modify (&block, ctree,
fold_convert (TREE_TYPE (ctree), vptr));
@@ -2348,7 +2356,7 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
On the other hand, if the context is a UNION or a MAP (a
RECORD_TYPE within a UNION_TYPE) always use the given FIELD_DECL. */
- if (context != TREE_TYPE (decl)
+ if (context != TREE_TYPE (decl)
&& !( TREE_CODE (TREE_TYPE (field)) == UNION_TYPE /* Field is union */
|| TREE_CODE (context) == UNION_TYPE)) /* Field is map */
{
@@ -4279,6 +4287,8 @@ gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping,
if (expr->value.function.esym == NULL
&& expr->value.function.isym != NULL
+ && expr->value.function.actual
+ && expr->value.function.actual->expr
&& expr->value.function.actual->expr->symtree
&& gfc_map_intrinsic_function (expr, mapping))
break;
@@ -4407,7 +4417,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
/* Reset the offset for the function call since the loop
is zero based on the data pointer. Note that the temp
comes first in the loop chain since it is added second. */
- if (gfc_is_alloc_class_array_function (expr))
+ if (gfc_is_class_array_function (expr))
{
tmp = loop.ss->loop_chain->info->data.array.descriptor;
gfc_conv_descriptor_offset_set (&loop.pre, tmp,
@@ -4456,7 +4466,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
dimen = rse.ss->dimen;
/* Skip the write-out loop for this case. */
- if (gfc_is_alloc_class_array_function (expr))
+ if (gfc_is_class_array_function (expr))
goto class_array_fcn;
/* Calculate the bounds of the scalarization. */
@@ -4749,7 +4759,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gcc_assert ((!comp && gfc_return_by_reference (sym)
&& sym->result->attr.dimension)
|| (comp && comp->attr.dimension)
- || gfc_is_alloc_class_array_function (expr));
+ || gfc_is_class_array_function (expr));
gcc_assert (se->loop != NULL);
/* Access the previously obtained result. */
gfc_conv_tmp_array_ref (se);
@@ -5402,7 +5412,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
fsym ? fsym->attr.intent : INTENT_INOUT,
fsym && fsym->attr.pointer);
- else if (gfc_is_alloc_class_array_function (e)
+ else if (gfc_is_class_array_function (e)
&& fsym && fsym->ts.type == BT_DERIVED)
/* See previous comment. For function actual argument,
the write out is not needed so the intent is set as
@@ -6191,7 +6201,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
call the finalization function of the temporary. Note that the
nullification of allocatable components needed by the result
is done in gfc_trans_assignment_1. */
- if (expr && ((gfc_is_alloc_class_array_function (expr)
+ if (expr && ((gfc_is_class_array_function (expr)
&& se->ss && se->ss->loop)
|| gfc_is_alloc_class_scalar_function (expr))
&& se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
@@ -6202,6 +6212,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
int n;
if (se->ss && se->ss->loop)
{
+ gfc_add_block_to_block (&se->ss->loop->pre, &se->pre);
se->expr = gfc_evaluate_now (se->expr, &se->ss->loop->pre);
tmp = gfc_class_data_get (se->expr);
info->descriptor = tmp;
@@ -6224,6 +6235,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
CLASS_DATA (expr->value.function.esym->result)->attr);
}
+ if ((gfc_is_class_array_function (expr)
+ || gfc_is_alloc_class_scalar_function (expr))
+ && CLASS_DATA (expr->value.function.esym->result)->attr.pointer)
+ goto no_finalization;
+
final_fndecl = gfc_class_vtab_final_get (se->expr);
is_final = fold_build2_loc (input_location, NE_EXPR,
boolean_type_node,
@@ -6254,6 +6270,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
tmp = gfc_call_free (tmp);
gfc_add_expr_to_block (&se->post, tmp);
}
+
+no_finalization:
expr->must_finalize = 0;
}
@@ -8392,7 +8410,7 @@ arrayfunc_assign_needs_temporary (gfc_expr * expr1, gfc_expr * expr2)
gfc_symbol *sym = expr1->symtree->n.sym;
/* Play it safe with class functions assigned to a derived type. */
- if (gfc_is_alloc_class_array_function (expr2)
+ if (gfc_is_class_array_function (expr2)
&& expr1->ts.type == BT_DERIVED)
return true;
@@ -9271,7 +9289,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
rss = NULL;
if ((expr1->ts.type == BT_DERIVED)
- && (gfc_is_alloc_class_array_function (expr2)
+ && (gfc_is_class_array_function (expr2)
|| gfc_is_alloc_class_scalar_function (expr2)))
expr2->must_finalize = 1;
@@ -9442,9 +9460,9 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
nullification occurs before the call to the finalizer. In the case of
a scalar to array assignment, this is done in gfc_trans_scalar_assign
as part of the deep copy. */
- if (!scalar_to_array && (expr1->ts.type == BT_DERIVED)
- && (gfc_is_alloc_class_array_function (expr2)
- || gfc_is_alloc_class_scalar_function (expr2)))
+ if (!scalar_to_array
+ && (expr1->ts.type == BT_DERIVED)
+ && (gfc_is_class_array_function (expr2) || gfc_is_alloc_class_scalar_function (expr2)))
{
tmp = rse.expr;
tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, rse.expr, 0);
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index fea26d15d0f..bad959bda88 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -4693,6 +4693,22 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr)
}
static void
+gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr)
+{
+ gfc_actual_arglist *s, *k;
+ gfc_expr *e;
+
+ /* Remove the KIND argument, if present. */
+ s = expr->value.function.actual;
+ k = s->next;
+ e = k->expr;
+ gfc_free_expr (e);
+ k->expr = NULL;
+
+ gfc_conv_intrinsic_funcall (se, expr);
+}
+
+static void
gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
bool arithmetic)
{
@@ -5816,7 +5832,7 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr)
gfc_add_class_array_ref (actual->expr);
argse.data_not_needed = 1;
- if (gfc_is_alloc_class_array_function (actual->expr))
+ if (gfc_is_class_array_function (actual->expr))
{
/* For functions that return a class array conv_expr_descriptor is not
able to get the descriptor right. Therefore this special case. */
@@ -7753,6 +7769,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
conv_generic_with_optional_char_arg (se, expr, 1, 3);
break;
+ case GFC_ISYM_SHAPE:
+ gfc_conv_intrinsic_shape (se, expr);
+ break;
+
default:
gfc_conv_intrinsic_funcall (se, expr);
break;
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 125f45ceb2a..a6764a175d7 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -611,12 +611,12 @@ set_parameter_value_inquire (stmtblock_t *block, tree var,
/* Don't evaluate the UNIT number multiple times. */
se.expr = gfc_evaluate_now (se.expr, &se.pre);
- /* UNIT numbers should be greater than zero. */
+ /* UNIT numbers should be greater than the min. */
i = gfc_validate_kind (BT_INTEGER, 4, false);
+ val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
cond1 = build2_loc (input_location, LT_EXPR, boolean_type_node,
se.expr,
- fold_convert (TREE_TYPE (se.expr),
- integer_zero_node));
+ fold_convert (TREE_TYPE (se.expr), val));
/* UNIT numbers should be less than the max. */
val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
cond2 = build2_loc (input_location, GT_EXPR, boolean_type_node,
@@ -2104,6 +2104,16 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
ts->kind = gfc_index_integer_kind;
}
+ /* gfortran reaches here for "print *, c_loc(xxx)". */
+ if (ts->type == BT_VOID
+ && code->expr1 && code->expr1->ts.type == BT_VOID
+ && code->expr1->symtree
+ && strcmp (code->expr1->symtree->name, "c_loc") == 0)
+ {
+ ts->type = BT_INTEGER;
+ ts->kind = gfc_index_integer_kind;
+ }
+
kind = ts->kind;
function = NULL;
arg2 = NULL;
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 98bb9514777..caa346f7016 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -544,6 +544,24 @@ determine_versionability (struct cgraph_node *node,
reason = "calls comdat-local function";
}
+ /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN
+ works only when inlined. Cloning them may still lead to better code
+ becuase ipa-cp will not give up on cloning further. If the function is
+ external this however leads to wrong code becuase we may end up producing
+ offline copy of the function. */
+ if (DECL_EXTERNAL (node->decl))
+ for (cgraph_edge *edge = node->callees; !reason && edge;
+ edge = edge->next_callee)
+ if (DECL_BUILT_IN (edge->callee->decl)
+ && DECL_BUILT_IN_CLASS (edge->callee->decl) == BUILT_IN_NORMAL)
+ {
+ if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
+ reason = "external function which calls va_arg_pack";
+ if (DECL_FUNCTION_CODE (edge->callee->decl)
+ == BUILT_IN_VA_ARG_PACK_LEN)
+ reason = "external function which calls va_arg_pack_len";
+ }
+
if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
node->name (), node->order, reason);
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 5eb7d5f31aa..cee0c6c95d0 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -403,6 +403,8 @@ ipa_merge_profiles (struct cgraph_node *dst,
if (!dst->count)
return;
+ if (!src->count || src->alias)
+ return;
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "Merging profiles of %s/%i to %s/%i\n",
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 4d26e2f7cd1..c68cbc54892 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -477,7 +477,7 @@ unroll_loop_constant_iterations (struct loop *loop)
exit_mod = niter % (max_unroll + 1);
- wont_exit = sbitmap_alloc (max_unroll + 1);
+ wont_exit = sbitmap_alloc (max_unroll + 2);
bitmap_ones (wont_exit);
auto_vec<edge> remove_edges;
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 6703d4106de..57d946d15fa 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2517,14 +2517,10 @@ write_symbol (struct streamer_tree_cache_d *cache,
const char *comdat;
unsigned char c;
- /* None of the following kinds of symbols are needed in the
- symbol table. */
- if (!TREE_PUBLIC (t)
- || is_builtin_fn (t)
- || DECL_ABSTRACT_P (t)
- || (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t)))
- return;
- gcc_assert (TREE_CODE (t) != RESULT_DECL);
+ gcc_checking_assert (TREE_PUBLIC (t)
+ && !is_builtin_fn (t)
+ && !DECL_ABSTRACT_P (t)
+ && (!VAR_P (t) || !DECL_HARD_REGISTER (t)));
gcc_assert (TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == FUNCTION_DECL);
@@ -2614,45 +2610,6 @@ write_symbol (struct streamer_tree_cache_d *cache,
lto_write_data (&slot_num, 4);
}
-/* Return true if NODE should appear in the plugin symbol table. */
-
-bool
-output_symbol_p (symtab_node *node)
-{
- struct cgraph_node *cnode;
- if (!node->real_symbol_p ())
- return false;
- /* We keep external functions in symtab for sake of inlining
- and devirtualization. We do not want to see them in symbol table as
- references unless they are really used. */
- cnode = dyn_cast <cgraph_node *> (node);
- if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
- && cnode->callers)
- return true;
-
- /* Ignore all references from external vars initializers - they are not really
- part of the compilation unit until they are used by folding. Some symbols,
- like references to external construction vtables can not be referred to at all.
- We decide this at can_refer_decl_in_current_unit_p. */
- if (!node->definition || DECL_EXTERNAL (node->decl))
- {
- int i;
- struct ipa_ref *ref;
- for (i = 0; node->iterate_referring (i, ref); i++)
- {
- if (ref->use == IPA_REF_ALIAS)
- continue;
- if (is_a <cgraph_node *> (ref->referring))
- return true;
- if (!DECL_EXTERNAL (ref->referring->decl))
- return true;
- }
- return false;
- }
- return true;
-}
-
-
/* Write an IL symbol table to OB.
SET and VSET are cgraph/varpool node sets we are outputting. */
@@ -2677,7 +2634,7 @@ produce_symtab (struct output_block *ob)
{
symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
+ if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
continue;
write_symbol (cache, node->decl, &seen, false);
}
@@ -2686,7 +2643,7 @@ produce_symtab (struct output_block *ob)
{
symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
+ if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
continue;
write_symbol (cache, node->decl, &seen, false);
}
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 16431e8dc65..c755b383d6d 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,76 @@
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-23 Martin Liska <mliska@suse.cz>
+
+ PR lto/81440
+ * lto-symtab.c (lto_symtab_merge): Handle and do not warn about
+ trailing arrays at the end of a struct.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-08 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-partition.c (lto_balanced_map): Watch overflow.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-08 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/81360
+ * lto.c (unify_scc): Register prevailing trees, not trees to be freed.
+ (read_cgraph_and_symbols): Use
+ symtab_node::output_to_lto_symbol_table_p.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto.c (register_resolution): Remove forgotten sanity check.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-30 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/81004
+ * lto.c: Include builtins.h
+ (register_resolution): Merge resolutions in case trees was
+ merged across units.
+ (lto_maybe_register_decl): Break out from ...
+ (lto_read_decls): ... here.
+ (unify_scc): Also register decls here.
+ (read_cgraph_and_symbols): Sanity check that all resolutions was
+ read.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR lto/83954
+ * lto-symtab.c (warn_type_compatibility_p): Do not recurse into the
+ component type of array types with non-aliased component.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-30 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/83954
+ * lto-symtab.c (warn_type_compatibility_p): Silence false positive
+ for type match warning on arrays of pointers.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2017-10-13 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-lang.c (lto_post_options): Clean shlib flag when not doing PIC.
+
2017-07-04 Release Manager
* GCC 6.4.0 released.
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index ebe908a3e17..0b0db619562 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -837,11 +837,13 @@ lto_post_options (const char **pfilename ATTRIBUTE_UNUSED)
flag_pie is 2. */
flag_pie = MAX (flag_pie, flag_pic);
flag_pic = flag_pie;
+ flag_shlib = 0;
break;
case LTO_LINKER_OUTPUT_EXEC: /* Normal executable */
flag_pic = 0;
flag_pie = 0;
+ flag_shlib = 0;
break;
case LTO_LINKER_OUTPUT_UNKNOWN:
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 3340d16c7c7..687396cfd55 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -755,7 +755,8 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
if (npartitions < n_lto_partitions)
partition_size = total_size / (n_lto_partitions - npartitions);
else
- partition_size = INT_MAX;
+ /* Watch for overflow. */
+ partition_size = INT_MAX / 16;
if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
partition_size = PARAM_VALUE (MIN_PARTITION_SIZE);
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 94b919b53e6..6b3b785b674 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -280,11 +280,25 @@ warn_type_compatibility_p (tree prevailing_type, tree type,
alias_set_type set1 = get_alias_set (type);
alias_set_type set2 = get_alias_set (prevailing_type);
- if (set1 && set2 && set1 != set2
- && (!POINTER_TYPE_P (type) || !POINTER_TYPE_P (prevailing_type)
+ if (set1 && set2 && set1 != set2)
+ {
+ tree t1 = type, t2 = prevailing_type;
+
+ /* Alias sets of arrays with aliased components are the same as alias
+ sets of the inner types. */
+ while (TREE_CODE (t1) == ARRAY_TYPE
+ && !TYPE_NONALIASED_COMPONENT (t1)
+ && TREE_CODE (t2) == ARRAY_TYPE
+ && !TYPE_NONALIASED_COMPONENT (t2))
+ {
+ t1 = TREE_TYPE (t1);
+ t2 = TREE_TYPE (t2);
+ }
+ if ((!POINTER_TYPE_P (t1) || !POINTER_TYPE_P (t2))
|| (set1 != TYPE_ALIAS_SET (ptr_type_node)
- && set2 != TYPE_ALIAS_SET (ptr_type_node))))
- lev |= 5;
+ && set2 != TYPE_ALIAS_SET (ptr_type_node)))
+ lev |= 5;
+ }
}
return lev;
@@ -348,18 +362,31 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
return false;
if (DECL_SIZE (decl) && DECL_SIZE (prevailing_decl)
- && !tree_int_cst_equal (DECL_SIZE (decl), DECL_SIZE (prevailing_decl))
+ && !tree_int_cst_equal (DECL_SIZE (decl), DECL_SIZE (prevailing_decl)))
+ {
+ if (!DECL_COMMON (decl) && !DECL_EXTERNAL (decl))
+ return false;
+
+ tree type = TREE_TYPE (decl);
+
+ /* For record type, check for array at the end of the structure. */
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ tree field = TYPE_FIELDS (type);
+ while (DECL_CHAIN (field) != NULL_TREE)
+ field = DECL_CHAIN (field);
+
+ return TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE;
+ }
/* As a special case do not warn about merging
int a[];
and
int a[]={1,2,3};
here the first declaration is COMMON
and sizeof(a) == sizeof (int). */
- && ((!DECL_COMMON (decl) && !DECL_EXTERNAL (decl))
- || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE
- || TYPE_SIZE (TREE_TYPE (decl))
- != TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl)))))
- return false;
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return (TYPE_SIZE (decl) == TYPE_SIZE (TREE_TYPE (type)));
+ }
return true;
}
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 3acc57f43ae..09d837537e0 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-symtab.h"
#include "stringpool.h"
#include "fold-const.h"
+#include "builtins.h"
/* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */
@@ -828,12 +829,19 @@ static void
register_resolution (struct lto_file_decl_data *file_data, tree decl,
enum ld_plugin_symbol_resolution resolution)
{
+ bool existed;
if (resolution == LDPR_UNKNOWN)
return;
if (!file_data->resolution_map)
file_data->resolution_map
= new hash_map<tree, ld_plugin_symbol_resolution>;
- file_data->resolution_map->put (decl, resolution);
+ ld_plugin_symbol_resolution_t &res
+ = file_data->resolution_map->get_or_insert (decl, &existed);
+ if (!existed
+ || resolution == LDPR_PREVAILING_DEF_IRONLY
+ || resolution == LDPR_PREVAILING_DEF
+ || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ res = resolution;
}
/* Register DECL with the global symbol table and change its
@@ -876,6 +884,18 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl,
decl, get_resolution (data_in, ix));
}
+/* Check if T is a decl and needs register its resolution info. */
+
+static void
+lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix)
+{
+ if (TREE_CODE (t) == VAR_DECL)
+ lto_register_var_decl_in_symtab (data_in, t, ix);
+ else if (TREE_CODE (t) == FUNCTION_DECL
+ && !DECL_BUILT_IN (t))
+ lto_register_function_decl_in_symtab (data_in, t, ix);
+}
+
/* For the type T re-materialize it in the type variant list and
the pointer/reference-to chains. */
@@ -1611,7 +1631,10 @@ unify_scc (struct data_in *data_in, unsigned from,
/* Fixup the streamer cache with the prevailing nodes according
to the tree node mapping computed by compare_tree_sccs. */
if (len == 1)
- streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
+ {
+ lto_maybe_register_decl (data_in, pscc->entries[0], from);
+ streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
+ }
else
{
tree *map2 = XALLOCAVEC (tree, 2 * len);
@@ -1623,8 +1646,12 @@ unify_scc (struct data_in *data_in, unsigned from,
qsort (map2, len, 2 * sizeof (tree), cmp_tree);
qsort (map, len, 2 * sizeof (tree), cmp_tree);
for (unsigned i = 0; i < len; ++i)
- streamer_tree_cache_replace_tree (cache, map[2*i],
- (uintptr_t)map2[2*i]);
+ {
+ lto_maybe_register_decl (data_in, map[2*i],
+ (uintptr_t)map2[2*i]);
+ streamer_tree_cache_replace_tree (cache, map[2*i],
+ (uintptr_t)map2[2*i]);
+ }
}
/* Free the tree nodes from the read SCC. */
@@ -1764,13 +1791,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
}
if (!flag_ltrans)
{
- /* Register variables and functions with the
- symbol table. */
- if (TREE_CODE (t) == VAR_DECL)
- lto_register_var_decl_in_symtab (data_in, t, from + i);
- else if (TREE_CODE (t) == FUNCTION_DECL
- && !DECL_BUILT_IN (t))
- lto_register_function_decl_in_symtab (data_in, t, from + i);
+ lto_maybe_register_decl (data_in, t, from + i);
/* Scan the tree for references to global functions or
variables and record those for later fixup. */
if (mentions_vars_p (t))
@@ -2861,13 +2882,25 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
/* Store resolutions into the symbol table. */
- ld_plugin_symbol_resolution_t *res;
FOR_EACH_SYMBOL (snode)
- if (snode->real_symbol_p ()
- && snode->lto_file_data
- && snode->lto_file_data->resolution_map
- && (res = snode->lto_file_data->resolution_map->get (snode->decl)))
- snode->resolution = *res;
+ if (snode->externally_visible && snode->real_symbol_p ()
+ && snode->lto_file_data && snode->lto_file_data->resolution_map
+ && !is_builtin_fn (snode->decl)
+ && !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl)))
+ {
+ ld_plugin_symbol_resolution_t *res;
+
+ res = snode->lto_file_data->resolution_map->get (snode->decl);
+ if (!res || *res == LDPR_UNKNOWN)
+ {
+ if (snode->output_to_lto_symbol_table_p ())
+ fatal_error (input_location, "missing resolution data for %s",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (snode->decl)));
+ }
+ else
+ snode->resolution = *res;
+ }
for (i = 0; all_file_decl_data[i]; i++)
if (all_file_decl_data[i]->resolution_map)
{
diff --git a/gcc/opts.c b/gcc/opts.c
index 8f9862db57c..1467782bc3a 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -972,6 +972,26 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
opts->x_flag_aggressive_loop_optimizations = 0;
opts->x_flag_strict_overflow = 0;
}
+
+ /* Comes from final.c -- no real reason to change it. */
+#define MAX_CODE_ALIGN 16
+#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
+
+ if (opts->x_align_loops > MAX_CODE_ALIGN_VALUE)
+ error_at (loc, "-falign-loops=%d is not between 0 and %d",
+ opts->x_align_loops, MAX_CODE_ALIGN_VALUE);
+
+ if (opts->x_align_jumps > MAX_CODE_ALIGN_VALUE)
+ error_at (loc, "-falign-jumps=%d is not between 0 and %d",
+ opts->x_align_jumps, MAX_CODE_ALIGN_VALUE);
+
+ if (opts->x_align_functions > MAX_CODE_ALIGN_VALUE)
+ error_at (loc, "-falign-functions=%d is not between 0 and %d",
+ opts->x_align_functions, MAX_CODE_ALIGN_VALUE);
+
+ if (opts->x_align_labels > MAX_CODE_ALIGN_VALUE)
+ error_at (loc, "-falign-labels=%d is not between 0 and %d",
+ opts->x_align_labels, MAX_CODE_ALIGN_VALUE);
}
#define LEFT_COLUMN 27
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 902b68780fe..fe45c7eea54 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -2064,7 +2064,7 @@ dead_or_set_regno_p (const_rtx insn, unsigned int test_regno)
if (GET_CODE (pattern) == COND_EXEC)
return 0;
- if (GET_CODE (pattern) == SET)
+ if (GET_CODE (pattern) == SET || GET_CODE (pattern) == CLOBBER)
return covers_regno_p (SET_DEST (pattern), test_regno);
else if (GET_CODE (pattern) == PARALLEL)
{
diff --git a/gcc/symtab.c b/gcc/symtab.c
index ef2524ba642..b867000c354 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "ipa-utils.h"
#include "calls.h"
+#include "builtins.h"
static const char *ipa_ref_use_name[] = {"read","write","addr","alias","chkp"};
@@ -2207,3 +2208,58 @@ symbol_table::symbol_suffix_separator ()
return '_';
#endif
}
+
+/* Return true if symbol should be output to the symbol table. */
+
+bool
+symtab_node::output_to_lto_symbol_table_p (void)
+{
+ /* Only externally visible symbols matter. */
+ if (!TREE_PUBLIC (decl))
+ return false;
+ if (!real_symbol_p ())
+ return false;
+ /* FIXME: variables probably should not be considered as real symbols at
+ first place. */
+ if (VAR_P (decl) && DECL_HARD_REGISTER (decl))
+ return false;
+ /* FIXME: Builtins corresponding to real functions probably should have
+ symbol table entries. */
+ if (is_builtin_fn (decl))
+ return false;
+
+ /* We have real symbol that should be in symbol table. However try to trim
+ down the refernces to libraries bit more because linker will otherwise
+ bring unnecesary object files into the final link.
+ FIXME: The following checks can easily be confused i.e. by self recursive
+ function or self-referring variable. */
+
+ /* We keep external functions in symtab for sake of inlining
+ and devirtualization. We do not want to see them in symbol table as
+ references unless they are really used. */
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode && (!definition || DECL_EXTERNAL (decl))
+ && cnode->callers)
+ return true;
+
+ /* Ignore all references from external vars initializers - they are not really
+ part of the compilation unit until they are used by folding. Some symbols,
+ like references to external construction vtables can not be referred to at
+ all. We decide this at can_refer_decl_in_current_unit_p. */
+ if (!definition || DECL_EXTERNAL (decl))
+ {
+ int i;
+ struct ipa_ref *ref;
+ for (i = 0; iterate_referring (i, ref); i++)
+ {
+ if (ref->use == IPA_REF_ALIAS)
+ continue;
+ if (is_a <cgraph_node *> (ref->referring))
+ return true;
+ if (!DECL_EXTERNAL (ref->referring->decl))
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 48b2a18f813..8eaa7830fd3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,290 @@
+2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-02-08 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * gcc.target/s390/nobp-function-pointer-attr.c: New test.
+ * gcc.target/s390/nobp-function-pointer-nothunk.c: New test.
+ * gcc.target/s390/nobp-function-pointer-z10.c: New test.
+ * gcc.target/s390/nobp-function-pointer-z900.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-attr.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-inline-attr.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-inline-z10.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-inline-z900.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-nothunk.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-z10.c: New test.
+ * gcc.target/s390/nobp-indirect-jump-z900.c: New test.
+ * gcc.target/s390/nobp-return-attr-all.c: New test.
+ * gcc.target/s390/nobp-return-attr-neg.c: New test.
+ * gcc.target/s390/nobp-return-mem-attr.c: New test.
+ * gcc.target/s390/nobp-return-mem-nothunk.c: New test.
+ * gcc.target/s390/nobp-return-mem-z10.c: New test.
+ * gcc.target/s390/nobp-return-mem-z900.c: New test.
+ * gcc.target/s390/nobp-return-reg-attr.c: New test.
+ * gcc.target/s390/nobp-return-reg-mixed.c: New test.
+ * gcc.target/s390/nobp-return-reg-nothunk.c: New test.
+ * gcc.target/s390/nobp-return-reg-z10.c: New test.
+ * gcc.target/s390/nobp-return-reg-z900.c: New test.
+ * gcc.target/s390/nobp-table-jump-inline-z10.c: New test.
+ * gcc.target/s390/nobp-table-jump-inline-z900.c: New test.
+ * gcc.target/s390/nobp-table-jump-z10.c: New test.
+ * gcc.target/s390/nobp-table-jump-z900.c: New test.
+
+2018-03-07 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ Backport from mainline
+ 2018-02-09 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/PR84295
+ * gcc.target/s390/pr84295.c: New test.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-02-20 Martin Liska <mliska@suse.cz>
+
+ PR c/84310
+ PR target/79747
+ * gcc.target/i386/pr84310.c: New test.
+ * gcc.target/i386/pr84310-2.c: Likewise.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-23 Martin Liska <mliska@suse.cz>
+
+ PR lto/81440
+ * gcc.dg/lto/pr81440.h: New test.
+ * gcc.dg/lto/pr81440_0.c: New test.
+ * gcc.dg/lto/pr81440_1.c: New test.
+
+2018-03-07 Martin Liska <mliska@suse.cz>
+
+ Backport from mainline
+ 2018-01-30 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/83954
+ * gcc.dg/lto/pr83954.h: New testcase.
+ * gcc.dg/lto/pr83954_0.c: New testcase.
+ * gcc.dg/lto/pr83954_1.c: New testcase.
+
+2018-03-06 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/56667
+ * gfortran.dg/implied_do_2.f90: New test.
+ * gfortran.dg/coarray_8.f90: Update for new error message.
+
+2018-03-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/71085
+ * gfortran.dg/pr71085.f90: New test.
+
+2018-03-03 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from trunk.
+ PR fortran/78990
+ * gfortran.dg/class_67.f90: New test.
+
+2017-03-02 Thomas Schwinge <thomas@codesourcery.com>
+
+ Backport from trunk r256891:
+ 2018-01-19 Cesar Philippidis <cesar@codesourcery.com>
+
+ PR target/83790
+ * gcc.target/nvptx/indirect_call.c: New test.
+
+2018-02-28 Alan Modra <amodra@gmail.com>
+
+ * lib/prune.exp (prune_gcc_output): Match lower case "in function"
+ GNU ld message.
+ * g++.dg/other/anon5.C: Match lower case "bad value" GNU ld message.
+
+2018-02-25 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83633
+ * gfortran.dg/explicit_shape_1.f90: New test.
+ * gfortran.dg/automatic_module_variable.f90: Update regex.
+ * gfortran.dg/bad_automatic_objects_1.f90: Ditto.
+
+2018-02-24 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/30792
+ * gfortran.dg/data_substring.f90: New test.
+
+2018-02-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from trunk
+ PR fortran/84506
+ * gfortran.dg/inquire_19.f90: New test.
+
+2018-02-23 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/84346
+ * gfortran.dg/statement_function_1.f90: Update test.
+
+2018-02-21 Sudakshina Das <sudi.das@arm.com>
+
+ Backport from trunk
+ 2018-01-12 Sudakshina Das <sudi.das@arm.com>
+
+ * gcc.c-torture/compile/pr82096.c: Add dg-skip-if
+ directive.
+
+ Backport from trunk
+ 2018-01-10 Sudakshina Das <sudi.das@arm.com>
+
+ PR target/82096
+ * gcc.c-torture/compile/pr82096.c: New test.
+
+2018-02-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/84277
+ * gnat.dg/array11.adb (Array11): Tweak index and remove warning.
+ * gnat.dg/dispatch1.adb: Rename into...
+ * gnat.dg/disp1.adb: ...this.
+ * gnat.dg/dispatch1_p.ads: Rename into...
+ * gnat.dg/disp1_pkg.ads: ...this.
+ * gnat.dg/disp2.adb: Rename into...
+ * gnat.dg/dispatch2.adb: ...this.
+ * gnat.dg/dispatch2_p.ads: Rename into...
+ * gnat.dg/disp2_pkg.ads: ...this.
+ * gnat.dg/dispatch2_p.adb: Rename into...
+ * gnat.dg/disp2_pkg.adb: this.
+ * gnat.dg/generic_dispatch.adb: Rename into...
+ * gnat.dg/generic_disp.adb: this.
+ * gnat.dg/generic_dispatch_p.ads: Rename into...
+ * gnat.dg/generic_disp_pkg.ads: ...this.
+ * gnat.dg/generic_dispatch_p.adb: Rename into...
+ * gnat.dg/generic_disp_pkg.adb: ...this.
+ * gnat.dg/null_pointer_deref1.adb (Null_Pointer_Deref1): Robustify.
+ * gnat.dg/null_pointer_deref2.adb (Null_Pointer_Deref2): Likewise.
+ * gnat.dg/object_overflow1.adb: Tweak index.
+ * gnat.dg/object_overflow2.adb: Likewise.
+ * gnat.dg/object_overflow3.adb: Likewise.
+ * gnat.dg/object_overflow4.adb: Likewise.
+ * gnat.dg/object_overflow5.adb: Likewise.
+
+2018-02-14 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from GCC 7 branch
+ 2018-02-14 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/84390
+ * gcc.target/powerpc/vsxcopy.c: Also match lxv when compiling
+ with -mcpu=power9.
+
+2018-02-12 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/68560
+ * gfortran.dg/shape_9.f90: New test.
+
+2018-02-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/35299
+ ChangeLog for r257566
+ * gfortran.dg/statement_function_3.f: New test.
+
+2018-02-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/54223
+ PR fortran/84276
+ * gfortran.dg/statement_function_1.f90: New test.
+ * gfortran.dg/statement_function_2.f90: New test.
+
+2018-02-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/82994
+ * gfortran.dg/deallocate_error_3.f90: New test.
+ * gfortran.dg/deallocate_error_4.f90: New test.
+
+2018-02-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/82049
+ * gfortran.dg/assumed_charlen_parameter.f90: New test.
+
+2018-02-01 Renlin Li <renlin.li@arm.com>
+
+ Backport from mainline
+ 2018-02-01 Richard Sandiford <richard.sandiford@linaro.org>
+
+ PR target/83370
+ * gcc.target/aarch64/pr83370.c: New.
+
+2018-02-01 Bin Cheng <bin.cheng@arm.com>
+
+ Backport from mainline
+ 2017-11-15 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/82726
+ * gcc.dg/tree-ssa/pr82726.c: New test.
+
+ Backport from mainline
+ 2017-01-23 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/70754
+ * gfortran.dg/pr70754.f90: New test.
+
+2018-02-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ Backport from mainline
+ 2018-01-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/target-supports.exp (check_effective_target_avx512f): Also
+ check for __builtin_ia32_addsd_round,
+ __builtin_ia32_getmantsd_round.
+ * gcc.target/i386/i386.exp (check_effective_target_avx512f):
+ Remove.
+
+2018-01-29 Alan Modra <amodra@gmail.com>
+
+ PR target/84033
+ * gcc.target/powerpc/swaps-p8-46.c: New.
+
+2018-01-23 Peter Bergner <bergner@vnet.ibm.com>
+
+ Back port from mainline
+ 2018-01-10 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/83399
+ * gcc.target/powerpc/pr83399.c: New test.
+
+2018-01-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ Back port from trunk
+ 2018-01-22 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/83862
+ * gcc.target/powerpc/pr83862.c: New test.
+
+2018-01-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83900
+ * gfortran.dg/matmul_18.f90: New test.
+
+2018-01-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/83900
+ * gfortran.dg/matmul_17.f90: New test.
+
+2018-01-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/80768
+ * gfortran.dg/num_images_1.f90: New test that tests fix in r250734.
+
+2018-01-17 Harald Anlauf <anlauf@gmx.de>
+
+ Back from mainline
+ PR fortran/83874
+ * gfortran.dg/pr83874.f90: New test.
+
+2018-01-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ Backport from mainline
+ 2017-12-18 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/83424
+ * gcc.dg/pr83424.c: New testsuite.
+
2018-01-14 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Backport from mainline
diff --git a/gcc/testsuite/g++.dg/cpp0x/elision3.C b/gcc/testsuite/g++.dg/cpp0x/elision3.C
new file mode 100644
index 00000000000..7c5c8b9f0b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/elision3.C
@@ -0,0 +1,21 @@
+// PR c++/84441
+// { dg-do compile { target c++11 } }
+
+struct B {
+ int *b;
+};
+struct A {
+ B b;
+ A (A &&);
+};
+struct C {
+ A c;
+ int d;
+};
+C bar ();
+struct D : C {
+ D ()
+ : C (0 ? bar () : bar ())
+ {}
+};
+D d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
new file mode 100644
index 00000000000..636bf1afd88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg7.C
@@ -0,0 +1,10 @@
+// PR c++/84489
+// { dg-do compile { target c++11 } }
+
+template <class T = int, T N = T(), bool B = (N >> 1)>
+T f1() {return 0;}
+
+int main()
+{
+ f1(); // Bug here
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual18.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual18.C
new file mode 100644
index 00000000000..aaa00b9cfc3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual18.C
@@ -0,0 +1,18 @@
+// PR c++/71784
+// { dg-do compile { target c++11 } }
+
+template<typename T> struct A {
+ template<typename U> void f(U const&) & { }
+ template<typename U> void f(U const&) && { }
+};
+
+template void A<int>::f<int>(int const&) &;
+template void A<float>::f<int>(int const&) &&;
+
+template<typename T> struct B {
+ void f(int const&) & { }
+ void f(int const&) && { }
+};
+
+template void B<int>::f(int const&) &;
+template void B<float>::f(int const&) &&;
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C
new file mode 100644
index 00000000000..89ce519d812
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-nsdmi1.C
@@ -0,0 +1,8 @@
+// PR c++/84520
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+ static void foo(int);
+ void (*f)(int) = [](auto i) { foo(i); };
+};
diff --git a/gcc/testsuite/g++.dg/other/anon5.C b/gcc/testsuite/g++.dg/other/anon5.C
index 2a6f57f12bc..ee4601e270e 100644
--- a/gcc/testsuite/g++.dg/other/anon5.C
+++ b/gcc/testsuite/g++.dg/other/anon5.C
@@ -4,7 +4,7 @@
// Ignore additional message on powerpc-ibm-aix
// { dg-prune-output "obtain more information" } */
// Ignore additional messages on Linux/x86 with PIE
-// { dg-prune-output "Bad value" } */
+// { dg-prune-output "\[Bb\]ad value" } */
namespace {
struct c
diff --git a/gcc/testsuite/g++.dg/tree-ssa/volatile1.C b/gcc/testsuite/g++.dg/tree-ssa/volatile1.C
new file mode 100644
index 00000000000..00f04a07d84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/volatile1.C
@@ -0,0 +1,28 @@
+// PR c++/84151
+// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-final { scan-tree-dump-not {\*this} "gimple" } }
+
+struct A {
+ static int& bar(int& a) {
+ return a;
+ }
+ static int i;
+
+ int foo() volatile {
+ int v = c;
+ return i + bar(v);
+ }
+
+ int c;
+};
+
+int A::i = 0;
+
+A a;
+
+int main() {
+ a.c = 2;
+ a.foo();
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/volatile2.C b/gcc/testsuite/g++.dg/tree-ssa/volatile2.C
new file mode 100644
index 00000000000..bec60442477
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/volatile2.C
@@ -0,0 +1,20 @@
+// PR c++/84686
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-times "= i" 10 "gimple" } }
+
+volatile int i;
+
+int main()
+{
+ i; //evaluated (a load is performed)
+ (i); //unevaluated => the load shall be performed
+
+ (void)i; //evaluated (a load is performed)
+ (void)(i); //unevaluated => the load shall be performed
+
+ (void)i; //evaluated (a load is performed)
+ (void)(i); //unevaluated => the load shall be performed
+
+ (i,i); // the two subexpression are evaluated
+ ((i),(i)); // no evaluation, => two loads shall happen
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr82096.c b/gcc/testsuite/gcc.c-torture/compile/pr82096.c
new file mode 100644
index 00000000000..d144b70585f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr82096.c
@@ -0,0 +1,11 @@
+/* { dg-require-effective-target arm_arch_v5t_ok { target arm*-*-* } } */
+/* { dg-skip-if "Do not combine float-abi values" { arm*-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=soft" } } */
+/* { dg-additional-options "-march=armv5t -mthumb -mfloat-abi=soft" { target arm*-*-* } } */
+
+static long long AL[24];
+
+int
+check_ok (void)
+{
+ return (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll));
+}
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c b/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
index e6bc1371f26..19457173eb3 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
@@ -3,9 +3,8 @@
the build not reproducible. Other skipped options could be tested here
as well. */
/* { dg-do compile } */
-/* { dg-options "-O2 -gdwarf -dA -fdebug-prefix-map=a=b" } */
-/* { dg-final { scan-assembler "DW_AT_producer: \"GNU C" { target { { { ! *-*-solaris2* } || gas } && { ! hppa*64*-*-* } } } } } */
-/* { dg-final { scan-assembler "\"GNU C\[^\\n\\r\]+ DW_AT_producer" { target { { *-*-solaris2* && { ! gas } } || { hppa*64*-*-* } } } } } */
+/* { dg-options "-O2 -gdwarf -dA -fno-merge-debug-strings -fdebug-prefix-map=a=b" } */
+/* { dg-final { scan-assembler "\"GNU C\[^\\n\\r\]+ DW_AT_producer" } } */
/* { dg-final { scan-assembler-not "debug-prefix-map" } } */
void func (void)
diff --git a/gcc/testsuite/gcc.dg/lto/pr81440.h b/gcc/testsuite/gcc.dg/lto/pr81440.h
new file mode 100644
index 00000000000..d9e6c3da645
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr81440.h
@@ -0,0 +1,4 @@
+typedef struct {
+ int i;
+ int ints[];
+} struct_t;
diff --git a/gcc/testsuite/gcc.dg/lto/pr81440_0.c b/gcc/testsuite/gcc.dg/lto/pr81440_0.c
new file mode 100644
index 00000000000..07f2a87da21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr81440_0.c
@@ -0,0 +1,9 @@
+/* { dg-lto-do link } */
+
+#include "pr81440.h"
+
+extern struct_t my_struct;
+
+int main() {
+ return my_struct.ints[0];
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr81440_1.c b/gcc/testsuite/gcc.dg/lto/pr81440_1.c
new file mode 100644
index 00000000000..d03533029c1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr81440_1.c
@@ -0,0 +1,6 @@
+#include "pr81440.h"
+
+struct_t my_struct = {
+ 20,
+ { 1, 2 }
+};
diff --git a/gcc/testsuite/gcc.dg/lto/pr83954.h b/gcc/testsuite/gcc.dg/lto/pr83954.h
new file mode 100644
index 00000000000..e0155402504
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr83954.h
@@ -0,0 +1,3 @@
+struct foo;
+extern struct foo *FOO_PTR_ARR[1];
+
diff --git a/gcc/testsuite/gcc.dg/lto/pr83954_0.c b/gcc/testsuite/gcc.dg/lto/pr83954_0.c
new file mode 100644
index 00000000000..065a31dab80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr83954_0.c
@@ -0,0 +1,8 @@
+/* { dg-lto-do link } */
+#include "pr83954.h"
+
+int main() {
+ // just to prevent symbol removal
+ FOO_PTR_ARR[1] = 0;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr83954_1.c b/gcc/testsuite/gcc.dg/lto/pr83954_1.c
new file mode 100644
index 00000000000..61b40fc7759
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr83954_1.c
@@ -0,0 +1,7 @@
+#include "pr83954.h"
+
+struct foo {
+ int x;
+};
+struct foo *FOO_PTR_ARR[1] = { 0 };
+
diff --git a/gcc/testsuite/gcc.dg/pr83424.c b/gcc/testsuite/gcc.dg/pr83424.c
new file mode 100644
index 00000000000..5a304f50292
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83424.c
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/83424 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O -fno-tree-ccp -fno-tree-coalesce-vars" } */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+typedef unsigned __int128 u128;
+
+u32 a, c;
+u8 b;
+
+static u128 __attribute__ ((noinline, noclone))
+foo (u128 p)
+{
+ u8 x = ~b;
+ p &= c;
+ x *= -p;
+ x &= a == 0;
+ x >>= 1;
+ return p + x;
+}
+
+int
+main (void)
+{
+ u128 x = foo (0);
+ if (x != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr82726.c b/gcc/testsuite/gcc.dg/tree-ssa/pr82726.c
new file mode 100644
index 00000000000..22bc59dacc8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr82726.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 --param tree-reassoc-width=4" } */
+/* { dg-additional-options "-mavx2" { target { x86_64-*-* i?86-*-* } } } */
+
+#define N 40
+#define M 128
+unsigned int in[N+M];
+unsigned short out[N];
+
+/* Outer-loop vectorization. */
+
+void
+foo (){
+ int i,j;
+ unsigned int diff;
+
+ for (i = 0; i < N; i++) {
+ diff = 0;
+ for (j = 0; j < M; j+=8) {
+ diff += in[j+i];
+ }
+ out[i]=(unsigned short)diff;
+ }
+
+ return;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr83370.c b/gcc/testsuite/gcc.target/aarch64/pr83370.c
new file mode 100644
index 00000000000..001373c4d39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr83370.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef void (*fun) (void);
+
+void
+f (fun x1)
+{
+ register fun x2 asm ("x16");
+ int arr[5000];
+ int *volatile ptr = arr;
+ asm ("mov %0, %1" : "=r" (x2) : "r" (x1));
+ x2 ();
+}
+
+void g (void) {}
+
+int
+main (void)
+{
+ f (g);
+}
diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp
index 2c3145118c8..82f7894ee7f 100644
--- a/gcc/testsuite/gcc.target/i386/i386.exp
+++ b/gcc/testsuite/gcc.target/i386/i386.exp
@@ -255,18 +255,6 @@ proc check_effective_target_rtm { } {
} "-mrtm" ]
}
-# Return 1 if avx512f instructions can be compiled.
-proc check_effective_target_avx512f { } {
- return [check_no_compiler_messages avx512f object {
- typedef long long __v8di __attribute__ ((__vector_size__ (64)));
- __v8di
- mm512_and_epi64 (__v8di __X, __v8di __Y)
- {
- return __builtin_ia32_pandq512_mask (__X, __Y, __X, -1);
- }
- } "-mavx512f" ]
-}
-
# Return 1 if avx512vl instructions can be compiled.
proc check_effective_target_avx512vl { } {
return [check_no_compiler_messages avx512vl object {
diff --git a/gcc/testsuite/gcc.target/i386/pr84310-2.c b/gcc/testsuite/gcc.target/i386/pr84310-2.c
new file mode 100644
index 00000000000..dbf5db6ff87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr84310-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -malign-loops=16" } */
+/* { dg-warning "is obsolete" "" { target *-*-* } 0 } */
+
+void
+c (void)
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr84310.c b/gcc/testsuite/gcc.target/i386/pr84310.c
new file mode 100644
index 00000000000..f82327e45f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr84310.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -falign-functions=100000" } */
+/* { dg-error "is not between 0 and 65536" "" { target *-*-* } 0 } */
+
+void
+test_func (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/indirect_call.c b/gcc/testsuite/gcc.target/nvptx/indirect_call.c
new file mode 100644
index 00000000000..5ac939e214c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/indirect_call.c
@@ -0,0 +1,19 @@
+/* { dg-options "-O2" } */
+/* { dg-do run } */
+
+int
+f1 (int a)
+{
+ return a + 1;
+}
+
+int (*f2)(int) = f1;
+
+int
+main ()
+{
+ if (f2 (100) != 101)
+ __builtin_abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83399.c b/gcc/testsuite/gcc.target/powerpc/pr83399.c
new file mode 100644
index 00000000000..96d9b382184
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83399.c
@@ -0,0 +1,15 @@
+/* PR target/83399 */
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O1 -mabi=elfv2 -mlittle -mvsx" } */
+
+typedef __attribute__((altivec(vector__))) int v4si_t;
+int
+foo (void)
+{
+ v4si_t a, u, v, y;
+ u = __builtin_altivec_lvx (32, ((void *) &a) - 32);
+ v = __builtin_altivec_lvx (64, ((void *) &a) - 32);
+ y = u + v;
+ return y[0];
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83862.c b/gcc/testsuite/gcc.target/powerpc/pr83862.c
new file mode 100644
index 00000000000..ac97e6aa5b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83862.c
@@ -0,0 +1,34 @@
+/* PR target/83862.c */
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mpower9-vector -O2 -mfloat128" } */
+
+/* On little endian systems, optimizing signbit of IEEE 128-bit values from
+ memory could abort if the memory address was indexed (reg+reg). The
+ optimization is only on 64-bit machines with direct move.
+
+ Compile with -g -O2 -mabi=ieeelongdouble -Wno-psabi. */
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+int sbr (TYPE a) { return __builtin_signbit (a); }
+int sbm (TYPE *a) { return __builtin_signbit (*a); }
+int sbo (TYPE *a) { return __builtin_signbit (a[4]); }
+int sbi (TYPE *a, unsigned long n) { return __builtin_signbit (a[n]); }
+void sbs (int *p, TYPE a) { *p = __builtin_signbit (a); }
+
+/* On big endian systems, this will generate 2 LDs and 1 LDX, while on
+ little endian systems, this will generate 3 LDs and an ADD. */
+
+/* { dg-final { scan-assembler-times {\mldx?\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mmfvsrd\M} 2 } } */
+/* { dg-final { scan-assembler-times {\msrdi\M} 5 } } */
+/* { dg-final { scan-assembler-not {\mmfvsrld\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvx?\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvw4x\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvd2x\M} } } */
+/* { dg-final { scan-assembler-not {\mstvx\M} } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c
new file mode 100644
index 00000000000..23494b695a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target { powerpc64le-*-* } } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2 " } */
+
+typedef __attribute__ ((__aligned__ (8))) unsigned long long __m64;
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+/* PR84033. Extracted from xmmintrin.h but with a pointer param to
+ allow swaps to happen when not inline. */
+int __attribute__ ((__noinline__))
+_mm_movemask_ps (__m128 *__A)
+{
+ __vector __m64 result;
+ static const __vector unsigned int perm_mask =
+ {
+ 0x00204060, 0x80808080, 0x80808080, 0x80808080
+ };
+
+ result = (__vector __m64)
+ __builtin_vec_vbpermq ((__vector unsigned char) (*__A),
+ (__vector unsigned char) perm_mask);
+ return result[1];
+}
+
+int
+main (void)
+{
+ union { unsigned int i[4]; __m128 m; } x
+ = { 0x80000000, 0x80000000, 0x7fffffff, 0x7fffffff };
+ if (_mm_movemask_ps (&x.m) != 3)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
index fbe3c67e7e5..2060046eaf2 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
@@ -1,8 +1,8 @@
/* { dg-do compile { target { powerpc64*-*-* } } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O1 -mvsx" } */
-/* { dg-final { scan-assembler "lxvd2x" } } */
-/* { dg-final { scan-assembler "stxvd2x" } } */
+/* { dg-final { scan-assembler {\mlxvd2x\M|\mlxv\M} } } */
+/* { dg-final { scan-assembler {\mstxvd2x\M|\mstxv\M} } } */
/* { dg-final { scan-assembler-not "xxpermdi" } } */
typedef float vecf __attribute__ ((vector_size (16)));
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c
new file mode 100644
index 00000000000..db9336d51dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int __attribute__((indirect_branch_call("thunk")))
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c
new file mode 100644
index 00000000000..c02b45a2cc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-call=thunk-extern -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c
new file mode 100644
index 00000000000..b5f13eb0793
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-call=thunk -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c
new file mode 100644
index 00000000000..486495b97ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-call=thunk -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c
new file mode 100644
index 00000000000..c62ddf56b8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void __attribute__((indirect_branch_jump("thunk")))
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int main() {
+ bar(code);
+ return 0;
+}
+
+/* 2x bar */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c
new file mode 100644
index 00000000000..63d64c15941
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void __attribute__((indirect_branch_jump("thunk-inline")))
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c
new file mode 100644
index 00000000000..28d7837e2a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c
new file mode 100644
index 00000000000..3c0c0072539
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "\tex\t" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c
new file mode 100644
index 00000000000..05c8bb8c12d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk-extern -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c
new file mode 100644
index 00000000000..71c86fdfebc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2x bar */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c
new file mode 100644
index 00000000000..89ad799c7a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c b/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c
new file mode 100644
index 00000000000..4bf88cf78c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return("thunk"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c b/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c
new file mode 100644
index 00000000000..8b32bfe5172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return("keep"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int __attribute__((function_return("keep")))
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c
new file mode 100644
index 00000000000..39cab8bd89e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return_mem("thunk"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c
new file mode 100644
index 00000000000..f99f152305c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk-extern -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 3 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c
new file mode 100644
index 00000000000..177fc32c24b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 3 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c
new file mode 100644
index 00000000000..0b318115a8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+
+/* 1 x foo, conditional return, shrink wrapped
+/* { dg-final { scan-assembler "jge\t__s390_indirect_jump" } } */
+
+/* 1 x foo, conditional return, shrink wrapped
+/* { dg-final { scan-assembler "jgle\t__s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c
new file mode 100644
index 00000000000..ebfc9ff0ebb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((function_return_reg("thunk"),noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c
new file mode 100644
index 00000000000..82833f7e0d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+/* We have to generate different thunks for indirect branches
+ depending on whether the code is compiled for pre z10 machines or
+ later. This testcase makes sure this works within the same compile
+ unit. */
+
+int __attribute__((noinline,noclone,target("arch=z10")))
+bar (int a)
+{
+ return a + 2;
+}
+
+int __attribute__((noinline,noclone,target("arch=z9-ec")))
+foo (int a)
+{
+ return a + 3;
+}
+
+int
+main ()
+{
+ if (bar (42) != 44)
+ __builtin_abort ();
+
+ if (foo (42) != 45)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar, 1 x foo */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* 1 x foo */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump_r1use" 1 } } */
+
+/* { dg-final { scan-assembler-times "ex\t" 1 } } */
+/* { dg-final { scan-assembler-times "exrl\t" 1 } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c
new file mode 100644
index 00000000000..4ea14e379f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mfunction-return-reg=thunk-extern -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c
new file mode 100644
index 00000000000..42c3e7435fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c
new file mode 100644
index 00000000000..3f4efa57e71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c
new file mode 100644
index 00000000000..8dfd7e4c786
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c
new file mode 100644
index 00000000000..46d2c54bcff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 -mzarch --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "\tex\t" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c
new file mode 100644
index 00000000000..9dfe391f337
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c
@@ -0,0 +1,77 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c
new file mode 100644
index 00000000000..f1439a8b120
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 -mzarch --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "ex\t" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_parameter.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_parameter.f90
new file mode 100644
index 00000000000..2653f1b127a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_charlen_parameter.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR fortran/82049
+! Original code contributed by John Harper <john dot harper at vuw dot ac dot nz>
+program ice ! f2003
+ implicit none
+ character(*), parameter:: a = 'ice', b = '*'
+ character(*), parameter:: c(2) = [character(len(a)) :: a, b]
+ print "(2A4)",adjustr(c)
+end program ice
diff --git a/gcc/testsuite/gfortran.dg/automatic_module_variable.f90 b/gcc/testsuite/gfortran.dg/automatic_module_variable.f90
index 201dcf4e1d3..ab041fcf4f5 100644
--- a/gcc/testsuite/gfortran.dg/automatic_module_variable.f90
+++ b/gcc/testsuite/gfortran.dg/automatic_module_variable.f90
@@ -1,10 +1,12 @@
! { dg-do compile }
! Tests fix for PR15976
!
+! Error message update with patch for PR fortran/83633
+!
module sd
integer, parameter :: n = 20
integer :: i(n)
- integer :: j(m) ! { dg-error "must have constant shape" }
+ integer :: j(m) ! { dg-error "array with nonconstant bounds" }
integer, pointer :: p(:)
integer, allocatable :: q(:)
contains
diff --git a/gcc/testsuite/gfortran.dg/bad_automatic_objects_1.f90 b/gcc/testsuite/gfortran.dg/bad_automatic_objects_1.f90
index 27344186194..61db2174e5b 100644
--- a/gcc/testsuite/gfortran.dg/bad_automatic_objects_1.f90
+++ b/gcc/testsuite/gfortran.dg/bad_automatic_objects_1.f90
@@ -5,16 +5,18 @@
!
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
!
+! Error message update with patch for PR fortran/83633
+!
module foo
integer :: i
end module foo
module bar
use foo
- integer, dimension (i) :: j ! { dg-error "must have constant shape" }
+ integer, dimension (i) :: j ! { dg-error "array with nonconstant bounds" }
character (len = i) :: c1 ! { dg-error "must have constant character length" }
end module bar
program foobar
use foo
- integer, dimension (i) :: k ! { dg-error "must have constant shape" }
+ integer, dimension (i) :: k ! { dg-error "array with nonconstant bounds" }
character (len = i) :: c2 ! { dg-error "must have constant character length" }
end program foobar
diff --git a/gcc/testsuite/gfortran.dg/class_67.f90 b/gcc/testsuite/gfortran.dg/class_67.f90
new file mode 100644
index 00000000000..20029939d64
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_67.f90
@@ -0,0 +1,55 @@
+! { dg-do run }
+!
+! Test the fix for PR78990 in which the scalarization of the assignment
+! in the main program failed for two reasons: (i) The conversion of 'v1'
+! into a class actual was being done after the call to 'return_t1', giving
+! rise to the ICE reported in comment #1; and (ii) The 'info' descriptor,
+! required for scalarization was not set, which gave rise to the ICE noted
+! by the contributor.
+!
+! Contributed by Chris Macmackin <cmacmackin@gmail.com>
+!
+module test_type
+ implicit none
+
+ type t1
+ integer :: i
+ contains
+ procedure :: assign
+ generic :: assignment(=) => assign
+ end type t1
+
+contains
+
+ elemental subroutine assign(this,rhs)
+ class(t1), intent(inout) :: this
+ class(t1), intent(in) :: rhs
+ this%i = rhs%i
+ end subroutine assign
+
+ function return_t1(arg)
+ class(t1), dimension(:), intent(in) :: arg
+ class(t1), dimension(:), allocatable :: return_t1
+ allocate(return_t1(size(arg)), source=arg)
+ end function return_t1
+
+ function return_t1_p(arg)
+ class(t1), dimension(:), intent(in), target :: arg
+ class(t1), dimension(:), pointer :: return_t1_p
+ return_t1_p => arg
+ end function return_t1_p
+end module test_type
+
+program test
+ use test_type
+ implicit none
+
+ type(t1), dimension(3) :: v1, v2
+ v1%i = [1,2,3]
+ v2 = return_t1(v1)
+ if (any (v2%i .ne. v1%i)) call abort
+
+ v1%i = [4,5,6]
+ v2 = return_t1_p(v1)
+ if (any (v2%i .ne. v1%i)) call abort
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_8.f90 b/gcc/testsuite/gfortran.dg/coarray_8.f90
index db6eb6c2e2d..060f94118ac 100644
--- a/gcc/testsuite/gfortran.dg/coarray_8.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_8.f90
@@ -145,7 +145,7 @@ end module mmm4
subroutine tfgh()
integer :: i(2)
- DATA i/(i, i=1,2)/ ! { dg-error "Expected PARAMETER symbol" }
+ DATA i/(i, i=1,2)/ ! { dg-error "Syntax error in DATA" }
do i = 1, 5 ! { dg-error "cannot be an array" }
end do ! { dg-error "Expecting END SUBROUTINE" }
end subroutine tfgh
@@ -153,7 +153,7 @@ end subroutine tfgh
subroutine tfgh2()
integer, save :: x[*]
integer :: i(2)
- DATA i/(x, x=1,2)/ ! { dg-error "Expected PARAMETER symbol" }
+ DATA i/(x, x=1,2)/ ! { dg-error "Syntax error in DATA" }
do x = 1, 5 ! { dg-error "cannot be a coarray" }
end do ! { dg-error "Expecting END SUBROUTINE" }
end subroutine tfgh2
diff --git a/gcc/testsuite/gfortran.dg/data_substring.f90 b/gcc/testsuite/gfortran.dg/data_substring.f90
new file mode 100644
index 00000000000..6d6b2c01579
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/data_substring.f90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! PR fortran/30792
+character string*1025
+integer i
+data (string(i:i),i=1,1025)/1025*'?'/ ! { dg-error "Invalid substring" }
+end
diff --git a/gcc/testsuite/gfortran.dg/deallocate_error_3.f90 b/gcc/testsuite/gfortran.dg/deallocate_error_3.f90
new file mode 100644
index 00000000000..149b7c8c15a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deallocate_error_3.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR fortran/82994
+! Code contributed by Gerhard Steinmetz
+program p
+ type t
+ end type
+ class(t) :: x ! { dg-error "must be dummy, allocatable or pointer" }
+ deallocate (x) ! { dg-error "not a nonprocedure pointer nor an allocatable" }
+end
diff --git a/gcc/testsuite/gfortran.dg/deallocate_error_4.f90 b/gcc/testsuite/gfortran.dg/deallocate_error_4.f90
new file mode 100644
index 00000000000..c12e776dd27
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deallocate_error_4.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! PR fortran/82994
+! Code contributed by Gerhard Steinmetz
+program p
+ type t
+ end type
+ class(t) :: x ! { dg-error "must be dummy, allocatable or pointer" }
+ allocate (x) ! { dg-error "neither a data pointer nor an allocatable" }
+ deallocate (x) ! { dg-error "not a nonprocedure pointer nor an allocatable" }
+end
diff --git a/gcc/testsuite/gfortran.dg/explicit_shape_1.f90 b/gcc/testsuite/gfortran.dg/explicit_shape_1.f90
new file mode 100644
index 00000000000..ca3cd00d855
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/explicit_shape_1.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! PR fortran/83633
+! Original testcase by Nathan T. Weeks <weeks at iastate dot edu>
+!
+integer :: A(command_argument_count()) = 1 ! { dg-error "nonconstant bounds" }
+write (*,*) A
+end
diff --git a/gcc/testsuite/gfortran.dg/implied_do_2.f90 b/gcc/testsuite/gfortran.dg/implied_do_2.f90
new file mode 100644
index 00000000000..5078ac804d3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implied_do_2.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! PR fortran/56667
+program error_message
+ implicit none
+ integer :: ir
+ write(*,*) ( ir, ir = 1,10 ! { dg-error "Expected a right parenthesis" }
+end program error_message
diff --git a/gcc/testsuite/gfortran.dg/inquire_19.f90 b/gcc/testsuite/gfortran.dg/inquire_19.f90
new file mode 100644
index 00000000000..7d01b6b56ce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/inquire_19.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR84506 INQUIRE(pos=) always sets pos=0 with -fdefault-integer-8
+program TestInquire
+ implicit none
+ integer(8) :: iUnit
+ integer(8) :: iPos
+ open(newunit=iunit, file='output.txt', access='stream', status='replace')
+ write(iUnit) 'TEXT'
+ inquire(iUnit, pos=iPos)
+ close(iUnit, status='delete')
+ !print *, iPos
+ if (iPos.ne.5) stop 1
+end program TestInquire
diff --git a/gcc/testsuite/gfortran.dg/matmul_17.f90 b/gcc/testsuite/gfortran.dg/matmul_17.f90
new file mode 100644
index 00000000000..b21f02be392
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_17.f90
@@ -0,0 +1,9 @@
+! { dg-do run }
+! PR Fortran/83900
+! Contributed by Gerhard Steinmetz <gscfq t t-online dot de>
+program p
+ integer, parameter :: a(3,2) = 1
+ real, parameter :: b(2,3) = 2
+ real, parameter :: c(3,3) = matmul(a, b)
+ if (any(c /= 4.)) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/matmul_18.f90 b/gcc/testsuite/gfortran.dg/matmul_18.f90
new file mode 100644
index 00000000000..acfd3c304ca
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_18.f90
@@ -0,0 +1,8 @@
+! { dg-do run }
+program p
+ integer, parameter :: a(3,2) = 1
+ real, parameter :: b(2,3) = 2
+ real d(3,3)
+ d = 4
+ if (any(d /= matmul(a,b))) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/num_images_1.f90 b/gcc/testsuite/gfortran.dg/num_images_1.f90
new file mode 100644
index 00000000000..b5547f60cad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/num_images_1.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single -std=f2008" }
+! PR Fortran/80768
+!
+program foo
+ implicit none
+ integer k5
+ k5 = num_images(failed=.false.) ! { dg-error "argument to NUM_IMAGES" }
+ print *, k5
+end program foo
diff --git a/gcc/testsuite/gfortran.dg/pr70754.f90 b/gcc/testsuite/gfortran.dg/pr70754.f90
new file mode 100644
index 00000000000..d7e790cc036
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr70754.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-Ofast" }
+module m
+ implicit none
+ private
+ save
+
+ integer, parameter, public :: &
+ ii4 = selected_int_kind(6), &
+ rr8 = selected_real_kind(13)
+
+ integer (ii4), dimension(40,40,199), public :: xyz
+ public :: foo
+contains
+ subroutine foo(a)
+ real (rr8), dimension(40,40), intent(out) :: a
+ real (rr8), dimension(40,40) :: b
+ integer (ii4), dimension(40,40) :: c
+ integer i, j
+
+ do i=1,20
+ b(i,j) = 123 * a(i,j) + 34 * a(i,j+1) &
+ + 34 * a(i,j-1) + a(i+1,j+1) &
+ + a(i+1,j-1) + a(i-1,j+1) &
+ + a(i-1,j-1)
+ c(i,j) = 123
+ end do
+
+ where ((xyz(:,:,2) /= 0) .and. (c /= 0))
+ a = b/real(c)
+ elsewhere
+ a = 456
+ endwhere
+ end subroutine foo
+end module m
diff --git a/gcc/testsuite/gfortran.dg/pr71085.f90 b/gcc/testsuite/gfortran.dg/pr71085.f90
new file mode 100644
index 00000000000..11d9850fb90
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr71085.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! PR 71085
+!
+! Testcase from PR by Vladimir Fuka <vladimir.fuka@gmail.com>
+!
+program pr71085
+ print *, f()
+contains
+ function f()
+ integer :: f(iargc()*10)
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/pr83874.f90 b/gcc/testsuite/gfortran.dg/pr83874.f90
new file mode 100644
index 00000000000..d1bdc97b783
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr83874.f90
@@ -0,0 +1,19 @@
+! { dg-do run }
+! PR fortran/83874
+! There was an ICE while initializing the character arrays
+!
+! Contributed by Harald Anlauf <anlauf@gmx.de>
+!
+program charinit
+ implicit none
+ type t
+ character(len=1) :: name
+ end type t
+ type(t), parameter :: z(2)= [ t ('a'), t ('b') ]
+ character(len=1), parameter :: names1(*) = z% name
+ character(len=*), parameter :: names2(2) = z% name
+ character(len=*), parameter :: names3(*) = z% name
+ if (.not. (names1(1) == "a" .and. names1(2) == "b")) call abort ()
+ if (.not. (names2(1) == "a" .and. names2(2) == "b")) call abort ()
+ if (.not. (names3(1) == "a" .and. names3(2) == "b")) call abort ()
+end program charinit
diff --git a/gcc/testsuite/gfortran.dg/shape_9.f90 b/gcc/testsuite/gfortran.dg/shape_9.f90
new file mode 100644
index 00000000000..6d33f976cb8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/shape_9.f90
@@ -0,0 +1,16 @@
+! { dg-do run }
+! { dg-require-effective-target lto }
+! { dg-options "-flto" }
+! Check that there are no warnings with LTO for a KIND argument.
+!
+program test
+ implicit none
+ real, allocatable :: x(:,:)
+
+ allocate(x(2,5))
+ if (any(shape(x) /= [ 2, 5 ])) call abort
+ if (any(shape(x,kind=1) /= [ 2, 5 ])) call abort
+ if (any(shape(x,kind=2) /= [ 2, 5 ])) call abort
+ if (any(shape(x,kind=4) /= [ 2, 5 ])) call abort
+ if (any(shape(x,kind=8) /= [ 2, 5 ])) call abort
+ end program test
diff --git a/gcc/testsuite/gfortran.dg/statement_function_1.f90 b/gcc/testsuite/gfortran.dg/statement_function_1.f90
new file mode 100644
index 00000000000..e717725e67e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_1.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! PR fortran/84276
+ subroutine stepns(hh, h, s, w)
+ real, intent(inout) :: h, hh, s
+ real, intent(out) :: w
+ real :: qofs
+ integer i
+ qofs(s) = s
+ w = qofs(hh + h)
+ i = 42
+ w = qofs(i) ! { dg-error "Type mismatch in argument" }
+ end subroutine stepns
+
+ subroutine step(hh, h, s, w)
+ real, intent(inout) :: h, hh, s
+ real, intent(out) :: w
+ real :: qofs
+ integer i
+ qofs(s, i) = i * s
+ i = 42
+ w = qofs(hh, i)
+ w = qofs(i = i, s = hh) ! { dg-error "invalid in a statement function" }
+ end subroutine step
+! { dg-prune-output " Obsolescent feature" }
diff --git a/gcc/testsuite/gfortran.dg/statement_function_2.f90 b/gcc/testsuite/gfortran.dg/statement_function_2.f90
new file mode 100644
index 00000000000..703ca1716ca
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_2.f90
@@ -0,0 +1,26 @@
+! { dg-do compile }
+! PR fortran/54223
+subroutine r(d)
+ implicit none
+ integer, optional :: d
+ integer :: h, q
+ q(d) = d + 1 ! statement function statement
+ h = q(d)
+end subroutine r
+
+subroutine s(x)
+ implicit none
+ integer, optional :: x
+ integer :: g, z
+ g(x) = x + 1 ! statement function statement
+ z = g() ! { dg-error "Missing actual argument" }
+end subroutine s
+
+subroutine t(a)
+ implicit none
+ integer :: a
+ integer :: f, y
+ f(a) = a + 1 ! statement function statement
+ y = f() ! { dg-error "Missing actual argument" }
+end subroutine t
+! { dg-prune-output " Obsolescent feature" }
diff --git a/gcc/testsuite/gfortran.dg/statement_function_3.f b/gcc/testsuite/gfortran.dg/statement_function_3.f
new file mode 100644
index 00000000000..dcfb3e2b9dc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/statement_function_3.f
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! PR fortran/35299
+ subroutine phtod(e,n,i,h)
+ dimension e(n)
+ hstar(e,b)=b**.4*((1.25*fun(-e/40)+.18)) ! { dg-error "must be scalar" }
+ a = 1.
+ h = hstar(e(i-1), a)
+ end
+
+ function fun(a)
+ real a(*)
+ fun = 42
+ end
+! { dg-prune-output " Obsolescent feature" }
+
diff --git a/gcc/testsuite/gnat.dg/array11.adb b/gcc/testsuite/gnat.dg/array11.adb
index 7be61c4b631..aab73470092 100644
--- a/gcc/testsuite/gnat.dg/array11.adb
+++ b/gcc/testsuite/gnat.dg/array11.adb
@@ -1,15 +1,17 @@
-- { dg-do compile }
+with System;
+
procedure Array11 is
type Rec is null record;
- type Ptr is access all Rec;
+ type Index_T is mod System.Memory_Size;
- type Arr1 is array (1..8) of aliased Rec; -- { dg-warning "padded" }
- type Arr2 is array (Long_Integer) of aliased Rec; -- { dg-warning "padded" }
+ type Arr1 is array (1 .. 8) of aliased Rec; -- { dg-warning "padded" }
+ type Arr2 is array (Index_T) of aliased Rec; -- { dg-warning "padded" }
A1 : Arr1;
- A2 : Arr2; -- { dg-warning "Storage_Error" }
+ A2 : Arr2;
begin
null;
diff --git a/gcc/testsuite/gnat.dg/dispatch1.adb b/gcc/testsuite/gnat.dg/disp1.adb
index 28e97e6e7e7..2fcefeafb42 100644
--- a/gcc/testsuite/gnat.dg/dispatch1.adb
+++ b/gcc/testsuite/gnat.dg/disp1.adb
@@ -1,7 +1,8 @@
-- { dg-do run }
-with dispatch1_p; use dispatch1_p;
-procedure dispatch1 is
+with Disp1_Pkg; use Disp1_Pkg;
+
+procedure Disp1 is
O : DT_I1;
Ptr : access I1'Class;
begin
diff --git a/gcc/testsuite/gnat.dg/dispatch1_p.ads b/gcc/testsuite/gnat.dg/disp1_pkg.ads
index 73de627516a..4d80e7655e1 100644
--- a/gcc/testsuite/gnat.dg/dispatch1_p.ads
+++ b/gcc/testsuite/gnat.dg/disp1_pkg.ads
@@ -1,4 +1,6 @@
-package dispatch1_p is
+package Disp1_Pkg is
+
type I1 is interface;
type DT_I1 is new I1 with null record;
-end;
+
+end Disp1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/dispatch2.adb b/gcc/testsuite/gnat.dg/disp2.adb
index ed57b13359e..2e1e6226080 100644
--- a/gcc/testsuite/gnat.dg/dispatch2.adb
+++ b/gcc/testsuite/gnat.dg/disp2.adb
@@ -1,7 +1,8 @@
-- { dg-do run }
-with dispatch2_p; use dispatch2_p;
-procedure dispatch2 is
+with Disp2_Pkg; use Disp2_Pkg;
+
+procedure Disp2 is
Obj : Object_Ptr := new Object;
begin
if Obj.Get_Ptr /= Obj.Impl_Of then
diff --git a/gcc/testsuite/gnat.dg/dispatch2_p.adb b/gcc/testsuite/gnat.dg/disp2_pkg.adb
index 243c3ca977a..ed460ec453f 100644
--- a/gcc/testsuite/gnat.dg/dispatch2_p.adb
+++ b/gcc/testsuite/gnat.dg/disp2_pkg.adb
@@ -1,7 +1,8 @@
---
-package body dispatch2_p is
+package body Disp2_Pkg is
+
function Impl_Of (Self : access Object) return Object_Ptr is
begin
return Object_Ptr (Self);
end Impl_Of;
-end;
+
+end Disp2_Pkg;
diff --git a/gcc/testsuite/gnat.dg/dispatch2_p.ads b/gcc/testsuite/gnat.dg/disp2_pkg.ads
index e7852b446b5..0b4903abe34 100644
--- a/gcc/testsuite/gnat.dg/dispatch2_p.ads
+++ b/gcc/testsuite/gnat.dg/disp2_pkg.ads
@@ -1,8 +1,11 @@
-package dispatch2_p is
+package Disp2_Pkg is
+
type Object is tagged null record;
type Object_Ptr is access all Object'CLASS;
---
+
function Impl_Of (Self : access Object) return Object_Ptr;
function Get_Ptr (Self : access Object) return Object_Ptr
renames Impl_Of;
-end;
+
+end Disp2_Pkg;
+
diff --git a/gcc/testsuite/gnat.dg/generic_dispatch.adb b/gcc/testsuite/gnat.dg/generic_disp.adb
index a22e495f451..2f828ff1b1b 100644
--- a/gcc/testsuite/gnat.dg/generic_dispatch.adb
+++ b/gcc/testsuite/gnat.dg/generic_disp.adb
@@ -1,9 +1,10 @@
-- { dg-do run }
-with generic_dispatch_p; use generic_dispatch_p;
-procedure generic_dispatch is
+with Generic_Disp_Pkg; use Generic_Disp_Pkg;
+
+procedure Generic_Disp is
I : aliased Integer := 0;
D : Iface'Class := Dispatching_Constructor (DT'Tag, I'access);
begin
null;
-end generic_dispatch;
+end Generic_Disp;
diff --git a/gcc/testsuite/gnat.dg/generic_dispatch_p.adb b/gcc/testsuite/gnat.dg/generic_disp_pkg.adb
index 7a4bbbd8a2b..b3aeb3ff078 100644
--- a/gcc/testsuite/gnat.dg/generic_dispatch_p.adb
+++ b/gcc/testsuite/gnat.dg/generic_disp_pkg.adb
@@ -1,7 +1,9 @@
-package body generic_dispatch_p is
+package body Generic_Disp_Pkg is
+
function Constructor (I : not null access Integer) return DT is
R : DT;
- begin
+ begin
return R;
end Constructor;
-end;
+
+end Generic_Disp_Pkg;
diff --git a/gcc/testsuite/gnat.dg/generic_dispatch_p.ads b/gcc/testsuite/gnat.dg/generic_disp_pkg.ads
index fe6115dd9c7..5be54921d83 100644
--- a/gcc/testsuite/gnat.dg/generic_dispatch_p.ads
+++ b/gcc/testsuite/gnat.dg/generic_disp_pkg.ads
@@ -1,5 +1,6 @@
with Ada.Tags.Generic_Dispatching_Constructor;
-package generic_dispatch_p is
+
+package Generic_Disp_Pkg is
type Iface is interface;
function Constructor (I : not null access Integer) return Iface is abstract;
function Dispatching_Constructor
@@ -10,4 +11,4 @@ package generic_dispatch_p is
type DT is new Iface with null record;
overriding
function Constructor (I : not null access Integer) return DT;
-end;
+end Generic_Disp_Pkg;
diff --git a/gcc/testsuite/gnat.dg/null_pointer_deref1.adb b/gcc/testsuite/gnat.dg/null_pointer_deref1.adb
index 6e7bf14e5df..ec7f9460559 100644
--- a/gcc/testsuite/gnat.dg/null_pointer_deref1.adb
+++ b/gcc/testsuite/gnat.dg/null_pointer_deref1.adb
@@ -17,5 +17,5 @@ procedure Null_Pointer_Deref1 is
begin
Data.all := 1;
exception
- when Constraint_Error | Storage_Error => null;
+ when others => null;
end;
diff --git a/gcc/testsuite/gnat.dg/null_pointer_deref2.adb b/gcc/testsuite/gnat.dg/null_pointer_deref2.adb
index 63e2dd11f39..284762216c5 100644
--- a/gcc/testsuite/gnat.dg/null_pointer_deref2.adb
+++ b/gcc/testsuite/gnat.dg/null_pointer_deref2.adb
@@ -20,7 +20,7 @@ procedure Null_Pointer_Deref2 is
begin
Data.all := 1;
exception
- when Constraint_Error | Storage_Error => null;
+ when others => null;
end T;
begin
diff --git a/gcc/testsuite/gnat.dg/object_overflow1.adb b/gcc/testsuite/gnat.dg/object_overflow1.adb
index ba7f657e710..d972f24a1fe 100644
--- a/gcc/testsuite/gnat.dg/object_overflow1.adb
+++ b/gcc/testsuite/gnat.dg/object_overflow1.adb
@@ -1,10 +1,12 @@
-- { dg-do compile }
+with Interfaces.C; use Interfaces.C;
+
procedure Object_Overflow1 is
procedure Proc (x : Boolean) is begin null; end;
- type Arr is array(Long_Integer) of Boolean;
+ type Arr is array(ptrdiff_t) of Boolean;
Obj : Arr; -- { dg-warning "Storage_Error" }
begin
diff --git a/gcc/testsuite/gnat.dg/object_overflow2.adb b/gcc/testsuite/gnat.dg/object_overflow2.adb
index 9601c563b2a..a429291e80a 100644
--- a/gcc/testsuite/gnat.dg/object_overflow2.adb
+++ b/gcc/testsuite/gnat.dg/object_overflow2.adb
@@ -1,10 +1,12 @@
-- { dg-do compile }
+with Interfaces.C; use Interfaces.C;
+
procedure Object_Overflow2 is
procedure Proc (x : Boolean) is begin null; end;
- type Arr is array(0 .. Long_Integer'Last) of Boolean;
+ type Arr is array(0 .. ptrdiff_t'Last) of Boolean;
Obj : Arr; -- { dg-warning "Storage_Error" }
begin
diff --git a/gcc/testsuite/gnat.dg/object_overflow3.adb b/gcc/testsuite/gnat.dg/object_overflow3.adb
index 5e27b4f0d81..d3c0c17c57d 100644
--- a/gcc/testsuite/gnat.dg/object_overflow3.adb
+++ b/gcc/testsuite/gnat.dg/object_overflow3.adb
@@ -1,10 +1,12 @@
-- { dg-do compile }
+with Interfaces.C; use Interfaces.C;
+
procedure Object_Overflow3 is
procedure Proc (x : Boolean) is begin null; end;
- type Arr is array(0 .. Long_Integer'Last) of Boolean;
+ type Arr is array(0 .. ptrdiff_t'Last) of Boolean;
type Rec is record
A : Arr;
diff --git a/gcc/testsuite/gnat.dg/object_overflow4.adb b/gcc/testsuite/gnat.dg/object_overflow4.adb
index 643989d348c..0e320e265ad 100644
--- a/gcc/testsuite/gnat.dg/object_overflow4.adb
+++ b/gcc/testsuite/gnat.dg/object_overflow4.adb
@@ -1,14 +1,16 @@
-- { dg-do compile }
+with Interfaces.C; use Interfaces.C;
+
procedure Object_Overflow4 is
procedure Proc (x : Integer) is begin null; end;
- type Index is new Long_Integer range 0 .. Long_Integer'Last;
+ type Index_T is new ptrdiff_t range 0 .. ptrdiff_t'Last;
- type Arr is array(Index range <>) of Integer;
+ type Arr is array(Index_T range <>) of Integer;
- type Rec (Size: Index := 6) is record -- { dg-warning "Storage_Error" }
+ type Rec (Size: Index_T := 6) is record -- { dg-warning "Storage_Error" }
A: Arr (0..Size);
end record;
diff --git a/gcc/testsuite/gnat.dg/object_overflow5.adb b/gcc/testsuite/gnat.dg/object_overflow5.adb
index 4a4f6cfe30e..42d00b24b95 100644
--- a/gcc/testsuite/gnat.dg/object_overflow5.adb
+++ b/gcc/testsuite/gnat.dg/object_overflow5.adb
@@ -1,14 +1,16 @@
-- { dg-do compile }
+with Interfaces.C; use Interfaces.C;
+
procedure Object_Overflow5 is
procedure Proc (c : Character) is begin null; end;
- type Index is new Long_Integer range 0 .. Long_Integer'Last;
+ type Index_T is new ptrdiff_t range 0 .. ptrdiff_t'Last;
- type Arr is array(Index range <>) of Character;
+ type Arr is array(Index_T range <>) of Character;
- type Rec (Size: Index := 6) is record -- { dg-warning "Storage_Error" }
+ type Rec (Size: Index_T := 6) is record -- { dg-warning "Storage_Error" }
A: Arr (0..Size);
end record;
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index ab6f3697ff8..2a89c35f576 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -28,7 +28,7 @@ proc prune_gcc_output { text } {
#send_user "Before:$text\n"
- regsub -all "(^|\n)(\[^\n\]*: )?In ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|substitution|program|subroutine|block-data)\[^\n\]*" $text "" text
+ regsub -all "(^|\n)(\[^\n\]*: \[iI\]|I)n ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|substitution|program|subroutine|block-data)\[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*(: )?At (top level|global scope):\[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*: (recursively )?required \[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*: . skipping \[0-9\]* instantiation contexts \[^\n\]*" $text "" text
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 09d42b28cf8..29faf59b998 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6690,11 +6690,22 @@ proc check_prefer_avx128 { } {
proc check_effective_target_avx512f { } {
return [check_no_compiler_messages avx512f object {
typedef double __m512d __attribute__ ((__vector_size__ (64)));
+ typedef double __m128d __attribute__ ((__vector_size__ (16)));
__m512d _mm512_add (__m512d a)
{
return __builtin_ia32_addpd512_mask (a, a, a, 1, 4);
}
+
+ __m128d _mm128_add (__m128d a)
+ {
+ return __builtin_ia32_addsd_round (a, a, 8);
+ }
+
+ __m128d _mm128_getmant (__m128d a)
+ {
+ return __builtin_ia32_getmantsd_round (a, a, 0, 8);
+ }
} "-O2 -mavx512f" ]
}
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 843f68e387b..f27410336bb 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -943,6 +943,17 @@ order_drefs (const void *a, const void *b)
return (*da)->pos - (*db)->pos;
}
+/* Compares two drefs A and B by their position. Callback for qsort. */
+
+static int
+order_drefs_by_pos (const void *a, const void *b)
+{
+ const dref *const da = (const dref *) a;
+ const dref *const db = (const dref *) b;
+
+ return (*da)->pos - (*db)->pos;
+}
+
/* Returns root of the CHAIN. */
static inline dref
@@ -2250,7 +2261,6 @@ combine_chains (chain_p ch1, chain_p ch2)
bool swap = false;
chain_p new_chain;
unsigned i;
- gimple *root_stmt;
tree rslt_type = NULL_TREE;
if (ch1 == ch2)
@@ -2292,31 +2302,55 @@ combine_chains (chain_p ch1, chain_p ch2)
new_chain->refs.safe_push (nw);
}
- new_chain->has_max_use_after = false;
- root_stmt = get_chain_root (new_chain)->stmt;
- for (i = 1; new_chain->refs.iterate (i, &nw); i++)
- {
- if (nw->distance == new_chain->length
- && !stmt_dominates_stmt_p (nw->stmt, root_stmt))
- {
- new_chain->has_max_use_after = true;
- break;
- }
- }
-
ch1->combined = true;
ch2->combined = true;
return new_chain;
}
-/* Try to combine the CHAINS. */
+/* Recursively update position information of all offspring chains to ROOT
+ chain's position information. */
static void
-try_combine_chains (vec<chain_p> *chains)
+update_pos_for_combined_chains (chain_p root)
+{
+ chain_p ch1 = root->ch1, ch2 = root->ch2;
+ dref ref, ref1, ref2;
+ for (unsigned j = 0; (root->refs.iterate (j, &ref)
+ && ch1->refs.iterate (j, &ref1)
+ && ch2->refs.iterate (j, &ref2)); ++j)
+ ref1->pos = ref2->pos = ref->pos;
+
+ if (ch1->type == CT_COMBINATION)
+ update_pos_for_combined_chains (ch1);
+ if (ch2->type == CT_COMBINATION)
+ update_pos_for_combined_chains (ch2);
+}
+
+/* Returns true if statement S1 dominates statement S2. */
+
+static bool
+pcom_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
+{
+ basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+
+ if (!bb1 || s1 == s2)
+ return true;
+
+ if (bb1 == bb2)
+ return gimple_uid (s1) < gimple_uid (s2);
+
+ return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
+}
+
+/* Try to combine the CHAINS in LOOP. */
+
+static void
+try_combine_chains (struct loop *loop, vec<chain_p> *chains)
{
unsigned i, j;
chain_p ch1, ch2, cch;
auto_vec<chain_p> worklist;
+ bool combined_p = false;
FOR_EACH_VEC_ELT (*chains, i, ch1)
if (chain_can_be_combined_p (ch1))
@@ -2338,6 +2372,78 @@ try_combine_chains (vec<chain_p> *chains)
{
worklist.safe_push (cch);
chains->safe_push (cch);
+ combined_p = true;
+ break;
+ }
+ }
+ }
+ if (!combined_p)
+ return;
+
+ /* Setup UID for all statements in dominance order. */
+ basic_block *bbs = get_loop_body (loop);
+ renumber_gimple_stmt_uids_in_blocks (bbs, loop->num_nodes);
+ free (bbs);
+
+ /* Re-association in combined chains may generate statements different to
+ order of references of the original chain. We need to keep references
+ of combined chain in dominance order so that all uses will be inserted
+ after definitions. Note:
+ A) This is necessary for all combined chains.
+ B) This is only necessary for ZERO distance references because other
+ references inherit value from loop carried PHIs.
+
+ We first update position information for all combined chains. */
+ dref ref;
+ for (i = 0; chains->iterate (i, &ch1); ++i)
+ {
+ if (ch1->type != CT_COMBINATION || ch1->combined)
+ continue;
+
+ for (j = 0; ch1->refs.iterate (j, &ref); ++j)
+ ref->pos = gimple_uid (ref->stmt);
+
+ update_pos_for_combined_chains (ch1);
+ }
+ /* Then sort references according to newly updated position information. */
+ for (i = 0; chains->iterate (i, &ch1); ++i)
+ {
+ if (ch1->type != CT_COMBINATION && !ch1->combined)
+ continue;
+
+ /* Find the first reference with non-ZERO distance. */
+ if (ch1->length == 0)
+ j = ch1->refs.length();
+ else
+ {
+ for (j = 0; ch1->refs.iterate (j, &ref); ++j)
+ if (ref->distance != 0)
+ break;
+ }
+
+ /* Sort all ZERO distance references by position. */
+ qsort (&ch1->refs[0], j, sizeof (ch1->refs[0]), order_drefs_by_pos);
+
+ if (ch1->combined)
+ continue;
+
+ /* For ZERO length chain, has_max_use_after must be true since root
+ combined stmt must dominates others. */
+ if (ch1->length == 0)
+ {
+ ch1->has_max_use_after = true;
+ continue;
+ }
+ /* Check if there is use at max distance after root for combined chains
+ and set flag accordingly. */
+ ch1->has_max_use_after = false;
+ gimple *root_stmt = get_chain_root (ch1)->stmt;
+ for (j = 1; ch1->refs.iterate (j, &ref); ++j)
+ {
+ if (ref->distance == ch1->length
+ && !pcom_stmt_dominates_stmt_p (ref->stmt, root_stmt))
+ {
+ ch1->has_max_use_after = true;
break;
}
}
@@ -2490,7 +2596,7 @@ tree_predictive_commoning_loop (struct loop *loop)
prepare_initializers (loop, chains);
/* Try to combine the chains that are always worked with together. */
- try_combine_chains (&chains);
+ try_combine_chains (loop, &chains);
if (dump_file && (dump_flags & TDF_DETAILS))
{
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index e29ea54f193..dbea307ae4f 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -2320,7 +2320,7 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (cfn != CFN_LAST)
fndecl = targetm.vectorize.builtin_vectorized_function
(cfn, vectype_out, vectype_in);
- else
+ else if (callee)
fndecl = targetm.vectorize.builtin_md_vectorized_function
(callee, vectype_out, vectype_in);
}
diff --git a/gcc/tree.c b/gcc/tree.c
index fa39842e767..84f324f03f1 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5445,9 +5445,10 @@ free_lang_data_in_decl (tree decl)
At this point, it is not needed anymore. */
DECL_SAVED_TREE (decl) = NULL_TREE;
- /* Clear the abstract origin if it refers to a method. Otherwise
- dwarf2out.c will ICE as we clear TYPE_METHODS and thus the
- origin will not be output correctly. */
+ /* Clear the abstract origin if it refers to a method.
+ Otherwise dwarf2out.c will ICE as we splice functions out of
+ TYPE_FIELDS and thus the origin will not be output
+ correctly. */
if (DECL_ABSTRACT_ORIGIN (decl)
&& DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
&& RECORD_OR_UNION_TYPE_P
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index fc76c961dde..bd37acf21c2 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,22 @@
+2018-02-20 Max Filippov <jcmvbkbc@gmail.com>
+
+ Backport from mainline
+ 2018-02-20 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/ieee754-df.S (__adddf3_aux): Add
+ .literal_position directive.
+ * config/xtensa/ieee754-sf.S (__addsf3_aux): Likewise.
+
+2018-01-23 Max Filippov <jcmvbkbc@gmail.com>
+
+ Backport from mainline
+ 2018-01-23 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/ieee754-df.S (__addsf3, __subsf3, __mulsf3)
+ (__divsf3): Make NaN return value quiet.
+ * config/xtensa/ieee754-sf.S (__adddf3, __subdf3, __muldf3)
+ (__divdf3): Make NaN return value quiet.
+
2017-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Backport from mainline
diff --git a/libgcc/config/xtensa/ieee754-df.S b/libgcc/config/xtensa/ieee754-df.S
index 1d9ef468f01..23e5c4aa0ab 100644
--- a/libgcc/config/xtensa/ieee754-df.S
+++ b/libgcc/config/xtensa/ieee754-df.S
@@ -55,6 +55,7 @@ __negdf2:
#ifdef L_addsubdf3
+ .literal_position
/* Addition */
__adddf3_aux:
@@ -64,17 +65,26 @@ __adddf3_aux:
.Ladd_xnan_or_inf:
/* If y is neither Infinity nor NaN, return x. */
- bnall yh, a6, 1f
+ bnall yh, a6, .Ladd_return_nan_or_inf
/* If x is a NaN, return it. Otherwise, return y. */
slli a7, xh, 12
or a7, a7, xl
- beqz a7, .Ladd_ynan_or_inf
-1: leaf_return
+ bnez a7, .Ladd_return_nan
.Ladd_ynan_or_inf:
/* Return y. */
mov xh, yh
mov xl, yl
+
+.Ladd_return_nan_or_inf:
+ slli a7, xh, 12
+ or a7, a7, xl
+ bnez a7, .Ladd_return_nan
+ leaf_return
+
+.Ladd_return_nan:
+ movi a4, 0x80000 /* make it a quiet NaN */
+ or xh, xh, a4
leaf_return
.Ladd_opposite_signs:
@@ -319,17 +329,24 @@ __subdf3_aux:
.Lsub_xnan_or_inf:
/* If y is neither Infinity nor NaN, return x. */
- bnall yh, a6, 1f
+ bnall yh, a6, .Lsub_return_nan_or_inf
+
+.Lsub_return_nan:
/* Both x and y are either NaN or Inf, so the result is NaN. */
movi a4, 0x80000 /* make it a quiet NaN */
or xh, xh, a4
-1: leaf_return
+ leaf_return
.Lsub_ynan_or_inf:
/* Negate y and return it. */
slli a7, a6, 11
xor xh, yh, a7
mov xl, yl
+
+.Lsub_return_nan_or_inf:
+ slli a7, xh, 12
+ or a7, a7, xl
+ bnez a7, .Lsub_return_nan
leaf_return
.Lsub_opposite_signs:
@@ -692,10 +709,7 @@ __muldf3_aux:
/* If y is zero, return NaN. */
bnez yl, 1f
slli a8, yh, 1
- bnez a8, 1f
- movi a4, 0x80000 /* make it a quiet NaN */
- or xh, xh, a4
- j .Lmul_done
+ beqz a8, .Lmul_return_nan
1:
/* If y is NaN, return y. */
bnall yh, a6, .Lmul_returnx
@@ -708,6 +722,9 @@ __muldf3_aux:
mov xl, yl
.Lmul_returnx:
+ slli a8, xh, 12
+ or a8, a8, xl
+ bnez a8, .Lmul_return_nan
/* Set the sign bit and return. */
extui a7, a7, 31, 1
slli xh, xh, 1
@@ -720,8 +737,11 @@ __muldf3_aux:
bnez xl, .Lmul_returny
slli a8, xh, 1
bnez a8, .Lmul_returny
- movi a7, 0x80000 /* make it a quiet NaN */
- or xh, yh, a7
+ mov xh, yh
+
+.Lmul_return_nan:
+ movi a4, 0x80000 /* make it a quiet NaN */
+ or xh, xh, a4
j .Lmul_done
.align 4
@@ -1320,10 +1340,11 @@ __divdf3_aux:
slli a7, a7, 31
xor xh, xh, a7
/* If y is NaN or Inf, return NaN. */
- bnall yh, a6, 1f
- movi a4, 0x80000 /* make it a quiet NaN */
- or xh, xh, a4
-1: leaf_return
+ ball yh, a6, .Ldiv_return_nan
+ slli a8, xh, 12
+ or a8, a8, xl
+ bnez a8, .Ldiv_return_nan
+ leaf_return
.Ldiv_ynan_or_inf:
/* If y is Infinity, return zero. */
@@ -1333,6 +1354,10 @@ __divdf3_aux:
/* y is NaN; return it. */
mov xh, yh
mov xl, yl
+
+.Ldiv_return_nan:
+ movi a4, 0x80000 /* make it a quiet NaN */
+ or xh, xh, a4
leaf_return
.Ldiv_highequal1:
diff --git a/libgcc/config/xtensa/ieee754-sf.S b/libgcc/config/xtensa/ieee754-sf.S
index 7864a74eefa..9fe0d1c8ff5 100644
--- a/libgcc/config/xtensa/ieee754-sf.S
+++ b/libgcc/config/xtensa/ieee754-sf.S
@@ -55,6 +55,7 @@ __negsf2:
#ifdef L_addsubsf3
+ .literal_position
/* Addition */
__addsf3_aux:
@@ -64,15 +65,23 @@ __addsf3_aux:
.Ladd_xnan_or_inf:
/* If y is neither Infinity nor NaN, return x. */
- bnall a3, a6, 1f
+ bnall a3, a6, .Ladd_return_nan_or_inf
/* If x is a NaN, return it. Otherwise, return y. */
slli a7, a2, 9
- beqz a7, .Ladd_ynan_or_inf
-1: leaf_return
+ bnez a7, .Ladd_return_nan
.Ladd_ynan_or_inf:
/* Return y. */
mov a2, a3
+
+.Ladd_return_nan_or_inf:
+ slli a7, a2, 9
+ bnez a7, .Ladd_return_nan
+ leaf_return
+
+.Ladd_return_nan:
+ movi a6, 0x400000 /* make it a quiet NaN */
+ or a2, a2, a6
leaf_return
.Ladd_opposite_signs:
@@ -265,16 +274,22 @@ __subsf3_aux:
.Lsub_xnan_or_inf:
/* If y is neither Infinity nor NaN, return x. */
- bnall a3, a6, 1f
+ bnall a3, a6, .Lsub_return_nan_or_inf
/* Both x and y are either NaN or Inf, so the result is NaN. */
+
+.Lsub_return_nan:
movi a4, 0x400000 /* make it a quiet NaN */
or a2, a2, a4
-1: leaf_return
+ leaf_return
.Lsub_ynan_or_inf:
/* Negate y and return it. */
slli a7, a6, 8
xor a2, a3, a7
+
+.Lsub_return_nan_or_inf:
+ slli a7, a2, 9
+ bnez a7, .Lsub_return_nan
leaf_return
.Lsub_opposite_signs:
@@ -537,11 +552,7 @@ __mulsf3_aux:
.Lmul_xnan_or_inf:
/* If y is zero, return NaN. */
slli a8, a3, 1
- bnez a8, 1f
- movi a4, 0x400000 /* make it a quiet NaN */
- or a2, a2, a4
- j .Lmul_done
-1:
+ beqz a8, .Lmul_return_nan
/* If y is NaN, return y. */
bnall a3, a6, .Lmul_returnx
slli a8, a3, 9
@@ -551,6 +562,8 @@ __mulsf3_aux:
mov a2, a3
.Lmul_returnx:
+ slli a8, a2, 9
+ bnez a8, .Lmul_return_nan
/* Set the sign bit and return. */
extui a7, a7, 31, 1
slli a2, a2, 1
@@ -562,8 +575,11 @@ __mulsf3_aux:
/* If x is zero, return NaN. */
slli a8, a2, 1
bnez a8, .Lmul_returny
- movi a7, 0x400000 /* make it a quiet NaN */
- or a2, a3, a7
+ mov a2, a3
+
+.Lmul_return_nan:
+ movi a4, 0x400000 /* make it a quiet NaN */
+ or a2, a2, a4
j .Lmul_done
.align 4
@@ -951,10 +967,10 @@ __divsf3_aux:
slli a7, a7, 31
xor a2, a2, a7
/* If y is NaN or Inf, return NaN. */
- bnall a3, a6, 1f
- movi a4, 0x400000 /* make it a quiet NaN */
- or a2, a2, a4
-1: leaf_return
+ ball a3, a6, .Ldiv_return_nan
+ slli a7, a2, 9
+ bnez a7, .Ldiv_return_nan
+ leaf_return
.Ldiv_ynan_or_inf:
/* If y is Infinity, return zero. */
@@ -962,6 +978,10 @@ __divsf3_aux:
beqz a8, .Ldiv_return_zero
/* y is NaN; return it. */
mov a2, a3
+
+.Ldiv_return_nan:
+ movi a4, 0x400000 /* make it a quiet NaN */
+ or a2, a2, a4
leaf_return
.align 4
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 8db45525a7d..79564c58897 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,46 @@
+2018-03-02 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2018-03-02 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/84671
+ * include/bits/parse_numbers.h (_Number_help): Add partial
+ specialization to handle digit separators. Adjust partial
+ specialization for recursion temrination to require _Pow == 1ULL.
+ * testsuite/20_util/duration/literals/84671.cc: New
+
+2018-02-19 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2018-02-15 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81797
+ * configure.ac (INCLUDE_DIR_NOTPARALLEL): Define.
+ * configure: Regenerate.
+ * include/Makefile.am (INCLUDE_DIR_NOTPARALLEL): Add .NOTPARALLEL when
+ defined.
+ * include/Makefile.in: Regenerate.
+
+2018-01-29 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2018-01-15 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/83833
+ * include/bits/random.h (chi_squared_distribution::param): Update
+ gamma distribution parameter.
+ * testsuite/26_numerics/random/chi_squared_distribution/83833.cc: New
+ test.
+
+2018-01-19 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2018-01-16 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/83834
+ * config/abi/pre/gnu.ver (GLIBCXX_3.4): Replace std::c[a-g]* wildcard
+ pattern with exact match for std::cerr.
+
2018-01-15 Jonathan Wakely <jwakely@redhat.com>
* python/libstdcxx/v6/printers.py (register_type_printers): Remove
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 5c6b0feb2b3..3fc73a85895 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -60,7 +60,7 @@ GLIBCXX_3.4 {
std::basic_[t-z]*;
std::ba[t-z]*;
std::b[b-z]*;
- std::c[a-g]*;
+ std::cerr;
# std::char_traits;
# std::c[i-z]*;
std::c[i-n]*;
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 5c99ebac81a..f055474c59f 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -619,6 +619,8 @@ CPU_DEFINES_SRCDIR
ATOMIC_FLAGS
ATOMIC_WORD_SRCDIR
ATOMICITY_SRCDIR
+INCLUDE_DIR_NOTPARALLEL_FALSE
+INCLUDE_DIR_NOTPARALLEL_TRUE
BUILD_PDF_FALSE
BUILD_PDF_TRUE
PDFLATEX
@@ -11596,7 +11598,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11599 "configure"
+#line 11601 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11702,7 +11704,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11705 "configure"
+#line 11707 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15388,7 +15390,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 15391 "configure"
+#line 15393 "configure"
int main()
{
typedef bool atomic_type;
@@ -15423,7 +15425,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15426 "configure"
+#line 15428 "configure"
int main()
{
typedef short atomic_type;
@@ -15458,7 +15460,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15461 "configure"
+#line 15463 "configure"
int main()
{
// NB: _Atomic_word not necessarily int.
@@ -15494,7 +15496,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15497 "configure"
+#line 15499 "configure"
int main()
{
typedef long long atomic_type;
@@ -15575,7 +15577,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15578 "configure"
+#line 15580 "configure"
int main()
{
_Decimal32 d1;
@@ -15617,7 +15619,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15620 "configure"
+#line 15622 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -15651,7 +15653,7 @@ $as_echo "$enable_int128" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15654 "configure"
+#line 15656 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -81017,6 +81019,18 @@ else
fi
+case "$build" in
+ *-*-darwin* ) glibcxx_include_dir_notparallel=yes ;;
+ * ) glibcxx_include_dir_notparallel=no ;;
+esac
+ if test $glibcxx_include_dir_notparallel = "yes"; then
+ INCLUDE_DIR_NOTPARALLEL_TRUE=
+ INCLUDE_DIR_NOTPARALLEL_FALSE='#'
+else
+ INCLUDE_DIR_NOTPARALLEL_TRUE='#'
+ INCLUDE_DIR_NOTPARALLEL_FALSE=
+fi
+
# Propagate the target-specific source directories through the build chain.
ATOMICITY_SRCDIR=config/${atomicity_dir}
@@ -81696,6 +81710,10 @@ if test -z "${BUILD_PDF_TRUE}" && test -z "${BUILD_PDF_FALSE}"; then
as_fn_error "conditional \"BUILD_PDF\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${INCLUDE_DIR_NOTPARALLEL_TRUE}" && test -z "${INCLUDE_DIR_NOTPARALLEL_FALSE}"; then
+ as_fn_error "conditional \"INCLUDE_DIR_NOTPARALLEL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
: ${CONFIG_STATUS=./config.status}
ac_write_fail=0
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 9e19e9927fd..b59f9926f36 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -456,6 +456,12 @@ AM_CONDITIONAL(BUILD_PDF,
test $ac_cv_prog_DBLATEX = "yes" &&
test $ac_cv_prog_PDFLATEX = "yes")
+case "$build" in
+ *-*-darwin* ) glibcxx_include_dir_notparallel=yes ;;
+ * ) glibcxx_include_dir_notparallel=no ;;
+esac
+AM_CONDITIONAL(INCLUDE_DIR_NOTPARALLEL,
+ test $glibcxx_include_dir_notparallel = "yes")
# Propagate the target-specific source directories through the build chain.
ATOMICITY_SRCDIR=config/${atomicity_dir}
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 1ef6d2a5469..e027024061c 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1459,3 +1459,8 @@ $(decimal_headers): ; @:
$(ext_headers): ; @:
$(experimental_headers): ; @:
$(experimental_bits_headers): ; @:
+
+if INCLUDE_DIR_NOTPARALLEL
+# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81797
+.NOTPARALLEL:
+endif
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 751f16b037e..224bd0af44d 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1879,6 +1879,9 @@ $(ext_headers): ; @:
$(experimental_headers): ; @:
$(experimental_bits_headers): ; @:
+# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81797
+@INCLUDE_DIR_NOTPARALLEL_TRUE@.NOTPARALLEL:
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h
index 7aa43fc2ba6..7823eb8ddf0 100644
--- a/libstdc++-v3/include/bits/parse_numbers.h
+++ b/libstdc++-v3/include/bits/parse_numbers.h
@@ -197,6 +197,13 @@ namespace __parse_int
"integer literal does not fit in unsigned long long");
};
+ // Skip past digit separators:
+ template<unsigned _Base, unsigned long long _Pow, char _Dig, char..._Digs>
+ struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...>
+ : _Number_help<_Base, _Pow, _Dig, _Digs...>
+ { };
+
+ // Terminating case for recursion:
template<unsigned _Base, unsigned long long _Pow, char _Dig>
struct _Number_help<_Base, _Pow, _Dig>
{
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 9de480c0215..52a9b8700b9 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -2618,7 +2618,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
void
param(const param_type& __param)
- { _M_param = __param; }
+ {
+ _M_param = __param;
+ typedef typename std::gamma_distribution<result_type>::param_type
+ param_type;
+ _M_gd.param(param_type{__param.n() / 2});
+ }
/**
* @brief Returns the greatest lower bound value of the distribution.
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/84671.cc b/libstdc++-v3/testsuite/20_util/duration/literals/84671.cc
new file mode 100644
index 00000000000..4f50ec4c9cc
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/84671.cc
@@ -0,0 +1,26 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++14 } }
+
+#include <chrono>
+
+// PR libstdc++/84671
+using namespace std::literals::chrono_literals;
+constexpr auto ns_ok = 12113ns;
+constexpr auto ns_fail = 12'11'3ns;
+static_assert(ns_ok == ns_fail, "digit separators work in duration literals");
diff --git a/libstdc++-v3/testsuite/26_numerics/random/chi_squared_distribution/83833.cc b/libstdc++-v3/testsuite/26_numerics/random/chi_squared_distribution/83833.cc
new file mode 100644
index 00000000000..821a1a40e2a
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/chi_squared_distribution/83833.cc
@@ -0,0 +1,40 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-ffloat-store" { target { m68*-*-* || ia32 } } }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::default_random_engine r1, r2;
+ using chi = std::chi_squared_distribution<double>;
+ chi::param_type p(5);
+ chi d1(p);
+ chi d2;
+ d2.param(p);
+ VERIFY( d1(r1) == d2(r2) ); // PR libstdc++/83833
+}
+
+int
+main()
+{
+ test01();
+}